ranui
Version:
A framework-agnostic Web Components UI library built on native custom elements, with TypeScript types, light/dark theming, SSR and PWA support.
199 lines (198 loc) • 7.92 kB
JavaScript
import { T as u, _ as f, i as l, p as w } from "./factory-WDxu11V0.js";
import { t as y } from "./events-Cqz3ramM.js";
import "./builder-EH76YCFS.js";
import { a as b, i as s, n as p, o as C, t as D } from "./utils-U-9uH7EX.js";
import { a as P, n as I } from "./ssr-BzykYefm.js";
import { n as k } from "./a11y-ZSlIUH9B.js";
import "./dropdown-B6i_Wh9a.js";
import { t as T } from "./floating-C16PP_Xu.js";
import "./content-CaSimA6g.js";
import { debounce as r, isMobile as d } from "ranuts/utils";
var _ = ":host{display:var(--ran-popover-host-display, block)}.ran-popover{box-sizing:var(--ran-popover-box-sizing, border-box);position:var(--ran-popover-position, relative);display:var(--ran-popover-display, block);margin:var(--ran-popover-margin, 0);padding:var(--ran-popover-padding, 0)}.ran-popover-block{display:var(--ran-popover-block-display, block)}", x = 8, R = 300, n = 16, z = /* @__PURE__ */ (function(e) {
return e.TOP = "top", e.BOTTOM = "bottom", e.LEFT = "left", e.RIGHT = "right", e;
})({}), c = {
top: "bottom",
bottom: "top",
left: "right",
right: "left"
}, A = class extends I {
_events = new y();
_slot;
popoverBlock;
popoverContent;
popoverInner;
popoverInnerBlock;
_shadowDom;
removeTimeId;
_repositionBound = !1;
_floating = new T({
host: this,
panel: () => this.popoverContent,
anchor: () => Array.from(this.children).find((e) => e.tagName !== "R-CONTENT") ?? this,
placement: () => this.placement,
offset: x,
containerId: () => this.getPopupContainerId,
afterPosition: (e, t) => {
const { anchorRect: o, panelRect: i, side: v } = e, h = c[v];
h && t.setAttribute("arrow", h), t.style.setProperty("--ran-dropdown-arrow-anchor-width", `${o.width}px`), t.style.setProperty("--ran-dropdown-arrow-anchor-height", `${o.height}px`), t.style.setProperty("--ran-dropdown-min-width", `${i.width}px`), t.style.setProperty("--ran-dropdown-min-height", `${i.height}px`);
const a = t.getBoundingClientRect(), m = o.left + o.width / 2, g = a.left + a.width / 2;
t.style.setProperty("--ran-dropdown-arrow-anchor-offset", `${m - g}px`), t.style.setProperty("--ran-dropdown-arrow-anchor-offset-y", `${o.top - a.top}px`);
}
});
static get observedAttributes() {
return [
"open",
"placement",
"trigger",
"sheet"
];
}
closePopover = () => {
this.setDropdownDisplayNone();
};
constructor() {
super(), this._shadowDom = D(this, _);
const e = u(), t = l().class("ran-popover-block").role("tooltip").children(w().class("slot").ref(e)).build();
this._shadowDom.appendChild(t), this.popoverBlock = t, this._slot = b(e, "slot");
}
get placement() {
return p(this, "placement", "top");
}
set placement(e) {
s(this, "placement", e);
}
get placementSide() {
return this.placement.split("-")[0];
}
get open() {
return this.hasAttribute("open");
}
set open(e) {
e ? this.setAttribute("open", "") : this.removeAttribute("open");
}
_applyOpen = () => {
this._floating.apply(this.open);
};
show = () => {
this.open = !0;
};
hide = () => {
this.open = !1;
};
toggle = () => {
this.open = !this.open;
};
get trigger() {
return p(this, "trigger", "hover");
}
set trigger(e) {
s(this, "trigger", e);
}
get getPopupContainerId() {
return p(this, "getPopupContainerId");
}
set getPopupContainerId(e) {
s(this, "getPopupContainerId", e);
}
get sheet() {
return p(this, "sheet");
}
set sheet(e) {
s(this, "sheet", e);
}
handlerExternalCss = () => {
C(this, this._shadowDom, "sheet", null, this.sheet);
};
initAria = () => {
this.hasAttribute("tabindex") || (this.tabIndex = 0), this.setAttribute("aria-haspopup", "dialog"), this.setAttribute("aria-expanded", "false");
};
updateAriaExpanded = (e) => {
this.setAttribute("aria-expanded", e ? "true" : "false");
};
stopPropagation = (e) => {
e.stopPropagation();
};
createContent = (e) => {
if (e) {
if (!this.popoverContent) {
const t = getComputedStyle(this).getPropertyValue("--ran-popover-content-padding").trim() || "12px";
this.popoverContent = f("r-dropdown").class("ran-popover-dropdown").style("display", "none").style("position", "absolute").cssVar("ran-dropdown-padding", t).build(), this.popoverContent?.addEventListener("click", this.stopPropagation);
const o = l().children(this.popoverContent).build();
this.popoverInner = o, this.trigger.includes("hover") && !d() && (this.popoverContent?.addEventListener("mouseleave", this.blur), this.popoverContent?.addEventListener("mouseenter", this.removeDropDownTimeId));
const i = this.getRootNode();
((i.getElementById ? i.getElementById(this.getPopupContainerId) : null) || document.getElementById(this.getPopupContainerId) || document.body).appendChild(o);
}
if (this.popoverContent && e.length > 0) {
this.popoverContent.innerHTML = "";
const t = document.createDocumentFragment();
for (const o of e) t.appendChild(o);
this.popoverContent.appendChild(t);
}
}
};
watchContent = (e) => {
const { value: t } = e.detail;
this.createContent(t.content);
};
blur = r(() => {
this.removeTimeId && this.removeDropDownTimeId(), this.removeTimeId = setTimeout(() => {
this.removeDropDownTimeId(), this.setDropdownDisplayNone();
}, R);
}, n);
removeDropDownTimeId = r(() => {
this.trigger.includes("hover") && !d() && (clearTimeout(this.removeTimeId), this.removeTimeId = void 0);
}, n);
setDropdownDisplayBlock = r(() => {
this.open = !0;
}, n);
setDropdownDisplayNone = r(() => {
this.open = !1;
}, n);
placementPosition = () => {
this._floating.position();
};
hoverPopover = (e) => {
e.stopPropagation(), e.preventDefault(), this.setDropdownDisplayBlock();
};
clickContent = (e) => {
e.stopPropagation();
};
clickPopover = (e) => {
e.stopPropagation(), e.preventDefault(), this.toggle();
};
keydownPopover = (e) => {
k(e) && (e.preventDefault(), this.setDropdownDisplayBlock()), e.key === "Escape" && (e.preventDefault(), this.setDropdownDisplayNone());
};
clickRemovePopover = (e) => {
this.hoverRemovePopover(e);
};
popoverTrigger = () => {
this._events.abort();
for (const e of this.children) e.tagName === "R-CONTENT" && this._events.on(e, "change", this.watchContent);
this.trigger.includes("hover") && (this._events.on(this, "mouseenter", this.hoverPopover), this._events.on(this, "mouseleave", this.blur)), this._events.on(this, "click", this.clickPopover).on(this, "keydown", this.keydownPopover).on(document, "click", this.clickRemovePopover);
};
hoverRemovePopover = (e) => {
e.stopPropagation(), this.setDropdownDisplayNone();
};
changePlacement = r(() => {
if (!this.getPopupContainerId && this.open) return;
const e = c[this.placementSide];
e && this.popoverContent?.setAttribute("arrow", e);
}, n);
connectedCallback() {
this.initAria(), this.handlerExternalCss();
for (const e of this.children) e.tagName === "R-CONTENT" && this.createContent(e.children);
this.popoverTrigger(), this.changePlacement();
}
disconnectedCallback() {
this._events.abort(), this.setDropdownDisplayBlock.cancel(), this.setDropdownDisplayNone.cancel(), this.blur.cancel(), this.removeDropDownTimeId.cancel(), this._floating.destroy(), clearTimeout(this.removeTimeId), this.removeTimeId = void 0, this.popoverInner?.remove(), this.popoverInner = void 0, this.popoverContent = void 0;
}
attributeChangedCallback(e, t, o) {
t !== o && (e === "trigger" && this.popoverTrigger(), e === "placement" && this.changePlacement(), e === "sheet" && this.handlerExternalCss(), e === "open" && this._applyOpen());
}
};
P("r-popover", A);
export {
A as n,
z as t
};