gridsmith-ui 0.31.0 → 0.32.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +64 -1
  2. package/dist/charts.d.ts +101 -30
  3. package/dist/charts.js +181 -106
  4. package/dist/charts.js.map +1 -1
  5. package/dist/chat.js +6 -6
  6. package/dist/{chunk-OWQ7M6R7.js → chunk-2724SJO2.js} +141 -24
  7. package/dist/chunk-2724SJO2.js.map +1 -0
  8. package/dist/{chunk-BKYWKMUN.js → chunk-DO6DLTFK.js} +11 -9
  9. package/dist/chunk-DO6DLTFK.js.map +1 -0
  10. package/dist/{chunk-GP2COVJC.js → chunk-H732QL56.js} +4 -4
  11. package/dist/{chunk-GP2COVJC.js.map → chunk-H732QL56.js.map} +1 -1
  12. package/dist/{chunk-XSQD3UGY.js → chunk-HCEHTJ5E.js} +17 -4
  13. package/dist/chunk-HCEHTJ5E.js.map +1 -0
  14. package/dist/{chunk-YFHTREH5.js → chunk-HUVZQOU4.js} +5 -5
  15. package/dist/{chunk-YFHTREH5.js.map → chunk-HUVZQOU4.js.map} +1 -1
  16. package/dist/{chunk-EKWXPSTI.js → chunk-JHZ22HQP.js} +75 -24
  17. package/dist/chunk-JHZ22HQP.js.map +1 -0
  18. package/dist/{chunk-3J67NISC.js → chunk-NGZJK57C.js} +15 -11
  19. package/dist/chunk-NGZJK57C.js.map +1 -0
  20. package/dist/{chunk-U7WBI4AV.js → chunk-OVHM55JF.js} +5 -5
  21. package/dist/{chunk-U7WBI4AV.js.map → chunk-OVHM55JF.js.map} +1 -1
  22. package/dist/{chunk-OFACAHRV.js → chunk-QY2RA2HO.js} +5 -5
  23. package/dist/{chunk-OFACAHRV.js.map → chunk-QY2RA2HO.js.map} +1 -1
  24. package/dist/{chunk-HUNEJIKV.js → chunk-R2IAK3J3.js} +3 -3
  25. package/dist/{chunk-HUNEJIKV.js.map → chunk-R2IAK3J3.js.map} +1 -1
  26. package/dist/{chunk-V73LHNRL.js → chunk-RS624TD5.js} +29 -10
  27. package/dist/chunk-RS624TD5.js.map +1 -0
  28. package/dist/{chunk-V2ARGHJN.js → chunk-SIEU4H3H.js} +9 -9
  29. package/dist/chunk-SIEU4H3H.js.map +1 -0
  30. package/dist/{chunk-DBHVJ7Z3.js → chunk-SS3C24IJ.js} +3 -2
  31. package/dist/chunk-SS3C24IJ.js.map +1 -0
  32. package/dist/{chunk-LE72KHIE.js → chunk-TMPPBXX3.js} +3 -3
  33. package/dist/{chunk-LE72KHIE.js.map → chunk-TMPPBXX3.js.map} +1 -1
  34. package/dist/{chunk-GT6M74IZ.js → chunk-WSKPESAX.js} +12 -10
  35. package/dist/chunk-WSKPESAX.js.map +1 -0
  36. package/dist/{chunk-2Q4HOGEI.js → chunk-XBVZIN26.js} +15 -5
  37. package/dist/chunk-XBVZIN26.js.map +1 -0
  38. package/dist/data-grid.js +10 -10
  39. package/dist/data-grid.js.map +1 -1
  40. package/dist/editor-mentions.js +2 -2
  41. package/dist/editor.js +4 -3
  42. package/dist/editor.js.map +1 -1
  43. package/dist/index.d.ts +53 -6
  44. package/dist/index.js +557 -232
  45. package/dist/index.js.map +1 -1
  46. package/dist/kanban.js +10 -9
  47. package/dist/kanban.js.map +1 -1
  48. package/dist/resizable.d.ts +11 -2
  49. package/dist/resizable.js +97 -22
  50. package/dist/resizable.js.map +1 -1
  51. package/dist/roots.css +2 -2
  52. package/dist/tokens.css +6 -6
  53. package/dist/virtualized.js +10 -9
  54. package/dist/virtualized.js.map +1 -1
  55. package/dist-static/tokens.css +6 -6
  56. package/package.json +1 -1
  57. package/dist/chunk-2Q4HOGEI.js.map +0 -1
  58. package/dist/chunk-3J67NISC.js.map +0 -1
  59. package/dist/chunk-BKYWKMUN.js.map +0 -1
  60. package/dist/chunk-DBHVJ7Z3.js.map +0 -1
  61. package/dist/chunk-EKWXPSTI.js.map +0 -1
  62. package/dist/chunk-GT6M74IZ.js.map +0 -1
  63. package/dist/chunk-OWQ7M6R7.js.map +0 -1
  64. package/dist/chunk-V2ARGHJN.js.map +0 -1
  65. package/dist/chunk-V73LHNRL.js.map +0 -1
  66. package/dist/chunk-XSQD3UGY.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../showcase/src/components/NumberInput.tsx","../../../showcase/src/components/Popover.tsx","../../../showcase/src/components/Pagination.tsx","../../../showcase/src/lib/use-pagination.ts"],"names":["useRef","useState","useCallback","jsxs","jsx","useEffect","sizes"],"mappings":"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","file":"chunk-SIEU4H3H.js","sourcesContent":["import { useCallback, useContext, useRef, useState } from \"react\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { cn, FIELD_FOCUS_WITHIN_RING, ERROR_FOCUS_WITHIN_RING, FOCUS_RING } from \"../lib/utils\";\nimport { useInputModality } from \"../lib/input-modality\";\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 /** The field's name where nothing on screen names it (\"Seats\"); inside a Field, the Field's label names it. */\n \"aria-label\"?: 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 \"aria-label\": ariaLabel,\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 // a field: clicked into, the active look; reached with Tab, the outline (Sprint 30, lib/input-modality.ts)\n useInputModality();\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 // Sprint 25.8.7 item 24, the APG spinbutton: \"Home: If the spinbutton has a minimum value, sets the value to its\n // minimum\", and End its maximum. Without that limit, or with a modifier held (Shift+Home selects), the key is the\n // caret's: the pattern keeps the platform's text editing keys for a field that can be typed in\n const plain = !e.shiftKey && !e.ctrlKey && !e.metaKey && !e.altKey;\n if (e.key === \"Home\" && plain && Number.isFinite(min)) { e.preventDefault(); commitValue(min); }\n if (e.key === \"End\" && plain && Number.isFinite(max)) { e.preventDefault(); commitValue(max); }\n },\n [increment, decrement, commitValue, min, max],\n );\n\n const s = sizes[size];\n const atMin = value <= min;\n const atMax = value >= max;\n // Sprint 25.8.7 item 24: the value is stated while the field holds a number (\"Authors SHOULD set the aria-valuenow\n // attribute when the spinbutton has a value\", WAI-ARIA 1.2), not while it is emptied to type afresh; it is the\n // committed value, which typing keeps within the limits\n const shown = focused ? draft : String(value);\n const holdsNumber = Number.isFinite(parseFloat(shown)) && Number.isFinite(value);\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 : FIELD_FOCUS_WITHIN_RING,\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 // kept out of the Tab order (the field's arrows step it) and never focused by a press: the outline all the same\n // if anything focuses it (Sprint 30)\n FOCUS_RING,\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 // a spinbutton that can be typed in (Sprint 25.8.7 item 24): its value, and each limit only when it exists\n role=\"spinbutton\"\n aria-label={ariaLabel}\n aria-valuenow={holdsNumber ? value : undefined}\n aria-valuemin={Number.isFinite(min) ? min : undefined}\n aria-valuemax={Number.isFinite(max) ? max : undefined}\n inputMode={decimals ? \"decimal\" : \"numeric\"}\n aria-invalid={error || undefined}\n value={shown}\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 FOCUS_RING,\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 { RowsCtx, SplitListFramerCtx } from \"../lib/surface-context\";\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 {/* an overlay's content is no collection's row, wherever it was opened from */}\n {/* a popup starts afresh: a list pane round it hears nothing of what it holds (the end review of 25.33's fix pass) */}\n <RowsCtx value={false}><SplitListFramerCtx value={null}>{children}</SplitListFramerCtx></RowsCtx>\n </div>,\n container ?? document.body\n )}\n </>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { cn, FOCUS_RING } from \"../lib/utils\";\nimport { focusAfterSelfRemoval, isTabStop, tabStops } from \"../lib/focus\";\nimport { Icon } from \"../lib/icons\";\nimport { Dropdown } from \"./Dropdown\";\nimport { Popover } from \"./Popover\";\nimport { NumberInput } from \"./NumberInput\";\nimport { Button } from \"./Button\";\nimport { AutoTooltip } from \"./Tooltip\";\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 * Keyboard focus on the button holds the list (Sprint 25.29 item 7): focus brought it into view, not a scroll, and each\n * load pushed it off the screen again. Enter loads, and the button is brought back into view; focus leaving looks again.\n * Only a load the keyboard's press made brings it back (Sprint 25.31 item 3): a clicked button has focus too, and bringing\n * it into view after every load scrolled, which loaded again, so one click loaded every page.\n * The last load takes the button with it, so focus goes to the first row that load brought (Sprint 25.30 item 1), in\n * whatever markup the list draws (Sprint 25.31 item 4), and the list holds no more (item 5). Only the press's own load\n * hands focus on: a load that leaves the button in place ends the press's watch.\n */\nfunction LoadMore({ hasMore, onLoadMore, loadMoreLabel, currentPage, scroll, className }: PaginationProps & { onLoadMore: () => void; scroll: boolean }) {\n const marker = useRef<HTMLDivElement>(null);\n const button = useRef<HTMLButtonElement>(null);\n const pager = useRef<HTMLDivElement>(null);\n // a press's watches: for the button going with its load (to hand focus on), and for its rows (to bring the button back)\n const watching = useRef<(() => void) | null>(null);\n const endWatch = () => {\n watching.current?.();\n watching.current = null;\n };\n // keyboard focus on the infinite list's button holds it (Sprint 25.29 item 7)\n const [held, setHeld] = useState(false);\n // a press with focus on the button: should it be the last, focus goes on to the first row it brought, the person\n // reading on where they asked to, else the last control before the pager, else the last resort round where it sat\n const press = () => {\n const b = button.current, root = pager.current;\n if (b && root && document.activeElement === b) {\n // the infinite list's: only while the keyboard holds it, since a mouse's focus shows the ring once a key is pressed,\n // and a scroll back would load again (the review of 16 October, 2). Plain Load more holds nothing, and no load\n // follows a scroll there: the keyboard's ring is enough.\n const byKey = scroll ? held : byKeyboard(b);\n const place = placeOf(root);\n const had = before(place);\n const hadRows = had.flatMap(rowsOf);\n const hadStops = had.flatMap(stopsIn);\n endWatch();\n // the watch lasts until the button goes (focus handed on), focus moves elsewhere, the next press, a load the list\n // starts by itself, or 10 s: never ended by the page number, which a page may count before its rows come (the\n // final review of 16 October, 1: the watch ended then, and the last load left focus on the page)\n const handOn = focusAfterSelfRemoval(b, {\n item: root,\n group: null,\n to: () => {\n // what the load brought, read again now it's in: the library's rows (a row with nothing in it to Tab to takes\n // focus itself, for the moment), else the Tab stops that appeared since the press, whatever the page draws\n const content = before(place);\n const fresh = appended(content.flatMap(rowsOf), hadRows);\n if (fresh) return tabStops(fresh)[0] ?? fresh;\n const stops = content.flatMap(stopsIn);\n return appended(stops, hadStops) ?? stops.at(-1);\n },\n });\n // a load by Enter: once its rows are in, above the button, with the button still here, it's brought back into view;\n // its rows, not its page number, which can come first (the final review, 1)\n const backInView = byKey ? whenRowsCome(place, hadRows, hadStops, b, () => { if (document.activeElement === b) b.scrollIntoView?.({ block: \"nearest\" }); }) : () => {};\n watching.current = () => { handOn(); backInView(); };\n }\n onLoadMore();\n };\n const load = useLatest(onLoadMore);\n const loadedAt = useRef<number | null>(null);\n // the last load takes the focused button, which fires no blur, so the list would hold for good: a filter that starts it\n // again never loaded as it scrolled (Sprint 25.31 item 5)\n if (held && !hasMore) setHeld(false);\n useEffect(() => {\n const el = marker.current;\n if (!scroll || !hasMore || !el || held || 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 // a load the list starts by itself: a press's watch ends, so the list loading on as the person scrolls after a click\n // never takes focus back up to that press's rows (the reviews of 16 October, 1)\n watching.current?.();\n watching.current = null;\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, held]);\n if (!hasMore) return null;\n return (\n <div ref={pager} 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 ref={button} type=\"button\" variant=\"secondary\" onClick={press}\n onFocus={(e) => setHeld(scroll && byKeyboard(e.currentTarget))} onBlur={() => setHeld(false)}>\n {loadMoreLabel ?? \"Load more\"}\n </Button>\n </div>\n );\n}\n\n/** Where a pager sits: the pager, or the nearest box round it with elements before it, its parent, and what follows it. */\ninterface PagerPlace { at: Element; parent: Element; next: Element | null }\n\n/**\n * A pager's place, read as a press begins (Sprint 25.31 item 4): the pager itself where its list comes before it (A3:\n * the list's next sibling, or the last child among the list's own items), else the nearest box round it that has\n * elements before it, as for a pager the page sets in a layout's box of its own.\n */\nfunction placeOf(el: Element): PagerPlace | null {\n for (let n: Element | null = el; n && n !== document.body; n = n.parentElement) {\n if (n.previousElementSibling && n.parentElement) return { at: n, parent: n.parentElement, next: n.nextElementSibling };\n }\n return null;\n}\n\n/**\n * What comes before that place now, its list among it: read again once a load is in, since new items can be the\n * pager's own siblings, and the last load takes the pager, whose place is then up to what followed it.\n */\nfunction before(place: PagerPlace | null): Element[] {\n if (!place) return [];\n const { at, parent, next } = place;\n const kids = Array.from(parent.children);\n const end = at.parentElement === parent ? kids.indexOf(at) : next?.parentElement === parent ? kids.indexOf(next) : kids.length;\n return kids.slice(0, end);\n}\n\n/** An element, when it matches, and what in it matches: rows and Tab stops can be the pager's own siblings. */\nconst withSelf = (el: Element, selector: string): Element[] => [...(el.matches(selector) ? [el] : []), ...el.querySelectorAll(selector)];\n\n/**\n * The rows in what a Load more follows: those the library's lists mark (the Table's rows and its cards on a phone,\n * `data-row-key` or `data-row-index`), else plain rows and items.\n */\nfunction rowsOf(list: Element): Element[] {\n const marked = withSelf(list, \"[data-row-key], [data-row-index]\");\n return marked.length ? marked : withSelf(list, 'tbody > tr, li, [role=\"row\"], [data-card]');\n}\n\n/** The Tab stops in an element, itself first. */\nconst stopsIn = (el: Element): HTMLElement[] => [...(isTabStop(el) ? [el] : []), ...tabStops(el)];\n\n/**\n * The first of `now`, in the page's order, that the press didn't see in `had`: lists append, so one after the last there\n * was, before one elsewhere, as a control the last load enabled above the list (the review of 16 October, 3).\n */\nfunction appended<T extends Element>(now: T[], had: Element[]): T | undefined {\n const seen = new Set(had);\n const fresh = now.filter((el) => !seen.has(el));\n const last = had.at(-1);\n return (last?.isConnected ? fresh.find((el) => last.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING) : undefined) ?? fresh[0];\n}\n\n/**\n * Calls `then` once the press's rows are in what comes before the pager, with the button still on the page (the final\n * review of 16 October, 1): a page may count the page as the press lands and draw its rows when they come. In a list the\n * library reads as rows, rows or Tab stops the press didn't see, so a spinner drawn first doesn't count; in one it can't\n * (a page's paragraphs), anything new before the pager. Ends with the button, or after 10 s. Returns what stops it.\n */\nfunction whenRowsCome(place: PagerPlace | null, hadRows: Element[], hadStops: Element[], button: HTMLElement, then: () => void): () => void {\n if (!place || typeof MutationObserver === \"undefined\") return () => {};\n const rows = new Set(hadRows), stops = new Set(hadStops);\n const observer = new MutationObserver((records) => {\n if (!button.isConnected) return stop();\n const content = before(place);\n const fresh = hadRows.length\n ? content.flatMap(rowsOf).some((r) => !rows.has(r)) || content.flatMap(stopsIn).some((s) => !stops.has(s))\n : records.some((r) => Array.from(r.addedNodes).some((n) => n instanceof Element && content.some((c) => c === n || c.contains(n))));\n if (!fresh) return;\n stop();\n then();\n });\n const timer = setTimeout(stop, 10_000);\n function stop() {\n observer.disconnect();\n clearTimeout(timer);\n }\n observer.observe(place.parent, { childList: true, subtree: true });\n return stop;\n}\n\n/** Focus the keyboard brought (`:focus-visible`), not a click; a browser without the selector counts every focus. */\nfunction byKeyboard(el: Element): boolean {\n try { return el.matches(\":focus-visible\"); } catch { return true; }\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 // the size in force is always among the choices: a project's size the options lack joins them (the review of 16 October,\n // 5: 20 against 10, 25 and 50 showed and read \"Select...\"), at its place in the page's own order (the final review, 4)\n const sizes = pageSizeOptions && pageSize != null ? withSize(pageSizeOptions, pageSize) : pageSizeOptions;\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's words, then the size chosen, which the Dropdown adds itself (WCAG 4.1.2, 2.5.3;\n Sprint 25.31 item 1): \"Rows per page, 10\" */}\n <Dropdown\n aria-label=\"Rows per page\"\n options={(sizes ?? 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 {/* an icon button's one tooltip, its name (Sprint 25.29 item 18, accessibility#10) */}\n <AutoTooltip content=\"Previous page\">\n <button type=\"button\"\n // a Previous on the first page turns disabled, which drops its focus: it hands focus on (Sprint 25.29 item 2)\n onClick={(e) => { focusAfterSelfRemoval(e.currentTarget); 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 FOCUS_RING,\n )}\n >\n <Icon name=\"chevron-right\" size={16} className=\"rotate-180\" />\n </button>\n </AutoTooltip>\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 FOCUS_RING,\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 <AutoTooltip content=\"Next page\">\n <button type=\"button\"\n // likewise a Next on the last page (Sprint 26's sweep; Sprint 25.29 item 2)\n onClick={(e) => { focusAfterSelfRemoval(e.currentTarget); 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 FOCUS_RING,\n )}\n >\n <Icon name=\"chevron-right\" size={16} />\n </button>\n </AutoTooltip>\n </div>}\n </nav>\n );\n}\n\n/** `size` among `options`, at its place in their own order: largest first stays largest first. */\nfunction withSize(options: number[], size: number): number[] {\n if (options.includes(size)) return options;\n const descending = options.length > 1 && options.every((n, i) => i === 0 || options[i - 1] >= n);\n const at = options.findIndex((n) => (descending ? n < size : n > size));\n return at < 0 ? [...options, size] : [...options.slice(0, at), size, ...options.slice(at)];\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 FOCUS_RING,\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 FOCUS_RING,\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\n/**\n * Pages a list in the project's list style (pagination, load more or infinite scroll) and page size, both from the\n * shell. It returns the pager: the rows to show now (`items`), the page and the counts, and the control's state, which a\n * Table, DataGrid, StackedList, Timeline or VirtualizedList takes as its `pager` prop to draw the rows and the control.\n * `resetOn` starts the list again at page 1 when its value changes (a sort, a search); `pageSize` and `style` set this\n * list apart from the project's.\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"]}
