gridsmith-ui 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Breadcrumbs-CGS8GKl-.d.ts +33 -0
- package/dist/chat.js +1 -1
- package/dist/{chunk-CKWITUSH.js → chunk-2PWGJ4PK.js} +10 -5
- package/dist/chunk-2PWGJ4PK.js.map +1 -0
- package/dist/chunk-2YSEME33.js +118 -0
- package/dist/chunk-2YSEME33.js.map +1 -0
- package/dist/{chunk-ICNWPNMM.js → chunk-6XAU44U4.js} +4 -3
- package/dist/chunk-6XAU44U4.js.map +1 -0
- package/dist/{chunk-RT7RYGC3.js → chunk-JXANCXK6.js} +4 -39
- package/dist/chunk-JXANCXK6.js.map +1 -0
- package/dist/{chunk-6PL7FXYH.js → chunk-MV7JXWXK.js} +318 -9
- package/dist/chunk-MV7JXWXK.js.map +1 -0
- package/dist/{chunk-EYMGLK4M.js → chunk-SVP2IG4S.js} +2 -2
- package/dist/{chunk-EYMGLK4M.js.map → chunk-SVP2IG4S.js.map} +1 -1
- package/dist/chunk-WOVYHFUD.js +50 -0
- package/dist/chunk-WOVYHFUD.js.map +1 -0
- package/dist/chunk-XVB55M3N.js +42 -0
- package/dist/chunk-XVB55M3N.js.map +1 -0
- package/dist/data-grid.js +4 -3
- package/dist/data-grid.js.map +1 -1
- package/dist/editor.js +2 -1
- package/dist/editor.js.map +1 -1
- package/dist/index.d.ts +199 -38
- package/dist/index.js +598 -369
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +22 -5
- package/dist/kanban.js.map +1 -1
- package/dist/resizable.d.ts +16 -1
- package/dist/resizable.js +87 -20
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +5 -0
- package/dist/virtualized.js +4 -3
- package/dist/virtualized.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6PL7FXYH.js.map +0 -1
- package/dist/chunk-CKWITUSH.js.map +0 -1
- package/dist/chunk-ICNWPNMM.js.map +0 -1
- package/dist/chunk-RT7RYGC3.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../showcase/src/lib/control-looks.ts","../../../showcase/src/lib/filter-row.ts","../../../showcase/src/components/Input.tsx","../../../showcase/src/components/InlineFieldError.tsx","../../../showcase/src/components/Field.tsx","../../../showcase/src/components/Dropdown.tsx","../../../showcase/src/components/NumberInput.tsx","../../../showcase/src/components/Popover.tsx","../../../showcase/src/lib/dev-warn.ts","../../../showcase/src/components/Pagination.tsx","../../../showcase/src/lib/use-pagination.ts"],"names":["jsxs","jsx","createContext","useContext","useCallback","useEffect","useRef","useId","useState","createPortal"],"mappings":"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","file":"chunk-ICNWPNMM.js","sourcesContent":["/**\n * Sprint 25.14 A20: the checked and switched looks, shared by the controls (Checkbox, RadioGroup, Toggle) and the Card's\n * selection indicators, so the two never drift apart (the review of 30 September: the Card kept the old switch, the\n * accent's gradient and the accent dot after the controls moved).\n */\n\n/** A checked box's fill and a selected radio's dot: the check colour, with the theme's check gradient (by default the accent's) over it. */\nexport const CHECK_FILL = \"bg-[var(--ds-check-bg)] [background-image:var(--ds-check-gradient,var(--ds-gradient))]\";\n\n/** A switch's track when on: the check colour, as a checked box's. */\nexport const SWITCH_TRACK_ON = \"bg-[var(--ds-check-bg)] border-transparent\";\n\n/**\n * A switch's track when off: from tokens only a regenerated stylesheet has (the theme writers emit them), falling back\n * to the switch as it was, so an app that hasn't regenerated never gets an outline in its old, fainter edge colour.\n */\nexport const SWITCH_TRACK_OFF = \"bg-[var(--ds-switch-off-fill,var(--ds-bg-muted))] border-[var(--ds-switch-off-edge,var(--ds-border-default))]\";\n\n/**\n * A switch's knob when on: the surface made opaque (a glass theme's half-white surface would show the track through it),\n * as pinned table cells are (D31); a surface that is wholly transparent stays so.\n */\nexport const SWITCH_KNOB_ON = \"bg-[var(--ds-bg-surface)] supports-[color:oklch(from_red_l_c_h)]:bg-[oklch(from_var(--ds-bg-surface)_l_c_h_/_max(alpha,min(1,alpha*1000)))]\";\n\n/** A switch's knob when off: the edge colour, beside the outline (the same fallback as the track). */\nexport const SWITCH_KNOB_OFF = \"bg-[var(--ds-switch-off-knob,var(--ds-bg-surface))]\";\n\n/** The knob moves and changes colour together with its track, so it never shows before the track does. */\nexport const SWITCH_KNOB_MOTION = \"transition-[transform,background-color] duration-[var(--ds-transition-speed)]\";\n","import { createContext } from \"react\";\n\n/**\n * A row of filters (PageHeader's filters slot) tells the controls in it that they are in one, so a text field takes a\n * search field's width, the table toolbar's (280 px), instead of a line of its own (the owner's\n * look at a bold header with content overlap, 30 September 2026: the search box filled a whole line).\n */\nexport const FilterRowContext = createContext(false);\n\n/**\n * A text field's width in a filter row: the toolbar search's 280 px, never wider than the row. A set width, not a flex\n * basis: a row that hugs its controls (the strip on a bold band) sizes itself from their widths, and a basis it doesn't\n * count pushed the field onto a line of its own.\n */\nexport const FILTER_FIELD_WIDTH = \"w-[280px] max-w-full\";\n","import { useCallback, useContext, useEffect, useRef, type Ref } from \"react\";\nimport { cn, FOCUS_RING, HAS_FOCUS_RING, ERROR_FOCUS_RING, ERROR_HAS_FOCUS_RING } from \"../lib/utils\";\nimport type { ReactNode, InputHTMLAttributes, TextareaHTMLAttributes, LabelHTMLAttributes } from \"react\";\nimport { ControlSizeContext } from \"./Button\";\nimport { useReportedChange } from \"../lib/form-context\";\nimport { SWITCH_KNOB_MOTION, SWITCH_KNOB_OFF, SWITCH_KNOB_ON, SWITCH_TRACK_OFF, SWITCH_TRACK_ON } from \"../lib/control-looks\";\nimport { FILTER_FIELD_WIDTH, FilterRowContext } from \"../lib/filter-row\";\n\n/** A native field's new value from its change event: `checked` for a box, `value` for the rest (Sprint 25.12 A15). */\n/** An uncontrolled field's value, which no edit equals: the field holds its value itself. */\nconst UNCONTROLLED = Symbol(\"uncontrolled\");\nconst valueOf = (e: { target: EventTarget | null }) => {\n const t = e.target as HTMLInputElement | HTMLTextAreaElement | null;\n if (!t) return undefined;\n return t instanceof HTMLInputElement && (t.type === \"checkbox\" || t.type === \"radio\") ? t.checked : t.value;\n};\n\ntype InputSize = \"sm\" | \"md\" | \"lg\";\n\n// \"prefix\" must be omitted from the inherited attributes: React's HTMLAttributes\n// declares the RDFa attribute `prefix?: string`, and intersecting it with\n// `prefix?: ReactNode` collapses the prop to string-only at use sites.\nconst INPUT_HEIGHT: Record<InputSize, string> = {\n sm: \"h-[var(--ds-control-height-sm)]\",\n md: \"h-[var(--ds-control-height-md)]\",\n lg: \"h-[var(--ds-control-height-lg)]\",\n};\n\nconst INPUT_TEXT: Record<InputSize, string> = {\n sm: \"px-ds-2 py-ds-1 text-xs\",\n md: \"px-ds-3 py-ds-2 text-sm\",\n lg: \"px-ds-4 py-ds-3 text-base\",\n};\n\nexport function Input({ className, size: sizeProp, error = false, prefix, suffix, ...props }: Omit<InputHTMLAttributes<HTMLInputElement>, \"size\" | \"prefix\"> & { size?: InputSize; error?: boolean; prefix?: ReactNode; suffix?: ReactNode }) {\n const contextSize = useContext(ControlSizeContext);\n const size = sizeProp ?? contextSize ?? \"md\";\n // in a row of filters, a search field's width rather than a line of its own (the owner, 30 September)\n const width = useContext(FilterRowContext) ? FILTER_FIELD_WIDTH : \"w-full\";\n // Sprint 25.12 A15: the user's typing marks the form's overlay (only a new value); the page's onChange runs as given.\n // Uncontrolled (defaultValue), every edit is new: clearing a prefilled field compared \"\" with no value (0.21.0).\n const onChange = useReportedChange(props.onChange, props.value === undefined ? UNCONTROLLED : props.value, valueOf);\n const borderColor = error ? \"border-[var(--ds-status-error)]\" : \"border-[var(--ds-input-border)]\";\n const hoverBorder = !error && !props.disabled && !props.readOnly ? \"hover:border-[var(--ds-input-border-hover)]\" : \"\";\n\n if (prefix || suffix) {\n return (\n <div\n className={cn(\n \"flex items-center\", width,\n INPUT_HEIGHT[size],\n \"bg-[var(--ds-input-bg)]\",\n \"border-[length:var(--ds-border-width)]\", borderColor,\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-input-shadow)]\",\n hoverBorder,\n error ? ERROR_HAS_FOCUS_RING : HAS_FOCUS_RING,\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n props.disabled && \"cursor-not-allowed opacity-disabled\",\n props.readOnly && \"bg-[var(--ds-bg-muted)] cursor-default\",\n className\n )}\n >\n {prefix && <span className=\"shrink-0 pl-ds-3 text-[var(--ds-text-muted)] flex items-center\">{prefix}</span>}\n <input\n aria-invalid={error || undefined}\n className={cn(\n \"flex-1 min-w-0 bg-transparent outline-none\",\n INPUT_TEXT[size],\n \"text-[var(--ds-text-primary)]\",\n \"placeholder:text-[var(--ds-text-muted)]\",\n \"disabled:cursor-not-allowed\",\n \"read-only:text-[var(--ds-text-secondary)] read-only:cursor-default\",\n )}\n {...props}\n onChange={props.onChange || props.value === undefined ? onChange : undefined}\n />\n {suffix && <span className=\"shrink-0 pr-ds-3 text-[var(--ds-text-muted)] flex items-center\">{suffix}</span>}\n </div>\n );\n }\n\n return (\n <input\n aria-invalid={error || undefined}\n className={cn(\n \"flex\", width,\n INPUT_TEXT[size], INPUT_HEIGHT[size],\n \"bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)]\",\n \"border-[length:var(--ds-border-width)]\", borderColor,\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-input-shadow)]\",\n \"placeholder:text-[var(--ds-text-muted)]\",\n hoverBorder,\n error ? ERROR_FOCUS_RING : FOCUS_RING,\n \"disabled:cursor-not-allowed disabled:opacity-disabled\",\n \"read-only:bg-[var(--ds-bg-muted)] read-only:text-[var(--ds-text-secondary)] read-only:cursor-default\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n className\n )}\n {...props}\n onChange={props.onChange || props.value === undefined ? onChange : undefined}\n />\n );\n}\n\ninterface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n autoResize?: boolean;\n maxRows?: number;\n error?: boolean;\n ref?: Ref<HTMLTextAreaElement>;\n}\n\nexport function Textarea({ className, autoResize, maxRows, error = false, ref, ...props }: TextareaProps) {\n // Sprint 25.12 A15: as Input\n const onChange = useReportedChange(props.onChange, props.value === undefined ? UNCONTROLLED : props.value, valueOf);\n const internalRef = useRef<HTMLTextAreaElement>(null);\n const textareaRef = (ref ?? internalRef) as React.RefObject<HTMLTextAreaElement>;\n\n const resize = useCallback(() => {\n const el = textareaRef.current;\n if (!el || !autoResize) return;\n el.style.height = \"auto\";\n let target = el.scrollHeight;\n if (maxRows) {\n const lineHeight = parseFloat(getComputedStyle(el).lineHeight) || 20;\n const maxHeight = lineHeight * maxRows + parseFloat(getComputedStyle(el).paddingTop) + parseFloat(getComputedStyle(el).paddingBottom);\n target = Math.min(target, maxHeight);\n }\n el.style.height = `${target}px`;\n }, [autoResize, maxRows, textareaRef]);\n\n useEffect(() => { resize(); }, [resize, props.value, props.defaultValue]);\n\n return (\n <textarea\n ref={textareaRef}\n aria-invalid={error || undefined}\n className={cn(\n \"flex min-h-[var(--ds-control-height-md)] w-full px-ds-3 py-ds-2 text-sm\",\n \"bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)]\",\n \"border-[length:var(--ds-border-width)]\",\n error ? \"border-[var(--ds-status-error)]\" : \"border-[var(--ds-input-border)] hover:border-[var(--ds-input-border-hover)]\",\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-input-shadow)]\",\n \"placeholder:text-[var(--ds-text-muted)]\",\n error ? ERROR_FOCUS_RING : FOCUS_RING,\n \"disabled:cursor-not-allowed disabled:opacity-disabled disabled:hover:border-[var(--ds-input-border)]\",\n \"read-only:bg-[var(--ds-bg-muted)] read-only:text-[var(--ds-text-secondary)] read-only:cursor-default read-only:hover:border-[var(--ds-input-border)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n autoResize && \"resize-none overflow-hidden\",\n className\n )}\n onInput={autoResize ? resize : undefined}\n {...props}\n onChange={props.onChange || props.value === undefined ? onChange : undefined}\n />\n );\n}\n\nexport function Label({ className, children, ...props }: LabelHTMLAttributes<HTMLLabelElement>) {\n return (\n <label\n className={cn(\n \"text-sm font-medium leading-none text-[var(--ds-text-secondary)]\",\n \"peer-disabled:cursor-not-allowed peer-disabled:opacity-disabled\",\n className\n )}\n {...props}\n >\n {children}\n </label>\n );\n}\n\nexport type ToggleLayout = \"full\" | \"compact\";\nexport type ToggleSize = \"sm\" | \"md\";\n\n// Track width/height and thumb diameter; the thumb sits 1px inside the border.\nconst TOGGLE_SIZES: Record<ToggleSize, { w: number; h: number; thumb: number }> = {\n sm: { w: 32, h: 18, thumb: 12 },\n md: { w: 44, h: 24, thumb: 16 },\n};\n\nexport function Toggle({ checked, onChange, label, disabled, error = false, layout = \"full\", size = \"md\", \"aria-labelledby\": ariaLabelledBy, ...rest }: { checked: boolean; onChange: (v: boolean) => void; label?: string; disabled?: boolean; error?: boolean; layout?: ToggleLayout; size?: ToggleSize; \"aria-labelledby\"?: string } & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onChange\">) {\n // Sprint 25.12 A15: a flip is a change, reported to the form's overlay\n const change = useReportedChange(onChange, checked);\n const dims = TOGGLE_SIZES[size];\n const travel = dims.w - dims.thumb - 3;\n const switchButton = (\n <button type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={!label && !ariaLabelledBy ? \"Toggle\" : undefined}\n aria-labelledby={ariaLabelledBy}\n aria-invalid={error || undefined}\n disabled={disabled}\n onClick={() => !disabled && change(!checked)}\n {...rest}\n className={cn(\n \"relative inline-flex shrink-0 items-center overflow-hidden\",\n \"border-[length:var(--ds-border-width)]\",\n \"rounded-[var(--ds-radius-full)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]\",\n disabled ? \"cursor-not-allowed\" : \"cursor-pointer\",\n // Sprint 25.14 A20: on, the checked colour, as a checkbox's; off, the outline in the edge colour (lib/control-looks.ts)\n checked ? SWITCH_TRACK_ON : SWITCH_TRACK_OFF,\n error && \"border-[var(--ds-status-error)]\"\n )}\n style={{ width: dims.w, height: dims.h }}\n >\n <span\n className={cn(\n \"pointer-events-none inline-block shrink-0\",\n // on: the surface made opaque; off: the edge colour, beside the outline\n checked ? SWITCH_KNOB_ON : SWITCH_KNOB_OFF,\n \"border-[length:var(--ds-border-width)] border-transparent\",\n \"rounded-[var(--ds-radius-full)]\",\n SWITCH_KNOB_MOTION\n )}\n style={{\n width: dims.thumb,\n height: dims.thumb,\n transform: checked\n ? `translateX(calc(${travel}px - var(--ds-border-width)))`\n : \"translateX(calc(1px + var(--ds-border-width)))\",\n }}\n />\n </button>\n );\n\n if (!label) {\n return <div className={cn(disabled && \"opacity-disabled\")}>{switchButton}</div>;\n }\n\n return (\n <label\n className={cn(\n layout === \"full\"\n ? \"flex items-center justify-between gap-ds-4\"\n : \"inline-flex items-center gap-ds-3\",\n disabled ? \"cursor-not-allowed opacity-disabled\" : \"cursor-pointer\",\n )}\n >\n <span className=\"text-sm font-medium text-[var(--ds-text-primary)]\">{label}</span>\n {switchButton}\n </label>\n );\n}\n","import { cn } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\n\ninterface InlineFieldErrorProps {\n message: string;\n id: string;\n className?: string;\n}\n\nexport function InlineFieldError({ message, id, className }: InlineFieldErrorProps) {\n return (\n <p\n id={id}\n role=\"alert\"\n className={cn(\n \"flex items-center gap-ds-1.5 text-xs text-[var(--ds-status-error)]\",\n \"mt-ds-1.5\",\n className\n )}\n >\n <Icon name=\"error\" size={14} className=\"shrink-0\" />\n <span>{message}</span>\n </p>\n );\n}\n","import { Children, cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, type ReactElement, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { useOptionalFormContext } from \"../lib/form-context\";\nimport { Label } from \"./Input\";\nimport { InlineFieldError } from \"./InlineFieldError\";\n\nexport interface FieldControlProps {\n id: string;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: true;\n \"aria-required\"?: true;\n required?: boolean;\n /** Set on Gridsmith form components (Input, Textarea, Dropdown, DatePicker, …). */\n error?: boolean;\n}\n\n/**\n * What a control inside a Field knows about it (Sprint 25.7, C5): the label's id, for a control that `<label for>`\n * cannot name (a slider is a div with role=\"slider\") to take it with aria-labelledby, and the hint and error ids.\n */\nexport interface FieldContextValue {\n controlId: string;\n labelId: string;\n describedBy?: string;\n /** The Field shows an error. */\n invalid?: boolean;\n required?: boolean;\n}\n\nconst FieldContext = createContext<FieldContextValue | null>(null);\n\n/** The Field a control sits in, or null. */\nexport function useField(): FieldContextValue | null {\n return useContext(FieldContext);\n}\n\n/** The wiring a control may be given as props: by a Field's clone, or by a page that labels it itself. */\nexport interface FieldControlWiring {\n id?: string;\n \"aria-labelledby\"?: string;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: boolean | \"true\" | \"false\";\n \"aria-required\"?: boolean | \"true\" | \"false\";\n required?: boolean;\n error?: boolean;\n}\n\n/**\n * What a Gridsmith control that is not a native input takes from the Field it sits in, merged with its own props, which\n * win (round 27 review: Dropdown, DatePicker and SegmentedControl dropped the Field's id and description, so the error\n * summary read \"A field: Needs attention\" with no link, and a screen reader heard the placeholder as the name):\n * - `id`, for the Field's `<label for>`, the summary's link and the focus after a submit;\n * - `labelId`, the label that names it by aria-labelledby, which reaches a button, a group or a radiogroup alike;\n * - `describedBy`, the hint and the error, each id once;\n * - `invalid` and `required`. A role that cannot carry aria-required (a button, a group) says it in its description\n * instead: `requiredNote` is the hidden text, already in `describedBy`, for the control to render.\n * Outside a Field a control gets its own props back.\n */\nexport function useFieldControl(own: FieldControlWiring, options: { requiredInDescription?: boolean } = {}): {\n id?: string;\n labelId?: string;\n describedBy?: string;\n invalid: boolean;\n required: boolean;\n requiredNote: ReactNode;\n} {\n const field = useField();\n const id = own.id ?? field?.controlId;\n const invalid = !!own.error || own[\"aria-invalid\"] === true || own[\"aria-invalid\"] === \"true\" || !!field?.invalid;\n const required = !!own.required || own[\"aria-required\"] === true || own[\"aria-required\"] === \"true\" || !!field?.required;\n const noteId = options.requiredInDescription && required && id ? `${id}-required` : undefined;\n const ids = [own[\"aria-describedby\"], field?.describedBy, noteId].filter(Boolean).join(\" \").split(/\\s+/).filter(Boolean);\n return {\n id,\n labelId: own[\"aria-labelledby\"] ?? field?.labelId,\n describedBy: [...new Set(ids)].join(\" \") || undefined,\n invalid,\n required,\n requiredNote: noteId ? <span id={noteId} hidden>Required</span> : null,\n };\n}\n\n/**\n * A field's label: any text or element, never nothing. Sprint 25.12 A31 (R28-59): run 75 labelled only the first of its\n * repeated rows (`label={index === 0 ? … : undefined}`), and every other row's fields had no name. A label that\n * shouldn't show takes `hideLabel`; repeated rows use AddAnother, which shows each label once.\n */\nexport type FieldLabel = Exclude<ReactNode, null | undefined | boolean>;\n\n/** Set by AddAnother around each row: a hidden label shows again when the group is too narrow for its headings. */\nexport const AddAnotherRowCtx = createContext(false);\n\nexport interface FieldProps {\n label: FieldLabel;\n /**\n * The label is read out but not shown (Sprint 25.12 A31): for a field whose purpose the page shows another way, such\n * as a column heading above repeated rows. In an AddAnother group it shows again when the group stacks its rows.\n */\n hideLabel?: boolean;\n /** The single form control. Receives id, aria-describedby, aria-invalid/error and required automatically. */\n children: ReactElement | ((props: FieldControlProps) => ReactNode);\n /** Persistent help text (format requirements, why a field is disabled). Shown below the control, above any error. */\n hint?: ReactNode;\n /** Current validation error. Rendered as InlineFieldError (role=\"alert\") and linked via aria-describedby. Wins over `validate`. */\n error?: string | null | false;\n /**\n * The field's check: the message for what is wrong with its value, or nothing (`validate={(v) => v ? undefined :\n * \"Enter a title\"}`). It gets the control's `value` (or `checked`); a closure over your own state works as well.\n * Inside a FormWrapper it runs at the project's validation timing (forms.validationTiming, through the form):\n * - `onBlur`: when the field is left;\n * - `onChange`: as the value changes, once the field has been left;\n * - `onSubmit`: on submit only.\n *\n * Whatever the timing, it runs on every submit, and FormWrapper's `onSubmit` gets its message under this Field's\n * `id`, or no key at all when the value passes, so an empty `errors` means the form is valid. A message that shows is\n * checked again as the value changes, so it goes as soon as the value is right. Focus\n * moving into the control's own popup (a Dropdown's list, a DatePicker's calendar) is not leaving the field. Outside\n * a FormWrapper it runs when the field is left (round 26, R26-2).\n */\n validate?: (value: unknown) => string | undefined | null | false;\n required?: boolean;\n /** Slot to the right of the label, e.g. a \"Forgot password?\" Link. */\n labelAction?: ReactNode;\n /** Explicit id for the control; generated when omitted. */\n id?: string;\n className?: string;\n}\n\n/**\n * Label + control + hint + error, wired together. Guarantees the label is\n * associated (htmlFor/id), that hint and error are announced\n * (aria-describedby), that the control is marked invalid, and that the error\n * sits directly below the field (forms-002/006/009/010). Use one Field per\n * control; do not add a separate <Label> or a label prop on the child.\n *\n * In a SettingsLayout panel a Field keeps the narrow page's reading width however wide the page is (the panel's\n * --ds-form-max, Sprint 25.9); a `max-w-*` class of your own wins.\n */\nexport function Field({ label, children, hint, error, required, labelAction, hideLabel = false, id: idProp, validate, className }: FieldProps) {\n const inGroupRow = useContext(AddAnotherRowCtx);\n const generated = useId();\n const id = idProp ?? `field-${generated}`;\n const hintId = `${id}-hint`;\n const errorId = `${id}-error`;\n\n // ── The field's own check (round 26, R26-2) ──\n const form = useOptionalFormContext();\n // outside a form, the only moment a field can check itself is when it is left\n const mode = form?.validationMode ?? \"onBlur\";\n const [localError, setLocalError] = useState<string | undefined>(undefined);\n const [left, setLeft] = useState(false);\n const checkError = validate ? (form ? form.errors[id] : localError) : undefined;\n const child = typeof children === \"function\" ? null : Children.only(children);\n const childProps = child && isValidElement(child) ? (child.props as Record<string, unknown>) : null;\n const latest = useLatest({ validate, childProps, id, mode, left, showing: !!checkError, form });\n const check = useCallback((): string | undefined => {\n const { validate: fn, childProps: props, id: controlId } = latest.current;\n if (!fn) return undefined;\n const value = props && \"value\" in props ? props.value : props && \"checked\" in props ? props.checked : (document.getElementById(controlId) as HTMLInputElement | null)?.value;\n const message = fn(value);\n return typeof message === \"string\" && message.length > 0 ? message : undefined;\n }, [latest]);\n const show = useCallback((message: string | undefined) => {\n const { form: f, id: controlId } = latest.current;\n if (f) f.setError(controlId, message);\n else setLocalError(message);\n }, [latest]);\n // every submit runs the check, whatever the timing\n const register = form?.register;\n const checks = !!validate;\n useEffect(() => (register && checks ? register(id, check) : undefined), [register, checks, id, check]);\n // Left: focus goes out of the field's React tree and doesn't come back straight away. React carries focus events\n // through portals, so moving into the control's own popup comes back in, and cancels the check.\n const leaving = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => () => { if (leaving.current) clearTimeout(leaving.current); }, []);\n const onFocusCapture = () => {\n if (leaving.current) { clearTimeout(leaving.current); leaving.current = null; }\n };\n const onBlurCapture = () => {\n if (!validate) return;\n if (leaving.current) clearTimeout(leaving.current);\n leaving.current = setTimeout(() => {\n leaving.current = null;\n setLeft(true);\n if (latest.current.mode !== \"onSubmit\" || latest.current.showing) show(check());\n }, 0);\n };\n // Changed: checked again once the page has the new value, if the timing is onChange and the field has been left,\n // or if its message shows, so it goes as soon as the value is right\n const recheck = () => {\n if (!validate) return;\n setTimeout(() => {\n const { mode: m, left: wasLeft, showing } = latest.current;\n if ((m === \"onChange\" && wasLeft) || showing) show(check());\n }, 0);\n };\n\n const shownError = typeof error === \"string\" && error.length > 0 ? error : checkError;\n const hasError = typeof shownError === \"string\" && shownError.length > 0;\n const describedBy = [hint ? hintId : null, hasError ? errorId : null].filter(Boolean).join(\" \") || undefined;\n const labelId = `${id}-label`;\n const fieldContext = useMemo<FieldContextValue>(() => ({ controlId: id, labelId, describedBy, invalid: hasError, required: !!required }), [id, labelId, describedBy, hasError, required]);\n\n const controlProps: FieldControlProps = {\n id,\n \"aria-describedby\": describedBy,\n ...(hasError ? { \"aria-invalid\": true as const, error: true } : {}),\n ...(required ? { \"aria-required\": true as const, required: true } : {}),\n };\n\n let control: ReactNode;\n if (typeof children === \"function\") {\n control = children(controlProps);\n } else {\n if (!child || !isValidElement(child)) throw new Error(\"Field expects a single form control as its child\");\n const isNative = typeof child.type === \"string\";\n const { error: errorFlag, ...ariaOnly } = controlProps;\n // with a check, the control's own onChange is kept and the check follows it (a Gridsmith control calls onChange\n // with its value; a native one's input event reaches the wrapper too)\n const ownOnChange = childProps?.onChange as ((...args: unknown[]) => void) | undefined;\n const onChange = validate && !isNative ? { onChange: (...args: unknown[]) => { ownOnChange?.(...args); recheck(); } } : {};\n // Native elements get ARIA only (an unknown `error` attribute would warn);\n // Gridsmith components get `error` so they render their error styling.\n control = cloneElement(child as ReactElement<Record<string, unknown>>, isNative ? ariaOnly : { ...ariaOnly, ...(errorFlag ? { error: true } : {}), ...onChange });\n }\n\n const labelNode = (\n <Label id={labelId} htmlFor={id} className={cn(hideLabel && \"sr-only\", hideLabel && inGroupRow && \"@max-[30rem]:not-sr-only\")}>\n {label}\n {required && <span aria-hidden=\"true\" className=\"ml-ds-0.5 text-[var(--ds-status-error)]\">*</span>}\n </Label>\n );\n\n return (\n // In a settings panel a field keeps the narrow reading width however wide the page is (--ds-form-max, Sprint 25.9 A4)\n <div\n className={cn(\"flex flex-col gap-ds-1.5 max-w-[var(--ds-form-max,none)]\", className)}\n {...(validate ? { onFocusCapture, onBlurCapture, onInputCapture: recheck } : {})}\n >\n {/* A hidden label with no action beside it takes no row of its own, so the field keeps its height (A31); in an\n AddAnother row it shows again once the group stacks its rows and hides its headings. */}\n {hideLabel && !labelAction ? labelNode : (\n <div className=\"flex items-center justify-between gap-ds-2\">\n {labelNode}\n {labelAction}\n </div>\n )}\n <FieldContext.Provider value={fieldContext}>{control}</FieldContext.Provider>\n {hint && (\n <p id={hintId} className=\"text-xs text-[var(--ds-text-muted)]\">{hint}</p>\n )}\n {hasError && <InlineFieldError id={errorId} message={shownError} className=\"mt-0\" />}\n </div>\n );\n}\n","import { cn, ACTIVE_RING, FOCUS_RING, ERROR_ACTIVE_RING, ERROR_FOCUS_RING } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { focusAfterRemoval, usePopupFocus } from \"../lib/focus\";\nimport { Tooltip } from \"./Tooltip\";\nimport { useTextOverflow } from \"../lib/use-text-overflow\";\nimport { useState, useRef, useEffect, useLayoutEffect, useCallback, useContext, useId, type Ref } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { ControlSizeContext } from \"./Button\";\nimport { useFieldControl, type FieldControlWiring } from \"./Field\";\nimport { useReportedChange } from \"../lib/form-context\";\n\ninterface Option {\n id: string;\n label: string;\n group?: string;\n}\n\ntype DropdownSize = \"sm\" | \"md\" | \"lg\";\n\nconst DROPDOWN_HEIGHT: Record<DropdownSize, string> = {\n sm: \"px-ds-2 py-ds-1 text-xs h-[var(--ds-control-height-sm)]\",\n md: \"px-ds-3 py-ds-2 text-sm h-[var(--ds-control-height-md)]\",\n lg: \"px-ds-4 py-ds-3 text-base h-[var(--ds-control-height-lg)]\",\n};\n\ninterface DropdownProps extends FieldControlWiring {\n options: Option[];\n value: string | string[];\n onChange: (value: string | string[]) => void;\n label?: string;\n disabled?: boolean;\n placeholder?: string;\n multiple?: boolean;\n searchable?: boolean;\n size?: DropdownSize;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n container?: Element | DocumentFragment;\n error?: boolean;\n /** When multiple, show removable chips below the trigger. Defaults to true. Set false in toolbar contexts where chips are shown elsewhere. */\n showChips?: boolean;\n /** Accessible name for the trigger, for when there is no visible `label` (e.g. in a toolbar). */\n \"aria-label\"?: string;\n}\n\nexport function Dropdown({\n options,\n value,\n onChange: onChangeProp,\n label,\n disabled,\n placeholder = \"Select...\",\n multiple,\n searchable,\n size: sizeProp,\n className,\n ref,\n container,\n error = false,\n showChips = true,\n \"aria-label\": ariaLabel,\n ...wiring\n}: DropdownProps) {\n // Sprint 25.12 A15: a choice the user makes marks the form's overlay; the list's search box doesn't (its own state)\n const onChange = useReportedChange(onChangeProp, value);\n const contextSize = useContext(ControlSizeContext);\n // Inside a Field the trigger takes the Field's id, label, hint, error and required state (round 27 review): the label\n // and then the trigger's own text name it, the list-box button pattern's \"Plan, Starter\" (APG collapsible listbox).\n const generatedId = useId();\n const control = useFieldControl({ ...wiring, error: error || undefined }, { requiredInDescription: true });\n const triggerId = control.id ?? generatedId;\n const labelSpanId = `${triggerId}-label`;\n const labelledBy = control.labelId ? `${control.labelId} ${triggerId}` : label && !ariaLabel ? `${labelSpanId} ${triggerId}` : undefined;\n const invalid = control.invalid;\n const size = sizeProp ?? contextSize ?? \"md\";\n const [open, setOpen] = useState(false);\n const [search, setSearch] = useState(\"\");\n const [positioned, setPositioned] = useState(false);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const searchRef = useRef<HTMLInputElement>(null);\n const [pos, setPos] = useState({ top: 0, left: 0, width: 0 });\n\n const selectedValues = Array.isArray(value) ? value : [value].filter(Boolean);\n\n const updatePos = useCallback(() => {\n if (!triggerRef.current) return;\n const rect = triggerRef.current.getBoundingClientRect();\n let top = rect.bottom + 4;\n let left = rect.left;\n const width = rect.width;\n\n if (menuRef.current) {\n const menuRect = menuRef.current.getBoundingClientRect();\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n if (left + menuRect.width > vw) left = Math.max(0, vw - menuRect.width - 8);\n if (top + menuRect.height > vh) {\n const above = rect.top - 4 - menuRect.height;\n if (above >= 0) top = above;\n else top = Math.max(0, vh - menuRect.height - 8);\n }\n }\n\n setPos({ top, left, width });\n }, []);\n\n // Opening clears the search; closing forgets the last position (render-time\n // state adjustment, so the menu never paints with stale values).\n const [prevOpen, setPrevOpen] = useState(open);\n if (open !== prevOpen) {\n setPrevOpen(open);\n if (open) setSearch(\"\");\n else setPositioned(false);\n }\n\n useEffect(() => {\n if (!open) return;\n updatePos();\n const raf = requestAnimationFrame(() => {\n updatePos();\n setPositioned(true);\n });\n const onScroll = () => updatePos();\n window.addEventListener(\"scroll\", onScroll, true);\n window.addEventListener(\"resize\", updatePos);\n return () => {\n cancelAnimationFrame(raf);\n window.removeEventListener(\"scroll\", onScroll, true);\n window.removeEventListener(\"resize\", updatePos);\n };\n }, [open, updatePos]);\n\n // Sprint 25.7: the user moved to an option since the list opened (arrows, Home/End, type-ahead). Tab then picks it (D14(a)).\n const moved = useRef(false);\n\n // Focus moves in once the panel is visible: it opens with visibility hidden until positioned, and a hidden element\n // cannot take focus (focusing it in the same frame used to leave focus on the trigger in real browsers).\n useLayoutEffect(() => {\n if (!open || !positioned) return;\n moved.current = false;\n if (searchRef.current) {\n searchRef.current.focus();\n return;\n }\n const els = Array.from(menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"option\"]') ?? []);\n (els.find((el) => el.getAttribute(\"aria-selected\") === \"true\") ?? els[0])?.focus();\n }, [open, positioned]);\n\n useEffect(() => {\n if (!open) return;\n const handler = (e: MouseEvent) => {\n const target = e.target as Node;\n if (triggerRef.current?.contains(target) || menuRef.current?.contains(target)) return;\n setOpen(false);\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open]);\n\n // Tab while open (D14(a)): a single-select list picks the option the user moved to; opened and left, nothing changes.\n const commitMoved = () => {\n if (multiple || !moved.current) return;\n const el = document.activeElement;\n const id = el instanceof HTMLElement && menuRef.current?.contains(el) ? el.getAttribute(\"data-option-id\") : null;\n if (id) onChange(id);\n };\n // Sprint 25.7: focus hands back on close, and Tab out carries on from the trigger (lib/focus usePopupFocus).\n const { isTop: isTopLayer, returnFocus } = usePopupFocus(open, { trigger: triggerRef, panel: menuRef, close: () => setOpen(false), tabExits: \"any\", onTabOut: commitMoved });\n\n // Keyboard while open: Escape closes (focus returns to the trigger); arrows,\n // Home/End move focus through the options; typing jumps to the first option\n // starting with those letters (when there is no search box); Enter/Space\n // activate the focused option natively.\n const typeahead = useRef({ buffer: \"\", at: 0 });\n useEffect(() => {\n if (!open) return;\n const optionButtons = () => Array.from(menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"option\"]') ?? []);\n const focusOption = (idx: number) => {\n const els = optionButtons();\n if (els.length === 0) return;\n els[((idx % els.length) + els.length) % els.length].focus();\n moved.current = true;\n };\n const onKey = (e: KeyboardEvent) => {\n const inMenu = menuRef.current?.contains(document.activeElement) || triggerRef.current === document.activeElement;\n if (!inMenu) return;\n const els = optionButtons();\n const current = els.findIndex((el) => el === document.activeElement);\n if (e.key === \"Escape\") { if (e.defaultPrevented || !isTopLayer()) return; e.preventDefault(); returnFocus(); setOpen(false); return; }\n if (e.key === \"ArrowDown\") { e.preventDefault(); focusOption(current < 0 ? 0 : current + 1); return; }\n if (e.key === \"ArrowUp\") { e.preventDefault(); focusOption(current < 0 ? els.length - 1 : current - 1); return; }\n const inSearch = document.activeElement === searchRef.current;\n if (e.key === \"Home\" && !inSearch) { e.preventDefault(); focusOption(0); return; }\n if (e.key === \"End\" && !inSearch) { e.preventDefault(); focusOption(els.length - 1); return; }\n if (!searchable && e.key.length === 1 && !e.metaKey && !e.ctrlKey && !e.altKey) {\n const now = Date.now();\n typeahead.current.buffer = now - typeahead.current.at > 700 ? e.key : typeahead.current.buffer + e.key;\n typeahead.current.at = now;\n const q = typeahead.current.buffer.toLowerCase();\n const hit = els.findIndex((el) => (el.textContent ?? \"\").trim().toLowerCase().startsWith(q));\n if (hit >= 0) { e.preventDefault(); focusOption(hit); }\n }\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, searchable, isTopLayer, returnFocus]);\n\n const filtered = searchable && search\n ? options.filter((o) => o.label.toLowerCase().includes(search.toLowerCase()))\n : options;\n\n const groups = new Map<string, Option[]>();\n for (const opt of filtered) {\n const g = opt.group ?? \"\";\n if (!groups.has(g)) groups.set(g, []);\n groups.get(g)!.push(opt);\n }\n const hasGroups = Array.from(groups.keys()).some((k) => k !== \"\");\n\n const handleSelect = (id: string) => {\n if (multiple) {\n const arr = selectedValues.includes(id)\n ? selectedValues.filter((v) => v !== id)\n : [...selectedValues, id];\n onChange(arr);\n } else {\n // Focus back on the trigger before the consumer runs, so a dialog it opens records the trigger (Sprint 25.7).\n returnFocus();\n onChange(id);\n setOpen(false);\n }\n };\n\n // Removing a chip moves focus to the chip before it, else the one after, else the trigger (D14(c)), once the value\n // no longer holds it. The next render drops the request either way, so a removal the consumer refused never moves\n // focus later.\n const chipsRef = useRef<HTMLDivElement>(null);\n const pendingChipFocus = useRef<{ index: number; value: string } | null>(null);\n useLayoutEffect(() => {\n const pending = pendingChipFocus.current;\n if (pending === null) return;\n pendingChipFocus.current = null;\n if (selectedValues.includes(pending.value)) return;\n const chips = Array.from(chipsRef.current?.querySelectorAll<HTMLElement>(\"[data-chip-remove]\") ?? []);\n focusAfterRemoval(chips, pending.index, triggerRef.current);\n });\n\n const displayLabel = multiple\n ? selectedValues.length > 0\n ? `${selectedValues.length} selected`\n : placeholder\n : options.find((o) => o.id === selectedValues[0])?.label ?? placeholder;\n\n const { ref: overflowRef, isTruncated } = useTextOverflow({ lines: 1, content: displayLabel });\n\n return (\n <div ref={ref} className={cn(\"relative\", className)}>\n {label && (\n <span id={labelSpanId} className=\"block mb-ds-1.5 text-sm font-medium text-[var(--ds-text-secondary)]\">{label}</span>\n )}\n {control.requiredNote}\n <button\n ref={triggerRef}\n id={triggerId}\n type=\"button\"\n onClick={() => !disabled && setOpen(!open)}\n onKeyDown={(e) => {\n if (disabled || open) return;\n if (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") { e.preventDefault(); setOpen(true); }\n }}\n disabled={disabled}\n aria-invalid={invalid || undefined}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-label={labelledBy ? undefined : ariaLabel}\n aria-labelledby={labelledBy}\n aria-describedby={control.describedBy}\n className={cn(\n \"w-full flex items-center justify-between gap-ds-2\",\n DROPDOWN_HEIGHT[size],\n \"bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)]\",\n \"border-[length:var(--ds-border-width)]\",\n invalid ? \"border-[var(--ds-status-error)]\" : \"border-[var(--ds-input-border)]\",\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-input-shadow)]\",\n \"transition-colors\",\n !invalid && !disabled && !open && \"hover:border-[var(--ds-input-border-hover)]\",\n open && (invalid ? ERROR_ACTIVE_RING : ACTIVE_RING),\n invalid ? ERROR_FOCUS_RING : FOCUS_RING,\n \"cursor-pointer disabled:cursor-not-allowed disabled:opacity-disabled\",\n !selectedValues.length && \"text-[var(--ds-text-muted)]\"\n )}\n >\n {isTruncated ? (\n <Tooltip content={displayLabel}><span ref={overflowRef} className=\"truncate\">{displayLabel}</span></Tooltip>\n ) : (\n <span ref={overflowRef} className=\"truncate\">{displayLabel}</span>\n )}\n <span className={cn(\"transition-transform\", open && \"rotate-180\")}>\n <Icon name=\"chevron-right\" size={14} className=\"rotate-90\" />\n </span>\n </button>\n\n {open && createPortal(\n <div\n ref={menuRef}\n // Safari focuses no button on a mousedown and drops focus to the body; a panel that can take focus keeps it\n // inside the control's React tree, so a Field's leave check never fires mid-choice (round 27 review)\n tabIndex={-1}\n // A choice is the list's own: its click must not also reach a clickable row or card around the Dropdown.\n onClick={(e) => e.stopPropagation()}\n className={cn(\n \"fixed z-[var(--ds-z-popover)] outline-none\",\n \"bg-[var(--ds-bg-surface-elevated)]\",\n \"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"rounded-[var(--ds-radius-md)] overflow-hidden\",\n \"shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]\",\n )}\n style={{ top: pos.top, left: pos.left, minWidth: pos.width, width: \"max-content\", maxWidth: \"calc(100vw - 16px)\", visibility: positioned ? \"visible\" : \"hidden\" }}\n >\n {searchable && (\n <div className=\"border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\" style={{ padding: \"var(--ds-space-2)\" }}>\n <input\n ref={searchRef}\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search…\"\n className={cn(\"w-full bg-transparent text-[var(--ds-text-primary)] placeholder:text-[var(--ds-text-muted)] outline-none\", size === \"sm\" ? \"text-xs\" : \"text-sm\")}\n />\n </div>\n )}\n <div role=\"listbox\" className=\"overflow-y-auto\" style={{ padding: \"var(--ds-space-1)\", maxHeight: \"var(--ds-dropdown-max-height)\" }}>\n {filtered.length === 0 ? (\n <p className={cn(\"text-[var(--ds-text-muted)] text-center py-ds-4\", size === \"sm\" ? \"text-xs\" : \"text-sm\")}>No options found</p>\n ) : hasGroups ? (\n Array.from(groups.entries()).map(([group, opts]) => (\n <div key={group}>\n {group && (\n <p className=\"text-2xs font-medium uppercase tracking-wider text-[var(--ds-text-muted)] px-ds-2 pt-ds-2 pb-ds-1\">\n {group}\n </p>\n )}\n {opts.map((opt) => (\n <OptionButton\n key={opt.id}\n opt={opt}\n isSelected={selectedValues.includes(opt.id)}\n multiple={multiple}\n onSelect={handleSelect}\n size={size}\n />\n ))}\n </div>\n ))\n ) : (\n filtered.map((opt) => (\n <OptionButton\n key={opt.id}\n opt={opt}\n isSelected={selectedValues.includes(opt.id)}\n multiple={multiple}\n onSelect={handleSelect}\n size={size}\n />\n ))\n )}\n </div>\n </div>,\n container ?? document.body\n )}\n\n {multiple && showChips && selectedValues.length > 0 && (\n <div ref={chipsRef} className=\"flex flex-wrap gap-ds-1 mt-ds-1.5\">\n {selectedValues.map((v, i) => {\n const opt = options.find((o) => o.id === v);\n return opt ? (\n <span\n key={v}\n className=\"inline-flex items-center gap-ds-1 text-xs rounded-[var(--ds-radius-sm)] bg-[var(--ds-bg-muted)] text-[var(--ds-text-secondary)] px-ds-1.5 py-ds-0.5\"\n >\n {opt.label}\n <button type=\"button\"\n data-chip-remove=\"\"\n onClick={() => { pendingChipFocus.current = { index: i, value: v }; handleSelect(v); }}\n className=\"hover:text-[var(--ds-text-primary)] cursor-pointer\"\n aria-label={`Remove ${opt.label}`}\n >\n <Icon name=\"close\" size={10} />\n </button>\n </span>\n ) : null;\n })}\n </div>\n )}\n </div>\n );\n}\n\nfunction OptionButton({\n opt,\n isSelected,\n multiple,\n onSelect,\n size = \"md\",\n}: {\n opt: Option;\n isSelected: boolean;\n multiple?: boolean;\n onSelect: (id: string) => void;\n size?: DropdownSize;\n}) {\n return (\n <button\n type=\"button\"\n role=\"option\"\n data-option-id={opt.id}\n aria-selected={isSelected}\n tabIndex={-1}\n onClick={() => onSelect(opt.id)}\n className={cn(\n \"w-full text-left cursor-pointer rounded-[var(--ds-radius-sm)]\",\n \"transition-colors flex items-center gap-ds-2\",\n \"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]\",\n size === \"sm\" ? \"px-ds-2 py-ds-1 text-xs\" : \"px-ds-2 py-ds-1.5 text-sm\",\n isSelected && !multiple\n ? \"bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]\"\n : \"text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-emphasis)]\"\n )}\n >\n {multiple && (\n <span\n className={cn(\n \"w-[var(--ds-icon-size-sm)] h-[var(--ds-icon-size-sm)] rounded-[var(--ds-radius-sm)] border-[length:var(--ds-border-width)] shrink-0 flex items-center justify-center\",\n isSelected\n ? \"bg-[var(--ds-accent-primary)] border-[var(--ds-accent-primary)]\"\n : \"border-[var(--ds-border-default)]\"\n )}\n >\n {isSelected && <Icon name=\"check\" size={10} className=\"text-[var(--ds-text-on-primary)]\" />}\n </span>\n )}\n <span className=\"flex-1\">{opt.label}</span>\n {isSelected && !multiple && <Icon name=\"check\" size={size === \"sm\" ? 12 : 14} />}\n </button>\n );\n}\n","import { useCallback, useContext, useRef, useState } from \"react\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { cn, FOCUS_WITHIN_RING, ERROR_FOCUS_WITHIN_RING } from \"../lib/utils\";\nimport { ControlSizeContext } from \"./Button\";\nimport { useReportedChange } from \"../lib/form-context\";\n\ninterface NumberInputProps {\n value: number;\n onChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n disabled?: boolean;\n placeholder?: string;\n prefix?: string;\n suffix?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n className?: string;\n error?: boolean;\n /** Allow decimal input. Default: true when step is not an integer, false otherwise. */\n allowDecimals?: boolean;\n /** Forwarded to the inner input element so a Label htmlFor can be associated. */\n id?: string;\n}\n\n// The height is the bordered box's (box-sizing: border-box), so the control measures exactly the token beside an\n// Input or a Button; the buttons and the field stretch to it.\nconst sizes = {\n sm: { box: \"h-[var(--ds-control-height-sm)]\", input: \"text-xs self-stretch\", btn: \"w-7 text-xs\" },\n md: { box: \"h-[var(--ds-control-height-md)]\", input: \"text-sm self-stretch\", btn: \"w-9 text-sm\" },\n lg: { box: \"h-[var(--ds-control-height-lg)]\", input: \"text-base self-stretch\", btn: \"w-10 text-base\" },\n};\n\nexport function NumberInput({\n value,\n onChange: onChangeProp,\n min = -Infinity,\n max = Infinity,\n step = 1,\n disabled = false,\n placeholder = \"0\",\n prefix,\n suffix,\n size: sizeProp,\n className,\n error = false,\n allowDecimals,\n id,\n}: NumberInputProps) {\n // Sprint 25.12 A15: a new value the user gives this control marks the form's overlay; the page's onChange runs as given\n const onChange = useReportedChange(onChangeProp, value);\n const contextSize = useContext(ControlSizeContext);\n const size = sizeProp ?? contextSize ?? \"md\";\n const intervalRef = useRef<ReturnType<typeof setInterval>>(undefined);\n const timeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n const inputRef = useRef<HTMLInputElement>(null);\n const [focused, setFocused] = useState(false);\n const [draft, setDraft] = useState(String(value));\n\n const decimals = allowDecimals ?? (step % 1 !== 0);\n\n // While not focused the draft mirrors the controlled value; on blur it\n // re-syncs (render-time state adjustment).\n const [prevSync, setPrevSync] = useState({ value, focused });\n if (value !== prevSync.value || focused !== prevSync.focused) {\n setPrevSync({ value, focused });\n if (!focused) setDraft(String(value));\n }\n\n const clamp = useCallback(\n (v: number) => Math.min(max, Math.max(min, v)),\n [min, max],\n );\n\n // Stepping reads the latest committed value through a ref so a held button\n // (setInterval in startRepeat) keeps counting instead of re-adding one step\n // to the value captured at mousedown. useLatest syncs it to the prop in a\n // layout effect (never during render); commitValue advances it in the handler.\n const valueRef = useLatest(value);\n\n // Commit a stepped or blurred value. The draft is updated too: the input\n // shows the draft while focused, and stepping happens while focused (the\n // buttons focus the input), so without this the text never moved and the\n // stale draft was committed back over the new value on blur.\n // `own`: the control settles on a value by itself (a blur with nothing typed falls back to the minimum), which is\n // not the user's change and doesn't mark the form's overlay (Sprint 25.12 A15).\n const commitValue = useCallback((v: number, own = false) => {\n const clamped = clamp(v);\n // Advance the ref now, not on the next render: repeat ticks can land\n // before React re-renders, and each must build on the previous one.\n valueRef.current = clamped;\n setDraft(String(clamped));\n (own ? onChangeProp : onChange)(clamped);\n return clamped;\n }, [onChange, onChangeProp, clamp, valueRef]);\n\n const increment = useCallback(() => commitValue(valueRef.current + step), [commitValue, step, valueRef]);\n const decrement = useCallback(() => commitValue(valueRef.current - step), [commitValue, step, valueRef]);\n\n const startRepeat = useCallback(\n (fn: () => void) => {\n fn();\n timeoutRef.current = setTimeout(() => {\n intervalRef.current = setInterval(fn, 75);\n }, 400);\n },\n [],\n );\n\n const stopRepeat = useCallback(() => {\n clearTimeout(timeoutRef.current);\n clearInterval(intervalRef.current);\n }, []);\n\n const handleInput = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const raw = e.target.value;\n\n if (raw === \"\" || raw === \"-\") {\n setDraft(raw);\n return;\n }\n\n if (!decimals && raw.includes(\".\")) return;\n\n const validPattern = decimals ? /^-?\\d*\\.?\\d*$/ : /^-?\\d*$/;\n if (!validPattern.test(raw)) return;\n\n setDraft(raw);\n\n const parsed = parseFloat(raw);\n if (!isNaN(parsed) && isFinite(parsed)) {\n onChange(clamp(parsed));\n }\n },\n [onChange, clamp, decimals],\n );\n\n const handleBlur = useCallback(() => {\n setFocused(false);\n const parsed = parseFloat(draft);\n if (!isNaN(parsed) && isFinite(parsed)) {\n // nothing typed: a value outside min and max clamped on the way through is the control's own (0.21.0)\n const committed = commitValue(parsed, draft === String(value));\n setDraft(String(committed));\n } else {\n const fallback = isFinite(min) ? min : 0;\n const committed = commitValue(value !== undefined ? value : fallback, true);\n setDraft(String(committed));\n }\n }, [draft, commitValue, min, value]);\n\n const handleFocus = useCallback(() => {\n setFocused(true);\n }, []);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"ArrowUp\") { e.preventDefault(); increment(); }\n if (e.key === \"ArrowDown\") { e.preventDefault(); decrement(); }\n },\n [increment, decrement],\n );\n\n const s = sizes[size];\n const atMin = value <= min;\n const atMax = value >= max;\n\n return (\n <div\n className={cn(\n \"flex items-center w-full\",\n s.box,\n \"border-[length:var(--ds-border-width)]\",\n error ? \"border-[var(--ds-status-error)]\" : \"border-[var(--ds-input-border)]\",\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-input-shadow)]\",\n \"bg-[var(--ds-input-bg)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n !error && !disabled && \"hover:border-[var(--ds-input-border-hover)]\",\n error ? ERROR_FOCUS_WITHIN_RING : cn(FOCUS_WITHIN_RING, \"focus-within:hover:border-[var(--ds-border-focus)]\"),\n disabled && \"opacity-disabled cursor-not-allowed\",\n className,\n )}\n >\n <button\n type=\"button\"\n tabIndex={-1}\n disabled={disabled || atMin}\n onMouseDown={(e) => { e.preventDefault(); inputRef.current?.focus(); if (!disabled && !atMin) startRepeat(decrement); }}\n onMouseUp={stopRepeat}\n onMouseLeave={stopRepeat}\n className={cn(\n \"inline-flex items-center justify-center shrink-0\",\n \"border-r-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]\",\n \"transition-colors cursor-pointer\",\n \"rounded-l-[var(--ds-radius-md)]\",\n s.btn, s.input,\n (disabled || atMin) && \"opacity-disabled cursor-not-allowed hover:bg-transparent hover:text-[var(--ds-text-muted)]\",\n )}\n aria-label=\"Decrease\"\n >\n −\n </button>\n\n <div className={cn(\"flex items-center flex-1 min-w-0 px-ds-2 gap-ds-1\", s.input)}>\n {prefix && <span className=\"text-[var(--ds-text-muted)] shrink-0 text-xs\">{prefix}</span>}\n <input\n ref={inputRef}\n id={id}\n type=\"text\"\n inputMode={decimals ? \"decimal\" : \"numeric\"}\n aria-invalid={error || undefined}\n value={focused ? draft : String(value)}\n onChange={handleInput}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n placeholder={placeholder}\n className={cn(\n \"w-full min-w-0 bg-transparent text-center outline-none\",\n \"text-[var(--ds-text-primary)]\",\n \"placeholder:text-[var(--ds-text-muted)]\",\n \"font-[family-name:var(--ds-font-mono)]\",\n s.input,\n disabled && \"cursor-not-allowed\",\n )}\n />\n {suffix && <span className=\"text-[var(--ds-text-muted)] shrink-0 text-xs\">{suffix}</span>}\n </div>\n\n <button\n type=\"button\"\n tabIndex={-1}\n disabled={disabled || atMax}\n onMouseDown={(e) => { e.preventDefault(); inputRef.current?.focus(); if (!disabled && !atMax) startRepeat(increment); }}\n onMouseUp={stopRepeat}\n onMouseLeave={stopRepeat}\n className={cn(\n \"inline-flex items-center justify-center shrink-0\",\n \"border-l-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]\",\n \"transition-colors cursor-pointer\",\n \"rounded-r-[var(--ds-radius-md)]\",\n s.btn, s.input,\n (disabled || atMax) && \"opacity-disabled cursor-not-allowed hover:bg-transparent hover:text-[var(--ds-text-muted)]\",\n )}\n aria-label=\"Increase\"\n >\n +\n </button>\n </div>\n );\n}\n","import { useRef, useEffect, type ReactNode, useState, useCallback } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn, GLASS_DROPDOWN } from \"../lib/utils\";\nimport { Slot } from \"../lib/slot\";\nimport { triggerType } from \"./Button\";\nimport { usePosition, type Side, type Align } from \"../lib/use-position\";\nimport { focusInitial, usePopupFocus, usePressMarks } from \"../lib/focus\";\nimport { useLatest } from \"../lib/use-latest\";\n\ninterface PopoverProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n trigger: ReactNode;\n children: ReactNode;\n side?: Side;\n align?: Align;\n width?: \"trigger\" | \"auto\" | (string & {});\n className?: string;\n container?: Element | DocumentFragment;\n}\n\nexport function Popover({ open, onOpenChange, trigger, children, side = \"bottom\", align = \"center\", width, className, container }: PopoverProps) {\n const triggerRef = useRef<HTMLElement>(null);\n const floatingRef = useRef<HTMLDivElement>(null);\n // Measured in commit-phase code (ref callback, click handler), never read from the ref during render.\n const [triggerWidth, setTriggerWidth] = useState<number | undefined>(undefined);\n const setTriggerNode = useCallback((node: HTMLElement | null) => {\n triggerRef.current = node;\n setTriggerWidth(node?.offsetWidth);\n }, []);\n\n const pos = usePosition(triggerRef, floatingRef, open, { side, align, offset: 8, flip: true });\n // Read from the listeners below, so a new onOpenChange each render never re-registers them (an inner list's Escape\n // listener would then run first, and this popover would see itself on top after the list closed).\n const onOpenChangeRef = useLatest(onOpenChange);\n // A press in a popup the content opens elsewhere in the page (a Dropdown's list) passes through this tree first.\n const { props: pressMarks, marked } = usePressMarks();\n\n // Sprint 25.7: Tab from the panel's last control (or Shift+Tab from its first) closes it and carries on from the\n // trigger; content that closes it (an Apply button) hands focus back through the safety net.\n const { isTop: isTopLayer, returnFocus } = usePopupFocus(open, { trigger: triggerRef, panel: floatingRef, close: () => onOpenChangeRef.current(false), tabExits: \"edges\", marked });\n\n useEffect(() => {\n if (!open) return;\n\n // Bubble phase on document, after the content's own handlers: content that stops or handles Escape (a draft\n // field going back a step, a list inside closing) keeps the popover open. It acts only with focus in it, or\n // nowhere, so an Escape meant for a field elsewhere never closes it.\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\" || e.defaultPrevented || !isTopLayer()) return;\n const active = document.activeElement;\n if (active && active !== document.body && !triggerRef.current?.contains(active) && !floatingRef.current?.contains(active)) return;\n e.preventDefault();\n returnFocus();\n onOpenChangeRef.current(false);\n };\n\n // A press outside the popover's React tree closes it, whatever is open inside it (Radix's dismissable layer). A\n // press in a popup opened from it (a Dropdown's list) is inside, so its click lands.\n const onPress = (e: MouseEvent) => {\n const target = e.target as Node;\n if (marked(e) || triggerRef.current?.contains(target) || floatingRef.current?.contains(target)) return;\n onOpenChangeRef.current(false);\n };\n\n document.addEventListener(\"keydown\", onKeyDown);\n document.addEventListener(\"mousedown\", onPress);\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n document.removeEventListener(\"mousedown\", onPress);\n };\n }, [open, onOpenChangeRef, isTopLayer, returnFocus, marked]);\n\n useEffect(() => {\n if (open) focusInitial(floatingRef.current);\n }, [open]);\n\n return (\n <>\n <Slot\n {...triggerType(trigger)}\n ref={setTriggerNode}\n onClick={() => { setTriggerWidth(triggerRef.current?.offsetWidth); onOpenChange(!open); }}\n >\n {trigger}\n </Slot>\n {open && createPortal(\n <div\n ref={floatingRef}\n data-gs=\"popover\"\n {...pressMarks}\n // Clicks inside are the panel's own, not a click on a row or card the trigger sits in.\n onClick={(e) => e.stopPropagation()}\n className={cn(\n \"fixed z-[var(--ds-z-popover)]\",\n \"bg-[var(--ds-bg-surface-elevated)]\",\n GLASS_DROPDOWN,\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"rounded-[var(--ds-radius-md)]\",\n className\n )}\n style={{\n top: pos.top,\n left: pos.left,\n width: width === \"trigger\" ? triggerWidth : width === \"auto\" ? undefined : width,\n }}\n >\n {children}\n </div>,\n container ?? document.body\n )}\n </>\n );\n}\n","// Bundlers set process.env.NODE_ENV. Where none did (a page with no build step), reading it throws and warnings stay off.\ndeclare const process: { env: { NODE_ENV?: string } };\nconst warned = new Set<string>();\n\n/** A mistake in a component's props, told to the developer once a page, in a development build. */\nexport function warnOnce(component: string, message: string): void {\n let dev = false;\n try {\n dev = process.env.NODE_ENV !== \"production\";\n } catch {\n dev = false;\n }\n const text = `${component}: ${message}`;\n if (!dev || warned.has(text)) return;\n warned.add(text);\n console.warn(text);\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { Dropdown } from \"./Dropdown\";\nimport { Popover } from \"./Popover\";\nimport { NumberInput } from \"./NumberInput\";\nimport { Button } from \"./Button\";\nimport { useShellPreferences } from \"../lib/preferences\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { FormChangeCtx } from \"../lib/form-context\";\nimport { warnOnce } from \"../lib/dev-warn\";\n\ninterface PaginationProps {\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n pageSize?: number;\n pageSizeOptions?: number[];\n onPageSizeChange?: (size: number) => void;\n /**\n * How the list shows more (round 22): page numbers, a Load more button, or loading as the user scrolls (with the\n * button kept for keyboard users). `usePagination` passes the project's dataDisplay.paginationStyle here in\n * `pager.props`, so `<Pagination {...pager.props} />` follows the project's style with nothing written on the page.\n */\n mode?: \"pagination\" | \"load-more\" | \"infinite-scroll\";\n /** Rows left to load (load-more and infinite-scroll). */\n hasMore?: boolean;\n /** Load the next rows (load-more and infinite-scroll). */\n onLoadMore?: () => void;\n /** The Load more button's label (default \"Load more\"). */\n loadMoreLabel?: string;\n className?: string;\n /** Set by `usePagination` in `pager.props`: which list the control belongs to (Sprint 25.13 A3). */\n pagerToken?: object;\n}\n\n/** The controls drawn for each pager: a list given the pager draws one, so a <Pagination> of the page's is a second. */\nconst controlsDrawn = new WeakMap<object, number>();\n\nexport function Pagination(props: PaginationProps) {\n const { pagerToken } = props;\n useEffect(() => {\n if (!pagerToken) return;\n const count = (controlsDrawn.get(pagerToken) ?? 0) + 1;\n controlsDrawn.set(pagerToken, count);\n if (count > 1) warnOnce(\"Pagination\", \"this list's pager already draws its control: a list given the pager (<Table pager={pager}>) draws it beneath the rows, so remove the separate <Pagination {...pager.props} />.\");\n return () => { controlsDrawn.set(pagerToken, (controlsDrawn.get(pagerToken) ?? 1) - 1); };\n }, [pagerToken]);\n if ((props.mode === \"load-more\" || props.mode === \"infinite-scroll\") && props.onLoadMore) return <LoadMore {...props} onLoadMore={props.onLoadMore} scroll={props.mode === \"infinite-scroll\"} />;\n return <PageNumbers {...props} />;\n}\n\n/**\n * The box that scrolls the marker into view: the nearest ancestor that scrolls up and down, else the page (null, the\n * viewport). A list in a fixed-height scroller loads more as that scroller moves (Sprint 25.13 A49: the trigger watched\n * the viewport, so scrolling inside the list never loaded more).\n */\nfunction scrollerOf(el: HTMLElement): HTMLElement | null {\n for (let n = el.parentElement; n && n !== document.body && n !== document.documentElement; n = n.parentElement) {\n const { overflowY } = getComputedStyle(n);\n if ((overflowY === \"auto\" || overflowY === \"scroll\") && n.scrollHeight > n.clientHeight) return n;\n }\n return null;\n}\n\n/**\n * An element's top in content coordinates: where it sits in the page, however far anything is scrolled. The window's\n * scroll is the document element's, so the walk stops below it (the review of 23 September: it was counted twice).\n */\nfunction contentTop(el: HTMLElement): number {\n let top = el.getBoundingClientRect().top + window.scrollY;\n for (let n = el.parentElement; n && n !== document.documentElement; n = n.parentElement) top += n.scrollTop;\n return top;\n}\n\n/**\n * Load more, by button or by scrolling (round 22). The scroll trigger is an observed marker above the button: when it\n * comes within 200 px of view the next rows load, and the observer is renewed after each load so a short list keeps\n * filling the window. It loads again only when the last load moved it — the list grew — or the user has scrolled since:\n * a list shown as a loading skeleton does not grow, and a Team page whose table showed one for half a second loaded\n * all 120 rows before its first row appeared. The button stays for keyboard users and for anyone who stops short.\n */\nfunction LoadMore({ hasMore, onLoadMore, loadMoreLabel, currentPage, scroll, className }: PaginationProps & { onLoadMore: () => void; scroll: boolean }) {\n const marker = useRef<HTMLDivElement>(null);\n const load = useLatest(onLoadMore);\n const loadedAt = useRef<number | null>(null);\n useEffect(() => {\n const el = marker.current;\n if (!scroll || !hasMore || !el || typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver((entries) => {\n if (!entries.some((e) => e.isIntersecting)) return;\n const at = contentTop(el);\n if (loadedAt.current !== null && Math.abs(at - loadedAt.current) < 1) return;\n loadedAt.current = at;\n load.current();\n }, { root: scrollerOf(el), rootMargin: \"200px 0px\" });\n observer.observe(el);\n const rearm = () => { loadedAt.current = null; };\n window.addEventListener(\"scroll\", rearm, { capture: true, passive: true });\n return () => {\n observer.disconnect();\n window.removeEventListener(\"scroll\", rearm, { capture: true });\n };\n }, [scroll, hasMore, currentPage, load]);\n if (!hasMore) return null;\n return (\n <div data-ds-pager=\"\" data-pagination-mode={scroll ? \"infinite-scroll\" : \"load-more\"} className={cn(\"flex flex-col items-center\", className)}>\n {scroll && <div ref={marker} data-load-more-trigger=\"\" aria-hidden=\"true\" className=\"h-px w-full\" />}\n <Button type=\"button\" variant=\"secondary\" onClick={onLoadMore}>{loadMoreLabel ?? \"Load more\"}</Button>\n </div>\n );\n}\n\nfunction PageNumbers({ currentPage, totalPages, onPageChange, pageSize: pageSizeProp, pageSizeOptions, onPageSizeChange, className }: PaginationProps) {\n const pages = buildPageRange(currentPage, totalPages);\n // Sprint 25.6 (B9): dataDisplay.itemsPerPage reaches the selector through the shell; a prop wins. App code pages its\n // list with usePagination, which reads the same value and passes it here in `pager.props` (round 21).\n const preferences = useShellPreferences();\n const pageSize = pageSizeProp ?? preferences.itemsPerPage;\n // A list that fits on one page shows no page numbers (GOV.UK: \"Do not show pagination if there's only one page of\n // content\"; the review of 30 September found \"‹ 1 ›\" under every short list). A size choice stays, so a user who\n // picked a larger size can pick a smaller one again.\n const sizeChoice = !!(pageSizeOptions && pageSize != null && onPageSizeChange);\n if (totalPages <= 1 && !sizeChoice) return null;\n\n return (\n <nav aria-label=\"Pagination\" data-ds-pager=\"\" className={cn(\"flex flex-wrap items-center gap-ds-3\", className)}>\n {sizeChoice && pageSizeOptions && pageSize != null && onPageSizeChange && (\n <div className=\"flex items-center gap-ds-2\">\n <span className=\"text-sm text-[var(--ds-text-muted)] whitespace-nowrap\">Rows per page</span>\n {/* the page size is how the list is viewed: it never marks an overlay's form (0.21.0) */}\n <FormChangeCtx value={null}>\n {/* named by the visible label, then the size chosen (WCAG 4.1.2, 2.5.3) */}\n <Dropdown\n aria-label={`Rows per page, ${pageSize}`}\n options={pageSizeOptions.map((n) => ({ id: String(n), label: String(n) }))}\n value={String(pageSize)}\n onChange={(v) => onPageSizeChange(Number(v))}\n size=\"sm\"\n className=\"w-[4.5rem]\"\n />\n </FormChangeCtx>\n </div>\n )}\n\n {totalPages > 1 && <div className=\"flex items-center gap-ds-1\">\n <button type=\"button\"\n onClick={() => onPageChange(currentPage - 1)}\n disabled={currentPage <= 1}\n aria-label=\"Previous page\"\n className={cn(\n \"inline-flex items-center justify-center h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] text-sm cursor-pointer\",\n \"rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"bg-[var(--ds-bg-surface)] text-[var(--ds-text-secondary)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]\",\n \"disabled:opacity-disabled disabled:cursor-not-allowed\"\n )}\n >\n <Icon name=\"chevron-right\" size={16} className=\"rotate-180\" />\n </button>\n\n {pages.map((p, i) =>\n p === \"...\" ? (\n <EllipsisJumper key={`ellipsis-${i}`} totalPages={totalPages} onPageChange={onPageChange} />\n ) : (\n <button type=\"button\"\n key={p}\n onClick={() => onPageChange(p as number)}\n aria-current={p === currentPage ? \"page\" : undefined}\n className={cn(\n \"inline-flex items-center justify-center h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] text-sm font-medium cursor-pointer\",\n \"rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n p === currentPage\n ? \"bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] text-[var(--ds-text-on-primary)] border-[var(--ds-accent-primary)]\"\n : \"bg-[var(--ds-bg-surface)] text-[var(--ds-text-secondary)] border-[var(--ds-border-default)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]\"\n )}\n >\n {p}\n </button>\n )\n )}\n\n <button type=\"button\"\n onClick={() => onPageChange(currentPage + 1)}\n disabled={currentPage >= totalPages}\n aria-label=\"Next page\"\n className={cn(\n \"inline-flex items-center justify-center h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] text-sm cursor-pointer\",\n \"rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"bg-[var(--ds-bg-surface)] text-[var(--ds-text-secondary)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]\",\n \"disabled:opacity-disabled disabled:cursor-not-allowed\"\n )}\n >\n <Icon name=\"chevron-right\" size={16} />\n </button>\n </div>}\n </nav>\n );\n}\n\nfunction buildPageRange(current: number, total: number): (number | \"...\")[] {\n if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1);\n\n const pages: (number | \"...\")[] = [1];\n\n if (current > 3) pages.push(\"...\");\n\n const start = Math.max(2, current - 1);\n const end = Math.min(total - 1, current + 1);\n for (let i = start; i <= end; i++) pages.push(i);\n\n if (current < total - 2) pages.push(\"...\");\n\n pages.push(total);\n return pages;\n}\n\nfunction EllipsisJumper({ totalPages, onPageChange }: { totalPages: number; onPageChange: (page: number) => void }) {\n const [open, setOpen] = useState(false);\n const [jumpPage, setJumpPage] = useState(1);\n\n const handleOpenChange = (next: boolean) => {\n if (next) setJumpPage(1);\n setOpen(next);\n };\n\n const handleGo = () => {\n const clamped = Math.min(totalPages, Math.max(1, jumpPage));\n onPageChange(clamped);\n setOpen(false);\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={handleOpenChange}\n trigger={\n <button\n type=\"button\"\n aria-label=\"Go to page\"\n onClick={() => handleOpenChange(true)}\n className={cn(\n \"inline-flex items-center justify-center h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] text-sm cursor-pointer\",\n \"rounded-[var(--ds-radius-md)]\",\n \"text-[var(--ds-text-muted)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]\",\n )}\n >\n …\n </button>\n }\n >\n <div className=\"flex flex-col gap-ds-2 p-ds-3\">\n <label className=\"text-xs font-medium text-[var(--ds-text-secondary)]\">Go to page</label>\n <div className=\"flex items-center gap-ds-2\">\n <NumberInput\n value={jumpPage}\n onChange={setJumpPage}\n min={1}\n max={totalPages}\n step={1}\n size=\"sm\"\n className=\"w-[5rem]\"\n />\n <button\n type=\"button\"\n onClick={handleGo}\n className={cn(\n \"px-ds-2.5 h-[var(--ds-control-height-sm)] text-xs font-medium cursor-pointer\",\n \"rounded-[var(--ds-radius-md)]\",\n \"bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"hover:opacity-90\",\n )}\n >\n Go\n </button>\n </div>\n </div>\n </Popover>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { warnOnce } from \"./dev-warn\";\nimport { PREFERENCE_HOUSE_DEFAULTS, useShellPreferences, type PreferencePaginationStyle } from \"./preferences\";\n\n/**\n * A long list in one hook (round 21; all three list styles since round 22). The page size and the list style are the\n * project's `dataDisplay.itemsPerPage` and `dataDisplay.paginationStyle`, read from the shell, so a mid-build\n * `update_rule` on either reaches every list with no page edited. The page gets what to show, the props for\n * `<Pagination>` — page numbers, a Load more button or loading on scroll, whichever the project's style is — and the\n * numbers the count line needs (\"Showing 51–100 of 200 events\", or \"Showing 40 of 120 members\" while a list grows).\n *\n * Run 58 hand-wrote the paging; runs 59 and 60 hand-wrote load-more and scroll loading — an IntersectionObserver, a\n * visible count and a page size copied in as a constant, twice in one app — because the library had no way to.\n *\n * const rows = events.map(toRow)\n * const pager = usePagination(rows)\n * <TableToolbar resultCount={rows.length} resultNoun={[\"event\", \"events\"]} pagination={pager} />\n * <Table columns={columns} data={rows} pager={pager} />\n *\n * The list takes the whole pager (Sprint 25.13 A3): Table, DataGrid, StackedList, Timeline and VirtualizedList draw the\n * pager's part of every row and its control beneath, and a sortable Table sorts every row, not one page. For anything\n * else, draw the page's items and the control yourself: `pager.items.map(…)` then `<Pagination {...pager.props} />`.\n *\n * A long page that must mount only the rows on screen (logs, a feed) still pages: the size the user asked for goes to\n * the hook, with its override note, and the list mounts only what is on screen of each page (A49):\n *\n * // @gridsmith-override dataDisplay.itemsPerPage: <the user's words>\n * const pager = usePagination(entries, { pageSize: 100 })\n * <VirtualizedList items={entries} pager={pager} estimateSize={() => 40} renderItem={(entry) => <LogLine entry={entry} />} />\n */\nexport interface Pager<T> {\n /** The list style this list follows: the project's, unless `style` was passed. */\n style: PreferencePaginationStyle;\n /** What to show: the current page's rows, or every row loaded so far on a list that grows. */\n items: T[];\n /** The current page, from 1; on a growing list, how many pages are loaded. */\n page: number;\n pageSize: number;\n totalItems: number;\n totalPages: number;\n /** The first and last row numbers on screen, from 1 (\"Showing 51–100\"); [0, 0] for an empty list. */\n range: [number, number];\n /** How many rows are on screen. */\n shown: number;\n /** Rows left to show: a next page, or more to load. */\n hasMore: boolean;\n /** The next page, or the next `pageSize` rows on a growing list. */\n loadMore: () => void;\n setPage: (page: number) => void;\n /** A page-size selector's choice; it wins over the project's page size and starts again at page 1. */\n setPageSize: (size: number) => void;\n /**\n * Spread onto <Pagination>: it renders page numbers, a Load more button or the scroll trigger, as `style` says. A list\n * given the whole pager (`<Table pager={pager}>`, Sprint 25.13 A3) draws this control itself.\n */\n props: {\n currentPage: number; totalPages: number; onPageChange: (page: number) => void; pageSize: number; onPageSizeChange: (size: number) => void;\n mode: PreferencePaginationStyle; hasMore: boolean; onLoadMore: () => void;\n /** The page sizes the user may choose between, when the page offers the choice (`pageSizeOptions` below). */\n pageSizeOptions?: number[];\n /** Which pager the control belongs to, so a second control for the same list is caught in development (A3). */\n pagerToken: object;\n };\n}\n\nexport interface PaginationOptions {\n /** A fixed page size for this list, over the project's. Leave it out: the project's page size is the rule. */\n pageSize?: number;\n /** Values that start the list again at page 1 when they change — the sort column and direction, a search query. */\n resetOn?: unknown;\n /**\n * A list style for this list only, over the project's. Leave it out: the project's style is the rule. Passing one that\n * differs is overriding a rule in force — ask the user first, and put `// @gridsmith-override\n * dataDisplay.paginationStyle: <their reason>` above the call.\n */\n style?: PreferencePaginationStyle;\n /**\n * The page sizes the user may choose between, beside the page numbers (`[10, 25, 50]`). The choice goes with the\n * control, so a list given the pager (A3) offers it too. Leave it out for the project's page size alone.\n */\n pageSizeOptions?: number[];\n}\n\n/** What identifies a list's first item across renders: its id, or the value itself; objects without an id are not compared. */\nfunction firstKey(item: unknown): unknown {\n if (item !== null && typeof item === \"object\") return \"id\" in item ? (item as { id: unknown }).id : undefined;\n return item;\n}\n\nfunction resetKey(resetOn: unknown): string {\n try { return JSON.stringify(resetOn ?? null); } catch { return String(resetOn); }\n}\n\nfunction signature(list: readonly unknown[], resetOn: unknown): string {\n let first = \"\";\n try { first = JSON.stringify(firstKey(list[0]) ?? null); } catch { first = \"\"; }\n return `${list.length}|${first}|${resetKey(resetOn)}`;\n}\n\n/** What a list was when last seen: whether a new one is the same list with items added at either end. */\ninterface Seen { sig: string; length: number; first: unknown; reset: string }\n\n/**\n * The same list with items added at its start or its end, and the caller's resetOn unchanged: a live log's new entry,\n * a feed's newest. Its first item, which has an id or is a value, is still first, or has moved down by what was added.\n */\nfunction grewAtAnEnd(seen: Seen, list: readonly unknown[], reset: string): boolean {\n if (reset !== seen.reset || list.length <= seen.length || seen.first === undefined || seen.length === 0) return false;\n return firstKey(list[0]) === seen.first || firstKey(list[list.length - seen.length]) === seen.first;\n}\n\nexport function usePagination<T>(list: readonly T[], options: PaginationOptions = {}): Pager<T> {\n const shell = useShellPreferences();\n const style: PreferencePaginationStyle = options.style ?? shell.paginationStyle ?? PREFERENCE_HOUSE_DEFAULTS.paginationStyle;\n const [chosenSize, setChosenSize] = useState<number | null>(null);\n const [pagerToken] = useState(() => ({}));\n const pageSize = Math.max(1, Math.floor(chosenSize ?? options.pageSize ?? shell.itemsPerPage ?? PREFERENCE_HOUSE_DEFAULTS.itemsPerPage));\n const [page, setPageState] = useState(1);\n\n // A different list — filtered, searched, sorted another way — starts again at page 1: its length, its first item's\n // id or the caller's resetOn values changed. The same list with items added at an end keeps its page, and a growing\n // list its depth (the review of 30 September: a live log's new entry collapsed a list grown to 200 back to 100).\n // Adjusted during render, so the stale page never paints.\n const sig = signature(list, options.resetOn);\n const reset = resetKey(options.resetOn);\n const [seen, setSeen] = useState<Seen>(() => ({ sig, length: list.length, first: firstKey(list[0]), reset }));\n const changed = seen.sig !== sig;\n const startsAgain = changed && !grewAtAnEnd(seen, list, reset);\n if (changed) {\n setSeen({ sig, length: list.length, first: firstKey(list[0]), reset });\n if (startsAgain && page !== 1) setPageState(1);\n }\n\n const totalItems = list.length;\n const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));\n const current = Math.min(Math.max(1, startsAgain ? 1 : page), totalPages);\n const grows = style !== \"pagination\";\n // page numbers show one page; a growing list shows every page loaded so far\n const start = grows ? 0 : (current - 1) * pageSize;\n const items = list.slice(start, current * pageSize);\n const range: [number, number] = items.length === 0 ? [0, 0] : [start + 1, start + items.length];\n const hasMore = current < totalPages;\n const setPage = (next: number) => setPageState(Math.min(Math.max(1, Math.floor(next)), totalPages));\n const loadMore = () => setPageState((p) => Math.min(p + 1, totalPages));\n const setPageSize = (size: number) => { setChosenSize(Math.max(1, Math.floor(size))); setPageState(1); };\n\n return {\n style, items, page: current, pageSize, totalItems, totalPages, range, shown: items.length, hasMore, loadMore, setPage, setPageSize,\n props: { currentPage: current, totalPages, onPageChange: setPage, pageSize, onPageSizeChange: setPageSize, mode: style, hasMore, onLoadMore: loadMore, pagerToken, ...(options.pageSizeOptions ? { pageSizeOptions: options.pageSizeOptions } : {}) },\n };\n}\n\n/**\n * The part of a whole list a pager shows (Sprint 25.13 A3): its page, or every page loaded so far on a list that grows.\n * A list given the pager draws this, then the pager's control.\n */\nexport function pagerPart<T>(list: readonly T[], pager?: Pager<unknown>): T[] {\n if (!pager) return list as T[];\n return pager.range[0] === 0 ? [] : list.slice(pager.range[0] - 1, pager.range[1]);\n}\n\n/** In development, a list handed one page with the pager: it needs every item, since it draws the pager's part itself. */\nexport function useWholeListCheck(component: string, length: number, pager?: Pager<unknown>): void {\n const total = pager?.totalItems;\n useEffect(() => {\n // the same items, either way: more than the pager counts leave the last ones where no page reaches them (the review\n // of 30 September)\n if (total !== undefined && length !== total) warnOnce(component, `the pager counts ${total} items but the list holds ${length}: give the list and usePagination the same items, every item of the list, and the list draws the pager's part (Sprint 25.13 A3).`);\n }, [component, length, total]);\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../showcase/src/lib/focus.ts","../../../showcase/src/lib/form-context.ts"],"names":["active","useRef","useCallback"],"mappings":"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","file":"chunk-RT7RYGC3.js","sourcesContent":["import { useCallback, useEffect, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState, type KeyboardEvent as ReactKeyboardEvent, type RefObject } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { useLatest } from \"./use-latest\";\n\n/**\n * Everything a keyboard user might land on: the candidates. Whether one is a\n * Tab stop right now is `isTabStop`'s call (a roving item with tabindex=\"-1\", a\n * hidden input or a disabled field matches this selector but is not a stop).\n */\nexport const FOCUSABLE =\n 'a[href], button:not(:disabled), input:not(:disabled), select:not(:disabled), textarea:not(:disabled), [tabindex]:not([tabindex=\"-1\"]), [contenteditable]:not([contenteditable=\"false\"])';\n\n/** A field that takes typing: keys pressed in one are its own (a grid's arrows, a time view's zoom keys leave them). */\nexport const FIELD = \"input, select, textarea, [contenteditable='true']\";\nconst SAFE_BUTTON = 'button:not([data-variant=\"destructive\"])';\n\n/** Mark an overlay's own close/dismiss button so initial focus skips it. */\nexport const OVERLAY_CLOSE_ATTR = \"data-overlay-close\";\n\n// ─── Tab stops ───────────────────────────────────────────────────────────────\n\n/** Rendered and not hidden. Real browsers answer with checkVisibility; with no layout (jsdom) the tree is walked. */\nfunction isRendered(el: HTMLElement): boolean {\n if (typeof el.checkVisibility === \"function\") return el.checkVisibility({ checkVisibilityCSS: true });\n for (let n: Element | null = el; n; n = n.parentElement) {\n if (n instanceof HTMLElement && n.hidden) return false;\n const style = getComputedStyle(n);\n if (style.display === \"none\") return false;\n if (n === el && style.visibility === \"hidden\") return false;\n }\n return true;\n}\n\n/** A native radio is a Tab stop when it is its group's checked radio, or the first when none is checked. */\nfunction isRadioStop(el: HTMLInputElement): boolean {\n if (!el.name) return true;\n const scope: ParentNode = el.form ?? el.ownerDocument;\n const group = Array.from(scope.querySelectorAll<HTMLInputElement>('input[type=\"radio\"]'))\n .filter((r) => r.name === el.name && !r.disabled && r.form === el.form);\n const checked = group.find((r) => r.checked);\n return (checked ?? group[0]) === el;\n}\n\n/**\n * Could the browser's own Tab land here? A focusable element with a\n * non-negative tabIndex, not disabled, not a hidden input, not inside an inert\n * subtree, rendered, and for a native radio the group's one stop (Sprint 25.7).\n */\nexport function isTabStop(el: Element): el is HTMLElement {\n if (!(el instanceof HTMLElement) || el.tabIndex < 0) return false;\n if ((el instanceof HTMLButtonElement || el instanceof HTMLInputElement || el instanceof HTMLSelectElement || el instanceof HTMLTextAreaElement) && el.disabled) return false;\n if (el instanceof HTMLInputElement && (el.type === \"hidden\" || (el.type === \"radio\" && !isRadioStop(el)))) return false;\n if (el.closest(\"[inert]\")) return false;\n return isRendered(el);\n}\n\n/** The Tab stops inside `root`, in document order. */\nexport function tabStops(root: ParentNode): HTMLElement[] {\n return Array.from(root.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(isTabStop);\n}\n\n/**\n * Move initial focus into an overlay the way users expect: the first visible\n * form field if there is one, otherwise the first focusable element that is\n * not the overlay's own close button.\n *\n * For destructive confirmations (`destructive: true`) the corpus rule applies\n * instead: focus the non-destructive action so Enter can't confirm by\n * accident. That is the first button not rendered with the destructive\n * variant, regardless of footer order; a lone destructive button falls back to\n * the general rule.\n *\n * React's `autoFocus` prop is not reflected as a DOM attribute, so a\n * field-first rule is the reliable general behaviour.\n */\nexport function focusInitial(root: HTMLElement | null | undefined, opts: { destructive?: boolean } = {}): boolean {\n if (!root) return false;\n const all = tabStops(root);\n if (!all.length) return false;\n const candidates = all.filter((el) => !el.hasAttribute(OVERLAY_CLOSE_ATTR));\n\n // Round 18 (the owner, 55.5; round 17 F-9): a destructive dialog that holds a field is a type-to-confirm dialog — its\n // confirm stays disabled until the text matches, so the field is the safe target. Cancel is the target only when the\n // dialog is buttons-only.\n const field = candidates.find((el) => el.matches(FIELD));\n if (opts.destructive && !field) {\n const safe = candidates.find((el) => el.matches(SAFE_BUTTON));\n if (safe) {\n safe.focus();\n return true;\n }\n }\n\n const target = candidates.find((el) => el.matches(FIELD)) ?? candidates[0] ?? all[0];\n target.focus();\n return true;\n}\n\n// ─── Remembering where focus was ─────────────────────────────────────────────\n\n/**\n * The element that had focus when `open` turned true, read before this commit's children can move it. An `autoFocus`\n * field inside a dialog takes focus while React commits (the layout phase), so an effect that reads\n * document.activeElement afterwards sees that field, not the opener (run 57's type-to-confirm dialog, Sprint 25.7).\n * Insertion effects run earlier in the commit, before any of that.\n */\nexport function useFocusBeforeOpen(open: boolean): RefObject<Element | null> {\n const before = useRef<Element | null>(null);\n useInsertionEffect(() => {\n if (open) before.current = document.activeElement;\n }, [open]);\n return before;\n}\n\n/** What counts as \"the row\" an opener sits in, for a row that is deleted while its menu or dialog is open. */\nconst ROW = 'tr, li, [role=\"row\"], [data-card], [data-row]';\n\n/**\n * The index of the one row a deletion took out, when the rows now read as the old rows with that one removed: every\n * row after it moved up by one. A list keyed by position (the library Table, `key={i}`) keeps a deleted row's\n * elements for the next item, and a paged list keeps its length by bringing a new item into its last row. Else -1:\n * an edit (even one that makes a row read like another) or a re-sort.\n */\nfunction deletedRow(before: readonly string[], now: readonly string[]): number {\n const refilled = now.length === before.length;\n if (!refilled && now.length !== before.length - 1) return -1;\n let k = 0;\n while (k < now.length && now[k] === before[k]) k++;\n const last = now.length - 1;\n // a refilled last row shows an item the list did not show\n if (refilled && (k >= last || before.includes(now[last]))) return -1;\n for (let j = k; j < (refilled ? last : now.length); j++) if (now[j] !== before[j + 1]) return -1;\n return k;\n}\n\nexport interface RememberFocusOptions {\n /** The element's page outlives a change of path (a list beside a pane whose selection is in the URL): give focus back even then. */\n ignoreRoute?: boolean;\n}\n\nexport interface RememberedFocus {\n readonly el: HTMLElement;\n /**\n * Put focus back (Sprint 25.7). Nothing happens once the page has changed — a new path, or a new URL that took the\n * element with it — since the new page owns focus (D14(d)); a new query or hash alone (a filter, a page number) is\n * no page change. Otherwise the element itself; if its row was deleted, the same control in the row before, else\n * the row after, else the first Tab stop of the list (D14(c), MOJ \"Add another\" order); else `fallback`. True when\n * focus landed.\n *\n * Rows carrying `data-row-key` are told apart by it. Without one, a list keyed by position (the library Table,\n * `key={i}`) keeps a deleted row's elements for the next item, so the rows' text decides: focus follows this item\n * to the one row that now shows it, and when the rows read as the old ones with one taken out, this row's item was\n * deleted or moved up. An edit keeps focus, even one that makes the row read like another.\n *\n * When focus lands back on the element in a row, the list is watched for 10 s: a row deleted a moment later (a\n * server round trip) that takes focus with it sends focus to its neighbour the same way.\n */\n restore(fallback?: HTMLElement | null): boolean;\n}\n\nexport function rememberFocus(el: HTMLElement, { ignoreRoute = false }: RememberFocusOptions = {}): RememberedFocus {\n const { href, pathname } = location;\n const row = el.closest<HTMLElement>(ROW);\n const before = row?.previousElementSibling ?? null;\n const after = row?.nextElementSibling ?? null;\n const list = row?.parentElement ?? null;\n const index = row ? tabStops(row).indexOf(el) : -1;\n const rows = list ? Array.from(list.children) : [];\n const at = row ? rows.indexOf(row) : -1;\n const texts = rows.map((r) => r.textContent ?? \"\");\n const keyOf = (r: Element | null) => r?.getAttribute(\"data-row-key\") ?? null;\n const key = keyOf(row);\n const pageChanged = () => !ignoreRoute && (location.pathname !== pathname || (location.href !== href && !el.isConnected));\n const land = (target: HTMLElement | null | undefined) => {\n if (!target || !target.isConnected) return false;\n target.focus();\n return document.activeElement === target;\n };\n const inRow = (r: Element | null | undefined) => {\n if (!r || !r.isConnected) return false;\n const stops = tabStops(r);\n return land(stops[Math.max(0, Math.min(index, stops.length - 1))]);\n };\n const byKey = (k: string | null) => (k !== null && list?.isConnected ? list.querySelector(`:scope > [data-row-key=\"${CSS.escape(k)}\"]`) : null);\n /** The row this item is in now, when the list moved under it; undefined when it did not. */\n const moved = (): Element | undefined => {\n if (!list?.isConnected || at < 0) return undefined;\n if (key !== null) {\n const same = byKey(key);\n return same === row ? undefined : same ?? byKey(keyOf(before)) ?? byKey(keyOf(after)) ?? undefined;\n }\n const now = Array.from(list.children, (r) => r.textContent ?? \"\");\n const text = texts[at];\n if (texts.indexOf(text) === texts.lastIndexOf(text)) {\n const found = now.flatMap((t, i) => (t === text ? [i] : []));\n if (found.length === 1) return list.children[found[0]] === row ? undefined : list.children[found[0]];\n }\n const k = deletedRow(texts, now);\n return k >= 0 && k <= at ? list.children[Math.max(0, at - 1)] ?? undefined : undefined;\n };\n const neighbour = () => inRow(byKey(keyOf(before)) ?? before) || inRow(byKey(keyOf(after)) ?? after) || (!!list?.isConnected && land(tabStops(list)[0]));\n let unwatch: (() => void) | null = null;\n const watch = () => {\n unwatch?.();\n if (!list || typeof MutationObserver === \"undefined\") return;\n const observer = new MutationObserver(() => {\n if (el.isConnected) return;\n const active = document.activeElement;\n const dropped = !active || active === document.body || !active.isConnected;\n stop();\n if (dropped && !pageChanged()) neighbour();\n });\n const onFocusIn = (e: FocusEvent) => { if (e.target !== el) stop(); };\n const timer = setTimeout(() => stop(), 10_000);\n function stop() {\n observer.disconnect();\n clearTimeout(timer);\n document.removeEventListener(\"focusin\", onFocusIn, true);\n unwatch = null;\n }\n observer.observe(list, { childList: true });\n if (list.parentNode) observer.observe(list.parentNode, { childList: true });\n document.addEventListener(\"focusin\", onFocusIn, true);\n unwatch = stop;\n };\n return {\n el,\n restore(fallback) {\n if (pageChanged()) return false;\n if (inRow(moved())) return true;\n if (land(el)) {\n if (row) watch();\n return true;\n }\n if (row && !row.isConnected && neighbour()) return true;\n return land(fallback);\n },\n };\n}\n\n/**\n * Remember what had focus when a modal overlay opened and give it back on\n * close (corpus: \"After an overlay closes, return focus to the element that\n * triggered it\"). With `root`, focus is given back only when it was lost or is\n * still inside the closing overlay, so a focus move the consumer made on close\n * wins. Returns `returnFocus()` for a command that must hand focus back before\n * it runs (CommandPalette: a command that opens a Dialog).\n */\nexport function useReturnFocus(open: boolean, root?: RefObject<HTMLElement | null>) {\n const remembered = useRef<RememberedFocus | null>(null);\n const before = useFocusBeforeOpen(open);\n useEffect(() => {\n if (open) {\n const active = before.current;\n remembered.current = active instanceof HTMLElement && active !== document.body && active.isConnected ? rememberFocus(active) : null;\n return;\n }\n const r = remembered.current;\n remembered.current = null;\n if (!r) return;\n const active = document.activeElement;\n const lost = !active || active === document.body || !active.isConnected;\n if (!root || lost || (active instanceof Node && !!root.current?.contains(active))) r.restore();\n }, [open, root, before]);\n return useCallback(() => { remembered.current?.restore(); }, []);\n}\n\n/**\n * Index of the single Tab stop in a radio-style group (APG radio pattern):\n * the checked item, else the first enabled item so a group with no selection\n * is still reachable. −1 when every item is disabled.\n */\nexport function rovingTabStop<T>(items: T[], isChecked: (item: T) => boolean, isDisabled: (item: T) => boolean = () => false): number {\n const checked = items.findIndex((item) => isChecked(item) && !isDisabled(item));\n return checked >= 0 ? checked : items.findIndex((item) => !isDisabled(item));\n}\n\n/**\n * Rule 4 (D14(c), MOJ \"Add another\" order): after the item at `index` was\n * removed, focus the item before it, else the one now in its place, else\n * `fallback`. `items` is the list as it is after the removal.\n */\nexport function focusAfterRemoval(items: ArrayLike<HTMLElement>, index: number, fallback?: HTMLElement | null) {\n (items[index - 1] ?? items[index] ?? fallback)?.focus();\n}\n\n// ─── Overlay layers ──────────────────────────────────────────────────────────\n// Every overlay that closes on Escape listens on `document`, so a Dropdown open\n// inside a Drawer used to close both with one key press. Open overlays register\n// here in the order they opened; only the topmost one acts on a global key.\n// (Two overlays opening in the same commit register child-first; in practice\n// overlays open one user action at a time.)\n\nconst layers: symbol[] = [];\n\n/**\n * Register this overlay as a layer while `open`. Returns a stable predicate\n * that is true when this overlay is the topmost open one — check it before\n * acting on Escape or trapping Tab.\n */\nexport function useOverlayLayer(open: boolean): () => boolean {\n const [id] = useState(() => Symbol(\"overlay-layer\"));\n useEffect(() => {\n if (!open) return;\n layers.push(id);\n return () => {\n const i = layers.indexOf(id);\n if (i >= 0) layers.splice(i, 1);\n };\n }, [open, id]);\n return useCallback(() => layers[layers.length - 1] === id, [id]);\n}\n\n/** Number of registered overlay layers (test seam). */\nexport function getOverlayLayerCount(): number {\n return layers.length;\n}\n\n// ─── Close on focus-out ──────────────────────────────────────────────────────\n\n/**\n * Close a non-modal popover (menu, picker, panel) when keyboard focus leaves\n * both its trigger and its panel — Tab and Shift+Tab out, or focus leaving the\n * document. Nested overlays (a Dropdown inside a Popover) register a layer on\n * top, so focus moving into them does not count as leaving. A pointer-down on\n * a non-focusable spot inside the panel briefly sends focus to body; that is\n * ignored so clicking panel chrome never closes it.\n */\nexport function useCloseOnFocusOut(\n open: boolean,\n triggerRef: RefObject<HTMLElement | null>,\n panelRef: RefObject<HTMLElement | null>,\n onClose: () => void,\n isTop: () => boolean = ALWAYS_TOP,\n) {\n // Latest-value ref written in a layout effect, not during render (React Compiler `refs` rule).\n const onCloseRef = useLatest(onClose);\n useEffect(() => {\n if (!open) return;\n let pointerInside = false;\n const inside = (n: EventTarget | Node | null) =>\n n instanceof Node && (!!triggerRef.current?.contains(n) || !!panelRef.current?.contains(n));\n const onPointerDown = (e: PointerEvent) => { pointerInside = inside(e.target); };\n const onFocusOut = (e: FocusEvent) => {\n if (!inside(e.target)) return;\n if (e.relatedTarget) {\n if (!inside(e.relatedTarget) && isTop()) onCloseRef.current();\n return;\n }\n setTimeout(() => {\n if (pointerInside) { pointerInside = false; return; }\n if (!inside(document.activeElement) && isTop()) onCloseRef.current();\n }, 0);\n };\n document.addEventListener(\"pointerdown\", onPointerDown, true);\n document.addEventListener(\"focusout\", onFocusOut, true);\n return () => {\n document.removeEventListener(\"pointerdown\", onPointerDown, true);\n document.removeEventListener(\"focusout\", onFocusOut, true);\n };\n }, [open, triggerRef, panelRef, isTop, onCloseRef]);\n}\n\n// ─── Close on a press outside ───────────────────────────────────────────────\n\n/**\n * Marks the presses that pass through a component's React tree, so a document\n * listener can tell a press inside it from one outside (Sprint 25.7; Radix's\n * dismissable layer). A popup that content inside it renders elsewhere in the\n * page — a Dropdown's list, a DatePicker's calendar, a Dialog — is outside its\n * element tree, but React carries the press through its own tree first. Spread\n * `props` on the tree's outer element; `marked(e)` is true for a pointer or\n * mouse press that went through it.\n */\nexport function usePressMarks() {\n const [marks] = useState(() => new WeakSet<Event>());\n return useMemo(() => {\n const mark = (e: { nativeEvent: Event }) => { marks.add(e.nativeEvent); };\n return { props: { onPointerDownCapture: mark, onMouseDownCapture: mark }, marked: (e: Event) => marks.has(e) };\n }, [marks]);\n}\n\n/**\n * Call `onOutside` for a pointer press outside `ref`'s element and its React\n * tree (Sprint 25.7): spread the returned handler on the element. For a\n * container that is not an overlay layer (the builder's floating toolbar).\n */\nexport function usePressOutside(enabled: boolean, ref: RefObject<HTMLElement | null>, onOutside: (e: PointerEvent) => void) {\n const onOutsideRef = useLatest(onOutside);\n const { props, marked } = usePressMarks();\n useEffect(() => {\n if (!enabled) return;\n const onPointerDown = (e: PointerEvent) => {\n if (marked(e) || (e.target instanceof Node && ref.current?.contains(e.target))) return;\n onOutsideRef.current(e);\n };\n document.addEventListener(\"pointerdown\", onPointerDown);\n return () => document.removeEventListener(\"pointerdown\", onPointerDown);\n }, [enabled, ref, onOutsideRef, marked]);\n return { onPointerDownCapture: props.onPointerDownCapture };\n}\n\n// ─── Popup focus (Sprint 25.7) ───────────────────────────────────────────────\n// Every non-modal popup — a list, a menu, a picker, a panel — renders in a portal\n// at the end of <body>. Without help, a choice removes the focused option and\n// focus falls to the page, and Tab out of the panel moves on from the end of the\n// document. usePopupFocus hands focus back and makes Tab carry on from the\n// control that opened the popup, in the browser's own order.\n\nexport type PopupTabExits = \"any\" | \"edges\" | \"none\";\n\ninterface OpenPopup {\n panel: RefObject<HTMLElement | null>;\n tabExits: PopupTabExits;\n leave: (e: KeyboardEvent) => void;\n}\n\n/** Open popups, so a popup inside another popup's panel can hand a Tab exit on to it. */\nconst openPopups = new Map<symbol, OpenPopup>();\n\nexport interface PopupFocusOptions {\n trigger: RefObject<HTMLElement | null>;\n panel: RefObject<HTMLElement | null>;\n /** Closes the popup (sets its open state false). */\n close: () => void;\n /**\n * How Tab leaves the panel. \"any\": every Tab leaves (single-stop lists and\n * menus). \"edges\": Tab leaves from the panel's last Tab stop and Shift+Tab\n * from its first (panels with several stops). \"none\": focus never enters the\n * panel (a combobox keeps it in its input), so the browser's Tab is left alone.\n */\n tabExits: PopupTabExits;\n /** Runs first when Tab leaves, before the popup closes — a list commits the option the user moved to (D14(a)). */\n onTabOut?: (e: KeyboardEvent) => void;\n /**\n * True for a press that went through the popup's React tree (`usePressMarks`), so a press in a list its content\n * opened elsewhere in the page is not a press outside it.\n */\n marked?: (e: Event) => boolean;\n}\n\n/**\n * Focus for a non-modal popup (Sprint 25.7, P10):\n * - records the opener when the popup opens (the trigger when focus was on the page);\n * - closes on focus-out, and registers the overlay layer (`isTop`);\n * - Tab out of the panel closes it and carries on from the opener: Shift+Tab lands\n * on the opener; Tab puts focus on the opener and lets the browser's own Tab run,\n * except that inside a modal the opener's being its last stop wraps to its first,\n * and inside another popup's panel that popup's own exit rule then applies;\n * - on close, when focus was lost (the focused option went with the panel), puts it\n * back — unless the close followed a press outside the popup and its React tree\n * (`marked`), or the page changed;\n * - returns `returnFocus()`, which a select handler calls before the consumer's\n * callback so a dialog that callback opens records the opener, and any focus\n * move the consumer makes wins.\n */\nexport function usePopupFocus(open: boolean, { trigger, panel, close, tabExits, onTabOut, marked }: PopupFocusOptions) {\n const isTop = useOverlayLayer(open);\n const [id] = useState(() => Symbol(\"popup\"));\n const closeRef = useLatest(close);\n const onTabOutRef = useLatest(onTabOut);\n const markedRef = useLatest(marked);\n const remembered = useRef<RememberedFocus | null>(null);\n // The last press while open, and whether it was in the trigger or panel; a key press since clears it.\n const lastPress = useRef<{ e: Event; inside: boolean } | null>(null);\n const wasOpen = useRef(false);\n\n useCloseOnFocusOut(open, trigger, panel, close, isTop);\n\n // The opener, as it was before this commit (content with autoFocus moves focus in during it).\n const before = useFocusBeforeOpen(open);\n useLayoutEffect(() => {\n if (!open) return;\n const active = before.current;\n const inPanel = active instanceof Node && !!panel.current?.contains(active);\n const opener = active instanceof HTMLElement && active !== document.body && !inPanel ? active : trigger.current;\n remembered.current = opener ? rememberFocus(opener) : null;\n lastPress.current = null;\n }, [open, trigger, panel, before]);\n\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: PointerEvent) => {\n const t = e.target;\n lastPress.current = { e, inside: t instanceof Node && (!!trigger.current?.contains(t) || !!panel.current?.contains(t)) };\n };\n const onKeyPress = () => { lastPress.current = null; };\n const leave = (e: KeyboardEvent) => {\n onTabOutRef.current?.(e);\n const r = remembered.current;\n const opener = r && r.el.isConnected ? r.el : trigger.current;\n // Focus the opener, then close now, so the panel is gone before the browser moves focus on.\n opener?.focus();\n flushSync(() => closeRef.current());\n if (!opener || !opener.isConnected) return;\n if (e.shiftKey) {\n e.preventDefault();\n return;\n }\n const modal = opener.closest<HTMLElement>('[aria-modal=\"true\"]');\n if (modal) {\n const stops = tabStops(modal);\n if (stops.length && stops[stops.length - 1] === opener) {\n e.preventDefault();\n stops[0].focus();\n return;\n }\n }\n for (const [otherId, other] of openPopups) {\n const outer = other.panel.current;\n if (otherId === id || !outer?.contains(opener)) continue;\n const stops = tabStops(outer);\n if (other.tabExits === \"any\" || stops[stops.length - 1] === opener) {\n other.leave(e);\n return;\n }\n break;\n }\n // The browser's own Tab carries on from the opener.\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Tab\" || e.defaultPrevented || tabExits === \"none\" || !isTop()) return;\n const p = panel.current;\n const active = document.activeElement;\n if (!p || !(active instanceof Node) || !p.contains(active)) return;\n if (tabExits === \"edges\") {\n const stops = tabStops(p);\n if (stops.length && active !== (e.shiftKey ? stops[0] : stops[stops.length - 1])) return;\n }\n leave(e);\n };\n openPopups.set(id, { panel, tabExits, leave });\n document.addEventListener(\"pointerdown\", onPointerDown, true);\n document.addEventListener(\"keydown\", onKeyPress, true);\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n openPopups.delete(id);\n document.removeEventListener(\"pointerdown\", onPointerDown, true);\n document.removeEventListener(\"keydown\", onKeyPress, true);\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [open, tabExits, isTop, id, trigger, panel, closeRef, onTabOutRef]);\n\n // The safety net: a close the component could not see (content that closes it,\n // a choice that removed the focused option) puts focus back when it was lost.\n useLayoutEffect(() => {\n if (open) {\n wasOpen.current = true;\n return;\n }\n if (!wasOpen.current) return;\n wasOpen.current = false;\n const r = remembered.current;\n remembered.current = null;\n // A close that followed a press outside the popup (and outside its React tree) leaves focus to that press.\n const press = lastPress.current;\n if (!r || (press && !press.inside && !markedRef.current?.(press.e))) return;\n // Focus that is somewhere real stays there: the user or the consumer put it there. Focus on the opener is\n // checked again, because the choice may have deleted the opener's row in this commit (see rememberFocus).\n const active = document.activeElement;\n if (active !== r.el && active && active !== document.body && active.isConnected) return;\n r.restore(trigger.current);\n }, [open, trigger, markedRef]);\n\n // Removed while open with focus in it (a row menu whose Delete removed its own row): give focus back once the DOM\n // has settled. The panel is still in the page while this runs. A popup focus never went into (a flyout opened by\n // hover) leaves focus where it is.\n useLayoutEffect(() => () => {\n if (!wasOpen.current) return;\n const active = document.activeElement;\n if (!(active instanceof Node) || !(panel.current?.contains(active) || trigger.current?.contains(active))) return;\n const r = remembered.current;\n queueMicrotask(() => {\n const now = document.activeElement;\n if (now && now !== document.body && now.isConnected) return;\n r?.restore();\n });\n }, [panel, trigger]);\n\n const returnFocus = useCallback(() => {\n remembered.current?.restore(trigger.current);\n }, [trigger]);\n\n return { isTop, returnFocus };\n}\n\n// ─── Grid keyboard (Sprint 25.7, P11) ────────────────────────────────────────\n\nexport interface GridKeyboardOptions<K> {\n /** Holds the items, which carry `data-grid-key={keyOf(item)}`. */\n container: RefObject<HTMLElement | null>;\n /** The item that is the Tab stop. Keep it in step with focus (setActive from the item's onFocus). */\n active: K;\n setActive: (item: K) => void;\n keyOf: (item: K) => string;\n /** Where a key moves focus from `from` (arrows, Home, End: the caller's geometry), or null for a key it leaves alone. */\n move: (from: K, e: ReactKeyboardEvent) => K | null;\n /** Enter and Space on an item. */\n onActivate?: (item: K, e: ReactKeyboardEvent) => void;\n /**\n * Printable keys go to the next item whose label starts with what was typed in the last 500 ms (the same letter\n * again cycles). Never the zoom keys (+, = and −), never with Ctrl, ⌘ or Alt.\n */\n typeahead?: { items: readonly K[]; labelOf: (item: K) => string };\n /** Runs after focus moves to an item, in place of the browser's own scrolling (a time view keeps the item clear of its pinned column). */\n scrollIntoView?: (key: string, el: HTMLElement) => void;\n /**\n * Keys held with Ctrl, ⌘ or Alt go to `move` too: an APG grid's Ctrl+Home and Ctrl+End. Typeahead and activation\n * still ignore them. Off by default, so the browser keeps its own (Alt+Left is Back).\n */\n modifierKeys?: boolean;\n}\n\nexport interface GridKeyboard<K> {\n /** On the container. */\n onKeyDown: (e: ReactKeyboardEvent) => void;\n tabIndexOf: (item: K) => 0 | -1;\n /** Focus the active item (after the next render when it is not in the DOM yet). */\n focusActive: () => void;\n /** Focus an item, as a key would (after the next render when it is not in the DOM yet); keep `active` in step. */\n focus: (item: K) => void;\n}\n\nconst TYPEAHEAD_MS = 500;\n/** The keys a time view zooms with (TimeViewport), in and out; typeahead leaves them to it. U+2212 is the minus sign. */\nexport const ZOOM_KEYS: { readonly in: readonly string[]; readonly out: readonly string[] } = { in: [\"+\", \"=\"], out: [\"-\", \"\\u2212\"] };\nconst isZoomKey = (key: string) => ZOOM_KEYS.in.includes(key) || ZOOM_KEYS.out.includes(key);\n\nfunction focusGridKey(root: HTMLElement | null, key: string, scrollIntoView?: (key: string, el: HTMLElement) => void): boolean {\n const el = root?.querySelector<HTMLElement>(`[data-grid-key=\"${CSS.escape(key)}\"]`);\n if (!el) return false;\n el.focus(scrollIntoView ? { preventScroll: true } : undefined);\n scrollIntoView?.(key, el);\n return true;\n}\n\n/** The next item whose label starts with `text`: a new search (one letter, or one letter repeated) starts after `from`. */\nfunction typeaheadMatch<K>(items: readonly K[], labelOf: (item: K) => string, keyOf: (item: K) => string, fromKey: string, text: string): K | null {\n const chars = [...text];\n const query = chars.every((c) => c === chars[0]) ? chars[0] : text;\n const at = items.findIndex((item) => keyOf(item) === fromKey);\n const first = at < 0 ? 0 : at + (query.length === 1 ? 1 : 0);\n for (let k = 0; k < items.length; k++) {\n const item = items[(first + k) % items.length];\n if (labelOf(item).trim().toLocaleLowerCase().startsWith(query)) return item;\n }\n return null;\n}\n\n/**\n * One Tab stop over a grid or rows of items (APG grid and tree patterns): the caller says where each key moves\n * (`move`), and the hook keeps the roving tabindex and puts focus on the new item — after the next render when the\n * item is not in the DOM yet (a date grid moving into the next month). Enter and Space activate, typeahead jumps by\n * label, and `scrollIntoView` places the item. It works by key, not DOM position, so a virtualised list can use it.\n * Keys typed in a field inside the container are left alone. Built for the date pickers, extended in Part D for\n * time-axis rows (it is Sprint 2X.3's `useGridNavigation`).\n */\nexport function useGridKeyboard<K>({ container, active, setActive, keyOf, move, onActivate, typeahead, scrollIntoView, modifierKeys = false }: GridKeyboardOptions<K>): GridKeyboard<K> {\n const pending = useRef<string | null>(null);\n const typed = useRef({ text: \"\", at: 0 });\n // One try, on the render the move caused: a key that never renders is dropped, so a later render cannot steal focus.\n useLayoutEffect(() => {\n const key = pending.current;\n if (key === null) return;\n pending.current = null;\n focusGridKey(container.current, key, scrollIntoView);\n });\n const activeKey = keyOf(active);\n const go = (next: K) => {\n const key = keyOf(next);\n setActive(next);\n if (!focusGridKey(container.current, key, scrollIntoView)) pending.current = key;\n };\n const onKeyDown = (e: ReactKeyboardEvent) => {\n const modified = e.altKey || e.ctrlKey || e.metaKey;\n if (e.defaultPrevented || (modified && !modifierKeys)) return;\n // React passes on keys from a portal opened inside an item (a dialog, a menu): they are that popup's own\n if (!(e.currentTarget as Node).contains(e.target as Node)) return;\n const target = e.target instanceof HTMLElement ? e.target : null;\n if (target?.closest(FIELD)) return;\n const next = move(active, e);\n if (next !== null) {\n e.preventDefault();\n go(next);\n return;\n }\n // Activation and typeahead act on the item itself, not a control inside it, and never with a modifier held.\n if (modified || target?.getAttribute(\"data-grid-key\") !== activeKey) return;\n const buffered = typed.current.text !== \"\" && Date.now() - typed.current.at <= TYPEAHEAD_MS;\n if (onActivate && (e.key === \"Enter\" || (e.key === \" \" && !buffered))) {\n e.preventDefault();\n onActivate(active, e);\n return;\n }\n if (!typeahead || [...e.key].length !== 1 || isZoomKey(e.key) || (e.key === \" \" && !buffered)) return;\n const text = (buffered ? typed.current.text : \"\") + e.key.toLocaleLowerCase();\n typed.current = { text, at: Date.now() };\n const match = typeaheadMatch(typeahead.items, typeahead.labelOf, keyOf, activeKey, text);\n if (match === null) return;\n e.preventDefault();\n if (keyOf(match) !== activeKey) go(match);\n };\n const focus = (item: K) => {\n const key = keyOf(item);\n if (!focusGridKey(container.current, key, scrollIntoView)) pending.current = key;\n };\n const focusActive = () => focus(active);\n const tabIndexOf = (item: K): 0 | -1 => (keyOf(item) === activeKey ? 0 : -1);\n return { onKeyDown, tabIndexOf, focusActive, focus };\n}\n\n// ─── Focus trap ──────────────────────────────────────────────────────────────\n\nconst ALWAYS_TOP = () => true;\n\n/**\n * Keep Tab and Shift+Tab inside `root` while `active` (corpus: a modal\n * overlay owns keyboard focus until it closes). Focus that has escaped the\n * root — a portalled menu that just closed, or the body — is pulled back in on\n * the next Tab. Pass the predicate from `useOverlayLayer` so a nested overlay\n * on top of this one keeps its own keyboard handling.\n */\nexport function useFocusTrap(root: RefObject<HTMLElement | null>, active: boolean, isTop: () => boolean = ALWAYS_TOP) {\n useEffect(() => {\n if (!active) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Tab\" || e.defaultPrevented || !root.current || !isTop()) return;\n const focusable = tabStops(root.current);\n if (focusable.length === 0) {\n e.preventDefault();\n return;\n }\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const current = document.activeElement;\n const inside = current instanceof Node && root.current.contains(current);\n if (e.shiftKey) {\n if (!inside || current === first) {\n e.preventDefault();\n last.focus();\n }\n } else if (!inside || current === last) {\n e.preventDefault();\n first.focus();\n }\n };\n document.addEventListener(\"keydown\", onKeyDown);\n return () => document.removeEventListener(\"keydown\", onKeyDown);\n }, [root, active, isTop]);\n}\n\n// ─── Non-modal dialog ────────────────────────────────────────────────────────\n\n/**\n * The lifecycle of a persistent, non-modal dialog — an assistant panel the\n * user works alongside (Drawer with modal={false}, CornerPanel). Unlike a\n * popover it does not close when focus leaves; unlike a modal it never traps.\n *\n * While `active`: remembers the opener and gives focus back on close when focus\n * was lost or inside the panel, never from where the user moved it; moves focus\n * into the panel on open (first field, else first non-close control); closes on\n * Escape only while focus is inside the panel, it is the topmost layer and\n * nothing inside handled the key, so Escape elsewhere is untouched. Outside\n * clicks do nothing. Tab out of the panel is allowed — the panel is portalled to the end\n * of the document, so the last Tab reaches the browser chrome; a Launcher\n * shortcut is the way back in.\n */\nexport function useNonModalDialog(\n root: RefObject<HTMLElement | null>,\n active: boolean,\n onClose: () => void,\n isTop: () => boolean = ALWAYS_TOP,\n) {\n const onCloseRef = useLatest(onClose);\n useReturnFocus(active, root);\n useEffect(() => {\n if (!active) return;\n const raf = requestAnimationFrame(() => focusInitial(root.current));\n return () => cancelAnimationFrame(raf);\n }, [active, root]);\n useEffect(() => {\n if (!active) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\" || e.defaultPrevented || !isTop()) return;\n const el = root.current;\n if (!el || !el.contains(document.activeElement)) return;\n e.preventDefault();\n onCloseRef.current();\n };\n document.addEventListener(\"keydown\", onKeyDown);\n return () => document.removeEventListener(\"keydown\", onKeyDown);\n }, [active, root, isTop, onCloseRef]);\n}\n","import { createContext, useCallback, useContext, useRef } from \"react\";\n\n/** When a form's fields check themselves: the project's forms.validationTiming, through FormWrapper. */\nexport type ValidationMode = \"onBlur\" | \"onSubmit\" | \"onChange\";\n\nexport interface FormErrors {\n [field: string]: string | undefined;\n}\n\n/** A field's check: the message for what is wrong with its value now, or nothing. */\nexport type FieldCheck = () => string | undefined;\n\nexport interface FormContextValue {\n errors: FormErrors;\n setError: (field: string, message: string | undefined) => void;\n clearErrors: () => void;\n validationMode: ValidationMode;\n submitted: boolean;\n /**\n * A Field given `validate` registers its check under its id, and the form runs every check on each submit (round 26,\n * R26-2: the forms of both runs checked their fields only on submit, although the project said on blur). Returns\n * the unregister.\n */\n register: (field: string, check: FieldCheck) => () => void;\n}\n\nexport const FormCtx = createContext<FormContextValue | null>(null);\n\nexport function useFormContext(): FormContextValue {\n const ctx = useContext(FormCtx);\n if (!ctx) throw new Error(\"useFormContext must be used within FormWrapper\");\n return ctx;\n}\n\n/** The FormWrapper a component sits in, or null. */\nexport function useOptionalFormContext(): FormContextValue | null {\n return useContext(FormCtx);\n}\n\n/**\n * Sprint 25.12 A15 (R28-25): the nearest FormWrapper's change reporter. A control calls it when the user gives it a new\n * value; the form passes it on to the overlay that holds it, so the overlay asks before discarding only after a change.\n * Null outside a FormWrapper: controls there never mark anything (a page that saves as you go has nothing to discard).\n */\nexport const FormChangeCtx = createContext<(() => void) | null>(null);\n\n/** Whether two control values are the same value: dates by time, arrays and plain objects by their parts. */\nexport function sameValue(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();\n if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((x, i) => sameValue(x, b[i]));\n if (a && b && typeof a === \"object\" && typeof b === \"object\" && Object.getPrototypeOf(a) === Object.prototype && Object.getPrototypeOf(b) === Object.prototype) {\n const ka = Object.keys(a as Record<string, unknown>);\n const kb = Object.keys(b as Record<string, unknown>);\n return ka.length === kb.length && ka.every((k) => sameValue((a as Record<string, unknown>)[k], (b as Record<string, unknown>)[k]));\n }\n // an empty text field and an unset value are the same answer: a control that commits \"\" over undefined changed nothing\n if ((a === \"\" && (b === undefined || b === null)) || (b === \"\" && (a === undefined || a === null))) return true;\n return false;\n}\n\n/**\n * Sprint 25.12 A15: a control's `onChange`, wrapped so a new value the user gives it reports a change to the nearest\n * FormWrapper before the page hears of it. `current` is the control's value now (its prop, or its own state when it\n * keeps one); `read` takes the new value from onChange's arguments (the first argument by default; an event's\n * `target.value` for native inputs). Only a different value reports: NumberInput committing the same number on blur,\n * or a search inside a Dropdown, changes nothing. Call it only from the user's own actions, never from an effect, so a\n * value the page sets, or one a control settles on by itself, never counts.\n */\nexport function useReportedChange<A extends unknown[]>(\n onChange: ((...args: A) => void) | undefined,\n current: unknown,\n read: (...args: A) => unknown = (...args: A) => args[0],\n): (...args: A) => void {\n const report = useContext(FormChangeCtx);\n const currentRef = useRef(current);\n currentRef.current = current;\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n const readRef = useRef(read);\n readRef.current = read;\n return useCallback((...args: A) => {\n if (report && !sameValue(currentRef.current, readRef.current(...args))) report();\n onChangeRef.current?.(...args);\n }, [report]);\n}\n"]}
|