import { type Placement } from './floating.js'; export interface FloatingPanelOptions { /** The anchor the panel positions against. */ reference: () => HTMLElement | null | undefined; /** The floating panel element. */ floating: () => HTMLElement | null | undefined; /** Whether the panel is currently open. */ open: () => boolean; /** * Caller hint for top-layer promotion via the native popover API (default * `true`). `false` forces the panel into normal DOM flow (`position: * absolute`) for nested-overlay scenarios (e.g. a Menu/Select inside a * Popover) — the caller drives visibility via `display`. * * Even when `true`, the panel is automatically kept OUT of the top layer * while it sits inside an open modal `` — it then renders * `position: fixed` within the dialog's own subtree, because a second * top-layer element over a modal dialog is invisible on iOS/WebKit * (Codeberg #23). Read the effective state from the returned * `topLayer`/`strategy`. */ portal?: () => boolean; /** Preferred placement. @default 'bottom-start' */ placement?: () => Placement; /** Main-axis gap between anchor and panel, in px. @default 4 */ offsetDistance?: () => number; /** Viewport padding kept by the shift middleware, in px. @default 8 */ shiftPadding?: () => number; /** Clamp the panel width to exactly the anchor width. @default false */ syncWidth?: () => boolean; /** Clamp the panel's *min*-width to the anchor width (it may still grow). @default false */ syncMinWidth?: () => boolean; } /** * Effective render mode of a floating panel, returned by {@link useFloatingPanel} * so the calling component's markup stays in lockstep with the positioning * effect — both read the same derived values, so the `popover` attribute and the * `showPopover()` decision can never diverge. */ export interface FloatingPanelState { /** * `true` when the panel is promoted to the browser top layer (the markup sets * the `popover` attribute and the effect calls `showPopover()`); `false` when * it renders in place — inside a modal ``, or the explicit * `portal=false` inline mode. */ readonly topLayer: boolean; /** CSS positioning strategy the panel element must match (`position: `). */ readonly strategy: 'fixed' | 'absolute'; } /** * Manages native popover state + Floating UI positioning for anchored overlay * panels (Select, Combobox, Popover, and through it Menu). Handles show/hide, * the autoUpdate lifecycle, position computation, a keyboard-aware height cap, * and cleanup — one positioning codepath shared across every overlay so an * iOS/visualViewport or flip/shift fix lands everywhere at once. * * `popover` (top layer) keeps the panel above any `overflow` clipping from * parent containers. `popover="manual"` (set by the caller in markup) leaves * the caller's own dismiss handlers in control; this helper only drives * `showPopover()`/`hidePopover()` and never reads the dismiss mode. * * Top-layer promotion is automatic but conditional: the helper skips it (and * returns `topLayer: false`) when the anchor sits inside an open modal * ``, where a second top-layer element is invisible on iOS/WebKit * (Codeberg #23) — the panel then renders `position: fixed` in place. Callers * mirror the returned `topLayer`/`strategy` in their markup via per-property * `style:` directives and {@link floatingPanelHidden}. Stacking needs no * caller wiring: in the two in-place modes the helper itself stamps the * panel's `z-index` imperatively (see the `zIndex` derivation below), so an * in-place panel always paints above later positioned siblings. * * The Floating-UI `size` middleware feeds the room actually left between the * anchor and the (visual) viewport edge into `--blocks-overlay-available-height`. * Variants cap height via `max-h-[min(,var(--…,100dvh))]`, so the * static design cap stays in CSS and the panel only ever shrinks to fit — and * recovers once room is restored (e.g. the iOS keyboard closes). */ export declare function useFloatingPanel(opts: FloatingPanelOptions): FloatingPanelState; /** * Whether a panel driven by {@link useFloatingPanel} must be hidden via * `display: none` while closed. Top-layer panels carry the `popover` attribute * and lean on the UA `[popover]:not(:popover-open){display:none}` rule, so they * report `false`; the in-place modes (in-dialog `fixed`, or the explicit * `portal=false` inline mode) have no such rule and are hidden by the caller. * * Callers apply the positioning frame with `style:` DIRECTIVES, never a single * dynamic `style={…}` string — `style={…}` compiles to `setAttribute('style')`, * which replaces the whole attribute and would wipe the `left`/`top` Floating UI * writes imperatively (the iOS `inset: auto` clobber behind Codeberg #23). * Per-property `style:` directives and Floating UI's `style.left/top` writes * coexist without ever overwriting each other: * * ```svelte *
* ``` */ export declare function floatingPanelHidden(panel: FloatingPanelState, open: boolean): boolean;