import type * as React from 'react'; import type { FormValidityHandle } from '../utils/formControl.cjs'; import type { PrimitivePropsWithRef } from '../utils/primitive.cjs'; import type { Orientation } from '../utils/useRovingFocus.cjs'; import type { SelectionChangeDetail, SelectionChangeReason } from '../utils/useSelection.cjs'; /** Whether a {@link ToggleGroup} allows one pressed item at a time, or several. */ export type ToggleGroupType = 'single' | 'multiple'; /** @internal Shared state distributed from {@link ToggleGroup} to its {@link ToggleGroupItem}s via context. */ export interface ToggleGroupContextValue { type: ToggleGroupType; value: string[]; disabled: boolean; /** Whether the group manages one tab stop; `false` makes every enabled item its own. */ rovingFocus: boolean; /** Displays a committed choice: items stay focusable and navigable, but pressing them changes nothing. */ readOnly: boolean; /** Whether arrow-key focus moving between siblings also presses the item it lands on. */ selectOnFocus: boolean; /** Layout axis the Indicator measures along, deciding which cross-axis custom properties it publishes. */ orientation: Orientation; /** The root element, which the Indicator measures the pressed item against. */ rootRef: React.RefObject; /** Commits one item: presses it, or unpresses it when the group's cardinality and `deselectable` allow. */ onItemToggle: (value: string, reason?: SelectionChangeReason) => void; /** The group's single tab stop, resolved against the DOM: a pressed item if one is enabled, else the first enabled item. */ firstEnabledValue: string | null; } /** One entry of {@link ToggleGroupProps.options} — a single toggle button. */ export interface ToggleGroupOption { /** Unique identifier matched against the group's pressed value(s). */ value: string; /** Text rendered inside the derived `ToggleGroupItem`. */ label: React.ReactNode; /** * Prevents this item from being pressed, and takes it out of the roving * order. * @default false */ disabled?: boolean | undefined; } /** Props for the {@link ToggleGroup} root; `type` picks single- or multiple-item selection. */ export interface ToggleGroupProps extends PrimitivePropsWithRef<'div'> { /** * The buttons the group renders, one derived `ToggleGroupItem` each. Ignored when * `children` is given, which switches to full manual composition. * @default undefined — nothing is derived; compose the items as `children`. */ options?: ToggleGroupOption[] | undefined; /** * Whether at most one item may be pressed at a time (`'single'`) or any number (`'multiple'`), deciding whether `value` takes a `string` or `string[]`. */ type: ToggleGroupType; /** * Pressed item's value(s), for controlled usage — a `string` or `string[]`, accepted regardless of cardinality; pair with `onValueChange`. * @default undefined — uncontrolled, tracks its own pressed items internally. */ value?: string | string[] | undefined; /** * Initially pressed item's value(s), for uncontrolled usage — the same bare * `string` or `string[]` shapes `value` accepts, under either cardinality. * @default undefined — starts with no item pressed. */ defaultValue?: string | string[] | undefined; /** * Fires whenever the pressed items change, carrying the whole selection as a `string[]` alongside `selectedValue`. * @default undefined — no-op if omitted. */ onValueChange?: ((detail: SelectionChangeDetail) => void) | undefined; /** * Disables every item in the group. * @default false */ disabled?: boolean | undefined; /** * Layout axis for arrow-key roving focus between items, exposed as * `data-orientation`. * @default 'horizontal' */ orientation?: Orientation | undefined; /** * Whether arrow-key navigation wraps from the last item back to the first * (and vice versa). * @default true */ loop?: boolean | undefined; /** * Whether a `'single'` group may clear all selections by re-pressing the current item; ignored when `type` is `'multiple'`. * @default true */ deselectable?: boolean | undefined; /** * Whether the group manages one tab stop with arrow-key navigation (`true`) * or every item is its own tab stop with no arrow handling (`false`). * @default true */ rovingFocus?: boolean | undefined; /** * Form field name; pressed values submit as repeated `name=value` pairs through hidden mirrored inputs. * @default undefined — the group renders no inputs and submits nothing. */ name?: string | undefined; /** * Marks the group required: `valueMissing` until an item is pressed, reported through `checkValidity()`/`reportValidity()`. * @default false */ required?: boolean | undefined; /** * Id of the `
` this group submits into, forwarded to every mirrored hidden input. * @default undefined — the group submits into its nearest ancestor form. */ form?: string | undefined; /** * Displays a committed choice the user may not change: items keep their tab stop and arrow navigation, the root carries `data-readonly`, and the value still submits. * @default false */ readOnly?: boolean | undefined; /** * Marks the group invalid via `data-invalid`; presentational only — use `required` or `setCustomValidity()` to block a submit. * @default false */ invalid?: boolean | undefined; /** * Whether roving focus landing on an item also presses it, so arrow keys browse the choices; only meaningful with `type="single"`, and never fired by focus arriving from outside the group. * @default false */ selectOnFocus?: boolean | undefined; /** * Shape rung the skin reads, mirrored to `data-variant` on the root; `'segmented'` paints the group as one joined strip with a sliding `ToggleGroupIndicator`. * @default undefined — the skin's own default shape. */ variant?: 'segmented' | (string & {}) | undefined; /** * Stretches the group to its container width, mirrored to `data-full-width` on the root. * @default undefined — the group is only as wide as its items. */ fullWidth?: boolean | undefined; /** * Visual size rung the skin scales the items by, mirrored to `data-size` on the root. * @default undefined — the skin's own default size. */ size?: 'sm' | 'lg' | (string & {}) | undefined; } /** * The forwarded ref's handle: the root `
` with constraint-validation * methods for checking and reporting the pressed item(s). */ export type ToggleGroupHandle = HTMLDivElement & FormValidityHandle; /** Props for a single {@link ToggleGroupItem}. */ export interface ToggleGroupItemProps extends PrimitivePropsWithRef<'button'> { /** Unique identifier compared against the group's pressed value(s). */ value: string; /** * Disables this item and excludes it from the roving focus order; under a read-only group it keeps its tab stop and carries `aria-disabled` instead. * @default false */ disabled?: boolean | undefined; } /** The pressed item's box relative to the group root, which {@link ToggleGroupIndicator} publishes as custom properties. */ export interface ToggleGroupRect { /** Offset in CSS pixels from the root's left edge. */ x: number; /** Offset in CSS pixels from the root's top edge. */ y: number; /** Measured width of the pressed item, in CSS pixels. */ width: number; /** Measured height of the pressed item, in CSS pixels. */ height: number; } /** Props for the {@link ToggleGroupIndicator}, the highlight that slides behind the pressed item. */ export interface ToggleGroupIndicatorProps extends PrimitivePropsWithRef<'div'> { }