/** * PreviewCardStore — Solid 2 port of Base UI React's `PreviewCardStore` * (`packages/react/src/preview-card/store/PreviewCardStore.ts`). * * Same scope as `TooltipStore` / `PopoverStore` in the Solid port: the React * store owns the full preview-card state machine; the Solid port keeps the * legacy per-root signal-based state but exposes a thin imperative surface * here so `PreviewCardHandle` / `actionsRef` can plug in without rewriting * the root. */ import { createChangeEventDetails, REASONS, } from "../../internals/change-event-details"; import { PopupTriggerMap } from "../../internals/floating-ui/popup-trigger-map"; import type { PreviewCardRootChangeEventDetails, PreviewCardRootChangeEventReason, } from "../preview-card-root-context"; export type PreviewCardStoreSetOpen = ( next: boolean, details: PreviewCardRootChangeEventDetails, ) => void; export class PreviewCardStore<_Payload = unknown> { public readonly context: { triggerElements: PopupTriggerMap }; private _setOpen: PreviewCardStoreSetOpen | null = null; private _open = false; constructor() { this.context = { triggerElements: new PopupTriggerMap(), }; } /** @internal */ attachSetOpen(fn: PreviewCardStoreSetOpen | null): void { this._setOpen = fn; } /** @internal */ setOpenMirror(next: boolean): void { this._open = next; } setOpen(next: boolean, details: PreviewCardRootChangeEventDetails): void { this._setOpen?.(next, details); } get isOpen(): boolean { return this._open; } } /** * A handle to control a preview card imperatively and to associate detached * triggers with it. Mirrors React's `PreviewCardHandle`. */ export class PreviewCardHandle { /** @internal */ public readonly store: PreviewCardStore; constructor() { this.store = new PreviewCardStore(); } /** * Opens the preview card against the trigger with the given `triggerId`. * The trigger must be rendered with ``. */ open(triggerId: string): void { const triggerElement = this.store.context.triggerElements.getById( triggerId, ) as HTMLElement | undefined; if (!triggerElement) { throw new Error( `Base UI: PreviewCardHandle.open: No trigger found with id "${triggerId}".`, ); } this.store.setOpen( true, createChangeEventDetails( REASONS.imperativeAction as PreviewCardRootChangeEventReason, undefined, triggerElement, ) as PreviewCardRootChangeEventDetails, ); } /** Closes the preview card. */ close(): void { this.store.setOpen( false, createChangeEventDetails( REASONS.imperativeAction as PreviewCardRootChangeEventReason, undefined, undefined, ) as PreviewCardRootChangeEventDetails, ); } /** Whether the preview card is currently open. */ get isOpen(): boolean { return this.store.isOpen; } } export function createPreviewCardHandle< Payload = unknown, >(): PreviewCardHandle { return new PreviewCardHandle(); }