/** * createTabs - the HEADLESS core behind , in the same spirit as * `createSvGrid` for the grid: a runes-based state machine (roving arrow-key * focus, automatic/manual activation, full WAI-ARIA wiring) exposed as * **prop-getters** you spread onto YOUR OWN markup. No styles, no DOM * assumptions - render it however you like. * * ```svelte * *
* {#each tabs as tab} * * {/each} *
*
...
* ``` * * The styled is just one renderer over this core. DOM focus movement is * a render concern, so the component watches `focusTick`/`focusId` and calls * `.focus()` itself; the core only decides *which* tab should take focus. */ import type { EditorDir } from './editor-contract'; export type TabItem = { id: string; label: string; disabled?: boolean; closable?: boolean; }; export type TabsOrientation = 'horizontal' | 'vertical'; export type TabsActivation = 'automatic' | 'manual'; /** Reactive inputs are passed as getters so the core tracks live prop changes. */ export type TabsConfig = { tabs: () => ReadonlyArray; value: () => string | undefined; onChange?: (id: string) => void; /** Fired when a closable tab is closed (Delete key, or the renderer's x). */ onClose?: (id: string) => void; orientation?: () => TabsOrientation; activation?: () => TabsActivation; /** Text direction; under `'rtl'` horizontal Left/Right arrows flip. */ dir?: () => EditorDir | undefined; ariaLabel?: () => string | undefined; }; export declare function createTabs(config: TabsConfig): { /** Currently selected tab id (falls back to the first enabled tab). */ readonly activeId: string; /** Tab id that should hold DOM focus after the latest keyboard move. */ readonly focusId: string; /** Monotonic counter; changes only on keyboard navigation. */ readonly focusTick: number; isActive: (tid: string) => boolean; select: (tid: string) => void; close: (tid: string) => void; onKeydown: (e: KeyboardEvent) => void; /** Spread onto the tablist container element. */ tablistProps: () => { role: "tablist"; 'aria-orientation': TabsOrientation; 'aria-label': string | undefined; }; /** Spread onto the tab button for `tid`. */ tabProps: (tid: string) => { role: "tab"; id: string; 'data-tab': string; 'aria-selected': boolean; 'aria-controls': string; tabindex: number; disabled: boolean | undefined; onclick: () => void; onkeydown: (e: KeyboardEvent) => void; }; /** Spread onto the tabpanel element for `tid` (usually the active id). */ panelProps: (tid: string) => { role: "tabpanel"; id: string; 'aria-labelledby': string; tabindex: number; }; }; export type Tabs = ReturnType;