import type { Placement } from "@floating-ui/react"; import type { ReactNode } from "react"; /** * Internal descriptor describing a map panel registered by a layer. * * Layers register panels via {@link usePanel}; the orchestrator renders * each descriptor as an {@link Panel} positioned next to its anchor. * * `children` is the panel content. `onDismiss` is the latest closure the * orchestrator should invoke when the panel is dismissed (Escape key or * outside-press) — the hook ships a stable wrapper that reads from a ref so * handler-identity changes do not cause extra store ticks. * * @internal */ export type PanelDescriptor = Readonly<{ id: string; /** * Anchor element. The orchestrator passes this to Floating UI as the * reference element. Null until the consumer mounts. */ anchor: HTMLElement | null; /** Lower number = higher priority. */ priority?: number; /** Placement preference. Default: "bottom". */ placement?: Placement; onDismiss?: () => void; /** Accessible label for the close button. Passed through to Panel. */ closeLabel?: string; /** Accessible label for the panel dialog, announced by screen readers on open. */ "aria-label"?: string; /** * Where vertical overflow scrolls. Default `shell` keeps `overflow-auto` on the * Panel scroll slot; `internal` uses `overflow-hidden` so consumers own scroll. */ contentScroll?: "shell" | "internal"; /** * Called by the orchestrator (via Panel.onCommit) on first visible * placement per open-cycle. Wired by `usePanel` when `resolveAutoPan` * is provided. Fourth arg is the natural content height of the inner scroll div. */ onCommit?: (panelRect: DOMRect, anchorRect: DOMRect, placement: Placement, panelScrollHeight: number) => void; children: ReactNode; }>; /** * Subscription-based store for map panels. * * Compatible with `useSyncExternalStore(subscribe, getSnapshot)`. * * Unlike the annotation store, panels use `upsert` semantics: the consumer * hook calls `upsert` on every render where the panel is open. `upsert` * replaces the descriptor in place without changing insertion order, so * children and other content fields can change without unmounting the * orchestrator's slot for that id. * * @internal */ export type PanelStore = Readonly<{ upsert: (descriptor: PanelDescriptor) => void; remove: (id: string) => void; subscribe: (callback: () => void) => () => void; getSnapshot: () => ReadonlyArray; }>; /** * Creates a {@link PanelStore} instance. * * Uses a `Map` for registration so that * insertion order is preserved across `upsert` calls (Map iteration order * is insertion order, and `set` on an existing key does not move it). * * `getSnapshot` returns a stable `ReadonlyArray` reference that only * changes when descriptors are actually mutated. * * @internal */ export declare const createPanelStore: () => PanelStore;