UNPKG

@limetech/lime-elements

Version:
185 lines (178 loc) • 7.89 kB
import { r as registerInstance, c as createEvent, h, a as getElement } from './index-DBTJNfo7.js'; import { c as createRandomString } from './random-string-JbKhhoXs.js'; import { E as ESCAPE } from './keycodes-rI0IeKpx.js'; import { f as focusTriggerElement, z as zipObject } from './focus-trigger-element-6aEStEKM.js'; import './_assignValue-DkGAX8ec.js'; import './_baseAssignValue-C8Uwn8zr.js'; import './_defineProperty-yVdnnt__.js'; import './_getNative-aN4R8EiP.js'; import './eq-D7VMHFyO.js'; import './isObject-BJQylLSL.js'; /** * Check if an element is a descendant of another * * If the child element is a descendant of a limel-portal, this function will * go back through the portal and check the original tree recursively * * @param element - the parent element * @param child - the child element to check * @returns `true` if child is a descendant of element, taking * portals into account */ function portalContains(element, child) { var _a; if (element.contains(child) || ((_a = element.shadowRoot) === null || _a === void 0 ? void 0 : _a.contains(child))) { return true; } const parent = findParent(child); if (!parent) { return false; } return portalContains(element, parent); } function findParent(element) { const portal = element.closest('.limel-portal--container'); if (portal) { return portal.portalSource; } const rootNode = element.getRootNode(); return rootNode.host; } const popoverCss = () => `.trigger-anchor{display:inline-block;position:relative}`; const Popover = class { constructor(hostRef) { registerInstance(this, hostRef); this.close = createEvent(this, "close"); /** * True if the content within the popover should be visible */ this.open = false; this.shouldRestoreFocusOnClose = false; this.handleGlobalKeyPress = (event) => { if (event.key !== ESCAPE) { return; } event.stopPropagation(); event.preventDefault(); this.requestCloseAndRestoreFocus(); }; this.requestCloseAndRestoreFocus = () => { this.shouldRestoreFocusOnClose = true; this.close.emit(); }; this.setTriggerRef = (elm) => { this.triggerSlot = elm; }; this.focusTrigger = () => { var _a, _b; const trigger = (_b = (_a = this.triggerSlot) === null || _a === void 0 ? void 0 : _a.assignedElements()) === null || _b === void 0 ? void 0 : _b[0]; focusTriggerElement(trigger); }; this.setTriggerAttributes = (element) => { const attributes = { 'aria-haspopup': true, 'aria-expanded': this.open, 'aria-controls': this.portalId, role: 'button', }; for (const [key, value] of Object.entries(attributes)) { if (value) { element.setAttribute(key, String(value)); } else { element.removeAttribute(key); } } }; this.portalId = createRandomString(); this.globalClickListener = this.globalClickListener.bind(this); } watchOpen() { this.setupGlobalHandlers(); if (!this.open && this.shouldRestoreFocusOnClose) { this.shouldRestoreFocusOnClose = false; setTimeout(this.focusTrigger, 0); } } componentWillLoad() { this.setupGlobalHandlers(); } componentDidRender() { if (!this.triggerSlot) { return; } // eslint-disable-next-line unicorn/no-array-for-each this.triggerSlot.assignedElements().forEach(this.setTriggerAttributes); } setupGlobalHandlers() { if (this.open) { document.addEventListener('click', this.globalClickListener, { capture: true, }); document.addEventListener('keydown', this.handleGlobalKeyPress); } else { document.removeEventListener('click', this.globalClickListener); document.removeEventListener('keydown', this.handleGlobalKeyPress); } } render() { const cssProperties = this.getCssProperties(); const popoverZIndex = getComputedStyle(this.host).getPropertyValue('--popover-z-index'); return (h("div", { key: '53e64435fa661015fbbf2e449890864c8008c329', class: "trigger-anchor" }, h("slot", { key: '85336e8f76377921850ffc7704c7588707c45066', name: "trigger", ref: this.setTriggerRef }), h("limel-portal", { key: 'a40bfde87375a494ac5404911b4b1f058a55becf', visible: this.open, containerId: this.portalId, containerStyle: { 'z-index': popoverZIndex }, openDirection: this.openDirection }, h("limel-popover-surface", { key: '396e369ae3e61a79bfd2f520e05187a6ff85f834', contentCollection: this.host.children, style: cssProperties })))); } globalClickListener(event) { const element = event.target; const clickedInside = portalContains(this.host, element); if (this.open && !clickedInside) { event.stopPropagation(); event.preventDefault(); this.close.emit(); } } getCssProperties() { const propertyNames = [ '--popover-surface-width', '--popover-body-background-color', '--popover-border-radius', '--popover-box-shadow', ]; const style = getComputedStyle(this.host); const values = propertyNames.map((property) => { return style.getPropertyValue(property); }); return zipObject(propertyNames, values); } get host() { return getElement(this); } static get watchers() { return { "open": [{ "watchOpen": 0 }] }; } }; Popover.style = popoverCss(); const popoverSurfaceCss = () => `@charset "UTF-8";:host(limel-popover-surface){isolation:isolate;position:relative;display:flex;width:var(--popover-surface-width, auto);max-height:inherit;max-width:calc(100vw - 2rem);margin:0 0.25rem}.limel-popover-surface{flex:1;min-width:0;min-height:0;border-radius:var(--popover-border-radius, 0.75rem);box-shadow:var(--popover-box-shadow, var(--shadow-depth-16));backdrop-filter:blur(0.3125rem);-webkit-backdrop-filter:blur(0.3125rem)}.limel-popover-surface:after{transition:opacity 0.4s ease;pointer-events:none;content:"";position:absolute;top:0;right:0;bottom:0;left:0;z-index:-1;opacity:0.95;border-radius:var(--popover-border-radius, 0.75rem);background-color:var(--popover-body-background-color, var(--lime-elevated-surface-background-color))}.limel-popover-surface:focus{outline:none}.limel-popover-surface:focus-visible{outline:none;box-shadow:var(--shadow-depth-8-focused)}.limel-popover-surface:focus:after,.limel-popover-surface:focus-within:after{opacity:1}.limel-popover-surface>*{box-sizing:border-box}`; const PopoverSurface = class { constructor(hostRef) { registerInstance(this, hostRef); } componentDidLoad() { this.appendElement(); } render() { return h("div", { key: '72e73b254be6cebbd27332329b10a58210ae0352', class: "limel-popover-surface", tabindex: "0" }); } appendElement() { const portalContainer = this.host.shadowRoot.querySelector('.limel-popover-surface'); const childElementsCopy = [...this.contentCollection]; for (const child of childElementsCopy) { if (child.slot === 'trigger') { continue; } portalContainer.append(child); } } get host() { return getElement(this); } }; PopoverSurface.style = popoverSurfaceCss(); export { Popover as limel_popover, PopoverSurface as limel_popover_surface };