flexipop
Version:
208 lines (207 loc) • 8.26 kB
JavaScript
var X = Object.defineProperty;
var Y = (n, e, t) => e in n ? X(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
var o = (n, e, t) => Y(n, typeof e != "symbol" ? e + "" : e, t);
const k = "bottom";
const z = ({ reference: n, popper: e }) => {
if (!n || !e)
throw new Error("Reference or popper element is null or undefined");
const t = /* @__PURE__ */ new WeakMap(), s = (c) => (t.has(c) || t.set(c, c.getBoundingClientRect()), t.get(c)), a = s(e), i = s(n);
return {
popperHeight: a.height,
popperWidth: a.width,
refHeight: i.height,
refWidth: i.width,
refLeft: i.left,
refTop: i.top,
refRight: i.right
};
}, B = (n, e, t, s) => {
const a = t, i = s - (t + e);
return a >= (n - e) / 2 && i >= (n - e) / 2;
}, C = (n, e, t, s) => (n - e) / 2 <= t && t + n / 2 + e / 2 <= s, U = (n, e, t, s, a) => t > a - s ? e() ? window.innerHeight - a : t - a : n() ? 0 : t + s, L = (n, e, t, s) => n <= s && t - n <= e, V = (n, e, t, s) => t <= s && -n <= e, N = (n, e, t, s, a, i) => {
const c = a - t - i, r = t - s, d = t + i - s + (a - t - i), l = c >= 0 ? a - s : r >= 0 ? t - s : t;
return n() ? 0 : e() ? d : l;
}, _ = (n, e, t, s) => n <= t && e - n - s >= n, $ = (n, e) => n >= e, f = ({
placement: n,
refWidth: e,
refTop: t,
refLeft: s,
refHeight: a,
popperWidth: i,
popperHeight: c,
windowHeight: r,
windowWidth: d,
offsetDistance: l
}) => {
const h = d - s - e, u = s, x = r - t - a, F = t, y = () => U(
() => V(t, a, c, r),
() => L(t, a, c, r),
t,
a,
c
), P = () => N(
() => _(s, d, i, e),
() => $(s, i),
s,
i,
d,
e
), A = () => B(i, e, s, d) ? s + e / 2 - i / 2 : P(), T = () => C(c, a, t, r) ? t + a / 2 - c / 2 : y(), D = () => s + i <= d ? s : P(), I = () => s + e - i >= 0 ? s + e - i : P(), j = () => t + c <= r ? t : y(), g = () => t + a - c >= 0 ? t + a - c : y();
let m = 0, E = 0;
const R = t - c - l, b = t + a + l, v = s - i - l, w = s + e + l, O = F >= c + l, S = x >= c + l, p = u >= i + l, M = h >= i + l;
switch (n.startsWith("top") ? E = O ? R : S ? b : Math.max(R, b) : n.startsWith("bottom") ? E = S ? b : O ? R : Math.max(b) : n.startsWith("left") ? m = p ? v : M ? w : Math.max(v, w) : n.startsWith("right") && (m = M ? w : p ? v : Math.max(w, v)), n) {
case "bottom":
case "bottom-middle":
case "top":
case "top-middle":
m = A();
break;
case "left":
case "left-middle":
case "right":
case "right-middle":
E = T();
break;
case "bottom-start":
case "top-start":
m = D();
break;
case "bottom-end":
case "top-end":
m = I();
break;
case "left-start":
case "right-start":
E = j();
break;
case "left-end":
case "right-end":
E = g();
break;
}
return { x: m, y: E };
};
class G {
/**
* Flexilla Popper
* @param reference
* @param popper
* @param options
*/
/**
* Creates an instance of CreatePopper
* @param {HTMLElement} reference - The reference element to position against
* @param {HTMLElement} popper - The element to be positioned
* @param {PopperOptions} [options] - Configuration options
* @param {number} [options.offsetDistance] - Distance between popper and reference element
* @param {Placement} [options.placement] - Preferred placement of the popper
* @param {Object} [options.eventEffect] - Event handling configuration
* @param {boolean} [options.eventEffect.disableOnResize] - Disable position updates on window resize
* @param {boolean} [options.eventEffect.disableOnScroll] - Disable position updates on scroll
* @param {Function} [options.onUpdate] - Callback function when position updates
*/
constructor(e, t, s = {}) {
o(this, "reference");
o(this, "popper");
o(this, "offsetDistance");
o(this, "placement");
o(this, "disableOnResize");
o(this, "disableOnScroll");
o(this, "onUpdate");
o(this, "isWindowEventsRegistered");
/**
* Validate Elements, check if reference and popper are valid HtmlELment
*/
o(this, "validateElements", () => {
if (!(this.reference instanceof HTMLElement)) throw new Error("Invalid HTMLElement for Reference Element");
if (!(this.popper instanceof HTMLElement)) throw new Error("Invalid HTMLElement for Popper");
if (typeof this.offsetDistance != "number") throw new Error("OffsetDistance must be a number");
});
/**
* Set Style Property
*/
o(this, "setPopperStyleProperty", (e, t) => {
this.popper.style.setProperty("--fx-popper-placement-x", `${e}px`), this.popper.style.setProperty("--fx-popper-placement-y", `${t}px`);
});
o(this, "setInitialStyles", () => {
this.popper.style.setProperty("--fx-popper-placement-x", ""), this.popper.style.setProperty("--fx-popper-placement-y", "");
});
o(this, "initPlacement", () => {
var u;
this.validateElements(), this.setInitialStyles();
const e = window.innerWidth, t = window.innerHeight, { popperHeight: s, popperWidth: a, refHeight: i, refWidth: c, refLeft: r, refTop: d } = z({ reference: this.reference, popper: this.popper }), { x: l, y: h } = f(
{
placement: this.placement,
refWidth: c,
refTop: d,
refLeft: r,
popperWidth: a,
refHeight: i,
popperHeight: s,
windowHeight: t,
windowWidth: e,
offsetDistance: this.offsetDistance
}
);
this.setPopperStyleProperty(l, h), (u = this.onUpdate) == null || u.call(this, { x: l, y: h, placement: this.placement });
});
o(this, "removeWindowEvents", () => {
this.isWindowEventsRegistered && (!this.disableOnResize && window.removeEventListener("resize", this.updatePosition), !this.disableOnScroll && window.removeEventListener("scroll", this.updatePosition), this.isWindowEventsRegistered = !1);
});
/**
* Add event Listeners : window resize and scroll
* These events depend on if it's disable or not
*/
o(this, "attachWindowEvent", () => {
this.isWindowEventsRegistered && this.removeWindowEvents(), this.disableOnResize || window.addEventListener("resize", this.updatePosition), this.disableOnScroll || window.addEventListener("scroll", this.updatePosition), this.isWindowEventsRegistered = !0;
});
/**
* Resets the popper position by clearing positioning styles
* @public
*/
o(this, "resetPosition", () => {
this.setInitialStyles();
});
/**
* Updates the popper position based on current reference element position
* @public
*/
o(this, "updatePosition", () => {
this.initPlacement(), this.attachWindowEvent();
});
/**
* Remove event listerners in case they are no longer needed
*/
/**
* Removes all event listeners and cleans up positioning styles
* @public
*/
o(this, "cleanupEvents", () => {
this.setInitialStyles(), this.removeWindowEvents();
});
const {
offsetDistance: a = 10,
placement: i = k,
eventEffect: c = {},
onUpdate: r
} = s;
if (!(e instanceof HTMLElement)) throw new Error("Invalid HTMLElement for Reference Element");
if (!(t instanceof HTMLElement)) throw new Error("Invalid HTMLElement for Popper");
if (s.offsetDistance && typeof s.offsetDistance != "number") throw new Error("OffsetDistance must be a number");
const { disableOnResize: d, disableOnScroll: l } = c;
this.isWindowEventsRegistered = !1, this.reference = e, this.popper = t, this.offsetDistance = a, this.placement = i, this.disableOnResize = d || !1, this.disableOnScroll = l || !1, this.onUpdate = r;
}
/**
* Updates popper configuration and recalculates position
* @public
* @param {Object} options - New configuration options
* @param {Placement} options.placement - New placement value
* @param {number} [options.offsetDistance] - New offset distance
*/
setOptions({ placement: e, offsetDistance: t }) {
this.placement = e, this.offsetDistance = t || this.offsetDistance, this.initPlacement(), this.attachWindowEvent();
}
}
export {
G as CreatePopper
};