gridsmith-ui 0.20.0 → 0.22.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/chat.js +3 -3
- package/dist/chunk-2RV23OBK.js +1349 -0
- package/dist/chunk-2RV23OBK.js.map +1 -0
- package/dist/chunk-7TOJ4G7S.js +197 -0
- package/dist/chunk-7TOJ4G7S.js.map +1 -0
- package/dist/{chunk-6MXHGH3D.js → chunk-AAYCQXZQ.js} +90 -161
- package/dist/chunk-AAYCQXZQ.js.map +1 -0
- package/dist/{chunk-ILIODA7W.js → chunk-CXMV7SXJ.js} +4 -3
- package/dist/chunk-CXMV7SXJ.js.map +1 -0
- package/dist/{chunk-EQDR57AM.js → chunk-EYMGLK4M.js} +3 -3
- package/dist/{chunk-EQDR57AM.js.map → chunk-EYMGLK4M.js.map} +1 -1
- package/dist/chunk-IVCVNAXG.js +115 -0
- package/dist/chunk-IVCVNAXG.js.map +1 -0
- package/dist/chunk-RG4KUCRS.js +9 -0
- package/dist/chunk-RG4KUCRS.js.map +1 -0
- package/dist/{chunk-JXANCXK6.js → chunk-RT7RYGC3.js} +39 -4
- package/dist/chunk-RT7RYGC3.js.map +1 -0
- package/dist/{chunk-XYDIBW3J.js → chunk-SBTBMAIU.js} +4 -3
- package/dist/chunk-SBTBMAIU.js.map +1 -0
- package/dist/data-grid.d.ts +38 -4
- package/dist/data-grid.js +304 -264
- package/dist/data-grid.js.map +1 -1
- package/dist/editor.d.ts +6 -5
- package/dist/editor.js +47 -11
- package/dist/editor.js.map +1 -1
- package/dist/index.d.ts +120 -153
- package/dist/index.js +1156 -1814
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +2 -2
- package/dist/resizable.js +9 -8
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +10 -0
- package/dist/{table-utils-GounRE6s.d.ts → table-utils-BkjNEWts.d.ts} +5 -1
- package/dist/use-pagination-DiJo0aW5.d.ts +153 -0
- package/dist/virtualized.d.ts +11 -1
- package/dist/virtualized.js +67 -18
- package/dist/virtualized.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6MXHGH3D.js.map +0 -1
- package/dist/chunk-ILIODA7W.js.map +0 -1
- package/dist/chunk-JN37OVTP.js +0 -67
- package/dist/chunk-JN37OVTP.js.map +0 -1
- package/dist/chunk-JXANCXK6.js.map +0 -1
- package/dist/chunk-TKVTZWBN.js +0 -50
- package/dist/chunk-TKVTZWBN.js.map +0 -1
- package/dist/chunk-XVB55M3N.js +0 -42
- package/dist/chunk-XVB55M3N.js.map +0 -1
- package/dist/chunk-XYDIBW3J.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../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","useContext","useCallback","useEffect","useRef","useId","useState","createPortal"],"mappings":"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","file":"chunk-2RV23OBK.js","sourcesContent":["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\";\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 // 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 w-full\",\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 w-full\",\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 checked ? \"bg-[var(--ds-accent-primary)]\" : \"bg-[var(--ds-bg-muted)]\",\n error ? \"border-[var(--ds-status-error)]\" : (checked ? \"border-transparent\" : \"border-[var(--ds-border-default)]\")\n )}\n style={{ width: dims.w, height: dims.h }}\n >\n <span\n className={cn(\n \"pointer-events-none inline-block shrink-0\",\n \"bg-[var(--ds-bg-surface)]\",\n \"border-[length:var(--ds-border-width)] border-transparent\",\n \"rounded-[var(--ds-radius-full)]\",\n \"transition-transform\"\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"]}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { TooltipCtx, Tooltip } from './chunk-CXMV7SXJ.js';
|
|
2
|
+
import { cn } from './chunk-M2QRNBDQ.js';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
import { createContext, forwardRef, useContext, isValidElement, useMemo } from 'react';
|
|
5
|
+
|
|
6
|
+
var sizes = {
|
|
7
|
+
sm: "h-4 w-4 border-[1.5px]",
|
|
8
|
+
md: "h-6 w-6 border-2",
|
|
9
|
+
lg: "h-8 w-8 border-[2.5px]"
|
|
10
|
+
};
|
|
11
|
+
function Spinner({ size = "md", color = "default", label = "Loading", className }) {
|
|
12
|
+
return /* @__PURE__ */ jsx(
|
|
13
|
+
"span",
|
|
14
|
+
{
|
|
15
|
+
role: "status",
|
|
16
|
+
"aria-label": label,
|
|
17
|
+
className: cn(
|
|
18
|
+
"inline-block rounded-[var(--ds-radius-full)] animate-spin",
|
|
19
|
+
color === "inherit" ? "border-current/30 border-t-current" : "border-[var(--ds-bg-emphasis)] border-t-[var(--ds-accent-primary)]",
|
|
20
|
+
sizes[size],
|
|
21
|
+
className
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
var ControlSizeContext = createContext(null);
|
|
27
|
+
var ButtonSizeContext = ControlSizeContext;
|
|
28
|
+
var variantStyles = {
|
|
29
|
+
default: "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] [background-origin:border-box] text-[var(--ds-text-on-primary)] border-transparent hover:bg-[var(--ds-accent-primary-hover)] hover:brightness-110",
|
|
30
|
+
secondary: "bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)] border-[var(--ds-border-default)] hover:bg-[var(--ds-bg-muted)]",
|
|
31
|
+
tertiary: "bg-[var(--ds-bg-muted)] text-[var(--ds-text-primary)] border-transparent hover:brightness-95",
|
|
32
|
+
outline: "bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)] border-[var(--ds-border-default)] hover:bg-[var(--ds-bg-muted)]",
|
|
33
|
+
ghost: "bg-transparent text-[var(--ds-text-primary)] border-transparent hover:bg-[var(--ds-bg-muted)] shadow-none",
|
|
34
|
+
destructive: "bg-[var(--ds-status-error)] text-[var(--ds-text-on-error)] border-transparent hover:opacity-90",
|
|
35
|
+
success: "bg-[var(--ds-status-success)] text-[var(--ds-text-on-success)] border-transparent hover:opacity-90",
|
|
36
|
+
warning: "bg-[var(--ds-status-warning)] text-[var(--ds-text-on-warning)] border-transparent hover:opacity-90",
|
|
37
|
+
link: "bg-transparent text-[var(--ds-accent-primary)] hover:text-[var(--ds-accent-primary-hover)] hover:underline"
|
|
38
|
+
};
|
|
39
|
+
var sizeStyles = {
|
|
40
|
+
// xs / icon-xs: dense tool chrome (builder toolbars, inline row actions).
|
|
41
|
+
xs: "h-ds-6 px-ds-3 py-0 text-xs",
|
|
42
|
+
sm: "h-[var(--ds-control-height-sm)] px-ds-4 py-ds-1 text-xs",
|
|
43
|
+
md: "h-[var(--ds-control-height-md)] px-ds-6 py-ds-2 text-sm",
|
|
44
|
+
lg: "h-[var(--ds-control-height-lg)] px-ds-8 py-ds-3 text-base",
|
|
45
|
+
"icon-xs": "h-ds-6 w-ds-6 p-0",
|
|
46
|
+
"icon-sm": "h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] p-0",
|
|
47
|
+
icon: "h-[var(--ds-control-height-md)] w-[var(--ds-control-height-md)] p-0",
|
|
48
|
+
"icon-lg": "h-[var(--ds-control-height-lg)] w-[var(--ds-control-height-lg)] p-0"
|
|
49
|
+
};
|
|
50
|
+
var linkSizeStyles = {
|
|
51
|
+
xs: "text-xs",
|
|
52
|
+
sm: "text-xs",
|
|
53
|
+
md: "text-sm",
|
|
54
|
+
lg: "text-base",
|
|
55
|
+
"icon-xs": "text-xs",
|
|
56
|
+
"icon-sm": "text-xs",
|
|
57
|
+
icon: "text-sm",
|
|
58
|
+
"icon-lg": "text-base"
|
|
59
|
+
};
|
|
60
|
+
var iconPaddingReduce = {
|
|
61
|
+
xs: 2,
|
|
62
|
+
sm: 2,
|
|
63
|
+
md: 4,
|
|
64
|
+
lg: 6
|
|
65
|
+
};
|
|
66
|
+
var HOVER_SCALE_CAP = { "--_btn-scale": "min(var(--ds-hover-scale), 1.02)" };
|
|
67
|
+
var Button = forwardRef(function Button2({ variant = "default", size: sizeProp, iconLeft, iconRight, loading, className, children, disabled, style, onClick, ...props }, ref) {
|
|
68
|
+
const contextSize = useContext(ControlSizeContext);
|
|
69
|
+
const size = sizeProp ?? contextSize ?? "md";
|
|
70
|
+
const isLink = variant === "link";
|
|
71
|
+
const spinnerSize = size === "lg" || size === "icon-lg" ? "md" : "sm";
|
|
72
|
+
let paddingStyle;
|
|
73
|
+
const isIconSize = size === "icon" || size === "icon-xs" || size === "icon-sm" || size === "icon-lg";
|
|
74
|
+
if (!isIconSize && !isLink && (iconLeft || iconRight)) {
|
|
75
|
+
const reduce = iconPaddingReduce[size];
|
|
76
|
+
paddingStyle = {};
|
|
77
|
+
if (iconLeft) paddingStyle.paddingLeft = `calc(${getCssPadding(size)} - ${reduce}px)`;
|
|
78
|
+
if (iconRight) paddingStyle.paddingRight = `calc(${getCssPadding(size)} - ${reduce}px)`;
|
|
79
|
+
}
|
|
80
|
+
const isLoading = loading && !disabled;
|
|
81
|
+
const isDisabled = !!disabled;
|
|
82
|
+
const handleClick = isLoading ? (e) => {
|
|
83
|
+
e.preventDefault();
|
|
84
|
+
} : onClick;
|
|
85
|
+
const ariaLabel = props["aria-label"];
|
|
86
|
+
const inTooltip = useContext(TooltipCtx);
|
|
87
|
+
const btn = /* @__PURE__ */ jsxs(
|
|
88
|
+
"button",
|
|
89
|
+
{
|
|
90
|
+
ref,
|
|
91
|
+
"data-variant": variant,
|
|
92
|
+
className: cn(
|
|
93
|
+
"relative inline-flex items-center justify-center gap-ds-2 whitespace-nowrap font-medium",
|
|
94
|
+
isLink ? cn(
|
|
95
|
+
"px-0 py-ds-0.5 h-auto",
|
|
96
|
+
linkSizeStyles[size],
|
|
97
|
+
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
98
|
+
"focus-visible:outline-2 focus-visible:outline-[var(--ds-accent-primary)] focus-visible:outline-offset-2",
|
|
99
|
+
"cursor-pointer",
|
|
100
|
+
"active:text-[var(--ds-accent-primary-active)]"
|
|
101
|
+
) : cn(
|
|
102
|
+
"border-[length:var(--ds-border-width)]",
|
|
103
|
+
"rounded-[var(--ds-radius-md)]",
|
|
104
|
+
"shadow-[var(--ds-shadow-button)]",
|
|
105
|
+
"hover:scale-[var(--_btn-scale)] hover:-translate-y-[var(--ds-hover-lift)]",
|
|
106
|
+
"active:shadow-[var(--ds-shadow-button-pressed)] active:translate-x-[var(--ds-press-depth)] active:translate-y-[var(--ds-press-depth)]",
|
|
107
|
+
"[transition:var(--ds-transition-interactive)]",
|
|
108
|
+
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
109
|
+
"cursor-pointer disabled:cursor-not-allowed disabled:opacity-disabled",
|
|
110
|
+
sizeStyles[size]
|
|
111
|
+
),
|
|
112
|
+
variantStyles[variant],
|
|
113
|
+
isLoading && !isLink && "cursor-wait pointer-events-none",
|
|
114
|
+
className
|
|
115
|
+
),
|
|
116
|
+
disabled: isDisabled,
|
|
117
|
+
"aria-busy": isLoading || void 0,
|
|
118
|
+
"aria-disabled": isLoading && !disabled ? true : void 0,
|
|
119
|
+
onClick: handleClick,
|
|
120
|
+
style: isLink ? style : { ...HOVER_SCALE_CAP, ...paddingStyle, ...style },
|
|
121
|
+
...props,
|
|
122
|
+
children: [
|
|
123
|
+
loading && !isLink && /* @__PURE__ */ jsx("span", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx(Spinner, { size: spinnerSize, color: "inherit" }) }),
|
|
124
|
+
/* @__PURE__ */ jsxs("span", { className: cn("inline-flex items-center gap-ds-2 min-w-0", loading && !isLink && "invisible"), children: [
|
|
125
|
+
iconLeft,
|
|
126
|
+
children,
|
|
127
|
+
iconRight
|
|
128
|
+
] })
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
if (isIconSize && ariaLabel && !inTooltip) {
|
|
133
|
+
return /* @__PURE__ */ jsx(Tooltip, { content: ariaLabel, children: btn });
|
|
134
|
+
}
|
|
135
|
+
return btn;
|
|
136
|
+
});
|
|
137
|
+
function getCssPadding(size) {
|
|
138
|
+
switch (size) {
|
|
139
|
+
case "xs":
|
|
140
|
+
return "var(--ds-space-3)";
|
|
141
|
+
case "sm":
|
|
142
|
+
return "var(--ds-space-4)";
|
|
143
|
+
case "md":
|
|
144
|
+
return "var(--ds-space-6)";
|
|
145
|
+
case "lg":
|
|
146
|
+
return "var(--ds-space-8)";
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function triggerType(node) {
|
|
150
|
+
if (!isValidElement(node)) return {};
|
|
151
|
+
return (node.type === "button" || node.type === Button) && node.props.type === void 0 ? { type: "button" } : {};
|
|
152
|
+
}
|
|
153
|
+
var PreferencesContext = createContext(null);
|
|
154
|
+
var HOUSE_DEFAULTS = {
|
|
155
|
+
validationTiming: "onBlur",
|
|
156
|
+
formActions: { align: "end", placement: "auto" },
|
|
157
|
+
itemsPerPage: 25,
|
|
158
|
+
paginationStyle: "pagination",
|
|
159
|
+
tableToCardsBreakpoint: "md",
|
|
160
|
+
emptyStyle: "illustration-cta",
|
|
161
|
+
loadingStyle: "skeleton",
|
|
162
|
+
destructiveMode: "dialog",
|
|
163
|
+
highSeverityActions: ["delete_account", "remove_team_member"],
|
|
164
|
+
typeToConfirmActions: ["delete_account"],
|
|
165
|
+
undoWindowSeconds: 5
|
|
166
|
+
};
|
|
167
|
+
var PREFERENCE_HOUSE_DEFAULTS = Object.freeze(HOUSE_DEFAULTS);
|
|
168
|
+
function usePreferences() {
|
|
169
|
+
const raw = useShellPreferences();
|
|
170
|
+
return useMemo(() => resolvePreferences(raw), [raw]);
|
|
171
|
+
}
|
|
172
|
+
function resolvePreferences(raw) {
|
|
173
|
+
const d = PREFERENCE_HOUSE_DEFAULTS;
|
|
174
|
+
const out = { ...d, formActions: { ...d.formActions }, highSeverityActions: [...d.highSeverityActions], typeToConfirmActions: [...d.typeToConfirmActions] };
|
|
175
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
176
|
+
if (value === void 0) continue;
|
|
177
|
+
if (key === "formActions") {
|
|
178
|
+
const actions = value;
|
|
179
|
+
if (actions?.align !== void 0) out.formActions.align = actions.align;
|
|
180
|
+
if (actions?.placement !== void 0) out.formActions.placement = actions.placement;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
out[key] = value;
|
|
184
|
+
}
|
|
185
|
+
return out;
|
|
186
|
+
}
|
|
187
|
+
function useShellPreferences() {
|
|
188
|
+
return useContext(PreferencesContext) ?? EMPTY;
|
|
189
|
+
}
|
|
190
|
+
var EMPTY = Object.freeze({});
|
|
191
|
+
function preferenceActionKey(label) {
|
|
192
|
+
return label.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export { Button, ButtonSizeContext, ControlSizeContext, PREFERENCE_HOUSE_DEFAULTS, PreferencesContext, Spinner, preferenceActionKey, triggerType, usePreferences, useShellPreferences };
|
|
196
|
+
//# sourceMappingURL=chunk-7TOJ4G7S.js.map
|
|
197
|
+
//# sourceMappingURL=chunk-7TOJ4G7S.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../showcase/src/components/Spinner.tsx","../../../showcase/src/components/Button.tsx","../../../showcase/src/lib/preferences.ts"],"names":["Button","jsx","createContext","useContext"],"mappings":"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","file":"chunk-7TOJ4G7S.js","sourcesContent":["import { cn } from \"../lib/utils\";\n\nconst sizes = {\n sm: \"h-4 w-4 border-[1.5px]\",\n md: \"h-6 w-6 border-2\",\n lg: \"h-8 w-8 border-[2.5px]\",\n} as const;\n\ninterface SpinnerProps {\n size?: keyof typeof sizes;\n color?: \"default\" | \"inherit\";\n label?: string;\n className?: string;\n}\n\nexport function Spinner({ size = \"md\", color = \"default\", label = \"Loading\", className }: SpinnerProps) {\n return (\n <span\n role=\"status\"\n aria-label={label}\n className={cn(\n \"inline-block rounded-[var(--ds-radius-full)] animate-spin\",\n color === \"inherit\"\n ? \"border-current/30 border-t-current\"\n : \"border-[var(--ds-bg-emphasis)] border-t-[var(--ds-accent-primary)]\",\n sizes[size],\n className\n )}\n />\n );\n}\n","import { cn } from \"../lib/utils\";\nimport { createContext, useContext, forwardRef, isValidElement, type ButtonHTMLAttributes, type CSSProperties, type ReactNode } from \"react\";\nimport { Tooltip, TooltipCtx } from \"./Tooltip\";\nimport { Spinner } from \"./Spinner\";\n\ntype ButtonVariant = \"default\" | \"secondary\" | \"tertiary\" | \"outline\" | \"ghost\" | \"destructive\" | \"success\" | \"warning\" | \"link\";\ntype ButtonSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"icon-xs\" | \"icon-sm\" | \"icon\" | \"icon-lg\";\n\nexport type ControlSize = \"sm\" | \"md\" | \"lg\";\nexport const ControlSizeContext = createContext<ControlSize | null>(null);\nexport const ButtonSizeContext = ControlSizeContext;\n\ninterface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n iconLeft?: ReactNode;\n iconRight?: ReactNode;\n loading?: boolean;\n children?: ReactNode;\n}\n\nconst variantStyles: Record<ButtonVariant, string> = {\n default: \"bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] [background-origin:border-box] text-[var(--ds-text-on-primary)] border-transparent hover:bg-[var(--ds-accent-primary-hover)] hover:brightness-110\",\n secondary: \"bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)] border-[var(--ds-border-default)] hover:bg-[var(--ds-bg-muted)]\",\n tertiary: \"bg-[var(--ds-bg-muted)] text-[var(--ds-text-primary)] border-transparent hover:brightness-95\",\n outline: \"bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)] border-[var(--ds-border-default)] hover:bg-[var(--ds-bg-muted)]\",\n ghost: \"bg-transparent text-[var(--ds-text-primary)] border-transparent hover:bg-[var(--ds-bg-muted)] shadow-none\",\n destructive: \"bg-[var(--ds-status-error)] text-[var(--ds-text-on-error)] border-transparent hover:opacity-90\",\n success: \"bg-[var(--ds-status-success)] text-[var(--ds-text-on-success)] border-transparent hover:opacity-90\",\n warning: \"bg-[var(--ds-status-warning)] text-[var(--ds-text-on-warning)] border-transparent hover:opacity-90\",\n link: \"bg-transparent text-[var(--ds-accent-primary)] hover:text-[var(--ds-accent-primary-hover)] hover:underline\",\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n // xs / icon-xs: dense tool chrome (builder toolbars, inline row actions).\n xs: \"h-ds-6 px-ds-3 py-0 text-xs\",\n sm: \"h-[var(--ds-control-height-sm)] px-ds-4 py-ds-1 text-xs\",\n md: \"h-[var(--ds-control-height-md)] px-ds-6 py-ds-2 text-sm\",\n lg: \"h-[var(--ds-control-height-lg)] px-ds-8 py-ds-3 text-base\",\n \"icon-xs\": \"h-ds-6 w-ds-6 p-0\",\n \"icon-sm\": \"h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] p-0\",\n icon: \"h-[var(--ds-control-height-md)] w-[var(--ds-control-height-md)] p-0\",\n \"icon-lg\": \"h-[var(--ds-control-height-lg)] w-[var(--ds-control-height-lg)] p-0\",\n};\n\n// Link buttons have no box, so only the text size follows `size`.\nconst linkSizeStyles: Record<ButtonSize, string> = {\n xs: \"text-xs\",\n sm: \"text-xs\",\n md: \"text-sm\",\n lg: \"text-base\",\n \"icon-xs\": \"text-xs\",\n \"icon-sm\": \"text-xs\",\n icon: \"text-sm\",\n \"icon-lg\": \"text-base\",\n};\n\nconst iconPaddingReduce: Record<Exclude<ButtonSize, \"icon\" | \"icon-xs\" | \"icon-sm\" | \"icon-lg\">, number> = {\n xs: 2,\n sm: 2,\n md: 4,\n lg: 6,\n};\n\nconst HOVER_SCALE_CAP = { '--_btn-scale': 'min(var(--ds-hover-scale), 1.02)' } as CSSProperties;\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button({ variant = \"default\", size: sizeProp, iconLeft, iconRight, loading, className, children, disabled, style, onClick, ...props }, ref) {\n const contextSize = useContext(ControlSizeContext);\n const size = sizeProp ?? contextSize ?? \"md\";\n const isLink = variant === \"link\";\n const spinnerSize = size === \"lg\" || size === \"icon-lg\" ? \"md\" : \"sm\";\n let paddingStyle: CSSProperties | undefined;\n const isIconSize = size === \"icon\" || size === \"icon-xs\" || size === \"icon-sm\" || size === \"icon-lg\";\n if (!isIconSize && !isLink && (iconLeft || iconRight)) {\n const reduce = iconPaddingReduce[size];\n paddingStyle = {};\n if (iconLeft) paddingStyle.paddingLeft = `calc(${getCssPadding(size)} - ${reduce}px)`;\n if (iconRight) paddingStyle.paddingRight = `calc(${getCssPadding(size)} - ${reduce}px)`;\n }\n\n const isLoading = loading && !disabled;\n const isDisabled = !!disabled;\n\n const handleClick = isLoading\n ? (e: React.MouseEvent<HTMLButtonElement>) => { e.preventDefault(); }\n : onClick;\n\n const ariaLabel = props[\"aria-label\"];\n // Round 15 (52.7): inside an explicit <Tooltip> the caller owns the label; the automatic one from aria-label would be a second tooltip.\n const inTooltip = useContext(TooltipCtx);\n\n const btn = (\n <button\n ref={ref}\n data-variant={variant}\n className={cn(\n \"relative inline-flex items-center justify-center gap-ds-2 whitespace-nowrap font-medium\",\n isLink\n ? cn(\n \"px-0 py-ds-0.5 h-auto\",\n linkSizeStyles[size],\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"focus-visible:outline-2 focus-visible:outline-[var(--ds-accent-primary)] focus-visible:outline-offset-2\",\n \"cursor-pointer\",\n \"active:text-[var(--ds-accent-primary-active)]\",\n )\n : cn(\n \"border-[length:var(--ds-border-width)]\",\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-shadow-button)]\",\n \"hover:scale-[var(--_btn-scale)] hover:-translate-y-[var(--ds-hover-lift)]\",\n \"active:shadow-[var(--ds-shadow-button-pressed)] active:translate-x-[var(--ds-press-depth)] active:translate-y-[var(--ds-press-depth)]\",\n \"[transition:var(--ds-transition-interactive)]\",\n \"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]\",\n \"cursor-pointer disabled:cursor-not-allowed disabled:opacity-disabled\",\n sizeStyles[size],\n ),\n variantStyles[variant],\n isLoading && !isLink && \"cursor-wait pointer-events-none\",\n className\n )}\n disabled={isDisabled}\n aria-busy={isLoading || undefined}\n aria-disabled={isLoading && !disabled ? true : undefined}\n onClick={handleClick}\n style={isLink ? style : { ...HOVER_SCALE_CAP, ...paddingStyle, ...style }}\n {...props}\n >\n {loading && !isLink && (\n <span className=\"absolute inset-0 flex items-center justify-center\">\n <Spinner size={spinnerSize} color=\"inherit\" />\n </span>\n )}\n <span className={cn(\"inline-flex items-center gap-ds-2 min-w-0\", loading && !isLink && \"invisible\")}>\n {iconLeft}\n {children}\n {iconRight}\n </span>\n </button>\n );\n\n if (isIconSize && ariaLabel && !inTooltip) {\n return <Tooltip content={ariaLabel}>{btn}</Tooltip>;\n }\n\n return btn;\n});\n\nfunction getCssPadding(size: Exclude<ButtonSize, \"icon\" | \"icon-xs\" | \"icon-sm\" | \"icon-lg\">): string {\n switch (size) {\n case \"xs\": return \"var(--ds-space-3)\";\n case \"sm\": return \"var(--ds-space-4)\";\n case \"md\": return \"var(--ds-space-6)\";\n case \"lg\": return \"var(--ds-space-8)\";\n }\n}\n\n/**\n * A trigger the library wires up (a Collapsible's, a menu's, a popover's) never submits the form it sits in (0.21.0): a\n * button element or Button given no type gets type=\"button\". A page's own Button keeps HTML's default, so its submits\n * still work.\n */\nexport function triggerType(node: unknown): { type?: \"button\" } {\n if (!isValidElement(node)) return {};\n return (node.type === \"button\" || node.type === Button) && (node.props as { type?: unknown }).type === undefined ? { type: \"button\" } : {};\n}\n","/**\n * The customer's UX preferences, carried once by AppShell the way the theme is (Sprint 25.6 B9).\n *\n * The generated shell passes the object the template emits from the profile's rules; the builder preview passes the\n * same values from the theme state. Components default from it when no prop is passed — FormWrapper's validation mode\n * and actions alignment, Table and DataGrid's mobile breakpoint, Pagination's page size, EmptyState's style, and the\n * destructive-action helper's mode, lists and undo window — so a page gets the customer's value by doing nothing. A\n * prop always wins; a component outside any shell keeps the default it always had (components read\n * `useShellPreferences`). App code reads `usePreferences`, which fills every field (round 21); a paged list reads its\n * page size through `usePagination`.\n */\nimport { createContext, useContext, useMemo } from \"react\";\n\nexport type PreferenceValidationTiming = \"onBlur\" | \"onSubmit\" | \"onChange\";\nexport type PreferenceBreakpoint = \"sm\" | \"md\" | \"lg\";\nexport type PreferenceEmptyStyle = \"illustration-cta\" | \"text-cta\" | \"redirect\";\nexport type PreferenceLoadingStyle = \"skeleton\" | \"spinner\" | \"progress-bar\";\nexport type PreferenceDestructiveMode = \"dialog\" | \"undo\";\n/** dataDisplay.paginationStyle — how a long list shows more: page numbers, a Load more button, or loading as the user scrolls. */\nexport type PreferencePaginationStyle = \"pagination\" | \"load-more\" | \"infinite-scroll\";\n\nexport interface AppShellPreferences {\n /** forms.validationTiming — when a field first shows its error. */\n validationTiming?: PreferenceValidationTiming;\n /** forms.actions — where a form's buttons sit and how they align. */\n formActions?: { align?: \"start\" | \"end\"; placement?: \"auto\" | \"inline\" };\n /** dataDisplay.itemsPerPage — the page size of a paged or load-more list. */\n itemsPerPage?: number;\n /** dataDisplay.paginationStyle — page numbers, a Load more button, or loading on scroll; usePagination and Pagination follow it (round 22). */\n paginationStyle?: PreferencePaginationStyle;\n /** responsive.tableToCardsBreakpoint — below this width a Table becomes stacked cards. */\n tableToCardsBreakpoint?: PreferenceBreakpoint;\n /** emptyStates.emptyStyle — illustration with an action, text with an action, or redirect to creation. */\n emptyStyle?: PreferenceEmptyStyle;\n /** emptyStates.loadingStyle — what a page shows while data loads. */\n loadingStyle?: PreferenceLoadingStyle;\n /** destructiveActions.mode — confirm in a dialog, or act now with an Undo toast. */\n destructiveMode?: PreferenceDestructiveMode;\n /** destructiveActions.highSeverityActions — always confirm in a dialog, even in undo mode. */\n highSeverityActions?: string[];\n /** destructiveActions.typeToConfirmActions — the user types the name before the confirm enables. */\n typeToConfirmActions?: string[];\n /** destructiveActions.undoWindowSeconds — how long the Undo toast stays. */\n undoWindowSeconds?: number;\n}\n\nexport const PreferencesContext = createContext<AppShellPreferences | null>(null);\n\n/** Every preference in force, the shell's value or the house default — what app code reads. */\nexport interface ResolvedPreferences {\n validationTiming: PreferenceValidationTiming;\n formActions: { align: \"start\" | \"end\"; placement: \"auto\" | \"inline\" };\n itemsPerPage: number;\n paginationStyle: PreferencePaginationStyle;\n tableToCardsBreakpoint: PreferenceBreakpoint;\n emptyStyle: PreferenceEmptyStyle;\n loadingStyle: PreferenceLoadingStyle;\n destructiveMode: PreferenceDestructiveMode;\n highSeverityActions: string[];\n typeToConfirmActions: string[];\n undoWindowSeconds: number;\n}\n\n/**\n * The house defaults for the fields the shell carries: the platform's preference-defaults.ts, mirrored in\n * decisions-schema.ts (DEFAULT_PATTERN_DECISIONS); a test keeps the three equal.\n */\nconst HOUSE_DEFAULTS: ResolvedPreferences = {\n validationTiming: \"onBlur\",\n formActions: { align: \"end\", placement: \"auto\" },\n itemsPerPage: 25,\n paginationStyle: \"pagination\",\n tableToCardsBreakpoint: \"md\",\n emptyStyle: \"illustration-cta\",\n loadingStyle: \"skeleton\",\n destructiveMode: \"dialog\",\n highSeverityActions: [\"delete_account\", \"remove_team_member\"],\n typeToConfirmActions: [\"delete_account\"],\n undoWindowSeconds: 5,\n};\nexport const PREFERENCE_HOUSE_DEFAULTS: Readonly<ResolvedPreferences> = Object.freeze(HOUSE_DEFAULTS);\n\n/**\n * For app code: every preference in force — the shell's value, else the house default — so a page never writes a\n * fallback of its own. Round 21 (run 58): with every field optional, TypeScript made the builder write\n * `const { itemsPerPage = 20 } = usePreferences()`, a second copy of the preference it then edited by hand when the\n * rule changed. Paged lists use `usePagination`, which reads the page size itself.\n */\nexport function usePreferences(): ResolvedPreferences {\n const raw = useShellPreferences();\n return useMemo(() => resolvePreferences(raw), [raw]);\n}\n\n/** The shell's values over the house defaults; a field the shell leaves undefined keeps its default. */\nexport function resolvePreferences(raw: AppShellPreferences): ResolvedPreferences {\n const d = PREFERENCE_HOUSE_DEFAULTS;\n const out: ResolvedPreferences = { ...d, formActions: { ...d.formActions }, highSeverityActions: [...d.highSeverityActions], typeToConfirmActions: [...d.typeToConfirmActions] };\n for (const [key, value] of Object.entries(raw) as Array<[keyof AppShellPreferences, unknown]>) {\n if (value === undefined) continue;\n if (key === \"formActions\") {\n const actions = value as AppShellPreferences[\"formActions\"];\n if (actions?.align !== undefined) out.formActions.align = actions.align;\n if (actions?.placement !== undefined) out.formActions.placement = actions.placement;\n continue;\n }\n (out as unknown as Record<string, unknown>)[key] = value;\n }\n return out;\n}\n\n/**\n * For components: only what the shell passed, or an empty object outside any shell — a component with no prop takes\n * the shell's value, and a bare component keeps the default it always had.\n */\nexport function useShellPreferences(): AppShellPreferences {\n return useContext(PreferencesContext) ?? EMPTY;\n}\n\nconst EMPTY: AppShellPreferences = Object.freeze({});\n\n/**\n * \"Remove range\" → \"remove_range\": the key the high-severity and type-to-confirm lists use. The engine's `actionKey`\n * (platform/src/lib/destructive-mode.ts) is the same rule for compliance; a platform test keeps the two identical.\n */\nexport function preferenceActionKey(label: string): string {\n return label.trim().toLowerCase().replace(/[^a-z0-9]+/g, \"_\").replace(/^_|_$/g, \"\");\n}\n"]}
|