import type { BasicToggleGroupListProps, CommonProps, Icon, Size } from "@trackunit/react-components"; import type { ComponentProps, ReactNode } from "react"; /** Extract IconName from Icon component props */ export type IconName = ComponentProps["name"]; /** Where the control appears in the UI hierarchy */ export type Placement = "standalone" | "menu"; /** Raw environment signal -- how much space the container has */ export type AvailableSpace = "constrained" | "comfortable"; /** Computed sizing decision -- set by the sizing middleware from placement + availableSpace */ export type Compactness = "compact" | "spacious"; /** The full rendering context that drives all layout decisions */ export type RenderContext = Readonly<{ placement: Placement; availableSpace: AvailableSpace; }>; /** Shared resolved fields set by cross-cutting middleware (before type-specific resolution) */ export type ResolvedControlPropsBase = Readonly<{ /** Physical size of the control -- aligns with component library Size type */ size: Size; /** Whether the control should be rendered at all */ visible: boolean; /** Spacing between sub-elements (e.g. stepper buttons) */ gap: string; /** Sizing decision: "compact" when in a menu or constrained container, "spacious" otherwise */ compactness: Compactness; /** Resolved icon (state-dependent for toggles, static for buttons) */ icon?: IconName; }>; /** All control type discriminants (derived from config unions + separator) */ type ControlType = ControlConfig["type"] | SeparatorItemConfig["type"]; /** * Discriminated union of resolved control props. * * Discriminant: `controlType` -- mirrors the config's `type` field. * Flat mapped type: every control type resolves to `ResolvedControlPropsBase` * plus a `controlType` discriminant. */ export type ResolvedControlProps = { [K in ControlType]: ResolvedControlPropsBase & Readonly<{ controlType: K; }>; }[ControlType]; /** * What happens to a control when responsive collapsing moves it into a menu. * * - `"menu"` (default) -- the control is placed inside the overflow menu * - `"hide"` -- the control is fully removed instead of being menued * * Use `"hide"` for controls that only make sense as standalone map overlays * and would be confusing or useless inside a menu (e.g. a visual indicator * that has no interactive menu representation). */ export type OverflowBehavior = "menu" | "hide"; /** Base fields shared by all controls */ type BaseControlConfig = Readonly