import { createContext, useContext } from "react"; import type { ReactNode } from "react"; /** Where the field label renders relative to the trigger. */ export type LabelPlacement = "above" | "inside"; /** * Sugar-owned field state, provided by `Select.Root` and read by the sugar parts * (`Select.Trigger`, `Select.Label`). `Select.Label` registers its content here * (rather than rendering in place); `Select.Root` / `Select.Trigger` render it in * the slot `labelPlacement` selects. See `Select.guide.md` for the model. */ export interface SelectFieldState { /** Chosen label placement — above the trigger or inside it. */ readonly labelPlacement: LabelPlacement; /** The label content to render — the registered `Select.Label` children. */ readonly labelContent?: ReactNode; /** Resolved accessible name applied to the trigger. */ readonly accessibilityLabel?: string; /** Resolved critical state (from `invalid` / `status` / `error`). */ readonly invalid?: boolean; /** Render the trigger as a static, non-pressable read-only display. */ readonly readOnly?: boolean; /** Register the label content (+ its accessible name, when it is a string). */ registerLabel(content: ReactNode, accessibleName?: string): void; /** Clear a previously registered label (on `Select.Label` unmount). */ unregisterLabel(): void; } const noop = (): void => undefined; export const SelectFieldContext = createContext({ labelPlacement: "inside", registerLabel: noop, unregisterLabel: noop, }); export function useSelectFieldState(): SelectFieldState { return useContext(SelectFieldContext); }