import { type Accessor, createContext, useContext } from "solid-js"; import type { TextDirection } from "../direction-provider/direction-provider-context.ts"; import type { BaseUIChangeEventDetails, REASONS, } from "../internals/change-event-details"; import type { Orientation } from "../internals/types"; /** * Change-event reason namespace for ``. Matches Base UI * React's union. */ export type AccordionRootChangeEventReason = | typeof REASONS.triggerPress | typeof REASONS.none; export type AccordionRootChangeEventDetails = BaseUIChangeEventDetails; /** * Accordion supports a single scalar value (single-expand) or an array * (multi-expand). Internally we always store an array — a single-expand value * is represented as either `[]` or `[currentlyOpen]`. The public surface * follows React's convention of `Value[]`. */ export type AccordionValue = Value[]; /** * Public state surface for the root — flows through `data-*` projection. * Matches Base UI React's `AccordionRootState`. */ export interface AccordionRootState { /** Currently-open item values (always an array internally). */ value: AccordionValue; /** Whether the accordion ignores user interaction. */ disabled: boolean; /** Visual orientation — controls arrow key direction. */ orientation: Orientation; } /** * Context shape shared across ``, ``, * `` and ``. Accessor-heavy so descendants * stay reactive without re-deriving. * * `accordionItemRefs` is a plain array (owned by ``) because * the trigger's keyboard handler reads it synchronously inside event handlers. */ export interface AccordionRootContextValue { /** Plain array of registered item elements, in DOM order. */ accordionItemRefs: Array; /** Current text direction (threaded through for RTL arrow-key swap). */ direction: Accessor; /** Whether the root (and by extension every item) is disabled. */ disabled: Accessor; /** * Imperative value-change entry point. Called by an item on toggle; the * root applies single/multi semantics internally. */ handleValueChange: ( newValue: unknown, nextOpen: boolean, eventDetails: AccordionRootChangeEventDetails, ) => void; /** Whether panels use `hidden="until-found"`. */ hiddenUntilFound: Accessor; /** Whether panels stay mounted when closed. */ keepMounted: Accessor; /** Whether arrow navigation between triggers loops at the extents. */ loopFocus: Accessor; /** Current orientation. */ orientation: Accessor; /** Root's projected state (for `data-*`). */ state: Accessor>; /** Currently-open item values. */ value: Accessor>; } /** * Context for the accordion compound. `createContext(null)` + * `== null` sentinel — Solid 2's `useContext` throws * `ContextNotFoundError` when the default is `undefined`, which would shadow * the intended Base UI error message below. */ export const AccordionRootContext = createContext | null>(null); export function useAccordionRootContext< Value = unknown, >(): AccordionRootContextValue { const context = useContext(AccordionRootContext); if (context == null) { throw new Error( "Base UI: AccordionRootContext is missing. Accordion parts must be placed within .", ); } return context as AccordionRootContextValue; }