/** * Contexts used by the composite primitives. * * There are two distinct contexts: * * - `CompositeListContext` — exposes registration helpers + the shared * `elementsRef` / `labelsRef` plain arrays. `useCompositeListItem` reads * from this context; `CompositeList` provides it. * - `CompositeRootContext` — exposes `highlightedIndex()` + its setter so * child items can read/update the focused-item state. This mirrors Base * UI React's `CompositeRootContext`. * * Solid 2 context providers are "context-as-provider" (RFC 02), so a * `{...}` is used at * the call sites — there is no `.Provider`. */ import { type Accessor } from "solid-js"; /** * Per-item metadata carried alongside the `Element → metadata` map. `index` * is managed by `CompositeList` — consumers supply their own custom fields. */ export type CompositeMetadata = { index?: number | null | undefined; } & CustomMetadata; /** * A disposer returned by subscription helpers. */ export type Disposer = () => void; /** * The notification payload shared through `CompositeListContext.subscribe`. * Consumers receive the sorted map on every change. */ export type CompositeMapListener = (map: Map | null>) => void; export interface CompositeListContextValue { /** Register a node + its metadata with the list. `source` is a unique, * per-item token that lets the list detect stale entries when a consumer * re-registers with a different node. Token shape is deliberately * `symbol` so consumers can create one per `useCompositeListItem` call. */ register: (source: symbol, node: Element, metadata: Metadata) => void; /** Unregister by `source` token (node may already be detached). */ unregister: (source: symbol) => void; /** Subscribe to sorted-map changes. */ subscribeMapChange: (fn: CompositeMapListener) => Disposer; /** * Plain array of elements ordered by DOM position. This is a plain * JavaScript array — NOT a reactive signal — because the root's keyboard * handler reads it at call time and libraries like floating-ui expect a * mutable `.current`-shaped list. Subscribe to `subscribeMapChange` for * ordering updates. */ elementsRef: Array; /** Parallel labels array, when the caller opted in by passing `labelsRef` * on ``. */ labelsRef?: Array | undefined; } /** * Phantom brand carried by the erased context value. The brand exists only * in the type system — at runtime the field is absent — so there's no cost * beyond TypeScript's assignability check. It prevents arbitrary * `CompositeListContextValue` objects from being mistaken for the erased * shape: only values produced by `eraseCompositeListContext` (or the frozen * no-op default) carry the brand. */ declare const erasedMetadataBrand: unique symbol; /** * Erased storage shape for `CompositeListContext`. `Metadata` is fixed to * `unknown` so the shape is concrete and the context can hold a single * monomorphic type. Providers erase via `eraseCompositeListContext`; * consumers reify via `useCompositeListContext()`. Both ends * preserve the brand so the erasure can't be bypassed with a plain cast. */ export type ErasedCompositeListContextValue = CompositeListContextValue & { readonly [erasedMetadataBrand]: true; }; /** * Erase the `Metadata` type parameter so a concrete * `CompositeListContextValue` can be stored on the shared context. * The cast is confined here — the context's `register`/`subscribeMapChange` * handlers never actually observe values typed against the wrong `Metadata` * because the corresponding `useCompositeListContext()` reader on * the other side re-projects them to the same concrete type before the * caller sees them. */ export declare function eraseCompositeListContext(value: CompositeListContextValue): ErasedCompositeListContextValue; /** * The context stores the erased shape. `` passes its concrete * `CompositeListContextValue` through `eraseCompositeListContext`; * consumers pull the branded value back out through * `useCompositeListContext()` which reifies `Metadata` at the call * site. */ export declare const CompositeListContext: import("solid-js").Context; /** * Read the nearest `CompositeListContext`. Returns the no-op default when * there is no provider, so callers don't have to handle `undefined`. The * single cast here is the only place `Metadata` is re-reified from the * erased storage shape. */ export declare function useCompositeListContext(): CompositeListContextValue; export interface CompositeRootContextValue { /** Current highlighted index. */ highlightedIndex: Accessor; /** Setter matching React Base UI's signature exactly. */ onHighlightedIndexChange: (index: number, shouldScrollIntoView?: boolean) => void; /** If `true`, hovering an item moves focus to it. */ highlightItemOnHover: Accessor; /** * Forwards an external keyboard event into the composite's `onKeyDown` * handler. Useful when the triggering element is rendered outside the * composite tree (e.g. menubar with detached triggers). */ relayKeyboardEvent: (event: KeyboardEvent) => void; /** `true` only when provided by a real ``. */ readonly present: boolean; } export declare const CompositeRootContext: import("solid-js").Context; /** * Read the composite root context. Returns `undefined` in the `optional: true` * form when no real `` is an ancestor; otherwise throws. */ export declare function useCompositeRootContext(optional: true): CompositeRootContextValue | undefined; export declare function useCompositeRootContext(optional?: false): CompositeRootContextValue; export {}; //# sourceMappingURL=composite-context.d.ts.map