@@ -72,6 +72,7 @@ function keepScroll(el, probe) {
72
72
  }
73
73
  }
74
74
  function takesRoom(box) {
75
+ if (box.hasAttribute("data-bulk-bar-spacer")) return false;
75
76
  const style = getComputedStyle(box);
76
77
  if (style.display === "none" || style.position === "absolute" || style.position === "fixed") return false;
77
78
  const rect = box.getBoundingClientRect();
@@ -129,5 +130,5 @@ function spaceBelow(el, main) {
129
130
  }
130
131
 
131
132
  export { FillContext, useFillHeight };
132
- //# sourceMappingURL=chunk-DBHVJ7Z3.js.map
133
- //# sourceMappingURL=chunk-DBHVJ7Z3.js.map
133
+ //# sourceMappingURL=chunk-SS3C24IJ.js.map
134
+ //# sourceMappingURL=chunk-SS3C24IJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../showcase/src/lib/use-fill-height.ts"],"names":[],"mappings":"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","file":"chunk-SS3C24IJ.js","sourcesContent":["import { createContext, useContext, useLayoutEffect, useState, type RefObject } from \"react\";\n\n/**\n * Sprint 25.16 A42 (P31): a page led by a chart, a board or a split view fills the height under its header, and its\n * content scrolls inside it; the page doesn't. SplitView (frame=\"page\"), Gantt and KanbanBoard use this one mechanism.\n *\n * The element takes the rest of the shell's <main> height (main's height less what sits above it and the padding below\n * it) when all of these hold:\n * - it leads the page: above it there is only the page's header, its chrome (notices, tabs, a toolbar, a search or\n * filters row, however tall) and short rows, so a board in a dashboard's last card keeps its own height;\n * - it is the page's last content: nothing after it, up to <main>, takes room, so nothing below it is cut off (the\n * shell's footer is not the page's: it sits below the fold, as it does under a SplitView frame=\"fill\");\n * - its height follows its content: neither its own class nor a box around it gives it one (a fixed height, a flex\n * column that already gives it the rest), and given more, the page grows;\n * - the rest is tall enough to use (a phone on its side keeps the natural height, and the page scrolls).\n * Outside the shell's <main> (AppShell marks it), or inside a view that fills (a Gantt in a SplitView's pane), it keeps\n * its own height. Returns the height in pixels, or null for the natural height.\n */\nexport function useFillHeight(ref: RefObject<HTMLElement | null>, enabled = true): number | null {\n const insideFill = useContext(FillContext);\n const active = enabled && !insideFill;\n const [height, setHeight] = useState<number | null>(null);\n useLayoutEffect(() => {\n const main = ref.current?.closest<HTMLElement>(\"main[data-shell-main]\");\n if (!active || !main || typeof ResizeObserver === \"undefined\") {\n setHeight(null);\n return;\n }\n let frame = 0;\n // the element is read on each measure: a view that changes its layout (stacked or side by side) changes its root\n const measure = () => {\n frame = 0;\n const el = ref.current;\n setHeight(el && main.contains(el) ? fillHeight(el, main) : null);\n };\n const schedule = () => {\n if (!frame) frame = requestAnimationFrame(measure);\n };\n measure();\n // main's height (the window, a phone's toolbar), and what sits above or after the element at the page's top level (a\n // header's actions wrapping, a banner or a note arriving): the boxes there now, and any that arrive\n const ro = new ResizeObserver(schedule);\n const watch = (box: Element) => {\n ro.observe(box);\n for (const child of Array.from(box.children)) ro.observe(child);\n };\n const page = main.querySelector<HTMLElement>(\"[data-shell-content]\");\n watch(main);\n if (page) watch(page);\n const mo = typeof MutationObserver === \"undefined\" ? null : new MutationObserver((records) => {\n for (const record of records) record.addedNodes.forEach((node) => { if (node instanceof Element) ro.observe(node); });\n schedule();\n });\n mo?.observe(main, { childList: true });\n if (page) mo?.observe(page, { childList: true });\n return () => {\n ro.disconnect();\n mo?.disconnect();\n if (frame) cancelAnimationFrame(frame);\n };\n }, [ref, active]);\n return active ? height : null;\n}\n\n/** Content inside a view that fills: it takes the view's height (h-full), never the page's. */\nexport const FillContext = createContext(false);\n\n/** Below this the rest of the screen is too short to scroll inside (about six rows of a chart). */\nconst MIN_FILL = 240;\n/** A row that may sit between the header and the view: tabs, a toolbar, a filters row (PageContainer's ROW_MAX). */\nconst ROW_MAX = 56;\n\nfunction fillHeight(el: HTMLElement, main: HTMLElement): number | null {\n // the page's own content: the shell's wrapper above its footer, else main\n const page = el.closest<HTMLElement>(\"[data-shell-content]\") ?? main;\n if (!leadsPage(el, page) || !isLastContent(el, page) || keepScroll(el, () => hasOwnHeight(el) || !followsContent(el, main))) return null;\n const mainBox = main.getBoundingClientRect();\n const top = el.getBoundingClientRect().top - mainBox.top - main.clientTop + main.scrollTop;\n const height = Math.floor(main.clientHeight - top - spaceBelow(el, main));\n return height >= MIN_FILL ? height : null;\n}\n\n/**\n * Runs a probe that changes the element's height for a moment, and puts back where everything inside it was scrolled:\n * at its natural height a region that scrolls inside it stops scrolling, and the browser drops its position (Sprint\n * 25.18: the week's hours opened at the working day, then the next measure sent them back to midnight).\n */\nfunction keepScroll<T>(el: HTMLElement, probe: () => T): T {\n const scrolled: Array<[HTMLElement, number, number]> = [];\n for (const node of [el, ...Array.from(el.querySelectorAll<HTMLElement>(\"*\"))]) {\n if (node.scrollTop || node.scrollLeft) scrolled.push([node, node.scrollTop, node.scrollLeft]);\n }\n try {\n return probe();\n } finally {\n for (const [node, top, left] of scrolled) {\n node.scrollTop = top;\n node.scrollLeft = left;\n }\n }\n}\n\n/**\n * Whether a box takes room on the page: an overlay, a portal's anchor, a hidden or an empty node doesn't, and nor does the\n * room the shell keeps at the page's foot while a bulk-action bar floats over it (Sprint 25.33): the view goes on filling.\n */\nfunction takesRoom(box: Element): boolean {\n if (box.hasAttribute(\"data-bulk-bar-spacer\")) return false;\n const style = getComputedStyle(box);\n if (style.display === \"none\" || style.position === \"absolute\" || style.position === \"fixed\") return false;\n const rect = box.getBoundingClientRect();\n return rect.height > 0 && rect.width > 0;\n}\n\n/**\n * The page's chrome, at any height: a notice (an Alert, a banner that wraps to two lines on a phone), tabs, a toolbar, a\n * search or filters row (the review of 1 October: a two-line banner turned the fill off). Content of the page's own (a\n * row of stats, cards, text) is not chrome.\n */\nconst CHROME = '[role=\"alert\"], [role=\"status\"], [role=\"tablist\"], [role=\"toolbar\"], [role=\"search\"]';\nconst isChrome = (box: Element) =>\n box.matches(CHROME) || (box.children.length > 0 && Array.from(box.children).every((child) => !takesRoom(child) || child.matches(CHROME)));\n\n/** Above the element, up to the page's root: only the page's header (its title), its chrome, and rows no taller than ROW_MAX. */\nfunction leadsPage(el: HTMLElement, page: HTMLElement): boolean {\n for (let node: HTMLElement | null = el; node && node !== page; node = node.parentElement) {\n for (let prev = node.previousElementSibling; prev; prev = prev.previousElementSibling) {\n if (!takesRoom(prev)) continue;\n if (prev.matches('[data-gs=\"page-header\"]') || prev.querySelector('[data-gs=\"page-header\"], h1')) continue;\n if (isChrome(prev)) continue;\n if (prev.getBoundingClientRect().height > ROW_MAX) return false;\n }\n }\n return true;\n}\n\n/** Nothing after the element, up to the page's root, takes room. */\nfunction isLastContent(el: HTMLElement, page: HTMLElement): boolean {\n for (let node: HTMLElement | null = el; node && node !== page; node = node.parentElement) {\n for (let next = node.nextElementSibling; next; next = next.nextElementSibling) {\n if (takesRoom(next)) return false;\n }\n }\n return true;\n}\n\n/**\n * The element's own CSS gives it a height that isn't its content's: a fixed height of its own (`h-[420px]`), or `h-full`\n * that resolves against a box which already has one. It keeps it. Read with the fill's own height set aside.\n */\nfunction hasOwnHeight(el: HTMLElement): boolean {\n const inline = el.style.height;\n el.style.height = \"\";\n const own = el.offsetHeight;\n el.style.height = \"auto\";\n const natural = el.offsetHeight;\n el.style.height = inline;\n return Math.abs(own - natural) > 1;\n}\n\n/**\n * Given more height, does the page grow? Probed once: the element is made a screen taller and main's top-level box\n * measured. A box of fixed height around it, or a flex column that already gives it its height, absorbs it.\n */\nfunction followsContent(el: HTMLElement, main: HTMLElement): boolean {\n let top: HTMLElement = el;\n while (top.parentElement && top.parentElement !== main) top = top.parentElement;\n const before = top.offsetHeight;\n const inline = el.style.height;\n el.style.height = `${el.offsetHeight + main.clientHeight}px`;\n const grows = top.offsetHeight > before;\n el.style.height = inline;\n return grows;\n}\n\n/** The padding, borders and margins under the element, up to main's own padding: they stay below it. */\nfunction spaceBelow(el: HTMLElement, main: HTMLElement): number {\n const px = (value: string) => parseFloat(value) || 0;\n let space = px(getComputedStyle(main).paddingBottom);\n for (let node: HTMLElement | null = el; node && node !== main; node = node.parentElement) {\n const style = getComputedStyle(node);\n space += px(style.marginBottom);\n if (node !== el) space += px(style.paddingBottom) + px(style.borderBottomWidth);\n }\n return space;\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { cn, useLatest, usePosition } from './chunk-OWQ7M6R7.js';
2
+ import { cn, useLatest, usePosition } from './chunk-2724SJO2.js';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { useRef, useLayoutEffect, useMemo } from 'react';
5
5
  import { createPortal } from 'react-dom';
@@ -204,5 +204,5 @@ function MentionList({ id, label, items, more = 0, activeIndex, onActiveIndexCha
204
204
  }
205
205
 
206
206
  export { Avatar, MentionList, foldForSearch, initialsOf, matchMentions, mentionOptionId, shownMentions, useActiveOptionInView };
207
- //# sourceMappingURL=chunk-LE72KHIE.js.map
208
- //# sourceMappingURL=chunk-LE72KHIE.js.map
207
+ //# sourceMappingURL=chunk-TMPPBXX3.js.map
208
+ //# sourceMappingURL=chunk-TMPPBXX3.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/initials.ts","../../../showcase/src/components/Avatar.tsx","../../../showcase/src/lib/use-active-option.ts","../../../showcase/src/lib/search-text.ts","../../../showcase/src/components/MentionList.tsx"],"names":["useRef","jsxs","jsx"],"mappings":";;;;;;;AAQO,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,OAAO,IAAA,CACJ,IAAA,EAAK,CACL,KAAA,CAAM,KAAK,CAAA,CACX,MAAA,CAAO,OAAO,CAAA,CACd,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,CACV,GAAA,CAAI,CAAC,IAAA,KAAS,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,CAAE,CAAC,CAAA,IAAK,EAAE,CAAA,CACvC,IAAA,CAAK,EAAE,CAAA,CACP,WAAA,EAAY;AACjB;AAGO,SAAS,WAAW,KAAA,EAAuB;AAChD,EAAA,MAAM,CAAA,GAAI,MAAM,IAAA,EAAK;AACrB,EAAA,IAAI,CAAC,GAAG,OAAO,EAAA;AACf,EAAA,IAAI,CAAC,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,IAAK,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,CAAE,MAAA,IAAU,CAAA,EAAG,OAAO,CAAA;AACvD,EAAA,OAAO,WAAW,CAAC,CAAA;AACrB;ACPA,IAAM,UAAA,GAAa;AAAA,EACjB,EAAA,EAAI,iBAAA;AAAA,EACJ,EAAA,EAAI,mBAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAGA,IAAM,aAAA,GAAgB;AAAA,EACpB,CAAA,EAAG,yGAAA;AAAA,EACH,CAAA,EAAG,yGAAA;AAAA,EACH,CAAA,EAAG,yGAAA;AAAA,EACH,CAAA,EAAG,yGAAA;AAAA,EACH,CAAA,EAAG;AACL,CAAA;AAEA,SAAS,WAAW,IAAA,EAA0C;AAC5D,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,KAAA,MAAW,EAAA,IAAM,MAAM,CAAA,GAAK,CAAA,GAAI,KAAK,EAAA,CAAG,UAAA,CAAW,CAAC,CAAA,KAAO,CAAA;AAC3D,EAAA,OAAS,IAAI,CAAA,GAAK,CAAA;AACpB;AAEA,SAAS,WAAA,CAAY,OAAoB,IAAA,EAAsB;AAC7D,EAAA,IAAI,KAAA,KAAU,UAAU,OAAO,gEAAA;AAC/B,EAAA,IAAI,KAAA,KAAU,WAAW,OAAO,yDAAA;AAChC,EAAA,OAAO,cAAc,KAAA,KAAU,MAAA,GAAS,UAAA,CAAW,IAAI,IAAI,KAAK,CAAA;AAClE;AAMA,SAAS,YAAA,CAAa,EAAE,MAAA,EAAO,EAA6B;AAC1D,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,OAAA,EAAQ,WAAA,EAAY,OAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,aAAA,EAAY,QAAO,SAAA,EAAU,OAAA,EAAQ,eAAA,EAAe,MAAA,EAAQ,WAAU,OAAA,EACnH,QAAA,EAAA;AAAA,IAAA,MAAA,KAAW,QAAA,oBAAY,GAAA,CAAC,QAAA,EAAA,EAAO,EAAA,EAAG,GAAA,EAAI,IAAG,GAAA,EAAI,CAAA,EAAE,GAAA,EAAI,SAAA,EAAU,iCAAA,EAAkC,CAAA;AAAA,IAC/F,MAAA,KAAW,MAAA,oBAAU,GAAA,CAAC,QAAA,EAAA,EAAO,IAAG,GAAA,EAAI,EAAA,EAAG,GAAA,EAAI,CAAA,EAAE,KAAI,IAAA,EAAK,MAAA,EAAO,WAAA,EAAY,GAAA,EAAI,WAAU,mCAAA,EAAoC,CAAA;AAAA,IAC3H,MAAA,KAAW,0BACV,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,QAAA,EAAA,EAAO,IAAG,GAAA,EAAI,EAAA,EAAG,KAAI,CAAA,EAAE,GAAA,EAAI,WAAU,+BAAA,EAAgC,CAAA;AAAA,sBACtE,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,KAAA,EAAM,CAAA,EAAE,KAAA,EAAM,KAAA,EAAM,GAAA,EAAI,MAAA,EAAO,KAAA,EAAM,EAAA,EAAG,KAAA,EAAM,WAAU,4BAAA,EAA6B;AAAA,KAAA,EAC/F,CAAA;AAAA,IAED,MAAA,KAAW,6BACV,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,QAAA,EAAA,EAAO,EAAA,EAAG,GAAA,EAAI,EAAA,EAAG,GAAA,EAAI,CAAA,EAAE,GAAA,EAAI,IAAA,EAAK,MAAA,EAAO,WAAA,EAAY,GAAA,EAAI,SAAA,EAAU,+BAAA,EAAgC,CAAA;AAAA,sBAClG,GAAA,CAAC,MAAA,EAAA,EAAK,EAAA,EAAG,KAAA,EAAM,IAAG,KAAA,EAAM,EAAA,EAAG,KAAA,EAAM,EAAA,EAAG,OAAM,WAAA,EAAY,KAAA,EAAM,aAAA,EAAc,OAAA,EAAQ,WAAU,+BAAA,EAAgC;AAAA,KAAA,EAC9H;AAAA,GAAA,EAEJ,CAAA;AAEJ;AAEO,SAAS,MAAA,CAAO,EAAE,QAAA,EAAU,GAAA,EAAK,GAAA,EAAK,IAAA,GAAO,IAAA,EAAM,MAAA,EAAQ,KAAA,GAAQ,MAAA,EAAQ,SAAA,EAAU,EAAgB;AAE1G,EAAA,MAAM,GAAA,GAAM,OAAO,QAAA,IAAY,EAAA;AAC/B,EAAA,MAAM,KAAA,GAAQ,MAAA,GAAS,CAAC,GAAA,EAAK,MAAM,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,GAAI,MAAA;AAClE,EAAA,MAAM,IAAA,GAAO,EAAA;AAAA,IACX,8DAAA;AAAA,IACA,iCAAA;AAAA,IACA,WAAW,IAAI,CAAA;AAAA,IACf;AAAA,GACF;AAGA,EAAA,MAAM,gBAAgB,GAAA,mBACpB,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,aAAA,EAAY,EAAA;AAAA,MACZ,GAAA;AAAA,MACA,GAAA,EAAK,KAAA,IAAS,GAAA,IAAO,QAAA,IAAY,EAAA;AAAA,MACjC,SAAA,EAAW,EAAA,CAAG,IAAA,EAAM,cAAc;AAAA;AAAA,GACpC,mBAEA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,aAAA,EAAY,EAAA;AAAA,MACZ,IAAA,EAAM,QAAQ,KAAA,GAAQ,MAAA;AAAA,MACtB,YAAA,EAAY,KAAA;AAAA,MACZ,SAAA,EAAW,EAAA;AAAA,QACT,IAAA;AAAA,QACA,WAAA,CAAY,KAAA,EAAO,GAAA,IAAO,QAAA,IAAY,EAAE,CAAA;AAAA,QACxC;AAAA,OACF;AAAA,MAGC,QAAA,EAAA,QAAA,IAAY,IAAA,GAAO,UAAA,CAAW,QAAQ,CAAA,GAAI;AAAA;AAAA,GAC7C;AAGF,EAAA,IAAI,CAAC,QAAQ,OAAO,aAAA;AAEpB,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sBAAA,EACZ,QAAA,EAAA;AAAA,IAAA,aAAA;AAAA,oBACD,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,EAAA;AAAA,UACT,UAAA;AAAA,UACA,SAAS,IAAA,IAAQ,4BAAA;AAAA,UACjB,SAAS,IAAA,IAAQ,0BAAA;AAAA,UACjB,SAAS,IAAA,IAAQ;AAAA,SACnB;AAAA,QACA,aAAA,EAAY,MAAA;AAAA,QAGZ,8BAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yGACd,QAAA,kBAAA,GAAA,CAAC,YAAA,EAAA,EAAa,QAAgB,CAAA,EAChC;AAAA;AAAA;AACF,GAAA,EACF,CAAA;AAEJ;ACnHO,SAAS,qBAAA,CAAsB,MAAqC,QAAA,EAAoC;AAE7G,EAAA,MAAM,KAAA,GAAQ,OAAsB,IAAI,CAAA;AACxC,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,IAAA,IAAI,CAAC,GAAA,IAAO,CAAC,QAAA,EAAU;AACrB,MAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAChB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,IAAA,GAAO,IAAI,WAAA,EAAY;AAC7B,IAAA,MAAM,MAAA,GAAS,OAAO,IAAA,CAAK,cAAA,KAAmB,aAAa,IAAA,CAAK,cAAA,CAAe,QAAQ,CAAA,GAAI,IAAA;AAC3F,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,GAAA,CAAI,QAAA,CAAS,MAAM,CAAA,EAAG;AACtC,IAAA,MAAM,OAAO,CAAA,EAAG,QAAQ,CAAA,EAAA,EAAS,MAAA,CAAO,eAAe,EAAE,CAAA,CAAA;AACzD,IAAA,IAAI,IAAA,KAAS,MAAM,OAAA,EAAS;AAC5B,IAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAChB,IAAA,MAAM,GAAA,GAAM,OAAO,qBAAA,EAAsB,CAAE,MAAM,GAAA,CAAI,qBAAA,EAAsB,CAAE,GAAA,GAAM,GAAA,CAAI,SAAA;AACvF,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,YAAA;AAC5B,IAAA,IAAI,MAAM,GAAA,CAAI,SAAA,MAAe,QAAA,CAAS,EAAE,KAAK,CAAA;AAAA,SAAA,IACpC,MAAA,GAAS,GAAA,CAAI,SAAA,GAAY,GAAA,CAAI,YAAA,EAAc,GAAA,CAAI,QAAA,CAAS,EAAE,GAAA,EAAK,MAAA,GAAS,GAAA,CAAI,YAAA,EAAc,CAAA;AAAA,EACrG,CAAC,CAAA;AACH;;;AC3BO,SAAS,cAAc,IAAA,EAAsB;AAClD,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,CAAE,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA,CAAE,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA,CAAE,WAAA,EAAY;AACrF;ACWA,IAAM,IAAA,GAAO,aAAA;AAON,SAAS,aAAA,CAAc,OAA4B,KAAA,EAAoC;AAC5F,EAAA,MAAM,CAAA,GAAI,KAAK,KAAK,CAAA;AACpB,EAAA,MAAM,IAAA,GAAO,CAAC,CAAA,KAAiC;AAC7C,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,CAAA,CAAE,KAAK,CAAA;AACzB,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,CAAC,CAAA,EAAG,OAAO,CAAA;AAC/B,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA,CAAE,IAAA,CAAK,CAAC,IAAA,KAAS,IAAA,CAAK,UAAA,CAAW,CAAC,CAAC,CAAA,EAAG,OAAO,CAAA;AACjE,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,CAAC,CAAA,EAAG,OAAO,CAAA;AAC7B,IAAA,OAAO,CAAA,CAAE,eAAe,IAAA,CAAK,CAAA,CAAE,WAAW,CAAA,CAAE,QAAA,CAAS,CAAC,CAAA,GAAI,CAAA,GAAI,EAAA;AAAA,EAChE,CAAA;AACA,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,CAAA,EAAG,CAAA,EAAG,IAAA,CAAK,CAAC,GAAE,CAAE,CAAA,CAAE,MAAA,CAAO,CAAC,EAAE,CAAA,EAAE,KAAM,CAAA,IAAK,CAAC,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAC,EAAE,GAAA,CAAI,CAAC,EAAE,CAAA,OAAQ,CAAC,CAAA;AACnH;AAGO,IAAM,kBAAkB,CAAC,MAAA,EAAgB,UAAkB,CAAA,EAAG,MAAM,WAAW,KAAK,CAAA;AAMpF,IAAM,kBAAA,GAAqB,EAAA;AAG3B,SAAS,cAAc,KAAA,EAA0E;AACtG,EAAA,OAAO,EAAE,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,GAAG,kBAAkB,CAAA,EAAG,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,CAAM,MAAA,GAAS,kBAAkB,CAAA,EAAE;AAC3G;AA0BO,SAAS,WAAA,CAAY,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,IAAA,GAAO,CAAA,EAAG,WAAA,EAAa,mBAAA,EAAqB,MAAA,EAAQ,UAAA,EAAY,OAAA,EAAQ,EAAqB;AAC3I,EAAA,MAAM,MAAA,GAASA,OAA8B,IAAI,CAAA;AACjD,EAAA,MAAM,cAAc,OAAA,IAAW,MAAA;AAC/B,EAAA,MAAM,MAAA,GAASA,OAA8B,IAAI,CAAA;AACjD,EAAA,MAAM,SAAA,GAAY,UAAU,UAAU,CAAA;AAEtC,EAAA,MAAM,SAAS,OAAA,CAAQ,OAAO,EAAE,OAAA,EAAS,EAAE,uBAAuB,MAAM,SAAA,CAAU,OAAA,EAAQ,IAAK,IAAI,OAAA,EAAQ,IAAmB,CAAA,EAAI,CAAC,SAAS,CAAC,CAAA;AAC7I,EAAA,MAAM,GAAA,GAAM,WAAA,CAAY,MAAA,EAAQ,WAAA,EAAa,MAAM,MAAA,GAAS,CAAA,EAAG,EAAE,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,OAAA,EAAS,MAAA,EAAQ,GAAG,CAAA;AAE5G,EAAA,qBAAA,CAAsB,MAAA,EAAQ,MAAM,MAAA,GAAS,CAAA,GAAI,gBAAgB,EAAA,EAAI,WAAW,IAAI,MAAS,CAAA;AAC7F,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAE/B,EAAA,OAAO,YAAA;AAAA,oBACLC,IAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,WAAA;AAAA,QACL,SAAA,EAAW,EAAA;AAAA,UACT,2DAAA;AAAA,UACA,oCAAA;AAAA,UACA,2FAAA;AAAA,UACA,0EAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,OAAO,EAAE,GAAA,EAAK,IAAI,GAAA,EAAK,IAAA,EAAM,IAAI,IAAA,EAAK;AAAA,QAGtC,QAAA,EAAA;AAAA,0BAAAC,IAAC,KAAA,EAAA,EAAI,GAAA,EAAK,MAAA,EAAQ,EAAA,EAAQ,MAAK,SAAA,EAAU,YAAA,EAAY,KAAA,EAAO,SAAA,EAAU,wCACrE,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,EAAG,sBACbD,IAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cAEC,EAAA,EAAI,eAAA,CAAgB,EAAA,EAAI,CAAC,CAAA;AAAA,cACzB,IAAA,EAAK,QAAA;AAAA,cACL,IAAA,EAAK,QAAA;AAAA,cACL,QAAA,EAAU,EAAA;AAAA,cACV,iBAAe,CAAA,KAAM,WAAA;AAAA,cACrB,SAAA,EAAW,EAAA;AAAA,gBACT,sHAAA;AAAA,gBACA,yDAAA;AAAA,gBACA,CAAA,KAAM,cAAc,uDAAA,GAA0D;AAAA,eAChF;AAAA,cAEA,WAAA,EAAa,CAAC,CAAA,KAAM,CAAA,CAAE,cAAA,EAAe;AAAA,cACrC,OAAA,EAAS,MAAM,MAAA,CAAO,CAAC,CAAA;AAAA,cACvB,YAAA,EAAc,MAAM,mBAAA,CAAoB,CAAC,CAAA;AAAA,cAGzC,QAAA,EAAA;AAAA,gCAAAC,IAAC,MAAA,EAAA,EAAK,aAAA,EAAY,QAAO,SAAA,EAAU,sBAAA,EACjC,0BAAAA,GAAAA,CAAC,MAAA,EAAA,EAAO,KAAK,CAAA,CAAE,MAAA,EAAQ,UAAU,CAAA,CAAE,KAAA,EAAO,MAAK,IAAA,EAAK,SAAA,EAAU,uBAAsB,CAAA,EACtF,CAAA;AAAA,gCACAD,IAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EACd,QAAA,EAAA;AAAA,kCAAAC,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0DAAA,EAA4D,YAAE,KAAA,EAAM,CAAA;AAAA,kBACnF,CAAA,CAAE,+BAAeA,GAAAA,CAAC,UAAK,SAAA,EAAU,oDAAA,EAAsD,YAAE,WAAA,EAAY;AAAA,iBAAA,EACxG;AAAA;AAAA,aAAA;AAAA,YAvBK,CAAA,CAAE;AAAA,WAyBV,CAAA,EACD,CAAA;AAAA,UACC,OAAO,CAAA,oBACND,IAAAA,CAAC,GAAA,EAAA,EAAE,WAAU,kIAAA,EACV,QAAA,EAAA;AAAA,YAAA,IAAA;AAAA,YAAK,QAAA;AAAA,YAAO,IAAA,KAAS,IAAI,SAAA,GAAY,OAAA;AAAA,YAAQ;AAAA,WAAA,EAChD;AAAA;AAAA;AAAA,KAEJ;AAAA,IACA,QAAA,CAAS;AAAA,GACX;AACF","file":"chunk-LE72KHIE.js","sourcesContent":["/**\n * Initials for an avatar. Round 21 (run 58): a builder passed each person's full name as `initials`, and the avatar\n * printed \"Amara Haddad\" across a 40 px circle on every row of the Team table. The avatar now reads what it is given:\n * up to three characters with no space are initials already and stay as they are (\"JB\", \"ABC\"); anything longer is a\n * name, and its first two words give the letters.\n */\n\n/** \"Sarah Chen\" → \"SC\"; \"Acme\" → \"A\"; \"Mary Jane Watson\" → \"MJ\". */\nexport function initialsOf(name: string): string {\n return name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((word) => Array.from(word)[0] ?? \"\")\n .join(\"\")\n .toUpperCase();\n}\n\n/** What an avatar shows for an `initials` value: initials as given, or the initials of a name. */\nexport function toInitials(value: string): string {\n const s = value.trim();\n if (!s) return \"\";\n if (!/\\s/.test(s) && Array.from(s).length <= 3) return s;\n return initialsOf(s);\n}\n","import { cn } from \"../lib/utils\";\nimport { toInitials } from \"../lib/initials\";\n\nexport type AvatarStatus = \"online\" | \"away\" | \"busy\" | \"offline\";\nexport type AvatarColor = \"auto\" | \"accent\" | \"neutral\" | 1 | 2 | 3 | 4 | 5;\n\ninterface AvatarProps {\n /** One to three letters (\"JB\"). A name passed here shows its initials (\"Amara Haddad\" → \"AH\"), never the whole name. */\n initials?: string;\n src?: string;\n alt?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n status?: AvatarStatus;\n /** Initials background. \"auto\" (default) derives a stable palette tint from alt/initials so groups vary; use \"accent\" sparingly. */\n color?: AvatarColor;\n className?: string;\n}\n\nconst sizeStyles = {\n sm: \"h-8 w-8 text-xs\",\n md: \"h-10 w-10 text-sm\",\n lg: \"h-12 w-12 text-base\",\n};\n\n// Fallbacks cover themes whose tokens CSS predates the decorative palette.\nconst paletteStyles = {\n 1: \"bg-[var(--ds-palette-1-bg,var(--ds-bg-muted))] text-[var(--ds-palette-1-text,var(--ds-text-secondary))]\",\n 2: \"bg-[var(--ds-palette-2-bg,var(--ds-bg-muted))] text-[var(--ds-palette-2-text,var(--ds-text-secondary))]\",\n 3: \"bg-[var(--ds-palette-3-bg,var(--ds-bg-muted))] text-[var(--ds-palette-3-text,var(--ds-text-secondary))]\",\n 4: \"bg-[var(--ds-palette-4-bg,var(--ds-bg-muted))] text-[var(--ds-palette-4-text,var(--ds-text-secondary))]\",\n 5: \"bg-[var(--ds-palette-5-bg,var(--ds-bg-muted))] text-[var(--ds-palette-5-text,var(--ds-text-secondary))]\",\n} as const;\n\nfunction paletteFor(seed: string): keyof typeof paletteStyles {\n let h = 0;\n for (const ch of seed) h = (h * 31 + ch.charCodeAt(0)) >>> 0;\n return ((h % 5) + 1) as keyof typeof paletteStyles;\n}\n\nfunction colorStyles(color: AvatarColor, seed: string): string {\n if (color === \"accent\") return \"bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]\";\n if (color === \"neutral\") return \"bg-[var(--ds-bg-muted)] text-[var(--ds-text-secondary)]\";\n return paletteStyles[color === \"auto\" ? paletteFor(seed) : color];\n}\n\n/**\n * Presence as a shape as well as a colour (Sprint 25.12 A48, WCAG 1.4.1), as Fluent's presence badges do: online a filled\n * dot, away a ring, busy a dot with a bar, offline a ring with a slash. The words are in the avatar's name.\n */\nfunction PresenceMark({ status }: { status: AvatarStatus }) {\n return (\n <svg viewBox=\"0 0 10 10\" width=\"10\" height=\"10\" aria-hidden=\"true\" focusable=\"false\" data-presence={status} className=\"block\">\n {status === \"online\" && <circle cx=\"5\" cy=\"5\" r=\"5\" className=\"fill-[var(--ds-status-success)]\" />}\n {status === \"away\" && <circle cx=\"5\" cy=\"5\" r=\"4\" fill=\"none\" strokeWidth=\"2\" className=\"stroke-[var(--ds-status-warning)]\" />}\n {status === \"busy\" && (\n <>\n <circle cx=\"5\" cy=\"5\" r=\"5\" className=\"fill-[var(--ds-status-error)]\" />\n <rect x=\"2.5\" y=\"4.1\" width=\"5\" height=\"1.8\" rx=\"0.9\" className=\"fill-[var(--ds-bg-canvas)]\" />\n </>\n )}\n {status === \"offline\" && (\n <>\n <circle cx=\"5\" cy=\"5\" r=\"4\" fill=\"none\" strokeWidth=\"2\" className=\"stroke-[var(--ds-text-muted)]\" />\n <line x1=\"3.1\" y1=\"6.9\" x2=\"6.9\" y2=\"3.1\" strokeWidth=\"1.5\" strokeLinecap=\"round\" className=\"stroke-[var(--ds-text-muted)]\" />\n </>\n )}\n </svg>\n );\n}\n\nexport function Avatar({ initials, src, alt, size = \"md\", status, color = \"auto\", className }: AvatarProps) {\n // A48: presence can't show words beside a small avatar, so the avatar's own name carries it (\"Priya Nair, online\")\n const who = alt ?? initials ?? \"\";\n const named = status ? [who, status].filter(Boolean).join(\", \") : undefined;\n const base = cn(\n \"inline-flex items-center justify-center font-medium shrink-0\",\n \"rounded-[var(--ds-radius-full)]\",\n sizeStyles[size],\n className,\n );\n\n // data-avatar: the Table and DataGrid card mode stacks a cell that holds an avatar (Sprint 25.4 C-2).\n const avatarElement = src ? (\n <img\n data-avatar=\"\"\n src={src}\n alt={named ?? alt ?? initials ?? \"\"}\n className={cn(base, \"object-cover\")}\n />\n ) : (\n <div\n data-avatar=\"\"\n role={named ? \"img\" : undefined}\n aria-label={named}\n className={cn(\n base,\n colorStyles(color, alt ?? initials ?? \"\"),\n \"border-[length:var(--ds-border-width)] border-transparent\",\n )}\n >\n {/* round 21: a full name passed as initials shows its initials, not the name squeezed into the circle */}\n {initials != null ? toInitials(initials) : null}\n </div>\n );\n\n if (!status) return avatarElement;\n\n return (\n <div className=\"relative inline-flex\">\n {avatarElement}\n <span\n className={cn(\n \"absolute\",\n size === \"sm\" && \"bottom-[-2px] right-[-2px]\",\n size === \"md\" && \"bottom-[0px] right-[0px]\",\n size === \"lg\" && \"bottom-[2px] right-[2px]\",\n )}\n aria-hidden=\"true\"\n >\n {/* the canvas behind the mark fills a ring's middle and draws the 2px halo that separates it from the photo */}\n <span className=\"block rounded-[var(--ds-radius-full)] bg-[var(--ds-bg-canvas)] shadow-[0_0_0_2px_var(--ds-bg-canvas)]\">\n <PresenceMark status={status} />\n </span>\n </span>\n </div>\n );\n}\n","import { useLayoutEffect, useRef, type RefObject } from \"react\";\n\n/**\n * Keeps the active option of a list driven by aria-activedescendant in view (Sprint 25.17's review; WCAG 2.4.11): when\n * the list opens and when the active option changes, the list scrolls just enough to show it. Only the list's own box\n * scrolls, never the page: the list sits fixed over it. The option is found by its id, in the list's own document or\n * shadow root.\n *\n * Only a change brings it back into view (the second review): a render that leaves the same option active — the page\n * scrolling, the list scrolled by touch or by its scrollbar — leaves the list where the user put it.\n */\nexport function useActiveOptionInView(list: RefObject<HTMLElement | null>, activeId: string | undefined): void {\n // the option last brought into view, by its id and its text: a filtered list reuses an id for another option\n const shown = useRef<string | null>(null);\n useLayoutEffect(() => {\n const box = list.current;\n if (!box || !activeId) {\n shown.current = null;\n return;\n }\n const root = box.getRootNode() as Document | ShadowRoot;\n const option = typeof root.getElementById === \"function\" ? root.getElementById(activeId) : null;\n if (!option || !box.contains(option)) return;\n const seen = `${activeId}\\u0000${option.textContent ?? \"\"}`;\n if (seen === shown.current) return;\n shown.current = seen;\n const top = option.getBoundingClientRect().top - box.getBoundingClientRect().top + box.scrollTop;\n const bottom = top + option.offsetHeight;\n if (top < box.scrollTop) box.scrollTo({ top });\n else if (bottom > box.scrollTop + box.clientHeight) box.scrollTo({ top: bottom - box.clientHeight });\n });\n}\n","/**\n * Text as a search reads it, one way for every picker (Sprint 25.17's second review): no case, no accents, and \"_\" as a\n * space, so \"@toma\" finds Tomás, \"Sao Paulo\" and \"São Paulo\" find America/Sao_Paulo, and \"New_York\" finds New York.\n */\nexport function foldForSearch(text: string): string {\n return text.normalize(\"NFD\").replace(/\\p{M}/gu, \"\").replace(/_/g, \" \").toLowerCase();\n}\n","import { useMemo, useRef, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { usePosition } from \"../lib/use-position\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { useActiveOptionInView } from \"../lib/use-active-option\";\nimport { foldForSearch } from \"../lib/search-text\";\nimport { Avatar } from \"./Avatar\";\n\nexport interface MentionSuggestion {\n id: string;\n label: string;\n avatar?: string;\n description?: string;\n}\n\n/** Text as a search reads it: no case, no accents (\"@toma\" finds Tomás, \"@zoe\" Zoë), as every picker reads it. */\nconst fold = foldForSearch;\n\n/**\n * The suggestions a query matches, by name or by description, ignoring case and accents, best first: a name that starts with it\n * (\"@Mar\": Marcus Chen), then a name with a word that does (Tomás Martin), then a name holding it anywhere (Amara), then\n * a description that does; in their own order within each.\n */\nexport function matchMentions(items: MentionSuggestion[], query: string): MentionSuggestion[] {\n const q = fold(query);\n const rank = (s: MentionSuggestion): number => {\n const name = fold(s.label);\n if (name.startsWith(q)) return 0;\n if (name.split(/\\s+/).some((word) => word.startsWith(q))) return 1;\n if (name.includes(q)) return 2;\n return s.description && fold(s.description).includes(q) ? 3 : -1;\n };\n return items.map((s) => ({ s, r: rank(s) })).filter(({ r }) => r >= 0).sort((a, b) => a.r - b.r).map(({ s }) => s);\n}\n\n/** An option's id, for the field's aria-activedescendant. */\nexport const mentionOptionId = (listId: string, index: number) => `${listId}-option-${index}`;\n\n/**\n * The most people a list shows (Sprint 25.17's second review: two thousand drawn at once took a key a third of a second\n * to paint): the best matches, and a line saying how many more match, which typing narrows.\n */\nexport const MENTION_LIST_LIMIT = 10;\n\n/** The matches a list shows, best first, and how many more there are. */\nexport function shownMentions(found: MentionSuggestion[]): { items: MentionSuggestion[]; more: number } {\n return { items: found.slice(0, MENTION_LIST_LIMIT), more: Math.max(0, found.length - MENTION_LIST_LIMIT) };\n}\n\nexport interface MentionListProps {\n /** The listbox's id: the field's aria-controls, and the stem of its options' ids. */\n id: string;\n /** The listbox's name (\"People\", \"Suggestions\"). */\n label: string;\n /** The people shown, at most MENTION_LIST_LIMIT (shownMentions). */\n items: MentionSuggestion[];\n /** How many more match than are shown: the list says so under its people. */\n more?: number;\n activeIndex: number;\n onActiveIndexChange: (index: number) => void;\n onPick: (item: MentionSuggestion) => void;\n /** Where the mention being typed is, in the viewport: the list opens under it, above it when the screen runs out below. */\n anchorRect: () => DOMRect | null;\n /** The list's element, for the owner's checks (a click outside, focus moving into it). */\n listRef?: RefObject<HTMLDivElement | null>;\n}\n\n/**\n * The list of suggestions while a mention is typed (Sprint 25.17 A17): MentionInput's and the editor's, so a mention\n * looks and works the same in a comment box and a document. The field keeps focus and carries aria-activedescendant\n * (the field's owner wires the keys: arrows move, Enter or Tab inserts, Escape closes); the options are no Tab stops,\n * and a pointer picks one without taking focus from the field.\n */\nexport function MentionList({ id, label, items, more = 0, activeIndex, onActiveIndexChange, onPick, anchorRect, listRef }: MentionListProps) {\n const ownRef = useRef<HTMLDivElement | null>(null);\n const floatingRef = listRef ?? ownRef;\n const boxRef = useRef<HTMLDivElement | null>(null);\n const anchorRef = useLatest(anchorRect);\n // the caret as an element for usePosition, which reads only its rectangle\n const anchor = useMemo(() => ({ current: { getBoundingClientRect: () => anchorRef.current() ?? new DOMRect() } as HTMLElement }), [anchorRef]);\n const pos = usePosition(anchor, floatingRef, items.length > 0, { side: \"bottom\", align: \"start\", offset: 4 });\n // the arrows move through a list longer than its box: the active person stays in view\n useActiveOptionInView(boxRef, items.length > 0 ? mentionOptionId(id, activeIndex) : undefined);\n if (items.length === 0) return null;\n\n return createPortal(\n <div\n ref={floatingRef}\n className={cn(\n \"fixed z-[var(--ds-z-popover)] min-w-[200px] flex flex-col\",\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)] shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]\",\n )}\n style={{ top: pos.top, left: pos.left }}\n >\n {/* rows inset in the list, rounded, as Combobox's and the menus' are (the second review: full-width square rows) */}\n <div ref={boxRef} id={id} role=\"listbox\" aria-label={label} className=\"max-h-[200px] overflow-y-auto p-ds-1\">\n {items.map((s, i) => (\n <button\n key={s.id}\n id={mentionOptionId(id, i)}\n type=\"button\"\n role=\"option\"\n tabIndex={-1}\n aria-selected={i === activeIndex}\n className={cn(\n \"flex items-center gap-ds-2.5 w-full px-ds-2 py-ds-1.5 text-left text-sm cursor-pointer rounded-[var(--ds-radius-sm)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n i === activeIndex ? \"bg-[var(--ds-bg-muted)] text-[var(--ds-text-primary)]\" : \"text-[var(--ds-text-secondary)]\",\n )}\n // the field keeps focus, so the pick lands where the mention is being typed\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onPick(s)}\n onMouseEnter={() => onActiveIndexChange(i)}\n >\n {/* the name follows as text, so the picture is decoration */}\n <span aria-hidden=\"true\" className=\"inline-flex shrink-0\">\n <Avatar src={s.avatar} initials={s.label} size=\"sm\" className=\"!h-6 !w-6 !text-2xs\" />\n </span>\n <span className=\"min-w-0\">\n <span className=\"block font-medium text-[var(--ds-text-primary)] truncate\">{s.label}</span>\n {s.description && <span className=\"block text-xs text-[var(--ds-text-muted)] truncate\">{s.description}</span>}\n </span>\n </button>\n ))}\n </div>\n {more > 0 && (\n <p className=\"px-ds-3 py-ds-1.5 text-xs text-[var(--ds-text-muted)] border-t-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]\">\n {more} more {more === 1 ? \"matches\" : \"match\"}: keep typing to narrow\n </p>\n )}\n </div>,\n document.body,\n );\n}\n"]}
1
+ {"version":3,"sources":["../../../showcase/src/lib/initials.ts","../../../showcase/src/components/Avatar.tsx","../../../showcase/src/lib/use-active-option.ts","../../../showcase/src/lib/search-text.ts","../../../showcase/src/components/MentionList.tsx"],"names":["useRef","jsxs","jsx"],"mappings":";;;;;;;AAQO,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,OAAO,IAAA,CACJ,IAAA,EAAK,CACL,KAAA,CAAM,KAAK,CAAA,CACX,MAAA,CAAO,OAAO,CAAA,CACd,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,CACV,GAAA,CAAI,CAAC,IAAA,KAAS,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,CAAE,CAAC,CAAA,IAAK,EAAE,CAAA,CACvC,IAAA,CAAK,EAAE,CAAA,CACP,WAAA,EAAY;AACjB;AAGO,SAAS,WAAW,KAAA,EAAuB;AAChD,EAAA,MAAM,CAAA,GAAI,MAAM,IAAA,EAAK;AACrB,EAAA,IAAI,CAAC,GAAG,OAAO,EAAA;AACf,EAAA,IAAI,CAAC,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,IAAK,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,CAAE,MAAA,IAAU,CAAA,EAAG,OAAO,CAAA;AACvD,EAAA,OAAO,WAAW,CAAC,CAAA;AACrB;ACPA,IAAM,UAAA,GAAa;AAAA,EACjB,EAAA,EAAI,iBAAA;AAAA,EACJ,EAAA,EAAI,mBAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAGA,IAAM,aAAA,GAAgB;AAAA,EACpB,CAAA,EAAG,yGAAA;AAAA,EACH,CAAA,EAAG,yGAAA;AAAA,EACH,CAAA,EAAG,yGAAA;AAAA,EACH,CAAA,EAAG,yGAAA;AAAA,EACH,CAAA,EAAG;AACL,CAAA;AAEA,SAAS,WAAW,IAAA,EAA0C;AAC5D,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,KAAA,MAAW,EAAA,IAAM,MAAM,CAAA,GAAK,CAAA,GAAI,KAAK,EAAA,CAAG,UAAA,CAAW,CAAC,CAAA,KAAO,CAAA;AAC3D,EAAA,OAAS,IAAI,CAAA,GAAK,CAAA;AACpB;AAEA,SAAS,WAAA,CAAY,OAAoB,IAAA,EAAsB;AAC7D,EAAA,IAAI,KAAA,KAAU,UAAU,OAAO,gEAAA;AAC/B,EAAA,IAAI,KAAA,KAAU,WAAW,OAAO,yDAAA;AAChC,EAAA,OAAO,cAAc,KAAA,KAAU,MAAA,GAAS,UAAA,CAAW,IAAI,IAAI,KAAK,CAAA;AAClE;AAMA,SAAS,YAAA,CAAa,EAAE,MAAA,EAAO,EAA6B;AAC1D,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,OAAA,EAAQ,WAAA,EAAY,OAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,aAAA,EAAY,QAAO,SAAA,EAAU,OAAA,EAAQ,eAAA,EAAe,MAAA,EAAQ,WAAU,OAAA,EACnH,QAAA,EAAA;AAAA,IAAA,MAAA,KAAW,QAAA,oBAAY,GAAA,CAAC,QAAA,EAAA,EAAO,EAAA,EAAG,GAAA,EAAI,IAAG,GAAA,EAAI,CAAA,EAAE,GAAA,EAAI,SAAA,EAAU,iCAAA,EAAkC,CAAA;AAAA,IAC/F,MAAA,KAAW,MAAA,oBAAU,GAAA,CAAC,QAAA,EAAA,EAAO,IAAG,GAAA,EAAI,EAAA,EAAG,GAAA,EAAI,CAAA,EAAE,KAAI,IAAA,EAAK,MAAA,EAAO,WAAA,EAAY,GAAA,EAAI,WAAU,mCAAA,EAAoC,CAAA;AAAA,IAC3H,MAAA,KAAW,0BACV,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,QAAA,EAAA,EAAO,IAAG,GAAA,EAAI,EAAA,EAAG,KAAI,CAAA,EAAE,GAAA,EAAI,WAAU,+BAAA,EAAgC,CAAA;AAAA,sBACtE,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,KAAA,EAAM,CAAA,EAAE,KAAA,EAAM,KAAA,EAAM,GAAA,EAAI,MAAA,EAAO,KAAA,EAAM,EAAA,EAAG,KAAA,EAAM,WAAU,4BAAA,EAA6B;AAAA,KAAA,EAC/F,CAAA;AAAA,IAED,MAAA,KAAW,6BACV,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,QAAA,EAAA,EAAO,EAAA,EAAG,GAAA,EAAI,EAAA,EAAG,GAAA,EAAI,CAAA,EAAE,GAAA,EAAI,IAAA,EAAK,MAAA,EAAO,WAAA,EAAY,GAAA,EAAI,SAAA,EAAU,+BAAA,EAAgC,CAAA;AAAA,sBAClG,GAAA,CAAC,MAAA,EAAA,EAAK,EAAA,EAAG,KAAA,EAAM,IAAG,KAAA,EAAM,EAAA,EAAG,KAAA,EAAM,EAAA,EAAG,OAAM,WAAA,EAAY,KAAA,EAAM,aAAA,EAAc,OAAA,EAAQ,WAAU,+BAAA,EAAgC;AAAA,KAAA,EAC9H;AAAA,GAAA,EAEJ,CAAA;AAEJ;AAEO,SAAS,MAAA,CAAO,EAAE,QAAA,EAAU,GAAA,EAAK,GAAA,EAAK,IAAA,GAAO,IAAA,EAAM,MAAA,EAAQ,KAAA,GAAQ,MAAA,EAAQ,SAAA,EAAU,EAAgB;AAE1G,EAAA,MAAM,GAAA,GAAM,OAAO,QAAA,IAAY,EAAA;AAC/B,EAAA,MAAM,KAAA,GAAQ,MAAA,GAAS,CAAC,GAAA,EAAK,MAAM,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,GAAI,MAAA;AAClE,EAAA,MAAM,IAAA,GAAO,EAAA;AAAA,IACX,8DAAA;AAAA,IACA,iCAAA;AAAA,IACA,WAAW,IAAI,CAAA;AAAA,IACf;AAAA,GACF;AAGA,EAAA,MAAM,gBAAgB,GAAA,mBACpB,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,aAAA,EAAY,EAAA;AAAA,MACZ,GAAA;AAAA,MACA,GAAA,EAAK,KAAA,IAAS,GAAA,IAAO,QAAA,IAAY,EAAA;AAAA,MACjC,SAAA,EAAW,EAAA,CAAG,IAAA,EAAM,cAAc;AAAA;AAAA,GACpC,mBAEA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,aAAA,EAAY,EAAA;AAAA,MACZ,IAAA,EAAM,QAAQ,KAAA,GAAQ,MAAA;AAAA,MACtB,YAAA,EAAY,KAAA;AAAA,MACZ,SAAA,EAAW,EAAA;AAAA,QACT,IAAA;AAAA,QACA,WAAA,CAAY,KAAA,EAAO,GAAA,IAAO,QAAA,IAAY,EAAE,CAAA;AAAA,QACxC;AAAA,OACF;AAAA,MAGC,QAAA,EAAA,QAAA,IAAY,IAAA,GAAO,UAAA,CAAW,QAAQ,CAAA,GAAI;AAAA;AAAA,GAC7C;AAGF,EAAA,IAAI,CAAC,QAAQ,OAAO,aAAA;AAEpB,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sBAAA,EACZ,QAAA,EAAA;AAAA,IAAA,aAAA;AAAA,oBACD,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,EAAA;AAAA,UACT,UAAA;AAAA,UACA,SAAS,IAAA,IAAQ,4BAAA;AAAA,UACjB,SAAS,IAAA,IAAQ,0BAAA;AAAA,UACjB,SAAS,IAAA,IAAQ;AAAA,SACnB;AAAA,QACA,aAAA,EAAY,MAAA;AAAA,QAGZ,8BAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yGACd,QAAA,kBAAA,GAAA,CAAC,YAAA,EAAA,EAAa,QAAgB,CAAA,EAChC;AAAA;AAAA;AACF,GAAA,EACF,CAAA;AAEJ;ACnHO,SAAS,qBAAA,CAAsB,MAAqC,QAAA,EAAoC;AAE7G,EAAA,MAAM,KAAA,GAAQ,OAAsB,IAAI,CAAA;AACxC,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,IAAA,IAAI,CAAC,GAAA,IAAO,CAAC,QAAA,EAAU;AACrB,MAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAChB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,IAAA,GAAO,IAAI,WAAA,EAAY;AAC7B,IAAA,MAAM,MAAA,GAAS,OAAO,IAAA,CAAK,cAAA,KAAmB,aAAa,IAAA,CAAK,cAAA,CAAe,QAAQ,CAAA,GAAI,IAAA;AAC3F,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,GAAA,CAAI,QAAA,CAAS,MAAM,CAAA,EAAG;AACtC,IAAA,MAAM,OAAO,CAAA,EAAG,QAAQ,CAAA,EAAA,EAAS,MAAA,CAAO,eAAe,EAAE,CAAA,CAAA;AACzD,IAAA,IAAI,IAAA,KAAS,MAAM,OAAA,EAAS;AAC5B,IAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAChB,IAAA,MAAM,GAAA,GAAM,OAAO,qBAAA,EAAsB,CAAE,MAAM,GAAA,CAAI,qBAAA,EAAsB,CAAE,GAAA,GAAM,GAAA,CAAI,SAAA;AACvF,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,YAAA;AAC5B,IAAA,IAAI,MAAM,GAAA,CAAI,SAAA,MAAe,QAAA,CAAS,EAAE,KAAK,CAAA;AAAA,SAAA,IACpC,MAAA,GAAS,GAAA,CAAI,SAAA,GAAY,GAAA,CAAI,YAAA,EAAc,GAAA,CAAI,QAAA,CAAS,EAAE,GAAA,EAAK,MAAA,GAAS,GAAA,CAAI,YAAA,EAAc,CAAA;AAAA,EACrG,CAAC,CAAA;AACH;;;AC3BO,SAAS,cAAc,IAAA,EAAsB;AAClD,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,CAAE,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA,CAAE,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA,CAAE,WAAA,EAAY;AACrF;ACWA,IAAM,IAAA,GAAO,aAAA;AAON,SAAS,aAAA,CAAc,OAA4B,KAAA,EAAoC;AAC5F,EAAA,MAAM,CAAA,GAAI,KAAK,KAAK,CAAA;AACpB,EAAA,MAAM,IAAA,GAAO,CAAC,CAAA,KAAiC;AAC7C,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,CAAA,CAAE,KAAK,CAAA;AACzB,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,CAAC,CAAA,EAAG,OAAO,CAAA;AAC/B,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA,CAAE,IAAA,CAAK,CAAC,IAAA,KAAS,IAAA,CAAK,UAAA,CAAW,CAAC,CAAC,CAAA,EAAG,OAAO,CAAA;AACjE,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,CAAC,CAAA,EAAG,OAAO,CAAA;AAC7B,IAAA,OAAO,CAAA,CAAE,eAAe,IAAA,CAAK,CAAA,CAAE,WAAW,CAAA,CAAE,QAAA,CAAS,CAAC,CAAA,GAAI,CAAA,GAAI,EAAA;AAAA,EAChE,CAAA;AACA,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,CAAA,EAAG,CAAA,EAAG,IAAA,CAAK,CAAC,GAAE,CAAE,CAAA,CAAE,MAAA,CAAO,CAAC,EAAE,CAAA,EAAE,KAAM,CAAA,IAAK,CAAC,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAC,EAAE,GAAA,CAAI,CAAC,EAAE,CAAA,OAAQ,CAAC,CAAA;AACnH;AAGO,IAAM,kBAAkB,CAAC,MAAA,EAAgB,UAAkB,CAAA,EAAG,MAAM,WAAW,KAAK,CAAA;AAMpF,IAAM,kBAAA,GAAqB,EAAA;AAG3B,SAAS,cAAc,KAAA,EAA0E;AACtG,EAAA,OAAO,EAAE,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,GAAG,kBAAkB,CAAA,EAAG,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,CAAM,MAAA,GAAS,kBAAkB,CAAA,EAAE;AAC3G;AA0BO,SAAS,WAAA,CAAY,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,IAAA,GAAO,CAAA,EAAG,WAAA,EAAa,mBAAA,EAAqB,MAAA,EAAQ,UAAA,EAAY,OAAA,EAAQ,EAAqB;AAC3I,EAAA,MAAM,MAAA,GAASA,OAA8B,IAAI,CAAA;AACjD,EAAA,MAAM,cAAc,OAAA,IAAW,MAAA;AAC/B,EAAA,MAAM,MAAA,GAASA,OAA8B,IAAI,CAAA;AACjD,EAAA,MAAM,SAAA,GAAY,UAAU,UAAU,CAAA;AAEtC,EAAA,MAAM,SAAS,OAAA,CAAQ,OAAO,EAAE,OAAA,EAAS,EAAE,uBAAuB,MAAM,SAAA,CAAU,OAAA,EAAQ,IAAK,IAAI,OAAA,EAAQ,IAAmB,CAAA,EAAI,CAAC,SAAS,CAAC,CAAA;AAC7I,EAAA,MAAM,GAAA,GAAM,WAAA,CAAY,MAAA,EAAQ,WAAA,EAAa,MAAM,MAAA,GAAS,CAAA,EAAG,EAAE,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,OAAA,EAAS,MAAA,EAAQ,GAAG,CAAA;AAE5G,EAAA,qBAAA,CAAsB,MAAA,EAAQ,MAAM,MAAA,GAAS,CAAA,GAAI,gBAAgB,EAAA,EAAI,WAAW,IAAI,MAAS,CAAA;AAC7F,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAE/B,EAAA,OAAO,YAAA;AAAA,oBACLC,IAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,WAAA;AAAA,QACL,SAAA,EAAW,EAAA;AAAA,UACT,2DAAA;AAAA,UACA,oCAAA;AAAA,UACA,2FAAA;AAAA,UACA,0EAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,OAAO,EAAE,GAAA,EAAK,IAAI,GAAA,EAAK,IAAA,EAAM,IAAI,IAAA,EAAK;AAAA,QAGtC,QAAA,EAAA;AAAA,0BAAAC,IAAC,KAAA,EAAA,EAAI,GAAA,EAAK,MAAA,EAAQ,EAAA,EAAQ,MAAK,SAAA,EAAU,YAAA,EAAY,KAAA,EAAO,SAAA,EAAU,wCACrE,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,EAAG,sBACbD,IAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cAEC,EAAA,EAAI,eAAA,CAAgB,EAAA,EAAI,CAAC,CAAA;AAAA,cACzB,IAAA,EAAK,QAAA;AAAA,cACL,IAAA,EAAK,QAAA;AAAA,cACL,QAAA,EAAU,EAAA;AAAA,cACV,iBAAe,CAAA,KAAM,WAAA;AAAA,cACrB,SAAA,EAAW,EAAA;AAAA,gBACT,sHAAA;AAAA,gBACA,yDAAA;AAAA,gBACA,CAAA,KAAM,cAAc,uDAAA,GAA0D;AAAA,eAChF;AAAA,cAEA,WAAA,EAAa,CAAC,CAAA,KAAM,CAAA,CAAE,cAAA,EAAe;AAAA,cACrC,OAAA,EAAS,MAAM,MAAA,CAAO,CAAC,CAAA;AAAA,cACvB,YAAA,EAAc,MAAM,mBAAA,CAAoB,CAAC,CAAA;AAAA,cAGzC,QAAA,EAAA;AAAA,gCAAAC,IAAC,MAAA,EAAA,EAAK,aAAA,EAAY,QAAO,SAAA,EAAU,sBAAA,EACjC,0BAAAA,GAAAA,CAAC,MAAA,EAAA,EAAO,KAAK,CAAA,CAAE,MAAA,EAAQ,UAAU,CAAA,CAAE,KAAA,EAAO,MAAK,IAAA,EAAK,SAAA,EAAU,uBAAsB,CAAA,EACtF,CAAA;AAAA,gCACAD,IAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EACd,QAAA,EAAA;AAAA,kCAAAC,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0DAAA,EAA4D,YAAE,KAAA,EAAM,CAAA;AAAA,kBACnF,CAAA,CAAE,+BAAeA,GAAAA,CAAC,UAAK,SAAA,EAAU,oDAAA,EAAsD,YAAE,WAAA,EAAY;AAAA,iBAAA,EACxG;AAAA;AAAA,aAAA;AAAA,YAvBK,CAAA,CAAE;AAAA,WAyBV,CAAA,EACD,CAAA;AAAA,UACC,OAAO,CAAA,oBACND,IAAAA,CAAC,GAAA,EAAA,EAAE,WAAU,kIAAA,EACV,QAAA,EAAA;AAAA,YAAA,IAAA;AAAA,YAAK,QAAA;AAAA,YAAO,IAAA,KAAS,IAAI,SAAA,GAAY,OAAA;AAAA,YAAQ;AAAA,WAAA,EAChD;AAAA;AAAA;AAAA,KAEJ;AAAA,IACA,QAAA,CAAS;AAAA,GACX;AACF","file":"chunk-TMPPBXX3.js","sourcesContent":["/**\n * Initials for an avatar. Round 21 (run 58): a builder passed each person's full name as `initials`, and the avatar\n * printed \"Amara Haddad\" across a 40 px circle on every row of the Team table. The avatar now reads what it is given:\n * up to three characters with no space are initials already and stay as they are (\"JB\", \"ABC\"); anything longer is a\n * name, and its first two words give the letters.\n */\n\n/** \"Sarah Chen\" → \"SC\"; \"Acme\" → \"A\"; \"Mary Jane Watson\" → \"MJ\". */\nexport function initialsOf(name: string): string {\n return name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((word) => Array.from(word)[0] ?? \"\")\n .join(\"\")\n .toUpperCase();\n}\n\n/** What an avatar shows for an `initials` value: initials as given, or the initials of a name. */\nexport function toInitials(value: string): string {\n const s = value.trim();\n if (!s) return \"\";\n if (!/\\s/.test(s) && Array.from(s).length <= 3) return s;\n return initialsOf(s);\n}\n","import { cn } from \"../lib/utils\";\nimport { toInitials } from \"../lib/initials\";\n\nexport type AvatarStatus = \"online\" | \"away\" | \"busy\" | \"offline\";\nexport type AvatarColor = \"auto\" | \"accent\" | \"neutral\" | 1 | 2 | 3 | 4 | 5;\n\ninterface AvatarProps {\n /** One to three letters (\"JB\"). A name passed here shows its initials (\"Amara Haddad\" → \"AH\"), never the whole name. */\n initials?: string;\n src?: string;\n alt?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n status?: AvatarStatus;\n /** Initials background. \"auto\" (default) derives a stable palette tint from alt/initials so groups vary; use \"accent\" sparingly. */\n color?: AvatarColor;\n className?: string;\n}\n\nconst sizeStyles = {\n sm: \"h-8 w-8 text-xs\",\n md: \"h-10 w-10 text-sm\",\n lg: \"h-12 w-12 text-base\",\n};\n\n// Fallbacks cover themes whose tokens CSS predates the decorative palette.\nconst paletteStyles = {\n 1: \"bg-[var(--ds-palette-1-bg,var(--ds-bg-muted))] text-[var(--ds-palette-1-text,var(--ds-text-secondary))]\",\n 2: \"bg-[var(--ds-palette-2-bg,var(--ds-bg-muted))] text-[var(--ds-palette-2-text,var(--ds-text-secondary))]\",\n 3: \"bg-[var(--ds-palette-3-bg,var(--ds-bg-muted))] text-[var(--ds-palette-3-text,var(--ds-text-secondary))]\",\n 4: \"bg-[var(--ds-palette-4-bg,var(--ds-bg-muted))] text-[var(--ds-palette-4-text,var(--ds-text-secondary))]\",\n 5: \"bg-[var(--ds-palette-5-bg,var(--ds-bg-muted))] text-[var(--ds-palette-5-text,var(--ds-text-secondary))]\",\n} as const;\n\nfunction paletteFor(seed: string): keyof typeof paletteStyles {\n let h = 0;\n for (const ch of seed) h = (h * 31 + ch.charCodeAt(0)) >>> 0;\n return ((h % 5) + 1) as keyof typeof paletteStyles;\n}\n\nfunction colorStyles(color: AvatarColor, seed: string): string {\n if (color === \"accent\") return \"bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]\";\n if (color === \"neutral\") return \"bg-[var(--ds-bg-muted)] text-[var(--ds-text-secondary)]\";\n return paletteStyles[color === \"auto\" ? paletteFor(seed) : color];\n}\n\n/**\n * Presence as a shape as well as a colour (Sprint 25.12 A48, WCAG 1.4.1), as Fluent's presence badges do: online a filled\n * dot, away a ring, busy a dot with a bar, offline a ring with a slash. The words are in the avatar's name.\n */\nfunction PresenceMark({ status }: { status: AvatarStatus }) {\n return (\n <svg viewBox=\"0 0 10 10\" width=\"10\" height=\"10\" aria-hidden=\"true\" focusable=\"false\" data-presence={status} className=\"block\">\n {status === \"online\" && <circle cx=\"5\" cy=\"5\" r=\"5\" className=\"fill-[var(--ds-status-success)]\" />}\n {status === \"away\" && <circle cx=\"5\" cy=\"5\" r=\"4\" fill=\"none\" strokeWidth=\"2\" className=\"stroke-[var(--ds-status-warning)]\" />}\n {status === \"busy\" && (\n <>\n <circle cx=\"5\" cy=\"5\" r=\"5\" className=\"fill-[var(--ds-status-error)]\" />\n <rect x=\"2.5\" y=\"4.1\" width=\"5\" height=\"1.8\" rx=\"0.9\" className=\"fill-[var(--ds-bg-canvas)]\" />\n </>\n )}\n {status === \"offline\" && (\n <>\n <circle cx=\"5\" cy=\"5\" r=\"4\" fill=\"none\" strokeWidth=\"2\" className=\"stroke-[var(--ds-text-muted)]\" />\n <line x1=\"3.1\" y1=\"6.9\" x2=\"6.9\" y2=\"3.1\" strokeWidth=\"1.5\" strokeLinecap=\"round\" className=\"stroke-[var(--ds-text-muted)]\" />\n </>\n )}\n </svg>\n );\n}\n\nexport function Avatar({ initials, src, alt, size = \"md\", status, color = \"auto\", className }: AvatarProps) {\n // A48: presence can't show words beside a small avatar, so the avatar's own name carries it (\"Priya Nair, online\")\n const who = alt ?? initials ?? \"\";\n const named = status ? [who, status].filter(Boolean).join(\", \") : undefined;\n const base = cn(\n \"inline-flex items-center justify-center font-medium shrink-0\",\n \"rounded-[var(--ds-radius-full)]\",\n sizeStyles[size],\n className,\n );\n\n // data-avatar: the Table and DataGrid card mode stacks a cell that holds an avatar (Sprint 25.4 C-2).\n const avatarElement = src ? (\n <img\n data-avatar=\"\"\n src={src}\n alt={named ?? alt ?? initials ?? \"\"}\n className={cn(base, \"object-cover\")}\n />\n ) : (\n <div\n data-avatar=\"\"\n role={named ? \"img\" : undefined}\n aria-label={named}\n className={cn(\n base,\n colorStyles(color, alt ?? initials ?? \"\"),\n \"border-[length:var(--ds-border-width)] border-transparent\",\n )}\n >\n {/* round 21: a full name passed as initials shows its initials, not the name squeezed into the circle */}\n {initials != null ? toInitials(initials) : null}\n </div>\n );\n\n if (!status) return avatarElement;\n\n return (\n <div className=\"relative inline-flex\">\n {avatarElement}\n <span\n className={cn(\n \"absolute\",\n size === \"sm\" && \"bottom-[-2px] right-[-2px]\",\n size === \"md\" && \"bottom-[0px] right-[0px]\",\n size === \"lg\" && \"bottom-[2px] right-[2px]\",\n )}\n aria-hidden=\"true\"\n >\n {/* the canvas behind the mark fills a ring's middle and draws the 2px halo that separates it from the photo */}\n <span className=\"block rounded-[var(--ds-radius-full)] bg-[var(--ds-bg-canvas)] shadow-[0_0_0_2px_var(--ds-bg-canvas)]\">\n <PresenceMark status={status} />\n </span>\n </span>\n </div>\n );\n}\n","import { useLayoutEffect, useRef, type RefObject } from \"react\";\n\n/**\n * Keeps the active option of a list driven by aria-activedescendant in view (Sprint 25.17's review; WCAG 2.4.11): when\n * the list opens and when the active option changes, the list scrolls just enough to show it. Only the list's own box\n * scrolls, never the page: the list sits fixed over it. The option is found by its id, in the list's own document or\n * shadow root.\n *\n * Only a change brings it back into view (the second review): a render that leaves the same option active — the page\n * scrolling, the list scrolled by touch or by its scrollbar — leaves the list where the user put it.\n */\nexport function useActiveOptionInView(list: RefObject<HTMLElement | null>, activeId: string | undefined): void {\n // the option last brought into view, by its id and its text: a filtered list reuses an id for another option\n const shown = useRef<string | null>(null);\n useLayoutEffect(() => {\n const box = list.current;\n if (!box || !activeId) {\n shown.current = null;\n return;\n }\n const root = box.getRootNode() as Document | ShadowRoot;\n const option = typeof root.getElementById === \"function\" ? root.getElementById(activeId) : null;\n if (!option || !box.contains(option)) return;\n const seen = `${activeId}\\u0000${option.textContent ?? \"\"}`;\n if (seen === shown.current) return;\n shown.current = seen;\n const top = option.getBoundingClientRect().top - box.getBoundingClientRect().top + box.scrollTop;\n const bottom = top + option.offsetHeight;\n if (top < box.scrollTop) box.scrollTo({ top });\n else if (bottom > box.scrollTop + box.clientHeight) box.scrollTo({ top: bottom - box.clientHeight });\n });\n}\n","/**\n * Text as a search reads it, one way for every picker (Sprint 25.17's second review): no case, no accents, and \"_\" as a\n * space, so \"@toma\" finds Tomás, \"Sao Paulo\" and \"São Paulo\" find America/Sao_Paulo, and \"New_York\" finds New York.\n */\nexport function foldForSearch(text: string): string {\n return text.normalize(\"NFD\").replace(/\\p{M}/gu, \"\").replace(/_/g, \" \").toLowerCase();\n}\n","import { useMemo, useRef, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { usePosition } from \"../lib/use-position\";\nimport { useLatest } from \"../lib/use-latest\";\nimport { useActiveOptionInView } from \"../lib/use-active-option\";\nimport { foldForSearch } from \"../lib/search-text\";\nimport { Avatar } from \"./Avatar\";\n\nexport interface MentionSuggestion {\n id: string;\n label: string;\n avatar?: string;\n description?: string;\n}\n\n/** Text as a search reads it: no case, no accents (\"@toma\" finds Tomás, \"@zoe\" Zoë), as every picker reads it. */\nconst fold = foldForSearch;\n\n/**\n * The suggestions a query matches, by name or by description, ignoring case and accents, best first: a name that starts with it\n * (\"@Mar\": Marcus Chen), then a name with a word that does (Tomás Martin), then a name holding it anywhere (Amara), then\n * a description that does; in their own order within each.\n */\nexport function matchMentions(items: MentionSuggestion[], query: string): MentionSuggestion[] {\n const q = fold(query);\n const rank = (s: MentionSuggestion): number => {\n const name = fold(s.label);\n if (name.startsWith(q)) return 0;\n if (name.split(/\\s+/).some((word) => word.startsWith(q))) return 1;\n if (name.includes(q)) return 2;\n return s.description && fold(s.description).includes(q) ? 3 : -1;\n };\n return items.map((s) => ({ s, r: rank(s) })).filter(({ r }) => r >= 0).sort((a, b) => a.r - b.r).map(({ s }) => s);\n}\n\n/** An option's id, for the field's aria-activedescendant. */\nexport const mentionOptionId = (listId: string, index: number) => `${listId}-option-${index}`;\n\n/**\n * The most people a list shows (Sprint 25.17's second review: two thousand drawn at once took a key a third of a second\n * to paint): the best matches, and a line saying how many more match, which typing narrows.\n */\nexport const MENTION_LIST_LIMIT = 10;\n\n/** The matches a list shows, best first, and how many more there are. */\nexport function shownMentions(found: MentionSuggestion[]): { items: MentionSuggestion[]; more: number } {\n return { items: found.slice(0, MENTION_LIST_LIMIT), more: Math.max(0, found.length - MENTION_LIST_LIMIT) };\n}\n\nexport interface MentionListProps {\n /** The listbox's id: the field's aria-controls, and the stem of its options' ids. */\n id: string;\n /** The listbox's name (\"People\", \"Suggestions\"). */\n label: string;\n /** The people shown, at most MENTION_LIST_LIMIT (shownMentions). */\n items: MentionSuggestion[];\n /** How many more match than are shown: the list says so under its people. */\n more?: number;\n activeIndex: number;\n onActiveIndexChange: (index: number) => void;\n onPick: (item: MentionSuggestion) => void;\n /** Where the mention being typed is, in the viewport: the list opens under it, above it when the screen runs out below. */\n anchorRect: () => DOMRect | null;\n /** The list's element, for the owner's checks (a click outside, focus moving into it). */\n listRef?: RefObject<HTMLDivElement | null>;\n}\n\n/**\n * The list of suggestions while a mention is typed (Sprint 25.17 A17): MentionInput's and the editor's, so a mention\n * looks and works the same in a comment box and a document. The field keeps focus and carries aria-activedescendant\n * (the field's owner wires the keys: arrows move, Enter or Tab inserts, Escape closes); the options are no Tab stops,\n * and a pointer picks one without taking focus from the field.\n */\nexport function MentionList({ id, label, items, more = 0, activeIndex, onActiveIndexChange, onPick, anchorRect, listRef }: MentionListProps) {\n const ownRef = useRef<HTMLDivElement | null>(null);\n const floatingRef = listRef ?? ownRef;\n const boxRef = useRef<HTMLDivElement | null>(null);\n const anchorRef = useLatest(anchorRect);\n // the caret as an element for usePosition, which reads only its rectangle\n const anchor = useMemo(() => ({ current: { getBoundingClientRect: () => anchorRef.current() ?? new DOMRect() } as HTMLElement }), [anchorRef]);\n const pos = usePosition(anchor, floatingRef, items.length > 0, { side: \"bottom\", align: \"start\", offset: 4 });\n // the arrows move through a list longer than its box: the active person stays in view\n useActiveOptionInView(boxRef, items.length > 0 ? mentionOptionId(id, activeIndex) : undefined);\n if (items.length === 0) return null;\n\n return createPortal(\n <div\n ref={floatingRef}\n className={cn(\n \"fixed z-[var(--ds-z-popover)] min-w-[200px] flex flex-col\",\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)] shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]\",\n )}\n style={{ top: pos.top, left: pos.left }}\n >\n {/* rows inset in the list, rounded, as Combobox's and the menus' are (the second review: full-width square rows) */}\n <div ref={boxRef} id={id} role=\"listbox\" aria-label={label} className=\"max-h-[200px] overflow-y-auto p-ds-1\">\n {items.map((s, i) => (\n <button\n key={s.id}\n id={mentionOptionId(id, i)}\n type=\"button\"\n role=\"option\"\n tabIndex={-1}\n aria-selected={i === activeIndex}\n className={cn(\n \"flex items-center gap-ds-2.5 w-full px-ds-2 py-ds-1.5 text-left text-sm cursor-pointer rounded-[var(--ds-radius-sm)]\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n i === activeIndex ? \"bg-[var(--ds-bg-muted)] text-[var(--ds-text-primary)]\" : \"text-[var(--ds-text-secondary)]\",\n )}\n // the field keeps focus, so the pick lands where the mention is being typed\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onPick(s)}\n onMouseEnter={() => onActiveIndexChange(i)}\n >\n {/* the name follows as text, so the picture is decoration */}\n <span aria-hidden=\"true\" className=\"inline-flex shrink-0\">\n <Avatar src={s.avatar} initials={s.label} size=\"sm\" className=\"!h-6 !w-6 !text-2xs\" />\n </span>\n <span className=\"min-w-0\">\n <span className=\"block font-medium text-[var(--ds-text-primary)] truncate\">{s.label}</span>\n {s.description && <span className=\"block text-xs text-[var(--ds-text-muted)] truncate\">{s.description}</span>}\n </span>\n </button>\n ))}\n </div>\n {more > 0 && (\n <p className=\"px-ds-3 py-ds-1.5 text-xs text-[var(--ds-text-muted)] border-t-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]\">\n {more} more {more === 1 ? \"matches\" : \"match\"}: keep typing to narrow\n </p>\n )}\n </div>,\n document.body,\n );\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { useTextOverflow } from './chunk-HUNEJIKV.js';
3
- import { AutoTooltip } from './chunk-XSQD3UGY.js';
2
+ import { useTextOverflow } from './chunk-R2IAK3J3.js';
3
+ import { AutoTooltip } from './chunk-HCEHTJ5E.js';
4
4
  import { Icon } from './chunk-53F7GVBQ.js';
5
- import { cn } from './chunk-OWQ7M6R7.js';
5
+ import { cn } from './chunk-2724SJO2.js';
6
6
  import { jsxs, jsx } from 'react/jsx-runtime';
7
7
 
8
8
  var severityToVariant = {
@@ -65,9 +65,10 @@ function getPaletteClasses(color, variant) {
65
65
  const styleFn = paletteByVariant[variant] ?? paletteByVariant.default;
66
66
  return styleFn(color);
67
67
  }
68
- function Badge({ variant = "default", severity, size = "md", color, iconLeft, iconRight, maxWidth, className, children }) {
68
+ function Badge({ variant = "default", severity, size = "md", color, iconLeft, iconRight, maxWidth, width, className, children }) {
69
69
  const resolvedVariant = severity ? severityToVariant[severity] : variant;
70
- const { ref: truncRef, isTruncated } = useTextOverflow({ lines: 1, disabled: !maxWidth });
70
+ const capped = !!(maxWidth || width);
71
+ const { ref: truncRef, isTruncated } = useTextOverflow({ lines: 1, disabled: !capped });
71
72
  const iconSize = iconSizes[size];
72
73
  const isIconOnly = (iconLeft || iconRight) && !children;
73
74
  const colorClasses = color ? getPaletteClasses(color, resolvedVariant) : variantStyles[resolvedVariant];
@@ -76,8 +77,9 @@ function Badge({ variant = "default", severity, size = "md", color, iconLeft, ic
76
77
  {
77
78
  "data-gs-badge": "",
78
79
  className: cn(
79
- "inline-flex items-center font-medium max-w-full whitespace-nowrap shrink-0",
80
+ "inline-flex items-center font-medium w-fit max-w-full whitespace-nowrap shrink-0",
80
81
  "rounded-[var(--ds-radius-full)]",
82
+ width && "justify-center",
81
83
  sizeStyles[size],
82
84
  isIconOnly && size === "xs" && "px-[3px]",
83
85
  isIconOnly && size === "sm" && "px-ds-1",
@@ -85,10 +87,10 @@ function Badge({ variant = "default", severity, size = "md", color, iconLeft, ic
85
87
  colorClasses,
86
88
  className
87
89
  ),
88
- style: maxWidth ? { maxWidth } : void 0,
90
+ style: capped ? { ...width ? { width } : {}, ...maxWidth ? { maxWidth } : {} } : void 0,
89
91
  children: [
90
92
  iconLeft && /* @__PURE__ */ jsx(Icon, { name: iconLeft, size: iconSize, className: "shrink-0", from: "Badge's iconLeft" }),
91
- maxWidth ? /* @__PURE__ */ jsx("span", { ref: truncRef, className: "truncate", children }) : children,
93
+ capped ? /* @__PURE__ */ jsx("span", { ref: truncRef, className: "truncate", children }) : children,
92
94
  iconRight && /* @__PURE__ */ jsx(Icon, { name: iconRight, size: iconSize, className: "shrink-0", from: "Badge's iconRight" })
93
95
  ]
94
96
  }
@@ -100,5 +102,5 @@ function Badge({ variant = "default", severity, size = "md", color, iconLeft, ic
100
102
  }
101
103
 
102
104
  export { Badge };
103
- //# sourceMappingURL=chunk-GT6M74IZ.js.map
104
- //# sourceMappingURL=chunk-GT6M74IZ.js.map
105
+ //# sourceMappingURL=chunk-WSKPESAX.js.map
106
+ //# sourceMappingURL=chunk-WSKPESAX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../showcase/src/components/Badge.tsx"],"names":[],"mappings":"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","file":"chunk-WSKPESAX.js","sourcesContent":["import { cn } from \"../lib/utils\";\nimport { Icon, type IconName } from \"../lib/icons\";\nimport { AutoTooltip } from \"./Tooltip\";\nimport { useTextOverflow } from \"../lib/use-text-overflow\";\nimport type { ReactNode } from \"react\";\n\nexport type BadgeVariant =\n | \"default\"\n | \"neutral\"\n | \"subtle\"\n | \"success\"\n | \"success-soft\"\n | \"warning\"\n | \"warning-soft\"\n | \"error\"\n | \"error-soft\"\n | \"outline\";\n\nexport type BadgeSize = \"xs\" | \"sm\" | \"md\";\nexport type BadgePaletteColor = 1 | 2 | 3 | 4 | 5;\nexport type BadgeSeverity = \"info\" | \"low\" | \"medium\" | \"high\" | \"critical\";\n\nconst severityToVariant: Record<BadgeSeverity, BadgeVariant> = {\n info: \"neutral\",\n low: \"success-soft\",\n medium: \"warning-soft\",\n high: \"error-soft\",\n critical: \"error\",\n};\n\nconst variantStyles: Record<BadgeVariant, string> = {\n default: \"bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] text-[var(--ds-text-on-primary)]\",\n neutral: \"bg-[var(--ds-text-muted)]/[0.12] text-[var(--ds-text-secondary)]\",\n subtle: \"bg-[var(--ds-bg-muted)] text-[var(--ds-text-secondary)]\",\n success: \"bg-[var(--ds-status-success)] text-[var(--ds-text-on-success)]\",\n \"success-soft\": \"bg-[var(--ds-status-success-bg)] text-[var(--ds-status-success-text)] border-[length:var(--ds-border-width)] border-[var(--ds-status-success)]/[0.2]\",\n warning: \"bg-[var(--ds-status-warning)] text-[var(--ds-text-on-warning)]\",\n \"warning-soft\": \"bg-[var(--ds-status-warning-bg)] text-[var(--ds-status-warning-text)] border-[length:var(--ds-border-width)] border-[var(--ds-status-warning)]/[0.2]\",\n error: \"bg-[var(--ds-status-error)] text-[var(--ds-text-on-error)]\",\n \"error-soft\": \"bg-[var(--ds-status-error-bg)] text-[var(--ds-status-error-text)] border-[length:var(--ds-border-width)] border-[var(--ds-status-error)]/[0.2]\",\n outline: \"bg-transparent text-[var(--ds-text-primary)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n};\n\nconst sizeStyles: Record<BadgeSize, string> = {\n xs: \"px-ds-1.5 py-[1px] text-[length:10px] gap-[3px]\",\n sm: \"px-ds-2 py-ds-0.5 text-[length:var(--ds-font-size-xs)] gap-ds-1\",\n md: \"px-ds-2.5 py-ds-0.5 text-[length:var(--ds-font-size-xs)] gap-ds-1\",\n};\n\nconst iconSizes: Record<BadgeSize, number> = {\n xs: 10,\n sm: 12,\n md: 12,\n};\n\ntype PaletteStyleFn = (n: BadgePaletteColor) => string;\n\nconst paletteByVariant: Record<string, PaletteStyleFn> = {\n default: (n) => paletteDefault[n],\n neutral: (n) => paletteSubtle[n],\n subtle: (n) => paletteSubtle[n],\n outline: (n) => paletteOutline[n],\n};\n\nconst paletteDefault: Record<BadgePaletteColor, string> = {\n 1: \"bg-[var(--ds-palette-1-bold)] text-[var(--ds-palette-1-on-bold)]\",\n 2: \"bg-[var(--ds-palette-2-bold)] text-[var(--ds-palette-2-on-bold)]\",\n 3: \"bg-[var(--ds-palette-3-bold)] text-[var(--ds-palette-3-on-bold)]\",\n 4: \"bg-[var(--ds-palette-4-bold)] text-[var(--ds-palette-4-on-bold)]\",\n 5: \"bg-[var(--ds-palette-5-bold)] text-[var(--ds-palette-5-on-bold)]\",\n};\n\nconst paletteSubtle: Record<BadgePaletteColor, string> = {\n 1: \"bg-[var(--ds-palette-1-bg)] text-[var(--ds-palette-1-text)]\",\n 2: \"bg-[var(--ds-palette-2-bg)] text-[var(--ds-palette-2-text)]\",\n 3: \"bg-[var(--ds-palette-3-bg)] text-[var(--ds-palette-3-text)]\",\n 4: \"bg-[var(--ds-palette-4-bg)] text-[var(--ds-palette-4-text)]\",\n 5: \"bg-[var(--ds-palette-5-bg)] text-[var(--ds-palette-5-text)]\",\n};\n\nconst paletteOutline: Record<BadgePaletteColor, string> = {\n 1: \"bg-transparent text-[var(--ds-palette-1-bold)] border-[length:var(--ds-border-width)] border-[var(--ds-palette-1-bold)]\",\n 2: \"bg-transparent text-[var(--ds-palette-2-bold)] border-[length:var(--ds-border-width)] border-[var(--ds-palette-2-bold)]\",\n 3: \"bg-transparent text-[var(--ds-palette-3-bold)] border-[length:var(--ds-border-width)] border-[var(--ds-palette-3-bold)]\",\n 4: \"bg-transparent text-[var(--ds-palette-4-bold)] border-[length:var(--ds-border-width)] border-[var(--ds-palette-4-bold)]\",\n 5: \"bg-transparent text-[var(--ds-palette-5-bold)] border-[length:var(--ds-border-width)] border-[var(--ds-palette-5-bold)]\",\n};\n\nfunction getPaletteClasses(color: BadgePaletteColor, variant: BadgeVariant): string {\n const styleFn = paletteByVariant[variant] ?? paletteByVariant.default;\n return styleFn(color);\n}\n\ninterface BadgeProps {\n variant?: BadgeVariant;\n /** Severity shorthand — maps to a variant. When set, overrides `variant`. */\n severity?: BadgeSeverity;\n size?: BadgeSize;\n /** Palette colour (1-5). Overrides variant colour with decorative palette tokens. */\n color?: BadgePaletteColor;\n /** Icon to show before the label */\n iconLeft?: IconName;\n /** Icon to show after the label */\n iconRight?: IconName;\n /** Max width before truncation (e.g. \"120px\", \"16ch\"). Shows tooltip when truncated. */\n maxWidth?: string;\n /**\n * A set width (a CSS length, e.g. \"6rem\"), for a set of badges that should line up: a table column of statuses gives\n * each the same width. The text is centred, and truncated with a tooltip if it doesn't fit. Without it a badge is as\n * wide as what it says (Sprint 25.33).\n */\n width?: string;\n className?: string;\n children?: ReactNode;\n}\n\nexport function Badge({ variant = \"default\", severity, size = \"md\", color, iconLeft, iconRight, maxWidth, width, className, children }: BadgeProps) {\n // severity sets the variant and variant is ignored when both are written\n const resolvedVariant = severity ? severityToVariant[severity] : variant;\n const capped = !!(maxWidth || width);\n const { ref: truncRef, isTruncated } = useTextOverflow({ lines: 1, disabled: !capped });\n const iconSize = iconSizes[size];\n const isIconOnly = (iconLeft || iconRight) && !children;\n\n const colorClasses = color\n ? getPaletteClasses(color, resolvedVariant)\n : variantStyles[resolvedVariant];\n\n const badge = (\n <span\n // Sprint 25.13 A1: a card header reads this to put a badge in its actions beside the title (D1a), and a card grid\n // to size from what its headers hold (A2)\n data-gs-badge=\"\"\n // w-fit: a grid or a column round it never stretches it (Sprint 25.33: run 94's level badges went 337 px wide on a\n // phone for 35 px of text); a set width is the caller's choice, centred\n className={cn(\n \"inline-flex items-center font-medium w-fit max-w-full whitespace-nowrap shrink-0\",\n \"rounded-[var(--ds-radius-full)]\",\n width && \"justify-center\",\n sizeStyles[size],\n isIconOnly && size === \"xs\" && \"px-[3px]\",\n isIconOnly && size === \"sm\" && \"px-ds-1\",\n isIconOnly && size === \"md\" && \"px-ds-1.5\",\n colorClasses,\n className\n )}\n style={capped ? { ...(width ? { width } : {}), ...(maxWidth ? { maxWidth } : {}) } : undefined}\n >\n {iconLeft && <Icon name={iconLeft} size={iconSize} className=\"shrink-0\" from=\"Badge's iconLeft\" />}\n {capped ? (\n <span ref={truncRef} className=\"truncate\">{children}</span>\n ) : (\n children\n )}\n {iconRight && <Icon name={iconRight} size={iconSize} className=\"shrink-0\" from=\"Badge's iconRight\" />}\n </span>\n );\n\n if (isTruncated) {\n return <AutoTooltip content={children}>{badge}</AutoTooltip>;\n }\n return badge;\n}\n"]}
@@ -1,7 +1,8 @@
1
1
  "use client";
2
- import { AutoTooltip, NATIVE_TITLE } from './chunk-XSQD3UGY.js';
2
+ import { inputModality } from './chunk-7RKC5C7G.js';
3
+ import { AutoTooltip, NATIVE_TITLE } from './chunk-HCEHTJ5E.js';
3
4
  import { slotDraws, slotIcon } from './chunk-53F7GVBQ.js';
4
- import { cn, FOCUS_RING } from './chunk-OWQ7M6R7.js';
5
+ import { cn, FOCUS_RING, pageAddress, pointOf, hasSelfRemovalWatch, focusAfterSelfRemoval, LAST_RESORT_MS } from './chunk-2724SJO2.js';
5
6
  import { jsxs, jsx } from 'react/jsx-runtime';
6
7
  import { createContext, forwardRef, useContext, isValidElement } from 'react';
7
8
 
@@ -34,6 +35,7 @@ function elementType(type) {
34
35
  for (let step = 0; step < 8 && isLazy(resolved); step++) resolved = resolved._init(resolved._payload);
35
36
  return resolved;
36
37
  }
38
+ var BUTTON_HANDOVER_MS = LAST_RESORT_MS * 2;
37
39
  var ControlSizeContext = createContext(null);
38
40
  var ButtonSizeContext = ControlSizeContext;
39
41
  var variantStyles = {
@@ -95,7 +97,15 @@ var Button = forwardRef(function Button2({ variant = "default", size: sizeProp,
95
97
  const isDisabled = !!disabled;
96
98
  const handleClick = isLoading ? (e) => {
97
99
  e.preventDefault();
98
- } : onClick;
100
+ } : (e) => {
101
+ const button = e.currentTarget;
102
+ const watch = document.activeElement === button && inputModality() !== "pointer";
103
+ const page = watch ? pageAddress() : null;
104
+ const point = watch ? pointOf(button) : void 0;
105
+ onClick?.(e);
106
+ if (!watch || pageAddress() !== page || hasSelfRemovalWatch(button)) return;
107
+ focusAfterSelfRemoval(button, { group: null, samePage: true, defer: BUTTON_HANDOVER_MS, removedOnly: true, point });
108
+ };
99
109
  const ariaLabel = props["aria-label"];
100
110
  const drawsTooltip = isIconSize && !!ariaLabel;
101
111
  const title = props.title;
@@ -169,5 +179,5 @@ function triggerType(node) {
169
179
  }
170
180
 
171
181
  export { Button, ButtonSizeContext, ControlSizeContext, Spinner, elementType, triggerType };
172
- //# sourceMappingURL=chunk-2Q4HOGEI.js.map
173
- //# sourceMappingURL=chunk-2Q4HOGEI.js.map
182
+ //# sourceMappingURL=chunk-XBVZIN26.js.map
183
+ //# sourceMappingURL=chunk-XBVZIN26.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../showcase/src/components/Spinner.tsx","../../../showcase/src/lib/element-type.ts","../../../showcase/src/components/Button.tsx"],"names":["Button","jsx"],"mappings":"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","file":"chunk-XBVZIN26.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","/**\n * An element's own component, through a lazy reference (Sprint 25.22's fresh-eyes review). A Next.js server component\n * hands each client component among its children on as a React.lazy reference, not as the component, so a check of\n * `element.type` against a component (PageContainer's header, Card's title, EmptyState's icon) missed every one, and a\n * server page drew without its layout: no colourful band, no contained breadcrumbs, a card's badge out of place. The\n * reference is resolved as React resolves one when it renders it: its component once loaded; while it loads, its promise\n * is thrown, so the component reading it suspends until it has it. Anything else is returned as it is.\n */\nconst LAZY = Symbol.for(\"react.lazy\");\n\ninterface LazyReference {\n $$typeof: symbol;\n _payload: unknown;\n _init: (payload: unknown) => unknown;\n}\n\nconst isLazy = (type: unknown): type is LazyReference =>\n type !== null && typeof type === \"object\" && (type as LazyReference).$$typeof === LAZY && typeof (type as LazyReference)._init === \"function\";\n\nexport function elementType(type: unknown): unknown {\n let resolved = type;\n // a reference to a reference resolves in turn; a handful of steps covers any real chain\n for (let step = 0; step < 8 && isLazy(resolved); step++) resolved = resolved._init(resolved._payload);\n return resolved;\n}\n","import { cn, FOCUS_RING } from \"../lib/utils\";\n// a server component hands its client children on as lazy references (Sprint 25.22's review)\nimport { elementType } from \"../lib/element-type\";\nimport { createContext, useContext, forwardRef, isValidElement, type ButtonHTMLAttributes, type CSSProperties, type ReactNode } from \"react\";\nimport { AutoTooltip, NATIVE_TITLE } from \"./Tooltip\";\nimport { Spinner } from \"./Spinner\";\nimport { slotIcon, type IconSlot, slotDraws } from \"../lib/icons\";\nimport { focusAfterSelfRemoval, hasSelfRemovalWatch, LAST_RESORT_MS, pageAddress, pointOf } from \"../lib/focus\";\nimport { inputModality } from \"../lib/input-modality\";\n\n/** How long a Button's own handover waits once the button has gone (Sprint 25.32): past every library rule's place. */\nexport const BUTTON_HANDOVER_MS = LAST_RESORT_MS * 2;\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 /** An icon name (\"clock\"), drawn as the theme's icon at the button's icon size, or an element. Not text: use children. */\n iconLeft?: IconSlot;\n /** As iconLeft, after the label. */\n iconRight?: IconSlot;\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-ink)] 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\n/** The icon size each button size draws a named icon at (Sprint 25.17 A26): what the library's own buttons pass by hand. */\nconst SLOT_ICON_PX: Record<ButtonSize, number> = { xs: 12, sm: 14, md: 16, lg: 18, \"icon-xs\": 12, \"icon-sm\": 14, icon: 16, \"icon-lg\": 18 };\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 // a slot that draws nothing (text, which no icon pack names) keeps the button's even padding\n const drawsLeft = slotDraws(iconLeft);\n const drawsRight = slotDraws(iconRight);\n if (!isIconSize && !isLink && (drawsLeft || drawsRight)) {\n const reduce = iconPaddingReduce[size];\n paddingStyle = {};\n if (drawsLeft) paddingStyle.paddingLeft = `calc(${getCssPadding(size)} - ${reduce}px)`;\n if (drawsRight) paddingStyle.paddingRight = `calc(${getCssPadding(size)} - ${reduce}px)`;\n }\n\n const isLoading = loading && !disabled;\n const isDisabled = !!disabled;\n\n // Sprint 25.32 (R29-2: round 29's \"Reconnect\" was drawn only while an app was disconnected, so its own press took it\n // away and focus fell to the page): a keyboard press that takes its button away hands focus on, where the browser's\n // own Tab would go on from where the button stood (D1: the first Tab stop after a live range taken round the button\n // before its press acts, else the last before it, within the page or the dialog it was in). Only a press that isn't a\n // pointer's (the keyboard's, a screen reader's), on the button holding focus (the review of 18 October): focus moved\n // by script after a pointer's press shows no ring, so a Space meant to scroll would press whatever it landed on. Only\n // the button leaving the page counts, not its being disabled while the press is pending. Set after the page's\n // handler, so a component that knows better (Pagination's own rule) has set its watch first, and this one steps\n // aside. It waits twice the last resort's time once the button has gone, so every place the library or the page gives\n // focus goes first (a drawer's Cancel, whose drawer sends focus back where its opener's panel sat, a last resort of\n // its own at LAST_RESORT_MS), and never acts across a change of page, whose new page owns focus. The user moving on\n // ends it.\n const handleClick = isLoading\n ? (e: React.MouseEvent<HTMLButtonElement>) => { e.preventDefault(); }\n : (e: React.MouseEvent<HTMLButtonElement>) => {\n const button = e.currentTarget;\n const watch = document.activeElement === button && inputModality() !== \"pointer\";\n // the page the press was on: a handler that navigated has a new page, which owns focus\n const page = watch ? pageAddress() : null;\n // where the button stands, taken before its press acts: the DOM keeps it once the button has gone\n const point = watch ? pointOf(button) : undefined;\n onClick?.(e);\n if (!watch || pageAddress() !== page || hasSelfRemovalWatch(button)) return;\n focusAfterSelfRemoval(button, { group: null, samePage: true, defer: BUTTON_HANDOVER_MS, removedOnly: true, point });\n };\n\n const ariaLabel = props[\"aria-label\"];\n // An icon-size Button with an aria-label draws its own tooltip from it. Round 15 (52.7): where a Tooltip the page put\n // around it shows, that one owns the label and this steps aside (AutoTooltip asks when it would show).\n const drawsTooltip = isIconSize && !!ariaLabel;\n // A title beside a tooltip is the browser's second one, a moment later (the review of 21.6 session B): a Button that\n // draws its tooltip shows the title's text in it instead (the Tooltip drops the button's own title), and a Tooltip the\n // page puts around a Button drops its title too (NATIVE_TITLE).\n const title = props.title;\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_RING,\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_RING,\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 {slotIcon(iconLeft, SLOT_ICON_PX[size], \"Button's iconLeft\")}\n {children}\n {slotIcon(iconRight, SLOT_ICON_PX[size], \"Button's iconRight\")}\n </span>\n </button>\n );\n\n if (drawsTooltip) {\n return <AutoTooltip content={title ?? ariaLabel}>{btn}</AutoTooltip>;\n }\n\n return btn;\n});\n// a Button's title is the native attribute: a Tooltip around it drops it, as it does an element's\n(Button as unknown as Record<symbol, true>)[NATIVE_TITLE] = true;\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 const type = elementType(node.type);\n return (type === \"button\" || type === Button) && (node.props as { type?: unknown }).type === undefined ? { type: \"button\" } : {};\n}\n"]}