import { type Accessor, createContext, useContext } from "solid-js"; import type { TabsRootChangeEventDetails, TabsTabValue, } from "./tabs-root-context.ts"; /** * Context published by ``. Child tabs consume this for composite- * focus coordination + the `activateOnFocus` hook on focus transitions. */ export interface TabsListContextValue { /** Whether focusing a tab should activate it. */ activateOnFocus: Accessor; /** Index of the highlighted (roving-focus) tab. `-1` if none. */ highlightedTabIndex: Accessor; /** Tab elements register here so the indicator can observe size changes. */ registerTabResizeObserverElement: (element: HTMLElement) => () => void; /** * Child tabs call this when they're activated by click or focus — dispatches * through the root's `onValueChange` channel. */ onTabActivation: ( newValue: TabsTabValue, eventDetails: TabsRootChangeEventDetails, ) => void; /** Setter for the highlighted tab index (used by child tabs on focus). */ setHighlightedTabIndex: (index: number) => void; /** The `` element itself (for indicator measurements). */ tabsListElement: Accessor; /** Marker — `true` when a real `` provided this context. */ readonly present: boolean; } const NOOP = (): void => {}; export const NOOP_TABS_LIST_CONTEXT: TabsListContextValue = { activateOnFocus: () => false, highlightedTabIndex: () => -1, registerTabResizeObserverElement: () => () => {}, onTabActivation: NOOP, setHighlightedTabIndex: NOOP, tabsListElement: () => null, present: false, }; export const TabsListContext = createContext( NOOP_TABS_LIST_CONTEXT, ); /** * Read the `` context. Throws when no list ancestor is present — * every tab / indicator requires a list. */ export function useTabsListContext(): TabsListContextValue { const context = useContext(TabsListContext); if (!context.present) { throw new Error( "Base UI: TabsListContext is missing. Tabs parts must be placed within .", ); } return context; }