import { PropertyValues } from 'lit'; import { VirtualTrigger } from '../../controllers/index.js'; import { SpectrumElement } from '../../element/index.js'; import { Placement, PopoverSize } from './Popover.types.js'; /** * Abstract base for the popover component. Owns the popover's behavior: the * dual-mode dialog lifecycle (`showPopover()` / `showModal()`), trigger and ARIA * wiring, positioning through the `PlacementController`, dismissal coordination, * and `swc-*` event dispatch. The concrete SWC subclass adds only the styles, the * render template, and the shadow-DOM element getters (`internalElement`, * `tipElement`) it overrides. * * @slot - Popover content. Free-form; consumers slot whatever pattern they build. */ export declare abstract class PopoverBase extends SpectrumElement { /** * @internal * * The valid placement values for the popover. Narrowed in downstream * first-party subclasses per the proxy pattern. */ static readonly VALID_PLACEMENTS: readonly Placement[]; /** * @internal * * The valid fixed sizes for the popover. */ static readonly VALID_SIZES: readonly PopoverSize[]; /** * Whether the popover is open. * * @default false */ open: boolean; /** * Opt in to blocking modal behavior (`.showModal()`): focus trap, * background inert, native `role="dialog"`. When unset, the popover uses * `popover="auto"` light-dismiss behavior. * * @default false */ modal: boolean; /** * Accessible name for the popover's dialog surface, forwarded as `aria-label` * to the internal element. Required in both modes (the surface is a dialog); * the component dev-warns when opened without one. */ accessibleLabel: string; /** * The placement of the popover relative to its trigger. * * @default 'bottom' */ placement: Placement; /** * Optional fixed size. When set, the popover uses a fixed inline size * (`s` → 336px, `m` → 416px, `l` → 576px); when unset, it fits its contents. */ size?: PopoverSize; /** * Hide the popover's arrow (tip). The arrow is shown by default. * * @default false */ hideArrow: boolean; /** * Main-axis offset in pixels from the trigger. * * @default 8 */ offset: number; /** * Cross-axis offset in pixels from the trigger. * * @default 0 */ crossOffset: number; /** * Distance from the viewport edge for the `flip` and `shift` middleware. * * Positioning implementation detail. Set by first-party components; excluded * from the public API. Users are not expected to set it. * * @internal * @default 8 */ containerPadding: number; /** * Allow the popover to flip to the opposite side when constrained. When * `false`, the popover stays in the requested placement. * * @default true */ shouldFlip: boolean; /** * Minimum inset of the tip from the popover's corners, passed to the * `PlacementController`'s `arrow` middleware as its `padding`. * * Positioning implementation detail. Set by first-party components; excluded * from the public API. Users are not expected to set it. * * @internal * @default 8 */ tipPadding: number; /** * ID of the trigger element in the same document tree root. */ for?: string; /** * Direct trigger reference. Overrides `for` when both are set. Use for * cross-shadow-root triggers or programmatic wiring. */ triggerElement: HTMLElement | VirtualTrigger | null; /** * Suppress the automatic click-to-toggle wiring on the resolved trigger. When * set, control visibility through the `open` property instead. ARIA * relationship wiring still applies. * * @default false */ manual: boolean; /** * The internal top-layer element (a `
` or a ``) the * lifecycle drives. Mandatory: the SWC rendering layer must implement this to * return the rendered `.swc-Popover` element from the shadow DOM (it may still * return `null` before the first render, which the lifecycle guards against). */ protected abstract get internalElement(): HTMLElement | null; /** * The arrow tip element passed to the `PlacementController`. Optional: returns * `null` in the base class (no arrow), and the SWC rendering layer overrides it * to return the rendered `.swc-Popover-tip` element when an arrow is shown. */ protected get tipElement(): HTMLElement | null; /** * The arrow's height in pixels, added to the trigger gap when the arrow is * shown. Returns `0` in the base class; the SWC rendering layer overrides it * with the token-derived value so the gap stays in sync with the tip, keeping * the base free of any coupling to the surface's CSS. */ protected get arrowHeight(): number; private _placementController; /** * Page-scroll lock for modal mode. Reference-counted at module scope so stacked * modal surfaces coordinate a single lock and restore the original overflow * exactly once. See {@link PageScrollLockController}. */ private _scrollLock; /** The trigger's AT-facing element that receives ARIA wiring. */ private _interactiveElement; /** The positioning anchor (an element or a `VirtualTrigger`). */ private _anchor; /** The element the click-to-toggle listeners are currently attached to. */ private _clickTrigger; /** * True between a trigger press start (`pointerdown`/`touchstart`) and its * `click`, so a light-dismiss inside that window is attributed to the press. * Both events open it, covering touch (where the dismiss can fire off * `touchstart` before `pointerdown`). */ private _triggerPointerActive; /** * Set when the trigger press light-dismissed an open popover (an `'outside'` * close observed while `_triggerPointerActive`), so the trailing `click` of * that same gesture is read as the close rather than a reopen. */ private _dismissedByTriggerPress; /** Cause of the in-progress close, read when dispatching `swc-close`. */ private _closeSource; /** Suppresses the open/close effect when `open` is synced from a native event. */ private _syncingOpen; /** * Suppresses the next `swc-open` dispatch. Set when re-showing an * already-open popover (a `modal` toggle swaps the internal element), so the * mode swap does not emit a second `swc-open` with no intervening close. */ private _suppressOpenEvent; /** Document Escape listener (default mode) used to label the close source. */ private _escapeListener?; /** Tears down the in-flight `_afterTransition` wiring (listener + fallback timer). */ private _cancelAfterTransition?; /** * Set after the first render. Auto-focus on open is suppressed until then so an * initially-`open` popover (server-rendered or a static demo) does not steal * focus on mount; only an open triggered after the element is live moves focus. */ private _hasCompletedFirstUpdate; /** * Set when a default-mode open should move focus into the dialog surface; * consumed by the first placement compute so focus lands after the surface is * anchored on screen (focusing it at its 0,0 reset origin would shift layout). * Modal mode moves focus natively via `showModal()`. */ private _pendingFocusOnOpen; disconnectedCallback(): void; protected update(changedProperties: PropertyValues): void; protected updated(changedProperties: PropertyValues): void; private _positioningChanged; private _wireTrigger; private _removeTriggerListeners; private _onTriggerPressStart; private _onTriggerClick; private _clearTriggerAria; private _isFocusWithin; private _startPositioning; private _show; private _focusSurface; private _hide; private _closeTeardown; private _stopPositioningWhenClosed; /** Set `open` without re-triggering the show/hide effect. */ private _syncOpen; protected _onBeforeToggle: (event: ToggleEvent) => void; protected _onCancel: (event: Event) => void; protected _onClose: () => void; protected _onPointerDown: (event: PointerEvent) => void; private _addEscapeListener; private _removeEscapeListener; private _dispatchOpen; private _dispatchClose; private _afterTransition; }