import { property, query } from "lit/decorators.js"; import GlobalStyle from "../../internal/global-style.js"; import { css, html, type PropertyValues, type TemplateResult } from "lit"; import { godown, htmlSlot, StyleController, styles } from "@godown/element"; import { hidePopover, showPopover } from "../../internal/popover.js"; const POPOVER = "popover"; const protoName = POPOVER; /** * {@link Popover} renders a popover. * * This requires the support of the popover API and CSS position-area. * * @fires toggle - Fired when the popover is toggled. * @slot popover - Popover content. * @slot - Popover trigger. * @category display */ @godown(protoName) @styles(css` :host { display: inline-block; } [part="trigger"] { display: contents; } [part="root"] { display: inherit; } [part="popover"] { inset: unset; z-index: 1; overflow: visible; position: absolute; position-try-fallbacks: flip-block; } `) class Popover extends GlobalStyle { anchorName = `--${POPOVER}-${Math.random().toString(36).slice(2)}`; @property({ type: Boolean, reflect: true }) open = false; @property() action: "hide" | "show" | "toggle" | "none" = "show"; @property() span: "span" | "spread" | "isolated" = "span"; /** * The position refers to the spatial location of the popover in relation to the trigger, * rather than the alignment property between them. */ @property() position: | "center" | "left" | "left-top" | "left-bottom" | "right" | "right-top" | "right-bottom" | "top" | "top-left" | "top-right" | "bottom" | "bottom-left" | "bottom-right" | "start" | "start-start" | "start-end" | "end" | "end-start" | "end-end" = "bottom"; @query(`[part=${POPOVER}]`, true) protected _popover: HTMLElement; constructor() { super(); new StyleController(this, () => { return { "[part=root],slot:not([name])::slotted(*)": { "anchor-name": this.anchorName, }, "[part=popover]": { "position-anchor": this.anchorName, "position-area": this.resolveArea(), }, }; }); } protected render(): TemplateResult<1> { return html`