gridsmith-ui 0.26.0 → 0.28.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 (111) hide show
  1. package/CHANGELOG.md +1010 -0
  2. package/README.md +21 -5
  3. package/dist/charts.d.ts +2 -2
  4. package/dist/charts.js +59 -44
  5. package/dist/charts.js.map +1 -1
  6. package/dist/chat.js +7 -6
  7. package/dist/chat.js.map +1 -1
  8. package/dist/{chunk-X2HEV7FB.js → chunk-2ROVDVLZ.js} +24 -34
  9. package/dist/chunk-2ROVDVLZ.js.map +1 -0
  10. package/dist/chunk-3BRQRKDO.js +1 -0
  11. package/dist/chunk-3BRQRKDO.js.map +1 -1
  12. package/dist/chunk-66JJCQU3.js +46 -0
  13. package/dist/chunk-66JJCQU3.js.map +1 -0
  14. package/dist/chunk-7Q46JXSK.js +1 -0
  15. package/dist/chunk-7Q46JXSK.js.map +1 -1
  16. package/dist/chunk-7RKC5C7G.js +35 -0
  17. package/dist/chunk-7RKC5C7G.js.map +1 -0
  18. package/dist/{chunk-OTCEJN64.js → chunk-BRAXJEEP.js} +8 -6
  19. package/dist/chunk-BRAXJEEP.js.map +1 -0
  20. package/dist/chunk-CRQ6KCRD.js +1 -0
  21. package/dist/chunk-CRQ6KCRD.js.map +1 -1
  22. package/dist/{chunk-MYIJNVTK.js → chunk-DQCHCLEJ.js} +11 -9
  23. package/dist/chunk-DQCHCLEJ.js.map +1 -0
  24. package/dist/{chunk-RWKCAKN3.js → chunk-EIWXVICU.js} +7 -6
  25. package/dist/chunk-EIWXVICU.js.map +1 -0
  26. package/dist/{chunk-SFY2KMHG.js → chunk-FD4YED7O.js} +6 -4
  27. package/dist/chunk-FD4YED7O.js.map +1 -0
  28. package/dist/{chunk-MD2EFMES.js → chunk-GXMTS3YD.js} +4 -3
  29. package/dist/chunk-GXMTS3YD.js.map +1 -0
  30. package/dist/chunk-HP7WUZPK.js +1 -0
  31. package/dist/chunk-HP7WUZPK.js.map +1 -1
  32. package/dist/chunk-HTXP5BMM.js +38 -0
  33. package/dist/chunk-HTXP5BMM.js.map +1 -0
  34. package/dist/chunk-NRHIYS5W.js +1 -0
  35. package/dist/chunk-NRHIYS5W.js.map +1 -1
  36. package/dist/{chunk-KWLNEH53.js → chunk-OPFJEL3Z.js} +59 -28
  37. package/dist/chunk-OPFJEL3Z.js.map +1 -0
  38. package/dist/chunk-OYNUU346.js +78 -0
  39. package/dist/chunk-OYNUU346.js.map +1 -0
  40. package/dist/chunk-QM4SJKWV.js +1 -0
  41. package/dist/chunk-QM4SJKWV.js.map +1 -1
  42. package/dist/{chunk-ZYVXV4WC.js → chunk-R4GXKH4U.js} +58 -11
  43. package/dist/chunk-R4GXKH4U.js.map +1 -0
  44. package/dist/{chunk-HXVXJUGV.js → chunk-TJEV7YAY.js} +38 -10
  45. package/dist/chunk-TJEV7YAY.js.map +1 -0
  46. package/dist/{chunk-EX64MN2U.js → chunk-TRDXWHD2.js} +8 -7
  47. package/dist/chunk-TRDXWHD2.js.map +1 -0
  48. package/dist/chunk-WH2FUFAC.js +1 -0
  49. package/dist/chunk-WH2FUFAC.js.map +1 -1
  50. package/dist/chunk-XVB55M3N.js +1 -0
  51. package/dist/chunk-XVB55M3N.js.map +1 -1
  52. package/dist/{chunk-CYN5O567.js → chunk-YUTF2X6B.js} +45 -22
  53. package/dist/chunk-YUTF2X6B.js.map +1 -0
  54. package/dist/chunk-ZI3OQDET.js +1 -0
  55. package/dist/chunk-ZI3OQDET.js.map +1 -1
  56. package/dist/data-grid.d.ts +1 -1
  57. package/dist/data-grid.js +21 -12
  58. package/dist/data-grid.js.map +1 -1
  59. package/dist/editor-mentions.js +3 -2
  60. package/dist/editor-mentions.js.map +1 -1
  61. package/dist/editor.js +47 -26
  62. package/dist/editor.js.map +1 -1
  63. package/dist/{feather-VFWLAILO.js → feather-FNBQ74RR.js} +10 -17
  64. package/dist/feather-FNBQ74RR.js.map +1 -0
  65. package/dist/{heroicons-H3Z7DFCF.js → heroicons-DODCSYWD.js} +9 -8
  66. package/dist/heroicons-DODCSYWD.js.map +1 -0
  67. package/dist/icons.d.ts +31 -4
  68. package/dist/icons.js +2 -1
  69. package/dist/icons.js.map +1 -1
  70. package/dist/index.d.ts +456 -66
  71. package/dist/index.js +2264 -1091
  72. package/dist/index.js.map +1 -1
  73. package/dist/kanban.js +20 -12
  74. package/dist/kanban.js.map +1 -1
  75. package/dist/{lucide-MR32KM4G.js → lucide-ZWE3EPGP.js} +9 -8
  76. package/dist/lucide-ZWE3EPGP.js.map +1 -0
  77. package/dist/{phosphor-ABQQL5N5.js → phosphor-DIHPA4AJ.js} +9 -8
  78. package/dist/phosphor-DIHPA4AJ.js.map +1 -0
  79. package/dist/resizable.js +24 -17
  80. package/dist/resizable.js.map +1 -1
  81. package/dist/roots.css +116 -22
  82. package/dist/{tabler-ANUSY4D2.js → tabler-D3VYTSGI.js} +9 -8
  83. package/dist/tabler-D3VYTSGI.js.map +1 -0
  84. package/dist/tokens.css +122 -34
  85. package/dist/{use-pagination-BnKOnBdz.d.ts → use-pagination-BxcRlNQG.d.ts} +6 -0
  86. package/dist/utils.d.ts +321 -5
  87. package/dist/utils.js +885 -1
  88. package/dist/utils.js.map +1 -1
  89. package/dist/virtualized.d.ts +1 -1
  90. package/dist/virtualized.js +20 -12
  91. package/dist/virtualized.js.map +1 -1
  92. package/dist-static/tokens.css +122 -34
  93. package/package.json +5 -3
  94. package/dist/chunk-CYN5O567.js.map +0 -1
  95. package/dist/chunk-EX64MN2U.js.map +0 -1
  96. package/dist/chunk-HXVXJUGV.js.map +0 -1
  97. package/dist/chunk-KWLNEH53.js.map +0 -1
  98. package/dist/chunk-M2QRNBDQ.js +0 -41
  99. package/dist/chunk-M2QRNBDQ.js.map +0 -1
  100. package/dist/chunk-MD2EFMES.js.map +0 -1
  101. package/dist/chunk-MYIJNVTK.js.map +0 -1
  102. package/dist/chunk-OTCEJN64.js.map +0 -1
  103. package/dist/chunk-RWKCAKN3.js.map +0 -1
  104. package/dist/chunk-SFY2KMHG.js.map +0 -1
  105. package/dist/chunk-X2HEV7FB.js.map +0 -1
  106. package/dist/chunk-ZYVXV4WC.js.map +0 -1
  107. package/dist/feather-VFWLAILO.js.map +0 -1
  108. package/dist/heroicons-H3Z7DFCF.js.map +0 -1
  109. package/dist/lucide-MR32KM4G.js.map +0 -1
  110. package/dist/phosphor-ABQQL5N5.js.map +0 -1
  111. package/dist/tabler-ANUSY4D2.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../showcase/src/components/Spinner.tsx","../../../showcase/src/components/Button.tsx","../../../showcase/src/lib/relative-time.ts","../../../showcase/src/lib/preferences.ts"],"names":["Button","jsx","createContext","useContext"],"mappings":"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","file":"chunk-R4GXKH4U.js","sourcesContent":["import { cn } from \"../lib/utils\";\n\nconst sizes = {\n sm: \"h-4 w-4 border-[1.5px]\",\n md: \"h-6 w-6 border-2\",\n lg: \"h-8 w-8 border-[2.5px]\",\n} as const;\n\ninterface SpinnerProps {\n size?: keyof typeof sizes;\n color?: \"default\" | \"inherit\";\n label?: string;\n className?: string;\n}\n\nexport function Spinner({ size = \"md\", color = \"default\", label = \"Loading\", className }: SpinnerProps) {\n return (\n <span\n role=\"status\"\n aria-label={label}\n className={cn(\n \"inline-block rounded-[var(--ds-radius-full)] animate-spin\",\n color === \"inherit\"\n ? \"border-current/30 border-t-current\"\n : \"border-[var(--ds-bg-emphasis)] border-t-[var(--ds-accent-primary)]\",\n sizes[size],\n className\n )}\n />\n );\n}\n","import { cn, 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 { Tooltip, TooltipCtx } from \"./Tooltip\";\nimport { Spinner } from \"./Spinner\";\nimport { slotIcon, type IconSlot, slotDraws } from \"../lib/icons\";\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 const handleClick = isLoading\n ? (e: React.MouseEvent<HTMLButtonElement>) => { e.preventDefault(); }\n : onClick;\n\n const ariaLabel = props[\"aria-label\"];\n // Round 15 (52.7): inside an explicit <Tooltip> the caller owns the label; the automatic one from aria-label would be a second tooltip.\n const inTooltip = useContext(TooltipCtx);\n\n const btn = (\n <button\n ref={ref}\n data-variant={variant}\n className={cn(\n \"relative inline-flex items-center justify-center gap-ds-2 whitespace-nowrap font-medium\",\n isLink\n ? cn(\n \"px-0 py-ds-0.5 h-auto\",\n linkSizeStyles[size],\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n FOCUS_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 (isIconSize && ariaLabel && !inTooltip) {\n return <Tooltip content={ariaLabel}>{btn}</Tooltip>;\n }\n\n return btn;\n});\n\nfunction getCssPadding(size: Exclude<ButtonSize, \"icon\" | \"icon-xs\" | \"icon-sm\" | \"icon-lg\">): string {\n switch (size) {\n case \"xs\": return \"var(--ds-space-3)\";\n case \"sm\": return \"var(--ds-space-4)\";\n case \"md\": return \"var(--ds-space-6)\";\n case \"lg\": return \"var(--ds-space-8)\";\n }\n}\n\n/**\n * A trigger the library wires up (a Collapsible's, a menu's, a popover's) never submits the form it sits in (0.21.0): a\n * button element or Button given no type gets type=\"button\". A page's own Button keeps HTML's default, so its submits\n * still work.\n */\nexport function triggerType(node: unknown): { type?: \"button\" } {\n if (!isValidElement(node)) return {};\n const type = elementType(node.type);\n return (type === \"button\" || type === Button) && (node.props as { type?: unknown }).type === undefined ? { type: \"button\" } : {};\n}\n","import { warnOnce } from \"./dev-warn\";\nimport { formatLocale } from \"./format-locale\";\n\n/**\n * Times as people read them, relative or in full (Sprint 25.17 A29), apart from the RelativeTime component since Sprint\n * 25.22 (nothing here needs React). Not on `gridsmith-ui/utils` (that sprint's review): a relative time and a full one\n * depend on the visitor's clock and time zone, which a server doesn't know, so a server page hands RelativeTime the time.\n */\n\n/** A time: an ISO string, a Date, or milliseconds since the epoch. */\nexport type TimeValue = string | Date | number;\n\nexport const MINUTE = 60_000;\nexport const HOUR = 60 * MINUTE;\nexport const DAY = 24 * HOUR;\n\n/** The house's threshold, dateTime.relativeThresholdHours: within this many hours a time reads relative. The shell's preferences default to it. */\nexport const HOUSE_RELATIVE_THRESHOLD_HOURS = 24;\n\nexport function toMillis(time: TimeValue): number {\n if (time instanceof Date) return time.getTime();\n if (typeof time === \"number\") return time;\n if (typeof time !== \"string\") return NaN;\n // a date alone (\"2026-09-01\") is that day on the calendar here, as people read it: Date.parse reads it as midnight in\n // UTC, which New York showed as the evening before (the 25.17 second review)\n const day = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(time.trim());\n if (day) return new Date(Number(day[1]), Number(day[2]) - 1, Number(day[3])).getTime();\n return Date.parse(time);\n}\n\n/**\n * A threshold as given, or the house's when it isn't a number of hours (a missing setting read as `Number(undefined)`\n * re-rendered every time in a loop: the 25.17 second review), which development builds are told about.\n */\nexport function thresholdOf(hours: unknown, from: string): number {\n if (typeof hours === \"number\" && Number.isFinite(hours) && hours >= 0) return hours;\n const house = HOUSE_RELATIVE_THRESHOLD_HOURS;\n warnOnce(from, `a threshold of ${String(hours)} isn't a number of hours, so the house's ${house} is used.`);\n return house;\n}\n\n/** Local midnight before a moment: days are counted on the calendar, so Monday 23:30 is two days before Wednesday 00:30. */\nfunction midnight(t: number): number {\n const d = new Date(t);\n d.setHours(0, 0, 0, 0);\n return d.getTime();\n}\n\n/**\n * A time as people read it (Sprint 25.17 A29, R28-48; date_time#1, #11 and #13): within `thresholdHours` of now,\n * relative (\"now\", \"5 minutes ago\", \"in 2 hours\", \"yesterday\", counting days on the calendar), in the page's language;\n * beyond it, the date and the time. The threshold is given: the project's is the shell's\n * (dateTime.relativeThresholdHours), which RelativeTime and useRelativeTimeFormat read for you.\n */\nexport function formatRelativeTime(time: TimeValue, options: { thresholdHours: number; now?: number; locale?: string }): string {\n const at = toMillis(time);\n if (!Number.isFinite(at)) return \"\";\n const now = options.now ?? Date.now();\n // the locale given (a component's useFormatLocale(), Sprint 25.20), else the browser's reading\n const locale = options.locale ?? formatLocale();\n const diff = at - now;\n const age = Math.abs(diff);\n // past the threshold the moment itself: a log or a table keeps its time of day (the review: a log read \"1 Oct 2026\"\n // on every row)\n if (age > thresholdOf(options.thresholdHours, \"formatRelativeTime\") * HOUR) return new Intl.DateTimeFormat(locale, { dateStyle: \"medium\", timeStyle: \"short\" }).format(at);\n // whole units, counted as they pass (\"5 minutes ago\" until the sixth minute), so the text changes when the shown time\n // refreshes, on the minute or the hour\n const rtf = new Intl.RelativeTimeFormat(locale, { numeric: \"auto\" });\n if (age < MINUTE) return rtf.format(0, \"second\");\n if (age < HOUR) return rtf.format(Math.trunc(diff / MINUTE), \"minute\");\n if (age < DAY) return rtf.format(Math.trunc(diff / HOUR), \"hour\");\n return rtf.format(Math.round((midnight(at) - midnight(now)) / DAY), \"day\");\n}\n\n/**\n * The full timestamp, as the tooltip and a screen reader give it: the date, the time and its zone, in the locale given\n * (a component's useFormatLocale()), else the browser's reading.\n */\nexport function formatFullTime(time: TimeValue, locale?: string): string {\n const at = toMillis(time);\n return Number.isFinite(at)\n ? new Intl.DateTimeFormat(locale ?? formatLocale(), { year: \"numeric\", month: \"long\", day: \"numeric\", hour: \"numeric\", minute: \"2-digit\", timeZoneName: \"short\" }).format(at)\n : \"\";\n}\n","/**\n * The customer's UX preferences, carried once by AppShell the way the theme is (Sprint 25.6 B9).\n *\n * The generated shell passes the object the template emits from the profile's rules; the builder preview passes the\n * same values from the theme state. Components default from it when no prop is passed — FormWrapper's validation mode\n * and actions alignment, Table and DataGrid's mobile breakpoint, Pagination's page size, EmptyState's style, the\n * destructive-action helper's mode, lists and undo window, and RelativeTime's threshold (Sprint 25.17 A29) and a flow's going back (useFlowSteps, Sprint 25.19 S3) — so a page\n * gets the customer's value by doing nothing. A\n * prop always wins; a component outside any shell keeps the default it always had (components read\n * `useShellPreferences`). App code reads `usePreferences`, which fills every field (round 21); a paged list reads its\n * page size through `usePagination`.\n */\nimport { createContext, useContext, useMemo } from \"react\";\nimport { HOUSE_RELATIVE_THRESHOLD_HOURS } from \"./relative-time\";\n\nexport type PreferenceValidationTiming = \"onBlur\" | \"onSubmit\" | \"onChange\";\nexport type PreferenceBreakpoint = \"sm\" | \"md\" | \"lg\";\nexport type PreferenceEmptyStyle = \"illustration-cta\" | \"text-cta\" | \"redirect\";\nexport type PreferenceLoadingStyle = \"skeleton\" | \"spinner\" | \"progress-bar\";\nexport type PreferenceDestructiveMode = \"dialog\" | \"undo\";\n/** dataDisplay.paginationStyle — how a long list shows more: page numbers, a Load more button, or loading as the user scrolls. */\nexport type PreferencePaginationStyle = \"pagination\" | \"load-more\" | \"infinite-scroll\";\n\nexport interface AppShellPreferences {\n /** forms.validationTiming — when a field first shows its error. */\n validationTiming?: PreferenceValidationTiming;\n /** forms.actions — where a form's buttons sit and how they align. */\n formActions?: { align?: \"start\" | \"end\"; placement?: \"auto\" | \"inline\" };\n /** dataDisplay.itemsPerPage — the page size of a paged or load-more list. */\n itemsPerPage?: number;\n /** dataDisplay.paginationStyle — page numbers, a Load more button, or loading on scroll; usePagination and Pagination follow it (round 22). */\n paginationStyle?: PreferencePaginationStyle;\n /** responsive.tableToCardsBreakpoint — below this width a Table becomes stacked cards. */\n tableToCardsBreakpoint?: PreferenceBreakpoint;\n /** emptyStates.emptyStyle — illustration with an action, text with an action, or redirect to creation. */\n emptyStyle?: PreferenceEmptyStyle;\n /** emptyStates.loadingStyle — what a page shows while data loads. */\n loadingStyle?: PreferenceLoadingStyle;\n /** destructiveActions.mode — confirm in a dialog, or act now with an Undo toast. */\n destructiveMode?: PreferenceDestructiveMode;\n /** destructiveActions.highSeverityActions — always confirm in a dialog, even in undo mode. */\n highSeverityActions?: string[];\n /** destructiveActions.typeToConfirmActions — the user types the name before the confirm enables. */\n typeToConfirmActions?: string[];\n /** destructiveActions.undoWindowSeconds — how long the Undo toast stays. */\n undoWindowSeconds?: number;\n /** dateTime.relativeThresholdHours — within this many hours a time reads relative (\"2 hours ago\"), older the date (RelativeTime). */\n relativeThresholdHours?: number;\n /**\n * forms.canNavigateBack — a flow with steps lets the user go back (Sprint 25.19 S3). On, its step list opens any step\n * already reached and it has a Back; off, the list only shows progress and there is no Back. useFlowSteps reads it.\n */\n canNavigateBack?: boolean;\n}\n\nexport const PreferencesContext = createContext<AppShellPreferences | null>(null);\n\n/** Every preference in force, the shell's value or the house default — what app code reads. */\nexport interface ResolvedPreferences {\n validationTiming: PreferenceValidationTiming;\n formActions: { align: \"start\" | \"end\"; placement: \"auto\" | \"inline\" };\n itemsPerPage: number;\n paginationStyle: PreferencePaginationStyle;\n tableToCardsBreakpoint: PreferenceBreakpoint;\n emptyStyle: PreferenceEmptyStyle;\n loadingStyle: PreferenceLoadingStyle;\n destructiveMode: PreferenceDestructiveMode;\n highSeverityActions: string[];\n typeToConfirmActions: string[];\n undoWindowSeconds: number;\n relativeThresholdHours: number;\n canNavigateBack: boolean;\n}\n\n/**\n * The house defaults for the fields the shell carries: the platform's preference-defaults.ts, mirrored in\n * decisions-schema.ts (DEFAULT_PATTERN_DECISIONS); a test keeps the three equal.\n */\nconst HOUSE_DEFAULTS: ResolvedPreferences = {\n validationTiming: \"onBlur\",\n formActions: { align: \"end\", placement: \"auto\" },\n itemsPerPage: 25,\n paginationStyle: \"pagination\",\n tableToCardsBreakpoint: \"md\",\n emptyStyle: \"illustration-cta\",\n loadingStyle: \"skeleton\",\n destructiveMode: \"dialog\",\n highSeverityActions: [\"delete_account\", \"remove_team_member\"],\n typeToConfirmActions: [\"delete_account\"],\n undoWindowSeconds: 5,\n relativeThresholdHours: HOUSE_RELATIVE_THRESHOLD_HOURS,\n canNavigateBack: true,\n};\nexport const PREFERENCE_HOUSE_DEFAULTS: Readonly<ResolvedPreferences> = Object.freeze(HOUSE_DEFAULTS);\n\n/**\n * For app code: every preference in force — the shell's value, else the house default — so a page never writes a\n * fallback of its own. Round 21 (run 58): with every field optional, TypeScript made the builder write\n * `const { itemsPerPage = 20 } = usePreferences()`, a second copy of the preference it then edited by hand when the\n * rule changed. Paged lists use `usePagination`, which reads the page size itself.\n */\nexport function usePreferences(): ResolvedPreferences {\n const raw = useShellPreferences();\n return useMemo(() => resolvePreferences(raw), [raw]);\n}\n\n/** The shell's values over the house defaults; a field the shell leaves undefined keeps its default. */\nexport function resolvePreferences(raw: AppShellPreferences): ResolvedPreferences {\n const d = PREFERENCE_HOUSE_DEFAULTS;\n const out: ResolvedPreferences = { ...d, formActions: { ...d.formActions }, highSeverityActions: [...d.highSeverityActions], typeToConfirmActions: [...d.typeToConfirmActions] };\n for (const [key, value] of Object.entries(raw) as Array<[keyof AppShellPreferences, unknown]>) {\n if (value === undefined) continue;\n if (key === \"formActions\") {\n const actions = value as AppShellPreferences[\"formActions\"];\n if (actions?.align !== undefined) out.formActions.align = actions.align;\n if (actions?.placement !== undefined) out.formActions.placement = actions.placement;\n continue;\n }\n (out as unknown as Record<string, unknown>)[key] = value;\n }\n return out;\n}\n\n/**\n * For components: only what the shell passed, or an empty object outside any shell — a component with no prop takes\n * the shell's value, and a bare component keeps the default it always had.\n */\nexport function useShellPreferences(): AppShellPreferences {\n return useContext(PreferencesContext) ?? EMPTY;\n}\n\nconst EMPTY: AppShellPreferences = Object.freeze({});\n\n/**\n * \"Remove range\" → \"remove_range\": the key the high-severity and type-to-confirm lists use. The engine's `actionKey`\n * (platform/src/lib/destructive-mode.ts) is the same rule for compliance; a platform test keeps the two identical.\n */\nexport function preferenceActionKey(label: string): string {\n return label.trim().toLowerCase().replace(/[^a-z0-9]+/g, \"_\").replace(/^_|_$/g, \"\");\n}\n"]}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { createContext, useEffect, useContext, useSyncExternalStore } from 'react';
