@godxjp/ui 20.0.0 → 20.2.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 (273) hide show
  1. package/README.md +8 -2
  2. package/dist/app/app-provider.js +37 -21
  3. package/dist/app/index.d.ts +2 -0
  4. package/dist/app/index.js +2 -0
  5. package/dist/app/storage.d.ts +17 -0
  6. package/dist/app/storage.js +28 -0
  7. package/dist/app/theme-axes.d.ts +2 -0
  8. package/dist/app/theme-axes.js +45 -0
  9. package/dist/components/charts/chart-cartesian.d.ts +2 -1
  10. package/dist/components/charts/chart-cartesian.js +52 -3
  11. package/dist/components/charts/chart-category-axis.d.ts +55 -0
  12. package/dist/components/charts/chart-category-axis.js +93 -0
  13. package/dist/components/charts/chart-frame.d.ts +10 -1
  14. package/dist/components/charts/chart-frame.js +19 -3
  15. package/dist/components/charts/compact-bar-trend.d.ts +1 -1
  16. package/dist/components/charts/compact-bar-trend.js +2 -0
  17. package/dist/components/charts/pie-chart.d.ts +1 -1
  18. package/dist/components/charts/pie-chart.js +12 -1
  19. package/dist/components/charts/recharts-peer.d.ts +49 -0
  20. package/dist/components/charts/recharts-peer.js +45 -0
  21. package/dist/components/data-display/card.d.ts +12 -1
  22. package/dist/components/data-display/card.js +22 -4
  23. package/dist/components/data-display/code-block.js +6 -2
  24. package/dist/components/data-display/data-table.d.ts +39 -4
  25. package/dist/components/data-display/data-table.js +802 -270
  26. package/dist/components/data-display/descriptions.d.ts +27 -6
  27. package/dist/components/data-display/descriptions.js +58 -17
  28. package/dist/components/data-display/index.d.ts +2 -0
  29. package/dist/components/data-display/index.js +2 -0
  30. package/dist/components/data-display/list-row.d.ts +10 -1
  31. package/dist/components/data-display/list-row.js +7 -1
  32. package/dist/components/data-display/popover.d.ts +9 -3
  33. package/dist/components/data-display/popover.js +65 -11
  34. package/dist/components/data-display/range-timeline.d.ts +38 -0
  35. package/dist/components/data-display/range-timeline.js +161 -0
  36. package/dist/components/data-display/scroll-area.js +13 -2
  37. package/dist/components/data-display/service-launcher-card.js +14 -12
  38. package/dist/components/data-display/table.d.ts +71 -3
  39. package/dist/components/data-display/table.js +56 -18
  40. package/dist/components/data-display/tree-list.js +4 -9
  41. package/dist/components/data-entry/calendar.d.ts +2 -2
  42. package/dist/components/data-entry/calendar.js +23 -3
  43. package/dist/components/data-entry/cascader.d.ts +1 -1
  44. package/dist/components/data-entry/cascader.js +188 -24
  45. package/dist/components/data-entry/color-picker.d.ts +1 -1
  46. package/dist/components/data-entry/color-picker.js +17 -5
  47. package/dist/components/data-entry/control-appearance.d.ts +64 -0
  48. package/dist/components/data-entry/control-appearance.js +39 -0
  49. package/dist/components/data-entry/control-surface.d.ts +61 -0
  50. package/dist/components/data-entry/control-surface.js +39 -0
  51. package/dist/components/data-entry/date-picker.d.ts +1 -1
  52. package/dist/components/data-entry/date-picker.js +344 -113
  53. package/dist/components/data-entry/date-range-picker.d.ts +1 -1
  54. package/dist/components/data-entry/date-range-picker.js +278 -140
  55. package/dist/components/data-entry/form-field.d.ts +1 -1
  56. package/dist/components/data-entry/form-field.js +39 -4
  57. package/dist/components/data-entry/form.d.ts +4 -0
  58. package/dist/components/data-entry/form.js +4 -2
  59. package/dist/components/data-entry/index.d.ts +7 -3
  60. package/dist/components/data-entry/index.js +10 -1
  61. package/dist/components/data-entry/input-otp.d.ts +1 -1
  62. package/dist/components/data-entry/input.d.ts +12 -34
  63. package/dist/components/data-entry/input.js +92 -24
  64. package/dist/components/data-entry/month-picker.d.ts +1 -1
  65. package/dist/components/data-entry/month-picker.js +47 -10
  66. package/dist/components/data-entry/month-range-picker.d.ts +1 -1
  67. package/dist/components/data-entry/month-range-picker.js +51 -11
  68. package/dist/components/data-entry/number-input.d.ts +7 -0
  69. package/dist/components/data-entry/number-input.js +147 -98
  70. package/dist/components/data-entry/password-input.d.ts +1 -1
  71. package/dist/components/data-entry/radio.d.ts +1 -1
  72. package/dist/components/data-entry/radio.js +61 -13
  73. package/dist/components/data-entry/search-input.d.ts +1 -1
  74. package/dist/components/data-entry/search-input.js +16 -2
  75. package/dist/components/data-entry/search-select.d.ts +2 -2
  76. package/dist/components/data-entry/search-select.js +209 -78
  77. package/dist/components/data-entry/select.d.ts +22 -4
  78. package/dist/components/data-entry/select.js +215 -163
  79. package/dist/components/data-entry/slider.d.ts +9 -1
  80. package/dist/components/data-entry/slider.js +87 -9
  81. package/dist/components/data-entry/switch.d.ts +3 -0
  82. package/dist/components/data-entry/switch.js +29 -3
  83. package/dist/components/data-entry/textarea.d.ts +14 -56
  84. package/dist/components/data-entry/textarea.js +80 -33
  85. package/dist/components/data-entry/time-picker.d.ts +2 -2
  86. package/dist/components/data-entry/time-picker.js +333 -109
  87. package/dist/components/data-entry/time-range-picker.d.ts +5 -0
  88. package/dist/components/data-entry/time-range-picker.js +89 -0
  89. package/dist/components/data-entry/transfer.d.ts +1 -1
  90. package/dist/components/data-entry/transfer.js +86 -28
  91. package/dist/components/data-entry/tree-select.d.ts +1 -1
  92. package/dist/components/data-entry/tree-select.js +201 -113
  93. package/dist/components/data-entry/tree-utils.js +7 -14
  94. package/dist/components/data-entry/upload-files.d.ts +2 -0
  95. package/dist/components/data-entry/upload-files.js +31 -0
  96. package/dist/components/data-entry/upload-request.d.ts +4 -0
  97. package/dist/components/data-entry/upload-request.js +53 -0
  98. package/dist/components/data-entry/upload-types.d.ts +28 -0
  99. package/dist/components/data-entry/upload-types.js +2 -0
  100. package/dist/components/data-entry/upload.d.ts +2 -2
  101. package/dist/components/data-entry/upload.js +475 -115
  102. package/dist/components/feedback/dialog.js +19 -19
  103. package/dist/components/feedback/sheet.js +3 -0
  104. package/dist/components/feedback/tooltip.js +3 -0
  105. package/dist/components/general/button.d.ts +2 -1
  106. package/dist/components/general/button.js +7 -1
  107. package/dist/components/general/index.d.ts +1 -0
  108. package/dist/components/general/index.js +2 -0
  109. package/dist/components/general/typography.d.ts +3 -0
  110. package/dist/components/general/typography.js +15 -1
  111. package/dist/components/general/visually-hidden.d.ts +3 -0
  112. package/dist/components/general/visually-hidden.js +9 -0
  113. package/dist/components/layout/app-launcher.d.ts +34 -0
  114. package/dist/components/layout/app-launcher.js +261 -0
  115. package/dist/components/layout/app-shell.d.ts +3 -1
  116. package/dist/components/layout/app-shell.js +34 -14
  117. package/dist/components/layout/auth-shell.d.ts +1 -1
  118. package/dist/components/layout/auth-shell.js +2 -0
  119. package/dist/components/layout/breadcrumb.d.ts +14 -2
  120. package/dist/components/layout/breadcrumb.js +46 -4
  121. package/dist/components/layout/flex.d.ts +1 -1
  122. package/dist/components/layout/flex.js +23 -2
  123. package/dist/components/layout/index.d.ts +3 -0
  124. package/dist/components/layout/index.js +5 -1
  125. package/dist/components/layout/org-switcher.js +20 -1
  126. package/dist/components/layout/page-container.d.ts +1 -1
  127. package/dist/components/layout/page-container.js +5 -3
  128. package/dist/components/layout/responsive-grid.d.ts +16 -2
  129. package/dist/components/layout/responsive-grid.js +29 -2
  130. package/dist/components/layout/sidebar.js +2 -1
  131. package/dist/components/layout/topbar-item.d.ts +3 -0
  132. package/dist/components/layout/topbar-item.js +18 -3
  133. package/dist/components/layout/topbar.d.ts +1 -1
  134. package/dist/components/layout/topbar.js +27 -6
  135. package/dist/components/navigation/dropdown-menu.d.ts +30 -2
  136. package/dist/components/navigation/dropdown-menu.js +73 -11
  137. package/dist/components/navigation/pagination.d.ts +2 -2
  138. package/dist/components/navigation/pagination.js +155 -83
  139. package/dist/components/navigation/steps.d.ts +2 -2
  140. package/dist/components/navigation/steps.js +29 -4
  141. package/dist/components/navigation/tabs.d.ts +5 -33
  142. package/dist/components/navigation/tabs.js +232 -64
  143. package/dist/components/ui/hover-card.js +3 -0
  144. package/dist/components/ui/input-otp.d.ts +26 -28
  145. package/dist/components/ui/input-otp.js +50 -7
  146. package/dist/components/ui/password-input.d.ts +36 -2
  147. package/dist/components/ui/password-input.js +27 -7
  148. package/dist/components/ui/rating.d.ts +25 -0
  149. package/dist/components/ui/rating.js +67 -27
  150. package/dist/components/ui/segmented.d.ts +9 -0
  151. package/dist/components/ui/segmented.js +17 -2
  152. package/dist/components/ui/separator.d.ts +4 -0
  153. package/dist/components/ui/separator.js +13 -0
  154. package/dist/components/ui/tag-input.d.ts +45 -0
  155. package/dist/components/ui/tag-input.js +109 -27
  156. package/dist/form/form-context.d.ts +29 -0
  157. package/dist/form/form-context.js +44 -4
  158. package/dist/form/form-field-array.d.ts +22 -0
  159. package/dist/form/form-field-array.js +50 -0
  160. package/dist/form/form-field-control.d.ts +2 -1
  161. package/dist/form/form-field-control.js +116 -40
  162. package/dist/form/form-root.d.ts +2 -1
  163. package/dist/form/form-root.js +142 -23
  164. package/dist/form/index.d.ts +3 -1
  165. package/dist/form/index.js +12 -1
  166. package/dist/i18n/index.d.ts +1 -1
  167. package/dist/i18n/index.js +3 -1
  168. package/dist/i18n/messages/en.json +59 -6
  169. package/dist/i18n/messages/ja.json +59 -6
  170. package/dist/i18n/messages/vi.json +59 -6
  171. package/dist/i18n/translate.d.ts +19 -0
  172. package/dist/i18n/translate.js +24 -0
  173. package/dist/inertia/index.d.ts +20 -0
  174. package/dist/inertia/index.js +60 -1
  175. package/dist/lib/control-styles.d.ts +25 -3
  176. package/dist/lib/control-styles.js +9 -3
  177. package/dist/lib/datetime/picker-format.d.ts +8 -0
  178. package/dist/lib/datetime/picker-format.js +54 -0
  179. package/dist/lib/overlay-portal.d.ts +18 -0
  180. package/dist/lib/overlay-portal.js +17 -0
  181. package/dist/props/components/app.prop.d.ts +13 -2
  182. package/dist/props/components/charts.prop.d.ts +21 -0
  183. package/dist/props/components/data-display.prop.d.ts +55 -4
  184. package/dist/props/components/data-entry.prop.d.ts +687 -43
  185. package/dist/props/components/form.prop.d.ts +142 -4
  186. package/dist/props/components/general.prop.d.ts +30 -1
  187. package/dist/props/components/index.d.ts +2 -2
  188. package/dist/props/components/layout.prop.d.ts +255 -8
  189. package/dist/props/components/navigation.prop.d.ts +113 -3
  190. package/dist/props/registry.d.ts +376 -10
  191. package/dist/props/registry.js +493 -9
  192. package/dist/props/vocabulary/data.prop.d.ts +179 -1
  193. package/dist/props/vocabulary/index.d.ts +4 -4
  194. package/dist/props/vocabulary/interaction.prop.d.ts +51 -2
  195. package/dist/props/vocabulary/navigation.prop.d.ts +40 -0
  196. package/dist/props/vocabulary/shared.prop.d.ts +33 -0
  197. package/dist/styles/badge-layout.css +2 -1
  198. package/dist/styles/card-layout.css +36 -5
  199. package/dist/styles/chart-layout.css +17 -1
  200. package/dist/styles/control.css +520 -14
  201. package/dist/styles/data-display-layout.css +248 -7
  202. package/dist/styles/data-entry-layout.css +13 -0
  203. package/dist/styles/layout.css +221 -4
  204. package/dist/styles/navigation-layout.css +230 -1
  205. package/dist/styles/shell-layout.css +690 -21
  206. package/dist/styles/table-layout.css +95 -6
  207. package/dist/styles/text-layout.css +5 -0
  208. package/dist/tokens/base.css +1 -0
  209. package/dist/tokens/components/badge.css +1 -0
  210. package/dist/tokens/components/chart.css +6 -0
  211. package/dist/tokens/components/control.css +81 -3
  212. package/dist/tokens/components/data-display.css +9 -0
  213. package/dist/tokens/components/descriptions.css +11 -0
  214. package/dist/tokens/components/flex.css +8 -0
  215. package/dist/tokens/components/navigation.css +55 -0
  216. package/dist/tokens/components/shell.css +100 -5
  217. package/dist/tokens/components/table.css +14 -0
  218. package/dist/tokens/foundation.css +2 -0
  219. package/dist/tokens/semantic/layout.css +9 -0
  220. package/docs/CONSUMER-RULES.md +13 -0
  221. package/docs/DESIGN-AUTHORITY.md +43 -6
  222. package/docs/DEVELOPMENT.md +4 -3
  223. package/docs/FORMS.md +151 -6
  224. package/docs/FRAME-COVERAGE-REPORT.md +29 -16
  225. package/docs/README.md +1 -1
  226. package/docs/STANDARDS-vocabulary-tokens.md +1 -1
  227. package/docs/TESTING.md +15 -6
  228. package/docs/charts/cjk-category-axis.tsx +81 -0
  229. package/docs/data-display/card/index.tsx +22 -0
  230. package/docs/data-display/data-table/examples/antd-parity.tsx +257 -0
  231. package/docs/data-display/data-table/index.tsx +23 -0
  232. package/docs/data-display/descriptions.tsx +41 -0
  233. package/docs/data-display/list-row.tsx +6 -6
  234. package/docs/data-display/scroll-area.tsx +31 -25
  235. package/docs/data-display/table.tsx +104 -45
  236. package/docs/data-display/timeline.tsx +41 -0
  237. package/docs/data-entry/date-picker.tsx +85 -0
  238. package/docs/data-entry/date-range-picker.tsx +26 -0
  239. package/docs/data-entry/form-dynamic-fields.tsx +199 -0
  240. package/docs/data-entry/form.tsx +74 -4
  241. package/docs/data-entry/input-otp.tsx +24 -0
  242. package/docs/data-entry/input.tsx +46 -1
  243. package/docs/data-entry/month-range-picker.tsx +1 -1
  244. package/docs/data-entry/select.tsx +27 -0
  245. package/docs/data-entry/switch.tsx +41 -0
  246. package/docs/data-entry/textarea.tsx +38 -0
  247. package/docs/data-entry/time-picker.tsx +85 -1
  248. package/docs/data-entry/time-range-picker.tsx +55 -0
  249. package/docs/data-entry/transfer.tsx +17 -0
  250. package/docs/data-entry/upload.tsx +56 -12
  251. package/docs/feedback/tooltip.tsx +1 -1
  252. package/docs/general/activity.tsx +2 -2
  253. package/docs/general/button/index.tsx +14 -1
  254. package/docs/general/typography.tsx +14 -1
  255. package/docs/layout/app-launcher.tsx +195 -0
  256. package/docs/layout/app-shell-arrangements.tsx +5 -5
  257. package/docs/layout/app-shell.tsx +11 -0
  258. package/docs/layout/flex.tsx +50 -0
  259. package/docs/layout/responsive-grid.tsx +21 -1
  260. package/docs/layout/topbar.tsx +5 -9
  261. package/docs/navigation/app-setting-picker.tsx +11 -0
  262. package/docs/navigation/breadcrumb.tsx +48 -0
  263. package/docs/navigation/dropdown-menu.tsx +21 -0
  264. package/docs/navigation/pagination.tsx +52 -0
  265. package/docs/navigation/steps.tsx +37 -0
  266. package/docs/navigation/tabs.tsx +97 -1
  267. package/docs/query/button-refetch.tsx +1 -0
  268. package/docs/showcase/settings-security-mfa.tsx +3 -3
  269. package/package.json +24 -4
  270. package/scripts/_agent-setup.mjs +76 -9
  271. package/scripts/init-guinea-pig.mjs +26 -4
  272. package/scripts/ui-audit.mjs +243 -30
  273. package/scripts/visual-audit.mjs +45 -7
@@ -19,6 +19,9 @@ function clamp(n, min, max) {
19
19
  if (max != null && out > max) out = max;
20
20
  return out;
21
21
  }
22
+ function normalizeNumeric(raw) {
23
+ return raw.normalize("NFKC").replace(/,/g, "");
24
+ }
22
25
  function roundTo(n, precision) {
23
26
  if (!Number.isFinite(n)) return n;
24
27
  const factor = 10 ** precision;
@@ -33,6 +36,13 @@ const NumberInput = React.forwardRef(
33
36
  max,
34
37
  step = 1,
35
38
  precision,
39
+ formatter,
40
+ parser,
41
+ keyboard = true,
42
+ changeOnWheel = false,
43
+ controls = true,
44
+ status,
45
+ variant,
36
46
  disabled,
37
47
  readOnly,
38
48
  size = "md",
@@ -51,7 +61,7 @@ const NumberInput = React.forwardRef(
51
61
  const [internal, setInternal] = React.useState(defaultValue);
52
62
  const numericValue = isControlled ? controlledValue ?? null : internal;
53
63
  const effectivePrecision = precision ?? decimalsOf(step);
54
- const formatter = React.useMemo(
64
+ const intlFormatter = React.useMemo(
55
65
  () => new Intl.NumberFormat(locale, {
56
66
  minimumFractionDigits: 0,
57
67
  maximumFractionDigits: Math.max(effectivePrecision, 0),
@@ -60,8 +70,18 @@ const NumberInput = React.forwardRef(
60
70
  [locale, effectivePrecision]
61
71
  );
62
72
  const formatAtRest = React.useCallback(
63
- (n) => n == null ? "" : formatter.format(n),
64
- [formatter]
73
+ (n) => formatter ? formatter(n) : n == null ? "" : intlFormatter.format(n),
74
+ [formatter, intlFormatter]
75
+ );
76
+ const parseDraft = React.useCallback(
77
+ (raw) => {
78
+ if (parser) return parser(raw);
79
+ const trimmed = normalizeNumeric(raw).trim();
80
+ if (trimmed === "" || trimmed === "-") return null;
81
+ const parsed = Number(trimmed);
82
+ return Number.isNaN(parsed) ? null : parsed;
83
+ },
84
+ [parser]
65
85
  );
66
86
  const [draft, setDraft] = React.useState(() => formatAtRest(numericValue));
67
87
  const [focused, setFocused] = React.useState(false);
@@ -91,126 +111,155 @@ const NumberInput = React.forwardRef(
91
111
  const atMin = min != null && numericValue != null && numericValue <= min;
92
112
  const atMax = max != null && numericValue != null && numericValue >= max;
93
113
  const interactive = !disabled && !readOnly;
114
+ const composing = React.useRef(false);
94
115
  const handleChange = (event) => {
95
116
  const raw = event.target.value;
96
117
  setDraft(raw);
97
118
  if (readOnly) return;
98
- const trimmed = raw.trim();
119
+ if (composing.current || event.nativeEvent.isComposing) return;
120
+ const trimmed = normalizeNumeric(raw).trim();
99
121
  if (trimmed === "" || trimmed === "-") {
100
122
  if (trimmed === "") commit(null);
101
123
  return;
102
124
  }
103
- const parsed = Number(trimmed);
104
- if (Number.isNaN(parsed)) return;
125
+ const parsed = parseDraft(raw);
126
+ if (parsed == null) return;
105
127
  if (!isControlled) setInternal(parsed);
106
128
  onValueChange?.(parsed);
107
129
  };
108
- const handleBlur = () => {
109
- setFocused(false);
110
- const trimmed = draft.trim();
111
- if (trimmed === "" || trimmed === "-") {
112
- commit(null);
113
- setDraft(formatAtRest(null));
130
+ const handleCompositionStart = () => {
131
+ composing.current = true;
132
+ };
133
+ const handleCompositionEnd = (event) => {
134
+ composing.current = false;
135
+ if (readOnly) return;
136
+ const raw = event.currentTarget.value;
137
+ const parsed = parseDraft(raw);
138
+ if (parsed == null) {
139
+ if (normalizeNumeric(raw).trim() === "") commit(null);
114
140
  return;
115
141
  }
116
- const parsed = Number(trimmed);
117
- const committed = commit(Number.isNaN(parsed) ? null : parsed);
142
+ if (!isControlled) setInternal(parsed);
143
+ onValueChange?.(parsed);
144
+ };
145
+ const handleBlur = () => {
146
+ setFocused(false);
147
+ const committed = commit(parseDraft(draft));
118
148
  setDraft(formatAtRest(committed));
119
149
  };
120
150
  const handleKeyDown = (event) => {
121
151
  if (!interactive) return;
122
- if (event.key === "ArrowUp") {
152
+ if (composing.current || event.nativeEvent.isComposing) return;
153
+ if (keyboard && event.key === "ArrowUp") {
123
154
  event.preventDefault();
124
155
  stepBy(1, event.shiftKey ? 10 : 1);
125
- } else if (event.key === "ArrowDown") {
156
+ } else if (keyboard && event.key === "ArrowDown") {
126
157
  event.preventDefault();
127
158
  stepBy(-1, event.shiftKey ? 10 : 1);
128
159
  } else if (event.key === "Enter") {
129
- const trimmed = draft.trim();
130
- const parsed = Number(trimmed);
131
- const committed = commit(trimmed === "" || Number.isNaN(parsed) ? null : parsed);
160
+ const committed = commit(parseDraft(draft));
132
161
  setDraft(formatAtRest(committed));
133
162
  }
134
163
  };
135
- return /* @__PURE__ */ jsxs("div", { "data-slot": "number-input", "data-size": size, className: cn("ui-number-input", className), children: [
136
- prefix != null ? /* @__PURE__ */ jsx(
137
- "span",
138
- {
139
- "data-slot": "number-input-prefix",
140
- className: "ui-number-input-affix",
141
- "aria-hidden": "true",
142
- children: prefix
143
- }
144
- ) : null,
145
- /* @__PURE__ */ jsx(
146
- Input,
147
- {
148
- ref,
149
- id,
150
- name,
151
- type: "text",
152
- inputMode: "decimal",
153
- autoComplete: "off",
154
- role: "spinbutton",
155
- "data-slot": "number-input-field",
156
- "data-testid": dataTestId,
157
- "data-field": ariaProps["data-field"],
158
- className: "ui-number-input-field",
159
- value: draft,
160
- placeholder,
161
- disabled,
162
- readOnly,
163
- ...fieldA11y,
164
- "aria-valuenow": numericValue ?? void 0,
165
- "aria-valuemin": min,
166
- "aria-valuemax": max,
167
- "aria-valuetext": numericValue != null ? formatAtRest(numericValue) : void 0,
168
- onChange: handleChange,
169
- onFocus: () => setFocused(true),
170
- onBlur: handleBlur,
171
- onKeyDown: handleKeyDown
172
- }
173
- ),
174
- suffix != null ? /* @__PURE__ */ jsx(
175
- "span",
176
- {
177
- "data-slot": "number-input-suffix",
178
- className: "ui-number-input-affix",
179
- "aria-hidden": "true",
180
- children: suffix
181
- }
182
- ) : null,
183
- /* @__PURE__ */ jsxs("span", { "data-slot": "number-input-steppers", className: "ui-number-input-steppers", children: [
184
- /* @__PURE__ */ jsx(
185
- Button,
186
- {
187
- type: "button",
188
- variant: "outline",
189
- size: "icon-xs",
190
- className: "ui-number-input-step ui-number-input-step-up",
191
- tabIndex: -1,
192
- disabled: !interactive || atMax,
193
- "aria-label": t("ui.numberInput.increment"),
194
- onClick: () => stepBy(1),
195
- children: /* @__PURE__ */ jsx(ChevronUp, { "aria-hidden": "true" })
196
- }
197
- ),
198
- /* @__PURE__ */ jsx(
199
- Button,
200
- {
201
- type: "button",
202
- variant: "outline",
203
- size: "icon-xs",
204
- className: "ui-number-input-step ui-number-input-step-down",
205
- tabIndex: -1,
206
- disabled: !interactive || atMin,
207
- "aria-label": t("ui.numberInput.decrement"),
208
- onClick: () => stepBy(-1),
209
- children: /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": "true" })
210
- }
211
- )
212
- ] })
213
- ] });
164
+ const handleWheel = (event) => {
165
+ if (!changeOnWheel || !interactive || !focused || event.deltaY === 0) return;
166
+ stepBy(event.deltaY < 0 ? 1 : -1);
167
+ };
168
+ return /* @__PURE__ */ jsxs(
169
+ "div",
170
+ {
171
+ "data-slot": "number-input",
172
+ "data-size": size,
173
+ "data-status": status,
174
+ "data-variant": variant,
175
+ "data-controls": controls ? void 0 : "off",
176
+ className: cn("ui-number-input", className),
177
+ children: [
178
+ prefix != null ? /* @__PURE__ */ jsx(
179
+ "span",
180
+ {
181
+ "data-slot": "number-input-prefix",
182
+ className: "ui-number-input-affix",
183
+ "aria-hidden": "true",
184
+ children: prefix
185
+ }
186
+ ) : null,
187
+ /* @__PURE__ */ jsx(
188
+ Input,
189
+ {
190
+ ref,
191
+ id,
192
+ name,
193
+ type: "text",
194
+ inputMode: "decimal",
195
+ autoComplete: "off",
196
+ role: "spinbutton",
197
+ "data-slot": "number-input-field",
198
+ "data-testid": dataTestId,
199
+ "data-field": ariaProps["data-field"],
200
+ className: "ui-number-input-field",
201
+ value: draft,
202
+ placeholder,
203
+ disabled,
204
+ readOnly,
205
+ status,
206
+ variant,
207
+ ...fieldA11y,
208
+ "aria-valuenow": numericValue ?? void 0,
209
+ "aria-valuemin": min,
210
+ "aria-valuemax": max,
211
+ "aria-valuetext": numericValue != null ? formatAtRest(numericValue) : void 0,
212
+ onChange: handleChange,
213
+ onCompositionStart: handleCompositionStart,
214
+ onCompositionEnd: handleCompositionEnd,
215
+ onFocus: () => setFocused(true),
216
+ onBlur: handleBlur,
217
+ onKeyDown: handleKeyDown,
218
+ onWheel: handleWheel
219
+ }
220
+ ),
221
+ suffix != null ? /* @__PURE__ */ jsx(
222
+ "span",
223
+ {
224
+ "data-slot": "number-input-suffix",
225
+ className: "ui-number-input-affix",
226
+ "aria-hidden": "true",
227
+ children: suffix
228
+ }
229
+ ) : null,
230
+ controls ? /* @__PURE__ */ jsxs("span", { "data-slot": "number-input-steppers", className: "ui-number-input-steppers", children: [
231
+ /* @__PURE__ */ jsx(
232
+ Button,
233
+ {
234
+ type: "button",
235
+ variant: "outline",
236
+ size: "icon-xs",
237
+ className: "ui-number-input-step ui-number-input-step-up",
238
+ tabIndex: -1,
239
+ disabled: !interactive || atMax,
240
+ "aria-label": t("ui.numberInput.increment"),
241
+ onClick: () => stepBy(1),
242
+ children: /* @__PURE__ */ jsx(ChevronUp, { "aria-hidden": "true" })
243
+ }
244
+ ),
245
+ /* @__PURE__ */ jsx(
246
+ Button,
247
+ {
248
+ type: "button",
249
+ variant: "outline",
250
+ size: "icon-xs",
251
+ className: "ui-number-input-step ui-number-input-step-down",
252
+ tabIndex: -1,
253
+ disabled: !interactive || atMin,
254
+ "aria-label": t("ui.numberInput.decrement"),
255
+ onClick: () => stepBy(-1),
256
+ children: /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": "true" })
257
+ }
258
+ )
259
+ ] }) : null
260
+ ]
261
+ }
262
+ );
214
263
  }
215
264
  );
216
265
  NumberInput.displayName = "NumberInput";
@@ -1,2 +1,2 @@
1
1
  export { PasswordInput } from "../ui/password-input.js";
2
- export type { PasswordInputProps } from "../ui/password-input.js";
2
+ export type { PasswordInputProps, PasswordVisibilityToggleProp } from "../ui/password-input.js";
@@ -4,7 +4,7 @@ import type { RadioGroupProp } from "../../props/components/data-entry.prop.js";
4
4
  export type { RadioGroupProp, RadioGroupProp as RadioGroupProps, } from "../../props/components/data-entry.prop.js";
5
5
  declare const RadioGroupRoot: React.ForwardRefExoticComponent<Omit<RadioGroupPrimitive.RadioGroupProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
6
6
  declare const RadioItem: React.ForwardRefExoticComponent<Omit<RadioGroupPrimitive.RadioGroupItemProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
7
- declare function RadioGroupOptions({ value, defaultValue, onValueChange, options, orientation, disabled, name, id, className, children, ...ariaProps }: RadioGroupProp): React.JSX.Element;
7
+ declare function RadioGroupOptions({ value, defaultValue, onValueChange, options, orientation, optionType, buttonStyle, disabled, name, id, className, children, ...ariaProps }: RadioGroupProp): React.JSX.Element;
8
8
  /** Single radio — use inside `Radio.Group` / `RadioGroupRoot`, or via `options` API. */
9
9
  export declare const Radio: React.ForwardRefExoticComponent<Omit<RadioGroupPrimitive.RadioGroupItemProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>> & {
10
10
  Root: React.ForwardRefExoticComponent<Omit<RadioGroupPrimitive.RadioGroupProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { jsx } from "react/jsx-runtime";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
5
5
  import { Circle } from "lucide-react";
@@ -42,12 +42,35 @@ const RadioItem = React.forwardRef(({ className, ...props }, ref) => /* @__PURE_
42
42
  }
43
43
  ));
44
44
  RadioItem.displayName = RadioGroupPrimitive.Item.displayName;
45
+ function RadioButtonBar({
46
+ options,
47
+ value,
48
+ optionDomId,
49
+ resolvedField
50
+ }) {
51
+ return /* @__PURE__ */ jsx(Fragment, { children: options.map((opt, index) => /* @__PURE__ */ jsx(
52
+ RadioGroupPrimitive.Item,
53
+ {
54
+ id: optionDomId(opt.value, index),
55
+ value: opt.value,
56
+ disabled: opt.disabled,
57
+ "data-slot": "radio-button",
58
+ "data-field": resolvedField,
59
+ "data-state": value === opt.value ? "checked" : "unchecked",
60
+ className: "ui-radio-button ui-focus-ring",
61
+ children: /* @__PURE__ */ jsx("span", { className: "ui-radio-button-label", children: opt.label })
62
+ },
63
+ opt.value
64
+ )) });
65
+ }
45
66
  function RadioGroupOptions({
46
67
  value,
47
68
  defaultValue,
48
69
  onValueChange,
49
70
  options,
50
71
  orientation = "vertical",
72
+ optionType = "default",
73
+ buttonStyle = "outline",
51
74
  disabled,
52
75
  name,
53
76
  id,
@@ -62,7 +85,7 @@ function RadioGroupOptions({
62
85
  const resolvedField = groupA11y["data-field"] ?? identity["data-field"];
63
86
  const optionDomId = (optionValue, index) => id ? `${id}-${optionValue}` : `${reactId}-${optionValue}-${index}`;
64
87
  if (options && options.length > 0) {
65
- return /* @__PURE__ */ jsx(
88
+ return /* @__PURE__ */ jsxs(
66
89
  RadioGroupRoot,
67
90
  {
68
91
  value,
@@ -74,19 +97,44 @@ function RadioGroupOptions({
74
97
  ...groupA11y,
75
98
  "data-field": resolvedField,
76
99
  "data-orientation": orientation,
77
- className: choiceGroupClassName(orientation, className),
78
- children: options.map((opt, index) => {
79
- const optionId = optionDomId(opt.value, index);
80
- return /* @__PURE__ */ jsx(Field, { id: optionId, label: opt.label, description: opt.description, children: /* @__PURE__ */ jsx(
81
- RadioItem,
100
+ "data-option-type": optionType === "default" ? void 0 : optionType,
101
+ "data-button-style": optionType === "button" ? buttonStyle : void 0,
102
+ className: cn(
103
+ optionType === "button" ? "ui-radio-button-bar" : choiceGroupClassName(orientation),
104
+ className
105
+ ),
106
+ children: [
107
+ optionType === "button" ? /* @__PURE__ */ jsx(
108
+ RadioButtonBar,
82
109
  {
83
- id: optionId,
84
- value: opt.value,
85
- disabled: opt.disabled,
86
- "data-field": resolvedField
110
+ options,
111
+ value,
112
+ optionDomId,
113
+ resolvedField
87
114
  }
88
- ) }, opt.value);
89
- })
115
+ ) : null,
116
+ optionType === "button" ? null : options.map((opt, index) => {
117
+ const optionId = optionDomId(opt.value, index);
118
+ return /* @__PURE__ */ jsx(
119
+ Field,
120
+ {
121
+ id: optionId,
122
+ label: opt.label,
123
+ description: opt.description,
124
+ children: /* @__PURE__ */ jsx(
125
+ RadioItem,
126
+ {
127
+ id: optionId,
128
+ value: opt.value,
129
+ disabled: opt.disabled,
130
+ "data-field": resolvedField
131
+ }
132
+ )
133
+ },
134
+ opt.value
135
+ );
136
+ })
137
+ ]
90
138
  }
91
139
  );
92
140
  }
@@ -1,4 +1,4 @@
1
1
  import * as React from "react";
2
2
  import type { SearchInputProp } from "../../props/components/data-entry.prop.js";
3
3
  export type SearchInputProps = SearchInputProp;
4
- export declare function SearchInput({ value: controlledValue, defaultValue, placeholder, debounce, onValueChange, onSearch, label, ariaLabel, className, inputClassName, id, disabled, ...ariaProps }: SearchInputProps): React.JSX.Element;
4
+ export declare function SearchInput({ value: controlledValue, defaultValue, placeholder, debounce, onValueChange, onSearch, label, ariaLabel, className, inputClassName, id, disabled, status, variant, ...ariaProps }: SearchInputProps): React.JSX.Element;
@@ -21,13 +21,18 @@ function SearchInput({
21
21
  inputClassName,
22
22
  id,
23
23
  disabled = false,
24
+ status,
25
+ variant,
24
26
  ...ariaProps
25
27
  }) {
26
28
  const { t } = useTranslation();
27
29
  const isControlled = controlledValue !== void 0;
28
30
  const [internal, setInternal] = React.useState(defaultValue);
29
31
  const value = isControlled ? controlledValue : internal;
30
- const debounced = useDebouncedValue(value, debounce);
32
+ const [composing, setComposing] = React.useState(false);
33
+ const settledValue = React.useRef(value);
34
+ if (!composing) settledValue.current = value;
35
+ const debounced = useDebouncedValue(composing ? settledValue.current : value, debounce);
31
36
  const reactId = React.useId();
32
37
  const inputId = id ?? `search-${reactId}`;
33
38
  const resolvedPlaceholder = placeholder ?? t("dataEntry.searchInput.placeholder");
@@ -61,10 +66,19 @@ function SearchInput({
61
66
  onChange: (e) => {
62
67
  setValue(e.target.value);
63
68
  },
69
+ onCompositionStart: () => {
70
+ setComposing(true);
71
+ },
72
+ onCompositionEnd: (e) => {
73
+ setComposing(false);
74
+ setValue(e.currentTarget.value);
75
+ },
64
76
  placeholder: resolvedPlaceholder,
77
+ status,
78
+ variant,
65
79
  ...fieldA11y,
66
80
  className: cn(
67
- "ui-search-input-control !pr-[var(--search-input-end-padding)] !pl-[var(--search-input-start-padding)]",
81
+ "ui-search-input-control !ps-[var(--search-input-start-padding)] !pe-[var(--search-input-end-padding)]",
68
82
  inputClassName
69
83
  ),
70
84
  disabled
@@ -1,10 +1,10 @@
1
1
  import * as React from "react";
2
2
  import type { SearchSelectProp } from "../../props/components/data-entry.prop.js";
3
- export type { SearchSelectProp, SearchSelectProp as SearchSelectProps, SearchSelectOptionProp, SearchSelectOptionProp as SearchSelectOption, SearchSelectLoadParamsProp, SearchSelectLoadResultProp, } from "../../props/components/data-entry.prop.js";
3
+ export type { SearchSelectProp, SearchSelectProp as SearchSelectProps, SearchSelectBaseProp, SearchSelectSingleProp, SearchSelectMultipleProp, SearchSelectOptionProp, SearchSelectOptionProp as SearchSelectOption, SearchSelectLoadParamsProp, SearchSelectLoadResultProp, } from "../../props/components/data-entry.prop.js";
4
4
  /**
5
5
  * SearchSelect — a searchable single-select combobox with a debounced search box, optional
6
6
  * optgroup-style grouping (`option.group`), and loading/empty states. Drive it EITHER remotely
7
7
  * with `loadOptions({ query, page })` (server search + infinite scroll) OR with a static `options`
8
8
  * array (client-side filter) — the latter supersedes the legacy `Autocomplete`.
9
9
  */
10
- export declare function SearchSelect({ value: valueProp, defaultValue, onValueChange, options: staticOptions, loadOptions, renderOption, labelRender, selectedLabel, selectedIcon, placeholder, searchPlaceholder, emptyMessage, loadingMessage, errorMessage, clearLabel, clearable, disabled, readOnly, size, open: openProp, onOpenChange, search: searchProp, onSearchChange, filterOption, renderError, renderLoadMore, name, id, className, "data-testid": dataTestId, "data-field": dataField, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby, "aria-errormessage": ariaErrorMessage, "aria-invalid": ariaInvalid, "aria-required": ariaRequired, }: SearchSelectProp): React.JSX.Element;
10
+ export declare function SearchSelect(props: SearchSelectProp): React.JSX.Element;