2
3
  import { jsx } from 'react/jsx-runtime';
3
4
 
@@ -17,6 +18,20 @@ function warnOnce(component, message) {
17
18
  warned.add(text);
18
19
  console.warn(text);
19
20
  }
21
+
22
+ // ../../showcase/src/lib/icon-pack-imports.ts
23
+ var ICON_PACK_IMPORTS = {
24
+ feather: "react-icons/fi",
25
+ heroicons: "@heroicons/react/24/outline",
26
+ phosphor: "@phosphor-icons/react",
27
+ tabler: "@tabler/icons-react"
28
+ };
29
+ function iconPackRegistration(pack) {
30
+ return {
31
+ importLine: "import { registerIconPack } from 'gridsmith-ui/icons'",
32
+ call: `registerIconPack('${pack}', () => import('${ICON_PACK_IMPORTS[pack]}'))`
33
+ };
34
+ }
20
35
  var subscribers = /* @__PURE__ */ new Set();
21
36
  function notifySubscribers() {
22
37
  subscribers.forEach((fn) => fn());
@@ -45,6 +60,11 @@ function useExtendedMap(pack) {
45
60
  }
46
61
  var loadingPacks = /* @__PURE__ */ new Set();
47
62
  var failedPacks = /* @__PURE__ */ new Set();
63
+ var packImports = /* @__PURE__ */ new Map([["lucide", () => import('lucide-react')]]);
64
+ function registerIconPack(pack, load) {
65
+ packImports.set(pack, load);
66
+ if (failedPacks.delete(pack)) void loadPack(pack);
67
+ }
48
68
  var PEER_PACKAGE = {
49
69
  lucide: "lucide-react",
50
70
  phosphor: "@phosphor-icons/react",
@@ -55,27 +75,35 @@ var PEER_PACKAGE = {
55
75
  async function loadPack(pack) {
56
76
  if (curatedCache.has(pack) || loadingPacks.has(pack) || failedPacks.has(pack)) return;
57
77
  loadingPacks.add(pack);
78
+ const load = packImports.get(pack);
79
+ if (!load) {
80
+ failedPacks.add(pack);
81
+ loadingPacks.delete(pack);
82
+ const lines = iconPackRegistration(pack);
83
+ warnOnce("IconProvider", `the ${pack} icon pack isn't registered, so its icons are drawn from Lucide. At the top of the shell, before any preloadPack: ${lines.importLine}; ${lines.call}`);
84
+ return;
85
+ }
58
86
  let mod;
59
87
  let curated;
60
88
  try {
61
89
  switch (pack) {
62
90
  case "lucide":
63
- mod = await import('./lucide-MR32KM4G.js');
91
+ mod = await import('./lucide-ZWE3EPGP.js');
64
92
  break;
65
93
  case "phosphor":
66
- mod = await import('./phosphor-ABQQL5N5.js');
94
+ mod = await import('./phosphor-DIHPA4AJ.js');
67
95
  break;
68
96
  case "heroicons":
69
- mod = await import('./heroicons-H3Z7DFCF.js');
97
+ mod = await import('./heroicons-DODCSYWD.js');
70
98
  break;
71
99
  case "tabler":
72
- mod = await import('./tabler-ANUSY4D2.js');
100
+ mod = await import('./tabler-D3VYTSGI.js');
73
101
  break;
74
102
  case "feather":
75
- mod = await import('./feather-VFWLAILO.js');
103
+ mod = await import('./feather-FNBQ74RR.js');
76
104
  break;
77
105
  }
78
- curated = await mod.loadCurated();
106
+ curated = await mod.loadCurated(load);
79
107
  } catch {
80
108
  loadingPacks.delete(pack);
81
109
  failedPacks.add(pack);
@@ -84,7 +112,7 @@ async function loadPack(pack) {
84
112
  }
85
113
  curatedCache.set(pack, curated);
86
114
  notifySubscribers();
87
- mod.loadExtended().then((extended) => {
115
+ mod.loadExtended(load).then((extended) => {
88
116
  extendedCache.set(pack, extended);
89
117
  notifySubscribers();
90
118
  }).catch(() => {
@@ -176,6 +204,6 @@ function NotAnIcon({ text, from }) {
176
204
  return null;
177
205
  }
178
206
 
179
- export { Icon, IconProvider, preloadPack, slotDraws, slotIcon, warnOnce };
180
- //# sourceMappingURL=chunk-HXVXJUGV.js.map
181
- //# sourceMappingURL=chunk-HXVXJUGV.js.map
207
+ export { Icon, IconProvider, preloadPack, registerIconPack, slotDraws, slotIcon, warnOnce };
208
+ //# sourceMappingURL=chunk-TJEV7YAY.js.map
209
+ //# sourceMappingURL=chunk-TJEV7YAY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../showcase/src/lib/dev-warn.ts","../../../showcase/src/lib/icon-pack-imports.ts","../../../showcase/src/lib/icons.tsx"],"names":[],"mappings":"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","file":"chunk-TJEV7YAY.js","sourcesContent":["// Bundlers set process.env.NODE_ENV. Where none did (a page with no build step), reading it throws and warnings stay off.\ndeclare const process: { env: { NODE_ENV?: string } };\nconst warned = new Set<string>();\n\n/** A mistake in a component's props, told to the developer once a page, in a development build. */\nexport function warnOnce(component: string, message: string): void {\n let dev = false;\n try {\n dev = process.env.NODE_ENV !== \"production\";\n } catch {\n dev = false;\n }\n const text = `${component}: ${message}`;\n if (!dev || warned.has(text)) return;\n warned.add(text);\n console.warn(text);\n}\n","/**\n * The import each icon pack takes, as an app writes it when it registers its theme's pack (Sprint 25.21 P1:\n * `registerIconPack('feather', () => import('react-icons/fi'))`). One table for the library's warning, the shells\n * `get_app_shell` writes and the engine's fix. Lucide is the library's own: every app installs it, as the fallback.\n * No React here, so the platform reads it as it reads the other showcase modules.\n */\nexport const ICON_PACK_IMPORTS = {\n feather: \"react-icons/fi\",\n heroicons: \"@heroicons/react/24/outline\",\n phosphor: \"@phosphor-icons/react\",\n tabler: \"@tabler/icons-react\",\n} as const;\n\n/** A pack an app registers: every pack but Lucide. */\nexport type RegisteredIconPack = keyof typeof ICON_PACK_IMPORTS;\n\n/** The two lines that register a pack, at the top of an app's shell, before any preloadPack. */\nexport function iconPackRegistration(pack: RegisteredIconPack): { importLine: string; call: string } {\n return {\n importLine: \"import { registerIconPack } from 'gridsmith-ui/icons'\",\n call: `registerIconPack('${pack}', () => import('${ICON_PACK_IMPORTS[pack]}'))`,\n };\n}\n","import { createContext, useContext, useEffect, useSyncExternalStore, type ReactElement, type ReactNode, type ComponentType } from \"react\";\nimport { warnOnce } from \"./dev-warn\";\nimport { iconPackRegistration, type RegisteredIconPack } from \"./icon-pack-imports\";\nimport type { PackLoad } from \"./icon-packs/types\";\n\n/* ── Types ────────────────────────────────────────────────────── */\n\n/**\n * Runtime list of curated icon names. The CuratedIconName type derives from\n * this array, so adding a name here extends autocomplete automatically.\n * Every name must have an alias (or auto-kebab match) in ALL five packs —\n * icon-completeness.test.tsx enforces this.\n */\nexport const CURATED_ICON_NAMES = [\n \"home\", \"folder\", \"chart\", \"settings\",\n \"chevron-right\", \"close\", \"plus\", \"search\",\n \"bell\", \"user\", \"check\", \"warning\", \"info\", \"error\",\n \"clock\", \"calendar\",\n \"bold\", \"italic\", \"underline\", \"strikethrough\",\n \"align-left\", \"align-center\", \"align-right\",\n \"list\", \"list-ordered\", \"list-checks\",\n \"link\", \"image\", \"table\", \"code\", \"quote\", \"minus\",\n \"superscript\", \"subscript\", \"highlight\", \"type\",\n \"chevron-up\", \"chevron-down\", \"chevron-left\", \"trash\",\n \"undo\", \"redo\",\n \"arrow-left\", \"grip-vertical\",\n \"mic\", \"paperclip\", \"send\",\n \"log-out\", \"edit\", \"menu\", \"more-horizontal\",\n \"star\", \"bookmark\", \"download\", \"upload\", \"sparkles\",\n \"file\", \"file-text\", \"eye\", \"eye-off\", \"copy\", \"external-link\", \"filter\", \"lock\",\n \"map-pin\",\n] as const;\n\ntype CuratedIconName = (typeof CURATED_ICON_NAMES)[number];\n\n/**\n * Curated names provide autocomplete and work identically across all 5 packs.\n * Any kebab-case string is also accepted — it resolves directly against the\n * active pack's native exports (e.g. \"clipboard-copy\" → Lucide's ClipboardCopy).\n */\nexport type IconName = CuratedIconName | (string & {});\n\nexport type IconPack = \"lucide\" | \"phosphor\" | \"heroicons\" | \"tabler\" | \"feather\";\n\ntype IconComponent = ComponentType<Record<string, unknown>>;\ntype IconMap = Record<string, IconComponent>;\n\n/* ── External store ──────────────────────────────────────────── */\n\ntype Subscriber = () => void;\nconst subscribers = new Set<Subscriber>();\nfunction notifySubscribers() {\n subscribers.forEach((fn) => fn());\n}\nfunction subscribe(cb: Subscriber): () => void {\n subscribers.add(cb);\n return () => { subscribers.delete(cb); };\n}\n\nconst curatedCache = new Map<IconPack, IconMap>();\nconst extendedCache = new Map<IconPack, IconMap>();\n\nfunction useCuratedMap(pack: IconPack): IconMap | null {\n return useSyncExternalStore(\n subscribe,\n () => curatedCache.get(pack) ?? null,\n () => null,\n );\n}\n\nfunction useExtendedMap(pack: IconPack): IconMap | null {\n return useSyncExternalStore(\n subscribe,\n () => extendedCache.get(pack) ?? null,\n () => null,\n );\n}\n\n/* ── Pack loading ────────────────────────────────────────────────\n Each pack is isolated in its own file under ./icon-packs/, and reads\n its package through an import handed to it: the app's own for its\n theme's pack (registerIconPack, Sprint 25.21 P1), the library's own\n for Lucide. No file the library publishes names a pack the app may\n not have installed, so no bundler looks for one: Next.js's webpack\n resolved every pack the library named, and failed the build.\n\n Loading is two-phase:\n 1. Curated map (50 static named imports) — available as soon as\n the pack chunk loads, cached and notified immediately.\n 2. Extended map (full barrel import + kebab-case iteration) —\n loaded in the background, cached and notified when ready. */\n\nconst loadingPacks = new Set<IconPack>();\nconst failedPacks = new Set<IconPack>();\n\ntype PackModule = {\n loadCurated(load: PackLoad): Promise<IconMap>;\n loadExtended(load: PackLoad): Promise<IconMap>;\n};\n\n/** Each pack's import: Lucide's is the library's own (every app installs it); the others are the app's, registered. */\nconst packImports = new Map<IconPack, PackLoad>([[\"lucide\", () => import(\"lucide-react\")]]);\n\n/**\n * The theme's icon pack, as the app's own import (Sprint 25.21 P1): `registerIconPack('feather', () =>\n * import('react-icons/fi'))` at the top of the shell, before any preloadPack. The library names no pack itself, so an\n * app's bundler only ever meets the pack the app installed. A pack drawn before it is registered draws Lucide's icons,\n * and draws its own once registered. Lucide needs no line.\n */\nexport function registerIconPack(pack: RegisteredIconPack, load: PackLoad): void {\n packImports.set(pack, load);\n // a draw that met the pack unregistered loads it now: its icons redraw once the pack's map arrives (a notice alone\n // changes no snapshot, so nothing would redraw to ask)\n if (failedPacks.delete(pack)) void loadPack(pack);\n}\n\n/** The npm package each pack needs — named in the error when a pack is missing. */\nconst PEER_PACKAGE: Record<IconPack, string> = {\n lucide: \"lucide-react\",\n phosphor: \"@phosphor-icons/react\",\n heroicons: \"@heroicons/react\",\n tabler: \"@tabler/icons-react\",\n feather: \"react-icons\",\n};\n\nasync function loadPack(pack: IconPack): Promise<void> {\n if (curatedCache.has(pack) || loadingPacks.has(pack) || failedPacks.has(pack)) return;\n loadingPacks.add(pack);\n\n // Each pack module reaches its package only through the import handed to it\n // (see icon-packs/*.ts), so the chunk import below always succeeds and it is\n // loadCurated() that rejects when the package is not installed.\n const load = packImports.get(pack);\n if (!load) {\n // not registered: Lucide's icons stand in (Icon's third tier), and the developer is told the line to add\n failedPacks.add(pack);\n loadingPacks.delete(pack);\n const lines = iconPackRegistration(pack as RegisteredIconPack);\n warnOnce(\"IconProvider\", `the ${pack} icon pack isn't registered, so its icons are drawn from Lucide. At the top of the shell, before any preloadPack: ${lines.importLine}; ${lines.call}`);\n return;\n }\n let mod: PackModule;\n let curated: IconMap;\n try {\n switch (pack) {\n case \"lucide\": mod = await import(\"./icon-packs/lucide\"); break;\n case \"phosphor\": mod = await import(\"./icon-packs/phosphor\"); break;\n case \"heroicons\": mod = await import(\"./icon-packs/heroicons\"); break;\n case \"tabler\": mod = await import(\"./icon-packs/tabler\"); break;\n case \"feather\": mod = await import(\"./icon-packs/feather\"); break;\n }\n curated = await mod!.loadCurated(load);\n } catch {\n loadingPacks.delete(pack);\n failedPacks.add(pack);\n console.error(`gridsmith-ui: ${PEER_PACKAGE[pack]} is not installed. Run: npm install ${PEER_PACKAGE[pack]}`);\n return;\n }\n\n curatedCache.set(pack, curated);\n notifySubscribers();\n\n mod!.loadExtended(load).then((extended) => {\n extendedCache.set(pack, extended);\n notifySubscribers();\n }).catch(() => {\n // Extended map failed (e.g. network error loading the full barrel).\n // Curated icons still work; extended names will not resolve.\n });\n}\n\n/** A pack's registered import, for the tests that load the packs directly; they register them first. */\nfunction importOf(pack: IconPack): PackLoad {\n const load = packImports.get(pack);\n if (!load) throw new Error(`gridsmith-ui: register the ${pack} icon pack first (registerIconPack)`);\n return load;\n}\n\n/** Exported for the icon-completeness test — not part of the public API. */\nexport const packLoaders: Record<IconPack, {\n curated: () => Promise<IconMap>;\n extended: () => Promise<IconMap>;\n}> = {\n lucide: { curated: () => import(\"./icon-packs/lucide\").then((m) => m.loadCurated(importOf(\"lucide\"))), extended: () => import(\"./icon-packs/lucide\").then((m) => m.loadExtended(importOf(\"lucide\"))) },\n phosphor: { curated: () => import(\"./icon-packs/phosphor\").then((m) => m.loadCurated(importOf(\"phosphor\"))), extended: () => import(\"./icon-packs/phosphor\").then((m) => m.loadExtended(importOf(\"phosphor\"))) },\n heroicons: { curated: () => import(\"./icon-packs/heroicons\").then((m) => m.loadCurated(importOf(\"heroicons\"))), extended: () => import(\"./icon-packs/heroicons\").then((m) => m.loadExtended(importOf(\"heroicons\"))) },\n tabler: { curated: () => import(\"./icon-packs/tabler\").then((m) => m.loadCurated(importOf(\"tabler\"))), extended: () => import(\"./icon-packs/tabler\").then((m) => m.loadExtended(importOf(\"tabler\"))) },\n feather: { curated: () => import(\"./icon-packs/feather\").then((m) => m.loadCurated(importOf(\"feather\"))), extended: () => import(\"./icon-packs/feather\").then((m) => m.loadExtended(importOf(\"feather\"))) },\n};\n\n/* ── Context ──────────────────────────────────────────────────── */\n\ninterface IconContextValue {\n pack: IconPack;\n weight: number;\n}\n\nconst IconCtx = createContext<IconContextValue>({ pack: \"lucide\", weight: 1.5 });\n\nexport function IconProvider({ pack, weight, children }: { pack: IconPack; weight: number; children: ReactNode }) {\n useEffect(() => {\n loadPack(pack);\n if (pack !== \"lucide\") loadPack(\"lucide\");\n }, [pack]);\n\n return <IconCtx.Provider value={{ pack, weight }}>{children}</IconCtx.Provider>;\n}\n\n/**\n * Start loading a pack's icon chunk before React mounts. Call this in your\n * app's entry point or shell for the fastest possible cold start, after the\n * pack is registered (every pack but Lucide, Sprint 25.21 P1):\n *\n * import { preloadPack, registerIconPack } from 'gridsmith-ui/icons'\n * registerIconPack('feather', () => import('react-icons/fi'))\n * preloadPack('feather')\n */\nexport function preloadPack(pack: IconPack): void {\n loadPack(pack);\n}\n\n/* ── Phosphor weight mapping ──────────────────────────────────── */\n\n/**\n * A stroke weight maps to a stroke weight only. `fill` and `duotone` change the\n * glyph itself (Phosphor's filled Check is a check inside a filled square), so\n * a theme's heaviest stroke must never reach them — the Sprint 22 bench found\n * every tick on a 2.5-weight theme rendered as a filled box (14 Sep 2026).\n */\nexport function getPhosphorWeight(numericWeight: number): \"thin\" | \"light\" | \"regular\" | \"bold\" {\n if (numericWeight <= 0.75) return \"thin\";\n if (numericWeight <= 1.25) return \"light\";\n if (numericWeight <= 1.75) return \"regular\";\n return \"bold\";\n}\n\n/* ── Icon component ───────────────────────────────────────────── */\n\n/**\n * `from`: the component slot that drew the icon (\"Button's iconLeft\"), named in the development warning when the theme's\n * pack has no icon by that name. A name no pack has draws nothing (Sprint 25.17 A26: an arrow or a word passed as an\n * icon was printed as text before slots took names).\n */\n/**\n * Whether a map holds an icon of its own by this name, never one its prototype lends: a slot now takes any string, and\n * \"constructor\", \"toString\" or \"__proto__\" read off a plain object drew junk or threw (Sprint 25.17's review). The icon\n * is then read off the map itself, so the compiler sees a component the map holds, not one made while rendering.\n */\nfunction owns(map: Record<string, IconComponent> | null | undefined, name: string): map is Record<string, IconComponent> {\n return !!map && Object.prototype.hasOwnProperty.call(map, name);\n}\n\nexport function Icon({ name, size = 16, className, from }: { name: IconName; size?: number; className?: string; from?: string }) {\n const { pack, weight } = useContext(IconCtx);\n\n const curatedMap = useCuratedMap(pack);\n const extendedMap = useExtendedMap(pack);\n const lucideCurated = useCuratedMap(\"lucide\");\n const lucideExtended = useExtendedMap(\"lucide\");\n\n // Ensure the active pack is loading (covers cases where Icon mounts\n // before IconProvider's useEffect fires, e.g. during SSR hydration)\n if (!curatedCache.has(pack) && !loadingPacks.has(pack)) {\n loadPack(pack);\n }\n\n let Comp: IconComponent | undefined | null = null;\n let renderPack: IconPack = pack;\n\n // Tier 1: curated map (available once pack chunk has loaded)\n if (owns(curatedMap, name)) {\n Comp = curatedMap[name];\n }\n\n // Tier 2: extended map (available after barrel import completes)\n if (!Comp && owns(extendedMap, name)) {\n Comp = extendedMap[name];\n }\n\n // Tier 3: lucide fallback (curated first, then extended)\n if (!Comp && pack !== \"lucide\") {\n const fallback = owns(lucideCurated, name) ? lucideCurated[name] : owns(lucideExtended, name) ? lucideExtended[name] : undefined;\n if (fallback) {\n Comp = fallback;\n renderPack = \"lucide\";\n }\n }\n\n const allMapsLoaded = !!(curatedMap && extendedMap && (pack === \"lucide\" || (lucideCurated && lucideExtended)));\n const missing = !Comp && allMapsLoaded;\n useEffect(() => {\n if (missing) warnOnce(\"Icon\", `\"${name}\" is not an icon name in the ${pack} pack${pack === \"lucide\" ? \"\" : \" or Lucide\"}, so ${from ?? \"it\"} draws nothing. Pass an icon name, or an element.`);\n }, [missing, name, pack, from]);\n\n if (!Comp) {\n if (allMapsLoaded) return null;\n return <span style={{ display: \"inline-block\", width: size, height: size }} className={className} />;\n }\n\n if (renderPack === \"phosphor\") {\n return <Comp size={size} weight={getPhosphorWeight(weight)} className={className} />;\n }\n\n if (renderPack === \"heroicons\") {\n return <Comp className={className} style={{ width: size, height: size, strokeWidth: weight }} />;\n }\n\n if (renderPack === \"tabler\") {\n return <Comp size={size} stroke={weight} className={className} />;\n }\n\n if (renderPack === \"feather\") {\n return <Comp size={size} className={className} strokeWidth={weight} />;\n }\n\n return <Comp size={size} strokeWidth={weight} className={className} />;\n}\n\n/* ── Icon slots ───────────────────────────────────────────────── */\n\n/**\n * What an icon slot takes (Sprint 25.17 A26): an icon name, drawn as the theme's icon at the slot's size, or an element,\n * drawn as given. `IconName` accepts any string, so text type-checks: in development a name the theme's pack lacks warns,\n * naming the slot, and draws nothing; the engine flags a literal that is no icon name (gs:icon-slot-not-an-icon).\n */\nexport type IconSlot = IconName | ReactElement | false | null | undefined;\n\n/** What an icon slot holds, drawn: a name as the theme's icon at `size`, anything else as given. */\nexport function slotIcon(icon: IconSlot | ReactNode, size: number, from: string): ReactNode {\n if (typeof icon === \"string\") {\n // \"\" is no icon (`saved ? \"check\" : \"\"`): nothing drawn, nothing warned\n if (!icon) return null;\n return ICON_NAME_SHAPE.test(icon) ? <Icon name={icon} size={size} from={from} /> : <NotAnIcon text={icon} from={from} />;\n }\n return icon;\n}\n\n/** The shape of an icon name: kebab case, as every pack's names are written (\"arrow-right\", \"file-text\"). */\nconst ICON_NAME_SHAPE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\n/**\n * Whether a slot draws something: an element, or a string shaped as an icon name. Text (\"→\", \"Save\") draws nothing, so\n * a button keeps its even padding for it (Sprint 25.17's review); a name the pack lacks still warns, once its maps load.\n */\nexport function slotDraws(icon: IconSlot | ReactNode): boolean {\n if (typeof icon === \"string\") return ICON_NAME_SHAPE.test(icon);\n return icon != null && icon !== false && icon !== true;\n}\n\n/** Text given to an icon slot: it draws nothing, and says so in development, naming the slot. */\nfunction NotAnIcon({ text, from }: { text: string; from: string }) {\n useEffect(() => {\n warnOnce(\"Icon\", `\"${text}\" is not an icon name, so ${from} draws nothing. Words go in the label; pass an icon name, or an element.`);\n }, [text, from]);\n return null;\n}\n"]}
@@ -1,6 +1,7 @@
1
- import { useTextOverflow, Tooltip } from './chunk-MD2EFMES.js';
2
- import { Icon } from './chunk-HXVXJUGV.js';
3
- import { cn } from './chunk-M2QRNBDQ.js';
1
+ "use client";
2
+ import { useTextOverflow, Tooltip } from './chunk-GXMTS3YD.js';
3
+ import { Icon } from './chunk-TJEV7YAY.js';
4
+ import { cn } from './chunk-66JJCQU3.js';
4
5
  import { jsxs, jsx } from 'react/jsx-runtime';
5
6
 
6
7
  var severityToVariant = {
@@ -15,11 +16,11 @@ var variantStyles = {
15
16
  neutral: "bg-[var(--ds-text-muted)]/[0.12] text-[var(--ds-text-secondary)]",
16
17
  subtle: "bg-[var(--ds-bg-muted)] text-[var(--ds-text-secondary)]",
17
18
  success: "bg-[var(--ds-status-success)] text-[var(--ds-text-on-success)]",
18
- "success-soft": "bg-[var(--ds-status-success-bg)] text-[var(--ds-status-success)] border-[length:var(--ds-border-width)] border-[var(--ds-status-success)]/[0.2]",
19
+ "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]",
19
20
  warning: "bg-[var(--ds-status-warning)] text-[var(--ds-text-on-warning)]",
20
21
  "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]",
21
22
  error: "bg-[var(--ds-status-error)] text-[var(--ds-text-on-error)]",
22
- "error-soft": "bg-[var(--ds-status-error-bg)] text-[var(--ds-status-error)] border-[length:var(--ds-border-width)] border-[var(--ds-status-error)]/[0.2]",
23
+ "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]",
23
24
  outline: "bg-transparent text-[var(--ds-text-primary)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]"
24
25
  };
25
26
  var sizeStyles = {
@@ -98,5 +99,5 @@ function Badge({ variant = "default", severity, size = "md", color, iconLeft, ic
98
99
  }
99
100
 
100
101
  export { Badge };
101
- //# sourceMappingURL=chunk-EX64MN2U.js.map
102
- //# sourceMappingURL=chunk-EX64MN2U.js.map
102
+ //# sourceMappingURL=chunk-TRDXWHD2.js.map
103
+ //# sourceMappingURL=chunk-TRDXWHD2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../showcase/src/components/Badge.tsx"],"names":[],"mappings":"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","file":"chunk-TRDXWHD2.js","sourcesContent":["import { cn } from \"../lib/utils\";\nimport { Icon, type IconName } from \"../lib/icons\";\nimport { Tooltip } 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 className?: string;\n children?: ReactNode;\n}\n\nexport function Badge({ variant = \"default\", severity, size = \"md\", color, iconLeft, iconRight, maxWidth, 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 { ref: truncRef, isTruncated } = useTextOverflow({ lines: 1, disabled: !maxWidth });\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 className={cn(\n \"inline-flex items-center font-medium max-w-full whitespace-nowrap shrink-0\",\n \"rounded-[var(--ds-radius-full)]\",\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={maxWidth ? { maxWidth } : undefined}\n >\n {iconLeft && <Icon name={iconLeft} size={iconSize} className=\"shrink-0\" from=\"Badge's iconLeft\" />}\n {maxWidth ? (\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 <Tooltip content={children}>{badge}</Tooltip>;\n }\n return badge;\n}\n"]}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useRef, useLayoutEffect } from 'react';
2
3
 
3
4
  // ../../showcase/src/lib/use-latest.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/use-latest.ts"],"names":[],"mappings":";;;AAcO,SAAS,UAAa,KAAA,EAAwB;AACnD,EAAA,MAAM,GAAA,GAAM,OAAO,KAAK,CAAA;AACxB,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,GAAA,CAAI,OAAA,GAAU,KAAA;AAAA,EAChB,CAAC,CAAA;AACD,EAAA,OAAO,GAAA;AACT","file":"chunk-WH2FUFAC.js","sourcesContent":["import { useLayoutEffect, useRef, type RefObject } from \"react\";\n\n/**\n * A ref that always holds the latest value of `value`, updated in a layout\n * effect (before paint, before any event can fire) rather than during render.\n *\n * Use it for callbacks read from long-lived listeners — `onClose` inside a\n * document keydown handler, `onDismiss` inside a timer — so the listener need\n * not be re-attached every render and never calls a stale closure.\n *\n * The write happens in a commit-phase effect, which is the React-sanctioned\n * place to touch refs (the React Compiler's `refs` rule rejects writes during\n * render).\n */\nexport function useLatest<T>(value: T): RefObject<T> {\n const ref = useRef(value);\n useLayoutEffect(() => {\n ref.current = value;\n });\n return ref;\n}\n"]}
1
+ {"version":3,"sources":["../../../showcase/src/lib/use-latest.ts"],"names":[],"mappings":";;;;AAcO,SAAS,UAAa,KAAA,EAAwB;AACnD,EAAA,MAAM,GAAA,GAAM,OAAO,KAAK,CAAA;AACxB,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,GAAA,CAAI,OAAA,GAAU,KAAA;AAAA,EAChB,CAAC,CAAA;AACD,EAAA,OAAO,GAAA;AACT","file":"chunk-WH2FUFAC.js","sourcesContent":["import { useLayoutEffect, useRef, type RefObject } from \"react\";\n\n/**\n * A ref that always holds the latest value of `value`, updated in a layout\n * effect (before paint, before any event can fire) rather than during render.\n *\n * Use it for callbacks read from long-lived listeners — `onClose` inside a\n * document keydown handler, `onDismiss` inside a timer — so the listener need\n * not be re-attached every render and never calls a stale closure.\n *\n * The write happens in a commit-phase effect, which is the React-sanctioned\n * place to touch refs (the React Compiler's `refs` rule rejects writes during\n * render).\n */\nexport function useLatest<T>(value: T): RefObject<T> {\n const ref = useRef(value);\n useLayoutEffect(() => {\n ref.current = value;\n });\n return ref;\n}\n"]}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { createContext, useContext, useRef, useCallback } from 'react';
2
3
 
3
4
  // ../../showcase/src/lib/form-context.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/form-context.ts"],"names":[],"mappings":";;;AA0BO,IAAM,OAAA,GAAU,cAAuC,IAAI;AAE3D,SAAS,cAAA,GAAmC;AACjD,EAAA,MAAM,GAAA,GAAM,WAAW,OAAO,CAAA;AAC9B,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAC1E,EAAA,OAAO,GAAA;AACT;AAGO,SAAS,sBAAA,GAAkD;AAChE,EAAA,OAAO,WAAW,OAAO,CAAA;AAC3B;AAOO,IAAM,aAAA,GAAgB,cAAmC,IAAI;AAG7D,SAAS,SAAA,CAAU,GAAY,CAAA,EAAqB;AACzD,EAAA,IAAI,MAAA,CAAO,EAAA,CAAG,CAAA,EAAG,CAAC,GAAG,OAAO,IAAA;AAC5B,EAAA,IAAI,CAAA,YAAa,QAAQ,CAAA,YAAa,IAAA,SAAa,CAAA,CAAE,OAAA,EAAQ,KAAM,CAAA,CAAE,OAAA,EAAQ;AAC7E,EAAA,IAAI,KAAA,CAAM,QAAQ,CAAC,CAAA,IAAK,MAAM,OAAA,CAAQ,CAAC,CAAA,EAAG,OAAO,CAAA,CAAE,MAAA,KAAW,EAAE,MAAA,IAAU,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA,KAAM,UAAU,CAAA,EAAG,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AAC9G,EAAA,IAAI,KAAK,CAAA,IAAK,OAAO,MAAM,QAAA,IAAY,OAAO,MAAM,QAAA,IAAY,MAAA,CAAO,eAAe,CAAC,CAAA,KAAM,OAAO,SAAA,IAAa,MAAA,CAAO,eAAe,CAAC,CAAA,KAAM,OAAO,SAAA,EAAW;AAC9J,IAAA,MAAM,EAAA,GAAK,MAAA,CAAO,IAAA,CAAK,CAA4B,CAAA;AACnD,IAAA,MAAM,EAAA,GAAK,MAAA,CAAO,IAAA,CAAK,CAA4B,CAAA;AACnD,IAAA,OAAO,EAAA,CAAG,MAAA,KAAW,EAAA,CAAG,MAAA,IAAU,GAAG,KAAA,CAAM,CAAC,CAAA,KAAM,SAAA,CAAW,EAA8B,CAAC,CAAA,EAAI,CAAA,CAA8B,CAAC,CAAC,CAAC,CAAA;AAAA,EACnI;AAEA,EAAA,IAAK,CAAA,KAAM,EAAA,KAAO,CAAA,KAAM,MAAA,IAAa,CAAA,KAAM,IAAA,CAAA,IAAW,CAAA,KAAM,EAAA,KAAO,CAAA,KAAM,MAAA,IAAa,CAAA,KAAM,IAAA,CAAA,EAAQ,OAAO,IAAA;AAC3G,EAAA,OAAO,KAAA;AACT;AAUO,SAAS,iBAAA,CACd,UACA,OAAA,EACA,IAAA,GAAgC,IAAI,IAAA,KAAY,IAAA,CAAK,CAAC,CAAA,EAChC;AACtB,EAAA,MAAM,MAAA,GAAS,WAAW,aAAa,CAAA;AACvC,EAAA,MAAM,UAAA,GAAa,OAAO,OAAO,CAAA;AACjC,EAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AACrB,EAAA,MAAM,WAAA,GAAc,OAAO,QAAQ,CAAA;AACnC,EAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AACtB,EAAA,MAAM,OAAA,GAAU,OAAO,IAAI,CAAA;AAC3B,EAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAClB,EAAA,OAAO,WAAA,CAAY,IAAI,IAAA,KAAY;AACjC,IAAA,IAAI,MAAA,IAAU,CAAC,SAAA,CAAU,UAAA,CAAW,OAAA,EAAS,OAAA,CAAQ,OAAA,CAAQ,GAAG,IAAI,CAAC,CAAA,EAAG,MAAA,EAAO;AAC/E,IAAA,WAAA,CAAY,OAAA,GAAU,GAAG,IAAI,CAAA;AAAA,EAC/B,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACb","file":"chunk-XVB55M3N.js","sourcesContent":["import { createContext, useCallback, useContext, useRef } from \"react\";\n\n/** When a form's fields check themselves: the project's forms.validationTiming, through FormWrapper. */\nexport type ValidationMode = \"onBlur\" | \"onSubmit\" | \"onChange\";\n\nexport interface FormErrors {\n [field: string]: string | undefined;\n}\n\n/** A field's check: the message for what is wrong with its value now, or nothing. */\nexport type FieldCheck = () => string | undefined;\n\nexport interface FormContextValue {\n errors: FormErrors;\n setError: (field: string, message: string | undefined) => void;\n clearErrors: () => void;\n validationMode: ValidationMode;\n submitted: boolean;\n /**\n * A Field given `validate` registers its check under its id, and the form runs every check on each submit (round 26,\n * R26-2: the forms of both runs checked their fields only on submit, although the project said on blur). Returns\n * the unregister.\n */\n register: (field: string, check: FieldCheck) => () => void;\n}\n\nexport const FormCtx = createContext<FormContextValue | null>(null);\n\nexport function useFormContext(): FormContextValue {\n const ctx = useContext(FormCtx);\n if (!ctx) throw new Error(\"useFormContext must be used within FormWrapper\");\n return ctx;\n}\n\n/** The FormWrapper a component sits in, or null. */\nexport function useOptionalFormContext(): FormContextValue | null {\n return useContext(FormCtx);\n}\n\n/**\n * Sprint 25.12 A15 (R28-25): the nearest FormWrapper's change reporter. A control calls it when the user gives it a new\n * value; the form passes it on to the overlay that holds it, so the overlay asks before discarding only after a change.\n * Null outside a FormWrapper: controls there never mark anything (a page that saves as you go has nothing to discard).\n */\nexport const FormChangeCtx = createContext<(() => void) | null>(null);\n\n/** Whether two control values are the same value: dates by time, arrays and plain objects by their parts. */\nexport function sameValue(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();\n if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((x, i) => sameValue(x, b[i]));\n if (a && b && typeof a === \"object\" && typeof b === \"object\" && Object.getPrototypeOf(a) === Object.prototype && Object.getPrototypeOf(b) === Object.prototype) {\n const ka = Object.keys(a as Record<string, unknown>);\n const kb = Object.keys(b as Record<string, unknown>);\n return ka.length === kb.length && ka.every((k) => sameValue((a as Record<string, unknown>)[k], (b as Record<string, unknown>)[k]));\n }\n // an empty text field and an unset value are the same answer: a control that commits \"\" over undefined changed nothing\n if ((a === \"\" && (b === undefined || b === null)) || (b === \"\" && (a === undefined || a === null))) return true;\n return false;\n}\n\n/**\n * Sprint 25.12 A15: a control's `onChange`, wrapped so a new value the user gives it reports a change to the nearest\n * FormWrapper before the page hears of it. `current` is the control's value now (its prop, or its own state when it\n * keeps one); `read` takes the new value from onChange's arguments (the first argument by default; an event's\n * `target.value` for native inputs). Only a different value reports: NumberInput committing the same number on blur,\n * or a search inside a Dropdown, changes nothing. Call it only from the user's own actions, never from an effect, so a\n * value the page sets, or one a control settles on by itself, never counts.\n */\nexport function useReportedChange<A extends unknown[]>(\n onChange: ((...args: A) => void) | undefined,\n current: unknown,\n read: (...args: A) => unknown = (...args: A) => args[0],\n): (...args: A) => void {\n const report = useContext(FormChangeCtx);\n const currentRef = useRef(current);\n currentRef.current = current;\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n const readRef = useRef(read);\n readRef.current = read;\n return useCallback((...args: A) => {\n if (report && !sameValue(currentRef.current, readRef.current(...args))) report();\n onChangeRef.current?.(...args);\n }, [report]);\n}\n"]}
1
+ {"version":3,"sources":["../../../showcase/src/lib/form-context.ts"],"names":[],"mappings":";;;;AA0BO,IAAM,OAAA,GAAU,cAAuC,IAAI;AAE3D,SAAS,cAAA,GAAmC;AACjD,EAAA,MAAM,GAAA,GAAM,WAAW,OAAO,CAAA;AAC9B,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAC1E,EAAA,OAAO,GAAA;AACT;AAGO,SAAS,sBAAA,GAAkD;AAChE,EAAA,OAAO,WAAW,OAAO,CAAA;AAC3B;AAOO,IAAM,aAAA,GAAgB,cAAmC,IAAI;AAG7D,SAAS,SAAA,CAAU,GAAY,CAAA,EAAqB;AACzD,EAAA,IAAI,MAAA,CAAO,EAAA,CAAG,CAAA,EAAG,CAAC,GAAG,OAAO,IAAA;AAC5B,EAAA,IAAI,CAAA,YAAa,QAAQ,CAAA,YAAa,IAAA,SAAa,CAAA,CAAE,OAAA,EAAQ,KAAM,CAAA,CAAE,OAAA,EAAQ;AAC7E,EAAA,IAAI,KAAA,CAAM,QAAQ,CAAC,CAAA,IAAK,MAAM,OAAA,CAAQ,CAAC,CAAA,EAAG,OAAO,CAAA,CAAE,MAAA,KAAW,EAAE,MAAA,IAAU,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA,KAAM,UAAU,CAAA,EAAG,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AAC9G,EAAA,IAAI,KAAK,CAAA,IAAK,OAAO,MAAM,QAAA,IAAY,OAAO,MAAM,QAAA,IAAY,MAAA,CAAO,eAAe,CAAC,CAAA,KAAM,OAAO,SAAA,IAAa,MAAA,CAAO,eAAe,CAAC,CAAA,KAAM,OAAO,SAAA,EAAW;AAC9J,IAAA,MAAM,EAAA,GAAK,MAAA,CAAO,IAAA,CAAK,CAA4B,CAAA;AACnD,IAAA,MAAM,EAAA,GAAK,MAAA,CAAO,IAAA,CAAK,CAA4B,CAAA;AACnD,IAAA,OAAO,EAAA,CAAG,MAAA,KAAW,EAAA,CAAG,MAAA,IAAU,GAAG,KAAA,CAAM,CAAC,CAAA,KAAM,SAAA,CAAW,EAA8B,CAAC,CAAA,EAAI,CAAA,CAA8B,CAAC,CAAC,CAAC,CAAA;AAAA,EACnI;AAEA,EAAA,IAAK,CAAA,KAAM,EAAA,KAAO,CAAA,KAAM,MAAA,IAAa,CAAA,KAAM,IAAA,CAAA,IAAW,CAAA,KAAM,EAAA,KAAO,CAAA,KAAM,MAAA,IAAa,CAAA,KAAM,IAAA,CAAA,EAAQ,OAAO,IAAA;AAC3G,EAAA,OAAO,KAAA;AACT;AAUO,SAAS,iBAAA,CACd,UACA,OAAA,EACA,IAAA,GAAgC,IAAI,IAAA,KAAY,IAAA,CAAK,CAAC,CAAA,EAChC;AACtB,EAAA,MAAM,MAAA,GAAS,WAAW,aAAa,CAAA;AACvC,EAAA,MAAM,UAAA,GAAa,OAAO,OAAO,CAAA;AACjC,EAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AACrB,EAAA,MAAM,WAAA,GAAc,OAAO,QAAQ,CAAA;AACnC,EAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AACtB,EAAA,MAAM,OAAA,GAAU,OAAO,IAAI,CAAA;AAC3B,EAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAClB,EAAA,OAAO,WAAA,CAAY,IAAI,IAAA,KAAY;AACjC,IAAA,IAAI,MAAA,IAAU,CAAC,SAAA,CAAU,UAAA,CAAW,OAAA,EAAS,OAAA,CAAQ,OAAA,CAAQ,GAAG,IAAI,CAAC,CAAA,EAAG,MAAA,EAAO;AAC/E,IAAA,WAAA,CAAY,OAAA,GAAU,GAAG,IAAI,CAAA;AAAA,EAC/B,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACb","file":"chunk-XVB55M3N.js","sourcesContent":["import { createContext, useCallback, useContext, useRef } from \"react\";\n\n/** When a form's fields check themselves: the project's forms.validationTiming, through FormWrapper. */\nexport type ValidationMode = \"onBlur\" | \"onSubmit\" | \"onChange\";\n\nexport interface FormErrors {\n [field: string]: string | undefined;\n}\n\n/** A field's check: the message for what is wrong with its value now, or nothing. */\nexport type FieldCheck = () => string | undefined;\n\nexport interface FormContextValue {\n errors: FormErrors;\n setError: (field: string, message: string | undefined) => void;\n clearErrors: () => void;\n validationMode: ValidationMode;\n submitted: boolean;\n /**\n * A Field given `validate` registers its check under its id, and the form runs every check on each submit (round 26,\n * R26-2: the forms of both runs checked their fields only on submit, although the project said on blur). Returns\n * the unregister.\n */\n register: (field: string, check: FieldCheck) => () => void;\n}\n\nexport const FormCtx = createContext<FormContextValue | null>(null);\n\nexport function useFormContext(): FormContextValue {\n const ctx = useContext(FormCtx);\n if (!ctx) throw new Error(\"useFormContext must be used within FormWrapper\");\n return ctx;\n}\n\n/** The FormWrapper a component sits in, or null. */\nexport function useOptionalFormContext(): FormContextValue | null {\n return useContext(FormCtx);\n}\n\n/**\n * Sprint 25.12 A15 (R28-25): the nearest FormWrapper's change reporter. A control calls it when the user gives it a new\n * value; the form passes it on to the overlay that holds it, so the overlay asks before discarding only after a change.\n * Null outside a FormWrapper: controls there never mark anything (a page that saves as you go has nothing to discard).\n */\nexport const FormChangeCtx = createContext<(() => void) | null>(null);\n\n/** Whether two control values are the same value: dates by time, arrays and plain objects by their parts. */\nexport function sameValue(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();\n if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((x, i) => sameValue(x, b[i]));\n if (a && b && typeof a === \"object\" && typeof b === \"object\" && Object.getPrototypeOf(a) === Object.prototype && Object.getPrototypeOf(b) === Object.prototype) {\n const ka = Object.keys(a as Record<string, unknown>);\n const kb = Object.keys(b as Record<string, unknown>);\n return ka.length === kb.length && ka.every((k) => sameValue((a as Record<string, unknown>)[k], (b as Record<string, unknown>)[k]));\n }\n // an empty text field and an unset value are the same answer: a control that commits \"\" over undefined changed nothing\n if ((a === \"\" && (b === undefined || b === null)) || (b === \"\" && (a === undefined || a === null))) return true;\n return false;\n}\n\n/**\n * Sprint 25.12 A15: a control's `onChange`, wrapped so a new value the user gives it reports a change to the nearest\n * FormWrapper before the page hears of it. `current` is the control's value now (its prop, or its own state when it\n * keeps one); `read` takes the new value from onChange's arguments (the first argument by default; an event's\n * `target.value` for native inputs). Only a different value reports: NumberInput committing the same number on blur,\n * or a search inside a Dropdown, changes nothing. Call it only from the user's own actions, never from an effect, so a\n * value the page sets, or one a control settles on by itself, never counts.\n */\nexport function useReportedChange<A extends unknown[]>(\n onChange: ((...args: A) => void) | undefined,\n current: unknown,\n read: (...args: A) => unknown = (...args: A) => args[0],\n): (...args: A) => void {\n const report = useContext(FormChangeCtx);\n const currentRef = useRef(current);\n currentRef.current = current;\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n const readRef = useRef(read);\n readRef.current = read;\n return useCallback((...args: A) => {\n if (report && !sameValue(currentRef.current, readRef.current(...args))) report();\n onChangeRef.current?.(...args);\n }, [report]);\n}\n"]}
@@ -1,13 +1,16 @@
1
- import { ControlSizeContext, triggerType, Button, useShellPreferences, PREFERENCE_HOUSE_DEFAULTS } from './chunk-ZYVXV4WC.js';
1
+ "use client";
2
+ import { ControlSizeContext, triggerType, Button, useShellPreferences, PREFERENCE_HOUSE_DEFAULTS } from './chunk-R4GXKH4U.js';
3
+ import { useInputModality } from './chunk-7RKC5C7G.js';
2
4
  import { useReportedChange, useOptionalFormContext, FormChangeCtx } from './chunk-XVB55M3N.js';
3
5
  import { RowsCtx } from './chunk-QM4SJKWV.js';
6
+ import { useRevealFocus } from './chunk-HTXP5BMM.js';
4
7
  import { usePopupFocus, focusAfterRemoval, usePressMarks, focusInitial } from './chunk-ZI3OQDET.js';
5
- import { useTextOverflow, Tooltip } from './chunk-MD2EFMES.js';
8
+ import { useTextOverflow, Tooltip } from './chunk-GXMTS3YD.js';
6
9
  import { Slot } from './chunk-7Q46JXSK.js';
7
- import { Icon, warnOnce } from './chunk-HXVXJUGV.js';
10
+ import { Icon, warnOnce } from './chunk-TJEV7YAY.js';
8
11
  import { usePosition } from './chunk-HP7WUZPK.js';
9
12
  import { useLatest } from './chunk-WH2FUFAC.js';
10
- import { cn, ERROR_HAS_FOCUS_RING, HAS_FOCUS_RING, ERROR_FOCUS_RING, FOCUS_RING, ERROR_ACTIVE_RING, ACTIVE_RING, ERROR_FOCUS_WITHIN_RING, FOCUS_WITHIN_RING, GLASS_DROPDOWN } from './chunk-M2QRNBDQ.js';
13
+ import { cn, ERROR_HAS_FOCUS_RING, FIELD_HAS_FOCUS_RING, ERROR_FOCUS_RING, FIELD_FOCUS_RING, FOCUS_RING, ERROR_ACTIVE_RING, ACTIVE_RING, ERROR_FOCUS_WITHIN_RING, FIELD_FOCUS_WITHIN_RING, GLASS_DROPDOWN } from './chunk-66JJCQU3.js';
11
14
  import { createContext, useContext, useRef, useCallback, useEffect, useId, useState, Children, isValidElement, useMemo, cloneElement, useLayoutEffect } from 'react';
12
15
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
13
16
  import { createPortal } from 'react-dom';
@@ -38,6 +41,7 @@ var INPUT_TEXT = {
38
41
  lg: "px-ds-4 py-ds-3 text-base"
39
42
  };
40
43
  function Input({ className, size: sizeProp, error = false, prefix, suffix, ...props }) {
44
+ useInputModality();
41
45
  const contextSize = useContext(ControlSizeContext);
42
46
  const size = sizeProp ?? contextSize ?? "md";
43
47
  const width = useContext(FilterRowContext) ? FILTER_FIELD_WIDTH : "w-full";
@@ -58,7 +62,7 @@ function Input({ className, size: sizeProp, error = false, prefix, suffix, ...pr
58
62
  "rounded-[var(--ds-radius-md)]",
59
63
  "shadow-[var(--ds-input-shadow)]",
60
64
  hoverBorder,
61
- error ? ERROR_HAS_FOCUS_RING : HAS_FOCUS_RING,
65
+ error ? ERROR_HAS_FOCUS_RING : FIELD_HAS_FOCUS_RING,
62
66
  "transition-colors duration-[var(--ds-transition-speed)]",
63
67
  props.disabled && "cursor-not-allowed opacity-disabled",
64
68
  props.readOnly && "bg-[var(--ds-bg-muted)] cursor-default",
@@ -103,7 +107,7 @@ function Input({ className, size: sizeProp, error = false, prefix, suffix, ...pr
103
107
  "shadow-[var(--ds-input-shadow)]",
104
108
  "placeholder:text-[var(--ds-text-muted)]",
105
109
  hoverBorder,
106
- error ? ERROR_FOCUS_RING : FOCUS_RING,
110
+ error ? ERROR_FOCUS_RING : FIELD_FOCUS_RING,
107
111
  "disabled:cursor-not-allowed disabled:opacity-disabled",
108
112
  "read-only:bg-[var(--ds-bg-muted)] read-only:text-[var(--ds-text-secondary)] read-only:cursor-default",
109
113
  "transition-colors duration-[var(--ds-transition-speed)]",
@@ -115,6 +119,7 @@ function Input({ className, size: sizeProp, error = false, prefix, suffix, ...pr
115
119
  );
116
120
  }
117
121
  function Textarea({ className, autoResize, maxRows, error = false, ref, ...props }) {
122
+ useInputModality();
118
123
  const onChange = useReportedChange(props.onChange, props.value === void 0 ? UNCONTROLLED : props.value, valueOf);
119
124
  const internalRef = useRef(null);
120
125
  const textareaRef = ref ?? internalRef;
@@ -146,7 +151,7 @@ function Textarea({ className, autoResize, maxRows, error = false, ref, ...props
146
151
  "rounded-[var(--ds-radius-md)]",
147
152
  "shadow-[var(--ds-input-shadow)]",
148
153
  "placeholder:text-[var(--ds-text-muted)]",
149
- error ? ERROR_FOCUS_RING : FOCUS_RING,
154
+ error ? ERROR_FOCUS_RING : FIELD_FOCUS_RING,
150
155
  "disabled:cursor-not-allowed disabled:opacity-disabled disabled:hover:border-[var(--ds-input-border)]",
151
156
  "read-only:bg-[var(--ds-bg-muted)] read-only:text-[var(--ds-text-secondary)] read-only:cursor-default read-only:hover:border-[var(--ds-input-border)]",
152
157
  "transition-colors duration-[var(--ds-transition-speed)]",
@@ -198,7 +203,7 @@ function Toggle({ checked, onChange, label, disabled, error = false, layout = "f
198
203
  "border-[length:var(--ds-border-width)]",
199
204
  "rounded-[var(--ds-radius-full)]",
200
205
  "transition-colors duration-[var(--ds-transition-speed)]",
201
- "focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
206
+ FOCUS_RING,
202
207
  disabled ? "cursor-not-allowed" : "cursor-pointer",
203
208
  // Sprint 25.14 A20: on, the checked colour, as a checkbox's; off, the outline in the edge colour (lib/control-looks.ts)
204
209
  checked ? SWITCH_TRACK_ON : SWITCH_TRACK_OFF,
@@ -249,12 +254,12 @@ function InlineFieldError({ message, id, className }) {
249
254
  id,
250
255
  role: "alert",
251
256
  className: cn(
252
- "flex items-center gap-ds-1.5 text-xs text-[var(--ds-status-error)]",
257
+ "flex items-center gap-ds-1.5 text-xs text-[var(--ds-status-error-text)]",
253
258
  "mt-ds-1.5",
254
259
  className
255
260
  ),
256
261
  children: [
257
- /* @__PURE__ */ jsx(Icon, { name: "error", size: 14, className: "shrink-0" }),
262
+ /* @__PURE__ */ jsx(Icon, { name: "error", size: 14, className: "shrink-0 text-[var(--ds-status-error)]" }),
258
263
  /* @__PURE__ */ jsx("span", { children: message })
259
264
  ]
260
265
  }
@@ -264,6 +269,9 @@ var FieldContext = createContext(null);
264
269
  function useField() {
265
270
  return useContext(FieldContext);
266
271
  }
272
+ function OutsideField({ children }) {
273
+ return /* @__PURE__ */ jsx(FieldContext.Provider, { value: null, children });
274
+ }
267
275
  function useFieldControl(own, options = {}) {
268
276
  const field = useField();
269
277
  const id = own.id ?? field?.controlId;
@@ -409,6 +417,7 @@ function Dropdown({
409
417
  ...wiring
410
418
  }) {
411
419
  const onChange = useReportedChange(onChangeProp, value);
420
+ useInputModality();
412
421
  const contextSize = useContext(ControlSizeContext);
413
422
  const generatedId = useId();
414
423
  const control = useFieldControl({ ...wiring, error: error || void 0 }, { requiredInDescription: true });
@@ -421,6 +430,8 @@ function Dropdown({
421
430
  const [search, setSearch] = useState("");
422
431
  const [positioned, setPositioned] = useState(false);
423
432
  const triggerRef = useRef(null);
433
+ const [listbox, setListbox] = useState(null);
434
+ useRevealFocus(listbox);
424
435
  const menuRef = useRef(null);
425
436
  const searchRef = useRef(null);
426
437
  const [pos, setPos] = useState({ top: 0, left: 0, width: 0 });
@@ -617,7 +628,7 @@ function Dropdown({
617
628
  "transition-colors",
618
629
  !invalid && !disabled && !open && "hover:border-[var(--ds-input-border-hover)]",
619
630
  open && (invalid ? ERROR_ACTIVE_RING : ACTIVE_RING),
620
- invalid ? ERROR_FOCUS_RING : FOCUS_RING,
631
+ invalid ? ERROR_FOCUS_RING : FIELD_FOCUS_RING,
621
632
  "cursor-pointer disabled:cursor-not-allowed disabled:opacity-disabled",
622
633
  !selectedValues.length && "text-[var(--ds-text-muted)]"
623
634
  ),
@@ -652,10 +663,11 @@ function Dropdown({
652
663
  value: search,
653
664
  onChange: (e) => setSearch(e.target.value),
654
665
  placeholder: "Search\u2026",
666
+ "data-popup-search": "",
655
667
  className: cn("w-full bg-transparent text-[var(--ds-text-primary)] placeholder:text-[var(--ds-text-muted)] outline-none", size === "sm" ? "text-xs" : "text-sm")
656
668
  }
657
669
  ) }),
658
- /* @__PURE__ */ jsx("div", { role: "listbox", className: "overflow-y-auto", style: { padding: "var(--ds-space-1)", maxHeight: "var(--ds-dropdown-max-height)" }, children: filtered.length === 0 ? /* @__PURE__ */ jsx("p", { className: cn("text-[var(--ds-text-muted)] text-center py-ds-4", size === "sm" ? "text-xs" : "text-sm"), children: "No options found" }) : hasGroups ? Array.from(groups.entries()).map(([group, opts]) => /* @__PURE__ */ jsxs("div", { children: [
670
+ /* @__PURE__ */ jsx("div", { ref: setListbox, role: "listbox", className: "overflow-y-auto scroll-p-[4px]", style: { padding: "max(var(--ds-space-1), 4px)", maxHeight: "var(--ds-dropdown-max-height)" }, children: filtered.length === 0 ? /* @__PURE__ */ jsx("p", { className: cn("text-[var(--ds-text-muted)] text-center py-ds-4", size === "sm" ? "text-xs" : "text-sm"), children: "No options found" }) : hasGroups ? Array.from(groups.entries()).map(([group, opts]) => /* @__PURE__ */ jsxs("div", { children: [
659
671
  group && /* @__PURE__ */ jsx("p", { className: "text-2xs font-medium uppercase tracking-wider text-[var(--ds-text-muted)] px-ds-2 pt-ds-2 pb-ds-1", children: group }),
660
672
  opts.map((opt) => /* @__PURE__ */ jsx(
661
673
  OptionButton,
@@ -701,7 +713,7 @@ function Dropdown({
701
713
  pendingChipFocus.current = { index: i, value: v };
702
714
  handleSelect(v);
703
715
  },
704
- className: "hover:text-[var(--ds-text-primary)] cursor-pointer",
716
+ className: cn("hover:text-[var(--ds-text-primary)] cursor-pointer", FOCUS_RING),
705
717
  "aria-label": `Remove ${opt.label}`,
706
718
  children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 10 })
707
719
  }
@@ -732,7 +744,8 @@ function OptionButton({
732
744
  className: cn(
733
745
  "w-full text-left cursor-pointer rounded-[var(--ds-radius-sm)]",
734
746
  "transition-colors flex items-center gap-ds-2",
735
- "focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
747
+ // the arrows move DOM focus here, so the option draws the outline; outside it, clear of the chosen one's fill
748
+ FOCUS_RING,
736
749
  size === "sm" ? "px-ds-2 py-ds-1 text-xs" : "px-ds-2 py-ds-1.5 text-sm",
737
750
  isSelected && !multiple ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]" : "text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-emphasis)]"
738
751
  ),
@@ -775,6 +788,7 @@ function NumberInput({
775
788
  id
776
789
  }) {
777
790
  const onChange = useReportedChange(onChangeProp, value);
791
+ useInputModality();
778
792
  const contextSize = useContext(ControlSizeContext);
779
793
  const size = sizeProp ?? contextSize ?? "md";
780
794
  const intervalRef = useRef(void 0);
@@ -877,7 +891,7 @@ function NumberInput({
877
891
  "bg-[var(--ds-input-bg)]",
878
892
  "transition-colors duration-[var(--ds-transition-speed)]",
879
893
  !error && !disabled && "hover:border-[var(--ds-input-border-hover)]",
880
- error ? ERROR_FOCUS_WITHIN_RING : cn(FOCUS_WITHIN_RING, "focus-within:hover:border-[var(--ds-border-focus)]"),
894
+ error ? ERROR_FOCUS_WITHIN_RING : FIELD_FOCUS_WITHIN_RING,
881
895
  disabled && "opacity-disabled cursor-not-allowed",
882
896
  className
883
897
  ),
@@ -901,6 +915,9 @@ function NumberInput({
901
915
  "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]",
902
916
  "transition-colors cursor-pointer",
903
917
  "rounded-l-[var(--ds-radius-md)]",
918
+ // kept out of the Tab order (the field's arrows step it) and never focused by a press: the outline all the same
919
+ // if anything focuses it (Sprint 30)
920
+ FOCUS_RING,
904
921
  s.btn,
905
922
  s.input,
906
923
  (disabled || atMin) && "opacity-disabled cursor-not-allowed hover:bg-transparent hover:text-[var(--ds-text-muted)]"
@@ -957,6 +974,7 @@ function NumberInput({
957
974
  "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]",
958
975
  "transition-colors cursor-pointer",
959
976
  "rounded-r-[var(--ds-radius-md)]",
977
+ FOCUS_RING,
960
978
  s.btn,
961
979
  s.input,
962
980
  (disabled || atMax) && "opacity-disabled cursor-not-allowed hover:bg-transparent hover:text-[var(--ds-text-muted)]"
@@ -1140,7 +1158,8 @@ function PageNumbers({ currentPage, totalPages, onPageChange, pageSize: pageSize
1140
1158
  "bg-[var(--ds-bg-surface)] text-[var(--ds-text-secondary)]",
1141
1159
  "transition-colors duration-[var(--ds-transition-speed)]",
1142
1160
  "hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]",
1143
- "disabled:opacity-disabled disabled:cursor-not-allowed"
1161
+ "disabled:opacity-disabled disabled:cursor-not-allowed",
1162
+ FOCUS_RING
1144
1163
  ),
1145
1164
  children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 16, className: "rotate-180" })
1146
1165
  }
@@ -1157,6 +1176,7 @@ function PageNumbers({ currentPage, totalPages, onPageChange, pageSize: pageSize
1157
1176
  "rounded-[var(--ds-radius-md)]",
1158
1177
  "border-[length:var(--ds-border-width)]",
1159
1178
  "transition-colors duration-[var(--ds-transition-speed)]",
1179
+ FOCUS_RING,
1160
1180
  p === currentPage ? "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] text-[var(--ds-text-on-primary)] border-[var(--ds-accent-primary)]" : "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)]"
1161
1181
  ),
1162
1182
  children: p
@@ -1178,7 +1198,8 @@ function PageNumbers({ currentPage, totalPages, onPageChange, pageSize: pageSize
1178
1198
  "bg-[var(--ds-bg-surface)] text-[var(--ds-text-secondary)]",
1179
1199
  "transition-colors duration-[var(--ds-transition-speed)]",
1180
1200
  "hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]",
1181
- "disabled:opacity-disabled disabled:cursor-not-allowed"
1201
+ "disabled:opacity-disabled disabled:cursor-not-allowed",
1202
+ FOCUS_RING
1182
1203
  ),
1183
1204
  children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 16 })
1184
1205
  }
@@ -1225,7 +1246,8 @@ function EllipsisJumper({ totalPages, onPageChange }) {
1225
1246
  "rounded-[var(--ds-radius-md)]",
1226
1247
  "text-[var(--ds-text-muted)]",
1227
1248
  "transition-colors duration-[var(--ds-transition-speed)]",
1228
- "hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]"
1249
+ "hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]",
1250
+ FOCUS_RING
1229
1251
  ),
1230
1252
  children: "\u2026"
1231
1253
  }
@@ -1255,7 +1277,8 @@ function EllipsisJumper({ totalPages, onPageChange }) {
1255
1277
  "rounded-[var(--ds-radius-md)]",
1256
1278
  "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]",
1257
1279
  "transition-colors duration-[var(--ds-transition-speed)]",
1258
- "hover:opacity-90"
1280
+ "hover:opacity-90",
1281
+ FOCUS_RING
1259
1282
  ),
1260
1283
  children: "Go"
1261
1284
  }
@@ -1346,6 +1369,6 @@ function useWholeListCheck(component, length, pager) {
1346
1369
  }, [component, length, total]);
1347
1370
  }
1348
1371
 
1349
- export { AddAnotherRowCtx, CHECK_FILL, Dropdown, Field, FilterRowContext, InlineFieldError, Input, Label, NumberInput, Pagination, Popover, SWITCH_KNOB_MOTION, SWITCH_KNOB_OFF, SWITCH_KNOB_ON, SWITCH_TRACK_OFF, SWITCH_TRACK_ON, Textarea, Toggle, pagerPart, useField, useFieldControl, usePagination, useWholeListCheck };
1350
- //# sourceMappingURL=chunk-CYN5O567.js.map
1351
- //# sourceMappingURL=chunk-CYN5O567.js.map
1372
+ export { AddAnotherRowCtx, CHECK_FILL, Dropdown, Field, FilterRowContext, InlineFieldError, Input, Label, NumberInput, OutsideField, Pagination, Popover, SWITCH_KNOB_MOTION, SWITCH_KNOB_OFF, SWITCH_KNOB_ON, SWITCH_TRACK_OFF, SWITCH_TRACK_ON, Textarea, Toggle, pagerPart, useField, useFieldControl, usePagination, useWholeListCheck };
1373
+ //# sourceMappingURL=chunk-YUTF2X6B.js.map
1374
+ //# sourceMappingURL=chunk-YUTF2X6B.js.map