@godxjp/ui 19.0.0 → 19.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 (445) hide show
  1. package/README.md +25 -128
  2. package/dist/app/app-provider.d.ts +1 -1
  3. package/dist/app/app-provider.js +3 -0
  4. package/dist/app/theme-axes.d.ts +4 -15
  5. package/dist/app/timezones.d.ts +1 -4
  6. package/dist/components/charts/area-chart.d.ts +2 -3
  7. package/dist/components/charts/bar-chart.d.ts +2 -3
  8. package/dist/components/charts/chart-frame.d.ts +7 -16
  9. package/dist/components/charts/chart-summary.d.ts +2 -2
  10. package/dist/components/charts/compact-bar-trend.d.ts +9 -24
  11. package/dist/components/charts/index.d.ts +1 -6
  12. package/dist/components/data-display/badge.d.ts +2 -12
  13. package/dist/components/data-display/card.d.ts +21 -41
  14. package/dist/components/data-display/carousel.d.ts +1 -2
  15. package/dist/components/data-display/code-block.d.ts +4 -0
  16. package/dist/components/data-display/code-block.js +24 -0
  17. package/dist/components/data-display/data-table.d.ts +15 -37
  18. package/dist/components/data-display/data-table.js +1 -3
  19. package/dist/components/data-display/descriptions.d.ts +2 -6
  20. package/dist/components/data-display/descriptions.js +0 -2
  21. package/dist/components/data-display/index.d.ts +4 -0
  22. package/dist/components/data-display/index.js +4 -0
  23. package/dist/components/data-display/list-row.d.ts +3 -22
  24. package/dist/components/data-display/permission-matrix.d.ts +7 -20
  25. package/dist/components/data-display/progress.d.ts +1 -1
  26. package/dist/components/data-display/prose.d.ts +4 -0
  27. package/dist/components/data-display/prose.js +20 -0
  28. package/dist/components/data-display/service-launcher-card.d.ts +3 -10
  29. package/dist/components/data-display/table.d.ts +20 -80
  30. package/dist/components/data-display/table.js +0 -3
  31. package/dist/components/data-display/timeline.d.ts +3 -5
  32. package/dist/components/data-entry/branch-scope-picker.d.ts +2 -19
  33. package/dist/components/data-entry/branch-scope-picker.js +0 -1
  34. package/dist/components/data-entry/calendar.d.ts +3 -2
  35. package/dist/components/data-entry/calendar.js +58 -3
  36. package/dist/components/data-entry/cascader.js +3 -1
  37. package/dist/components/data-entry/checkbox-group.js +12 -5
  38. package/dist/components/data-entry/checkbox.js +30 -21
  39. package/dist/components/data-entry/command-palette.d.ts +8 -22
  40. package/dist/components/data-entry/date-picker.d.ts +4 -5
  41. package/dist/components/data-entry/date-picker.js +12 -3
  42. package/dist/components/data-entry/date-range-picker.d.ts +1 -1
  43. package/dist/components/data-entry/date-range-picker.js +17 -6
  44. package/dist/components/data-entry/form-errors.d.ts +7 -18
  45. package/dist/components/data-entry/form-field.d.ts +1 -1
  46. package/dist/components/data-entry/form-field.js +15 -6
  47. package/dist/components/data-entry/form.d.ts +1 -9
  48. package/dist/components/data-entry/input.d.ts +16 -14
  49. package/dist/components/data-entry/input.js +13 -3
  50. package/dist/components/data-entry/month-picker.js +6 -4
  51. package/dist/components/data-entry/month-range-picker.d.ts +4 -6
  52. package/dist/components/data-entry/month-range-picker.js +11 -5
  53. package/dist/components/data-entry/number-input.d.ts +1 -5
  54. package/dist/components/data-entry/number-input.js +1 -0
  55. package/dist/components/data-entry/radio.js +19 -6
  56. package/dist/components/data-entry/search-select.d.ts +3 -5
  57. package/dist/components/data-entry/search-select.js +8 -2
  58. package/dist/components/data-entry/select.d.ts +15 -2
  59. package/dist/components/data-entry/select.js +57 -10
  60. package/dist/components/data-entry/switch.js +9 -2
  61. package/dist/components/data-entry/textarea.d.ts +10 -16
  62. package/dist/components/data-entry/textarea.js +8 -1
  63. package/dist/components/data-entry/time-picker.d.ts +3 -5
  64. package/dist/components/data-entry/tree-select.js +3 -1
  65. package/dist/components/data-entry/upload-types.d.ts +1 -5
  66. package/dist/components/data-entry/use-upload-draft.d.ts +0 -4
  67. package/dist/components/feedback/dialog.d.ts +6 -15
  68. package/dist/components/feedback/overlay-header-tone.d.ts +1 -1
  69. package/dist/components/feedback/sheet.d.ts +3 -10
  70. package/dist/components/feedback/sheet.js +1 -1
  71. package/dist/components/feedback/sonner.js +2 -3
  72. package/dist/components/general/activity.d.ts +4 -30
  73. package/dist/components/general/button.js +1 -10
  74. package/dist/components/general/logo.d.ts +6 -28
  75. package/dist/components/general/reveal.d.ts +3 -9
  76. package/dist/components/general/typography.d.ts +1 -3
  77. package/dist/components/layout/account-chip.d.ts +8 -0
  78. package/dist/components/layout/account-chip.js +45 -0
  79. package/dist/components/layout/auth-divider.d.ts +2 -9
  80. package/dist/components/layout/auth-shell.d.ts +1 -14
  81. package/dist/components/layout/breadcrumb.d.ts +1 -5
  82. package/dist/components/layout/centered-shell.d.ts +4 -18
  83. package/dist/components/layout/error-surface.d.ts +11 -28
  84. package/dist/components/layout/error-surface.js +4 -1
  85. package/dist/components/layout/index.d.ts +2 -0
  86. package/dist/components/layout/index.js +2 -0
  87. package/dist/components/layout/legal-document-shell.d.ts +5 -28
  88. package/dist/components/layout/master-detail.d.ts +2 -18
  89. package/dist/components/layout/page-container.js +0 -1
  90. package/dist/components/layout/responsive-grid.d.ts +6 -1
  91. package/dist/components/layout/responsive-grid.js +9 -2
  92. package/dist/components/layout/service-role-panel.d.ts +7 -19
  93. package/dist/components/layout/sidebar.d.ts +5 -27
  94. package/dist/components/layout/sidebar.js +0 -1
  95. package/dist/components/layout/split-pane.d.ts +0 -7
  96. package/dist/components/layout/topbar.d.ts +1 -14
  97. package/dist/components/navigation/app-setting-picker.js +1 -3
  98. package/dist/components/navigation/filter-bar.d.ts +1 -6
  99. package/dist/components/navigation/pagination-utils.d.ts +2 -12
  100. package/dist/components/navigation/tabs-scroll.d.ts +2 -36
  101. package/dist/components/navigation/tabs.js +4 -8
  102. package/dist/components/query/data-state.d.ts +2 -2
  103. package/dist/components/ui/credential-reveal.d.ts +1 -4
  104. package/dist/components/ui/hover-card.d.ts +1 -2
  105. package/dist/components/ui/separator.d.ts +2 -15
  106. package/dist/components/ui/toggle-group.d.ts +1 -5
  107. package/dist/components/ui/toggle.d.ts +6 -31
  108. package/dist/email/brand-mark.d.ts +6 -34
  109. package/dist/email/color.d.ts +7 -17
  110. package/dist/email/geometry.d.ts +4 -8
  111. package/dist/email/index.d.ts +4 -48
  112. package/dist/email/inline-style.d.ts +3 -9
  113. package/dist/email/urgency.d.ts +2 -7
  114. package/dist/form/form-context.d.ts +2 -5
  115. package/dist/form/form-root.d.ts +1 -2
  116. package/dist/i18n/messages/en.json +4 -0
  117. package/dist/i18n/messages/ja.json +4 -0
  118. package/dist/i18n/messages/vi.json +4 -0
  119. package/dist/inertia/index.d.ts +2 -10
  120. package/dist/lib/control-styles.d.ts +10 -21
  121. package/dist/lib/control-styles.js +4 -6
  122. package/dist/lib/datetime/format-date.d.ts +1 -4
  123. package/dist/lib/field-a11y.d.ts +31 -36
  124. package/dist/lib/field-a11y.js +16 -2
  125. package/dist/lib/format.d.ts +4 -8
  126. package/dist/lib/hooks.d.ts +6 -12
  127. package/dist/lib/permission-grid.d.ts +3 -18
  128. package/dist/lib/query-error.d.ts +3 -3
  129. package/dist/props/components/app.prop.d.ts +19 -27
  130. package/dist/props/components/charts.prop.d.ts +2 -3
  131. package/dist/props/components/data-display.prop.d.ts +48 -72
  132. package/dist/props/components/data-entry.prop.d.ts +41 -30
  133. package/dist/props/components/form.prop.d.ts +2 -6
  134. package/dist/props/components/general.prop.d.ts +11 -27
  135. package/dist/props/components/layout.prop.d.ts +89 -260
  136. package/dist/props/components/navigation.prop.d.ts +27 -42
  137. package/dist/props/registry.d.ts +31 -0
  138. package/dist/props/registry.js +33 -0
  139. package/dist/props/vocabulary/data.prop.d.ts +18 -49
  140. package/dist/props/vocabulary/index.d.ts +1 -1
  141. package/dist/props/vocabulary/interaction.prop.d.ts +10 -12
  142. package/dist/props/vocabulary/layout.prop.d.ts +8 -30
  143. package/dist/props/vocabulary/shared.prop.d.ts +3 -2
  144. package/dist/styles/alert-layout.css +1 -32
  145. package/dist/styles/badge-layout.css +4 -18
  146. package/dist/styles/base.css +14 -113
  147. package/dist/styles/card-layout.css +6 -128
  148. package/dist/styles/chart-layout.css +2 -17
  149. package/dist/styles/control.css +380 -458
  150. package/dist/styles/core.css +21 -0
  151. package/dist/styles/data-display-layout.css +175 -94
  152. package/dist/styles/data-entry-layout.css +0 -45
  153. package/dist/styles/density.css +1 -30
  154. package/dist/styles/dialog-layout.css +5 -69
  155. package/dist/styles/focus-ring.css +13 -87
  156. package/dist/styles/fonts.css +1 -31
  157. package/dist/styles/form-layout.css +7 -91
  158. package/dist/styles/index.css +2 -20
  159. package/dist/styles/layout.css +38 -456
  160. package/dist/styles/logo-layout.css +1 -35
  161. package/dist/styles/motion.css +3 -42
  162. package/dist/styles/navigation-layout.css +3 -50
  163. package/dist/styles/shell-layout.css +37 -403
  164. package/dist/styles/table-layout.css +16 -274
  165. package/dist/styles/text-layout.css +7 -21
  166. package/dist/styles/toggle.css +1 -23
  167. package/dist/theme/dxs.canonical.css +1 -55
  168. package/dist/theme/example.service.css +1 -26
  169. package/dist/theme/famgia.service.css +5 -15
  170. package/dist/tokens/axes.css +3 -40
  171. package/dist/tokens/base.css +1 -4
  172. package/dist/tokens/components/activity.css +6 -42
  173. package/dist/tokens/components/badge.css +4 -13
  174. package/dist/tokens/components/banner.css +4 -9
  175. package/dist/tokens/components/card.css +32 -88
  176. package/dist/tokens/components/chart.css +9 -26
  177. package/dist/tokens/components/control.css +37 -222
  178. package/dist/tokens/components/data-display.css +28 -79
  179. package/dist/tokens/components/data-entry.css +5 -19
  180. package/dist/tokens/components/descriptions.css +7 -27
  181. package/dist/tokens/components/email.css +38 -84
  182. package/dist/tokens/components/error-surface.css +2 -18
  183. package/dist/tokens/components/feedback.css +27 -124
  184. package/dist/tokens/components/form.css +13 -45
  185. package/dist/tokens/components/legal-document.css +16 -41
  186. package/dist/tokens/components/list-row.css +11 -36
  187. package/dist/tokens/components/logo.css +2 -57
  188. package/dist/tokens/components/navigation.css +16 -94
  189. package/dist/tokens/components/scroll-area.css +2 -18
  190. package/dist/tokens/components/separator.css +8 -30
  191. package/dist/tokens/components/sheet.css +3 -14
  192. package/dist/tokens/components/shell.css +53 -307
  193. package/dist/tokens/components/sidebar.css +5 -22
  194. package/dist/tokens/components/table.css +19 -140
  195. package/dist/tokens/components/toggle.css +3 -65
  196. package/dist/tokens/components/upload.css +7 -43
  197. package/dist/tokens/foundation.css +108 -383
  198. package/dist/tokens/semantic/layout.css +33 -207
  199. package/docs/CANONICAL-CONTRACTS.md +206 -0
  200. package/docs/COMPONENTS.md +157 -0
  201. package/docs/COMPOSITION-VS-COMPONENT.md +105 -0
  202. package/docs/CONSUMER-RULES.md +14 -0
  203. package/docs/CUSTOMER-THEMING.md +162 -0
  204. package/docs/DATETIME.md +69 -0
  205. package/docs/DEVELOPMENT.md +173 -0
  206. package/docs/FORMS.md +143 -0
  207. package/docs/FRAME-A11Y-CI.md +267 -0
  208. package/docs/FRAME-COVERAGE-LEDGER.md +123 -0
  209. package/docs/FRAME-COVERAGE-REPORT.md +140 -0
  210. package/docs/FRAME-COVERAGE-STANDARD.md +65 -0
  211. package/docs/FRAME-COVERAGE.md +29 -0
  212. package/docs/PROPS-REGISTRY.md +61 -0
  213. package/docs/PROPS-VOCABULARY.md +100 -0
  214. package/docs/README.md +60 -0
  215. package/docs/REGISTRY.md +70 -0
  216. package/docs/SPACING.md +56 -0
  217. package/docs/STANDARDS-vocabulary-tokens.md +48 -0
  218. package/docs/TESTING.md +98 -0
  219. package/docs/TOKENS.md +347 -0
  220. package/docs/asset-modules.d.ts +46 -0
  221. package/docs/assets/cover-terrain.svg +6 -0
  222. package/docs/assets/portrait-amber.svg +5 -0
  223. package/docs/assets/portrait-clay.svg +5 -0
  224. package/docs/assets/portrait-indigo.svg +5 -0
  225. package/docs/assets/portrait-iris.svg +5 -0
  226. package/docs/assets/portrait-moss.svg +5 -0
  227. package/docs/assets/portrait-plum.svg +5 -0
  228. package/docs/assets/portrait-slate.svg +5 -0
  229. package/docs/charts/compact-bar-trend.tsx +328 -0
  230. package/docs/charts/size-tiers.tsx +192 -0
  231. package/docs/data-display/accordion.tsx +99 -0
  232. package/docs/data-display/avatar.tsx +355 -0
  233. package/docs/data-display/badge.tsx +247 -0
  234. package/docs/data-display/card/examples/detail-panel.tsx +106 -0
  235. package/docs/data-display/card/index.md +3 -0
  236. package/docs/data-display/card/index.tsx +285 -0
  237. package/docs/data-display/carousel.tsx +156 -0
  238. package/docs/data-display/charts.tsx +198 -0
  239. package/docs/data-display/code-block.tsx +90 -0
  240. package/docs/data-display/collapsible.tsx +162 -0
  241. package/docs/data-display/credential-reveal.tsx +145 -0
  242. package/docs/data-display/data-table/examples/approval-queue.tsx +212 -0
  243. package/docs/data-display/data-table/examples/grid-features.tsx +158 -0
  244. package/docs/data-display/data-table/examples/list-page.tsx +175 -0
  245. package/docs/data-display/data-table/index.md +5 -0
  246. package/docs/data-display/data-table/index.tsx +295 -0
  247. package/docs/data-display/descriptions.tsx +143 -0
  248. package/docs/data-display/empty-state.tsx +164 -0
  249. package/docs/data-display/hover-card.tsx +181 -0
  250. package/docs/data-display/list-row.tsx +420 -0
  251. package/docs/data-display/permission-matrix.tsx +184 -0
  252. package/docs/data-display/popover-touch.tsx +27 -0
  253. package/docs/data-display/popover.tsx +245 -0
  254. package/docs/data-display/progress.tsx +84 -0
  255. package/docs/data-display/prose.tsx +105 -0
  256. package/docs/data-display/qr-code.tsx +68 -0
  257. package/docs/data-display/scroll-area.tsx +271 -0
  258. package/docs/data-display/service-launcher-card.tsx +145 -0
  259. package/docs/data-display/stat-card.tsx +99 -0
  260. package/docs/data-display/table.tsx +251 -0
  261. package/docs/data-display/timeline.tsx +112 -0
  262. package/docs/data-display/touch-actions.tsx +36 -0
  263. package/docs/data-display/tree-list.tsx +107 -0
  264. package/docs/data-entry/branch-scope-picker.tsx +123 -0
  265. package/docs/data-entry/calendar.tsx +180 -0
  266. package/docs/data-entry/cascader.tsx +378 -0
  267. package/docs/data-entry/checkbox.tsx +256 -0
  268. package/docs/data-entry/color-picker.tsx +117 -0
  269. package/docs/data-entry/command-palette.tsx +179 -0
  270. package/docs/data-entry/command.tsx +262 -0
  271. package/docs/data-entry/country-picker-recipe.tsx +170 -0
  272. package/docs/data-entry/date-picker.tsx +191 -0
  273. package/docs/data-entry/date-range-picker.tsx +149 -0
  274. package/docs/data-entry/form/examples/employee-settings.tsx +267 -0
  275. package/docs/data-entry/form/examples/invoice-form.tsx +387 -0
  276. package/docs/data-entry/form-field/examples/a11y-contract.tsx +240 -0
  277. package/docs/data-entry/form-field/examples/create-form.tsx +105 -0
  278. package/docs/data-entry/form-field/index.md +8 -0
  279. package/docs/data-entry/form-field/index.tsx +326 -0
  280. package/docs/data-entry/form-inertia.tsx +80 -0
  281. package/docs/data-entry/form-root.tsx +102 -0
  282. package/docs/data-entry/form.tsx +724 -0
  283. package/docs/data-entry/input-otp.tsx +231 -0
  284. package/docs/data-entry/input.tsx +114 -0
  285. package/docs/data-entry/label.tsx +100 -0
  286. package/docs/data-entry/month-picker.tsx +101 -0
  287. package/docs/data-entry/month-range-picker.tsx +115 -0
  288. package/docs/data-entry/number-input.tsx +240 -0
  289. package/docs/data-entry/password-input.tsx +106 -0
  290. package/docs/data-entry/password-strength.tsx +97 -0
  291. package/docs/data-entry/radio-group.tsx +95 -0
  292. package/docs/data-entry/rating.tsx +87 -0
  293. package/docs/data-entry/search-input.tsx +120 -0
  294. package/docs/data-entry/select-async-contracts.tsx +108 -0
  295. package/docs/data-entry/select-matrix.tsx +204 -0
  296. package/docs/data-entry/select.tsx +369 -0
  297. package/docs/data-entry/slider.tsx +130 -0
  298. package/docs/data-entry/switch.tsx +67 -0
  299. package/docs/data-entry/tag-input.tsx +108 -0
  300. package/docs/data-entry/textarea.tsx +209 -0
  301. package/docs/data-entry/time-picker.tsx +99 -0
  302. package/docs/data-entry/toggle-count.tsx +293 -0
  303. package/docs/data-entry/toggle-group.tsx +225 -0
  304. package/docs/data-entry/toggle.tsx +127 -0
  305. package/docs/data-entry/transfer.tsx +97 -0
  306. package/docs/data-entry/tree-select.tsx +204 -0
  307. package/docs/data-entry/upload.tsx +184 -0
  308. package/docs/feedback/alert-dialog.tsx +270 -0
  309. package/docs/feedback/alert.tsx +248 -0
  310. package/docs/feedback/banner.tsx +183 -0
  311. package/docs/feedback/danger-confirm.tsx +88 -0
  312. package/docs/feedback/dialog-touch.tsx +24 -0
  313. package/docs/feedback/dialog.tsx +193 -0
  314. package/docs/feedback/sheet.tsx +410 -0
  315. package/docs/feedback/skeleton.tsx +111 -0
  316. package/docs/feedback/toast.tsx +135 -0
  317. package/docs/feedback/tooltip.tsx +171 -0
  318. package/docs/feedback/two-factor-setup.tsx +68 -0
  319. package/docs/foundation/_email-specimen.ts +274 -0
  320. package/docs/foundation/colors.tsx +202 -0
  321. package/docs/foundation/density.tsx +232 -0
  322. package/docs/foundation/email-tokens.tsx +306 -0
  323. package/docs/foundation/radius-shadow.tsx +152 -0
  324. package/docs/foundation/spacing.tsx +211 -0
  325. package/docs/foundation/typography.tsx +147 -0
  326. package/docs/general/activity.tsx +224 -0
  327. package/docs/general/button/examples/destructive-confirm.tsx +90 -0
  328. package/docs/general/button/examples/form-actions.tsx +85 -0
  329. package/docs/general/button/examples/toolbar.tsx +160 -0
  330. package/docs/general/button/index.md +12 -0
  331. package/docs/general/button/index.tsx +211 -0
  332. package/docs/general/logo.tsx +131 -0
  333. package/docs/general/reveal.tsx +41 -0
  334. package/docs/general/typography.tsx +152 -0
  335. package/docs/layout/account-chip.tsx +72 -0
  336. package/docs/layout/admin-collection.tsx +122 -0
  337. package/docs/layout/app-shell.tsx +374 -0
  338. package/docs/layout/aspect-ratio.tsx +119 -0
  339. package/docs/layout/auth-account-summary.tsx +103 -0
  340. package/docs/layout/auth-divider.tsx +28 -0
  341. package/docs/layout/auth-footer.tsx +37 -0
  342. package/docs/layout/auth-identity.tsx +36 -0
  343. package/docs/layout/auth-recovery/examples/mfa-challenge.md +41 -0
  344. package/docs/layout/auth-recovery/examples/mfa-challenge.tsx +254 -0
  345. package/docs/layout/auth-recovery/examples/mobile-390.md +25 -0
  346. package/docs/layout/auth-recovery/examples/mobile-390.tsx +82 -0
  347. package/docs/layout/auth-recovery/examples/password-recovery.md +24 -0
  348. package/docs/layout/auth-recovery/examples/password-recovery.tsx +197 -0
  349. package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.md +27 -0
  350. package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.tsx +156 -0
  351. package/docs/layout/auth-recovery/index.md +140 -0
  352. package/docs/layout/auth-recovery/index.tsx +96 -0
  353. package/docs/layout/auth-shell-context.tsx +103 -0
  354. package/docs/layout/auth-shell-device.tsx +112 -0
  355. package/docs/layout/auth-shell-registration.tsx +335 -0
  356. package/docs/layout/auth-shell-variants.tsx +139 -0
  357. package/docs/layout/auth-shell.tsx +59 -0
  358. package/docs/layout/auth-stack.tsx +40 -0
  359. package/docs/layout/centered-shell.tsx +102 -0
  360. package/docs/layout/error-surface/examples/application-403.tsx +84 -0
  361. package/docs/layout/error-surface/examples/application-404.tsx +77 -0
  362. package/docs/layout/error-surface/examples/system-500.tsx +47 -0
  363. package/docs/layout/error-surface/examples/system-503.tsx +48 -0
  364. package/docs/layout/error-surface/index.md +153 -0
  365. package/docs/layout/error-surface/index.tsx +239 -0
  366. package/docs/layout/flex.tsx +262 -0
  367. package/docs/layout/legal-document-shell/_data.ts +110 -0
  368. package/docs/layout/legal-document-shell/examples/desktop-1440.md +12 -0
  369. package/docs/layout/legal-document-shell/examples/desktop-1440.tsx +83 -0
  370. package/docs/layout/legal-document-shell/examples/mobile-390.md +22 -0
  371. package/docs/layout/legal-document-shell/examples/mobile-390.tsx +70 -0
  372. package/docs/layout/legal-document-shell/examples/tablet-1024.md +3 -0
  373. package/docs/layout/legal-document-shell/examples/tablet-1024.tsx +84 -0
  374. package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.md +18 -0
  375. package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.tsx +61 -0
  376. package/docs/layout/legal-document-shell/index.md +51 -0
  377. package/docs/layout/legal-document-shell/index.tsx +101 -0
  378. package/docs/layout/master-detail.tsx +387 -0
  379. package/docs/layout/org-switcher.tsx +131 -0
  380. package/docs/layout/page-container.tsx +946 -0
  381. package/docs/layout/resizable-panel.tsx +419 -0
  382. package/docs/layout/responsive-grid.tsx +235 -0
  383. package/docs/layout/separator.tsx +327 -0
  384. package/docs/layout/service-role-panel.tsx +144 -0
  385. package/docs/layout/sidebar.tsx +586 -0
  386. package/docs/layout/split-pane.tsx +451 -0
  387. package/docs/layout/topbar.tsx +347 -0
  388. package/docs/navigation/app-setting-picker.tsx +141 -0
  389. package/docs/navigation/breadcrumb.tsx +128 -0
  390. package/docs/navigation/context-menu.tsx +117 -0
  391. package/docs/navigation/dropdown-menu.tsx +213 -0
  392. package/docs/navigation/filter-bar.tsx +227 -0
  393. package/docs/navigation/menubar.tsx +141 -0
  394. package/docs/navigation/navigation-menu.tsx +165 -0
  395. package/docs/navigation/pagination.tsx +241 -0
  396. package/docs/navigation/steps.tsx +263 -0
  397. package/docs/navigation/tabs-rtl.tsx +28 -0
  398. package/docs/navigation/tabs.tsx +308 -0
  399. package/docs/navigation/toolbar.tsx +339 -0
  400. package/docs/providers/app-provider.tsx +191 -0
  401. package/docs/providers/format-date.tsx +230 -0
  402. package/docs/query/button-refetch.tsx +160 -0
  403. package/docs/query/data-state.tsx +192 -0
  404. package/docs/query/infinite-query-state.tsx +93 -0
  405. package/docs/query/mutation-feedback.tsx +70 -0
  406. package/docs/query/prefetch-link.tsx +262 -0
  407. package/docs/query/touch-actions.tsx +68 -0
  408. package/docs/showcase/acme-portal.tsx +441 -0
  409. package/docs/showcase/acme-website.tsx +455 -0
  410. package/docs/showcase/case1-warehouse-dashboard.tsx +343 -0
  411. package/docs/showcase/case2-employee-me.tsx +441 -0
  412. package/docs/showcase/case3-approval-workflow.tsx +527 -0
  413. package/docs/showcase/case4-login.tsx +307 -0
  414. package/docs/showcase/case5-shift-calendar.tsx +795 -0
  415. package/docs/showcase/case6-agency-handy.tsx +1072 -0
  416. package/docs/showcase/futurelastic-web.tsx +390 -0
  417. package/docs/showcase/org-switcher.tsx +313 -0
  418. package/docs/showcase/permission-matrix.tsx +343 -0
  419. package/docs/showcase/public-landing.tsx +210 -0
  420. package/docs/showcase/settings-account-sections.tsx +559 -0
  421. package/docs/showcase/settings-security-mfa.tsx +145 -0
  422. package/docs/showcase/table-approval-queue.tsx +199 -0
  423. package/docs/showcase/table-bulk-actions.tsx +460 -0
  424. package/docs/showcase/table-compact-kintone.tsx +438 -0
  425. package/docs/showcase/table-conditional-format.tsx +367 -0
  426. package/docs/showcase/table-crud-list.tsx +544 -0
  427. package/docs/showcase/table-density.tsx +340 -0
  428. package/docs/showcase/table-expandable-rows.tsx +471 -0
  429. package/docs/showcase/table-filter-chips.tsx +461 -0
  430. package/docs/showcase/table-footer-totals.tsx +311 -0
  431. package/docs/showcase/table-grouped-subtotals.tsx +388 -0
  432. package/docs/showcase/table-master-detail.tsx +479 -0
  433. package/docs/showcase/table-pagination.tsx +320 -0
  434. package/docs/showcase/table-states.tsx +363 -0
  435. package/docs/showcase/table-sticky-columns.tsx +373 -0
  436. package/docs/showcase/table-tree-rows.tsx +444 -0
  437. package/docs/showcase/table-view-tabs.tsx +488 -0
  438. package/package.json +10 -11
  439. package/scripts/_agent-setup.mjs +16 -2
  440. package/scripts/audit-hook.mjs +3 -13
  441. package/scripts/init-agent-kit.mjs +1 -14
  442. package/scripts/postinstall.mjs +12 -12
  443. package/scripts/ui-audit.mjs +93 -31
  444. package/scripts/visual-audit-rules.mjs +51 -7
  445. package/scripts/visual-audit.mjs +118 -47
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { X } from "lucide-react";
5
5
  import { useTranslation } from "../../i18n/use-translation.js";
6
- import { useFieldNameFallback } from "../../lib/field-a11y.js";
6
+ import { useFieldIdentity, useFieldNameFallback } from "../../lib/field-a11y.js";
7
7
  import { cn } from "../../lib/utils.js";
8
8
  const inputBaseClass = [
9
9
  "ui-control ui-input border-input bg-background w-full rounded-[var(--control-radius)] transition-[color,box-shadow] outline-none",
@@ -13,6 +13,7 @@ const inputBaseClass = [
13
13
  ];
14
14
  const Input = React.forwardRef(
15
15
  ({
16
+ size,
16
17
  className,
17
18
  type,
18
19
  allowClear = false,
@@ -29,6 +30,11 @@ const Input = React.forwardRef(
29
30
  "aria-label": props["aria-label"],
30
31
  "aria-labelledby": props["aria-labelledby"]
31
32
  });
33
+ const identity = useFieldIdentity({
34
+ id: props.id,
35
+ name: props.name,
36
+ "data-field": props["data-field"]
37
+ });
32
38
  const innerRef = React.useRef(null);
33
39
  const setRefs = React.useCallback(
34
40
  (node) => {
@@ -68,13 +74,15 @@ const Input = React.forwardRef(
68
74
  {
69
75
  type,
70
76
  "data-slot": "input",
77
+ "data-size": size,
71
78
  ref: setRefs,
72
79
  value,
73
80
  defaultValue,
74
81
  onChange,
75
82
  className: cn(inputBaseClass, className),
76
83
  ...props,
77
- ...nameFallback
84
+ ...nameFallback,
85
+ ...identity
78
86
  }
79
87
  );
80
88
  }
@@ -97,6 +105,7 @@ const Input = React.forwardRef(
97
105
  {
98
106
  type,
99
107
  "data-slot": "input",
108
+ "data-size": size,
100
109
  ref: setRefs,
101
110
  value,
102
111
  defaultValue,
@@ -108,7 +117,8 @@ const Input = React.forwardRef(
108
117
  className
109
118
  ),
110
119
  ...props,
111
- ...nameFallback
120
+ ...nameFallback,
121
+ ...identity
112
122
  }
113
123
  ),
114
124
  trailing != null ? /* @__PURE__ */ jsx("span", { className: "ui-input-trailing", children: trailing }) : null
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  import { CalendarIcon, ChevronLeft, ChevronRight, X } from "lucide-react";
5
5
  import { usePickerLocales, useTranslation } from "../../i18n/use-translation.js";
6
6
  import { useControlledLatch } from "../../lib/hooks.js";
7
- import { pickFieldA11y } from "../../lib/field-a11y.js";
7
+ import { pickFieldA11y, useFieldIdentity } from "../../lib/field-a11y.js";
8
8
  import { cn } from "../../lib/utils.js";
9
9
  import { Button } from "../general/button.js";
10
10
  import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
@@ -38,6 +38,7 @@ function MonthPicker({
38
38
  const inputId = id ?? autoId;
39
39
  const dialogId = `${inputId}-dialog`;
40
40
  const fieldA11y = pickFieldA11y(ariaProps);
41
+ const identity = useFieldIdentity({ id, name, "data-field": fieldA11y["data-field"] });
41
42
  const isControlled = useControlledLatch(valueProp !== void 0);
42
43
  const [internalValue, setInternalValue] = React.useState(defaultValue);
43
44
  const value = isControlled ? valueProp : internalValue;
@@ -62,10 +63,10 @@ function MonthPicker({
62
63
  "div",
63
64
  {
64
65
  "data-disabled": disabled ? "" : void 0,
66
+ "data-state": open ? "open" : "closed",
65
67
  className: cn(
66
68
  "ui-control ui-control-composite-field",
67
- "focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]",
68
- open && "border-ring ring-ring/50 ring-[3px]",
69
+ "aria-invalid:border-destructive",
69
70
  className
70
71
  ),
71
72
  onClick: () => {
@@ -76,7 +77,8 @@ function MonthPicker({
76
77
  "input",
77
78
  {
78
79
  id: inputId,
79
- name,
80
+ name: name ?? identity.name,
81
+ "data-field": fieldA11y["data-field"] ?? identity["data-field"],
80
82
  value: text,
81
83
  disabled,
82
84
  placeholder: placeholder ?? t("dataEntry.monthPicker.placeholder") ?? YM_HINT,
@@ -2,11 +2,9 @@ import * as React from "react";
2
2
  import type { MonthRangePickerProp } from "../../props/components/data-entry.prop.js";
3
3
  export type { MonthRangePickerProp, MonthRangePickerProp as MonthRangePickerProps, } from "../../props/components/data-entry.prop.js";
4
4
  /**
5
- * MonthRangePicker — year/month (`yyyy/MM`) RANGE rendered as ONE input-styled
6
- * control (Ant Design RangePicker convention): `[ from → to ✕ 📅 ]`. The two
7
- * inner fields stay real, typeable `yyyy/MM` inputs (form-submittable via
8
- * `${name}_from` / `${name}_to`); the Ant-style month grid is the visual
9
- * affordance. Grid picks are two-step (from, then to — swapped when picked
10
- * backwards) and a pick on a COMPLETE range starts a new one (reset-on-complete).
5
+ * MonthRangePicker — year/month (`yyyy/MM`) RANGE rendered as ONE input-styled control (Ant Design
6
+ * RangePicker convention): `[ from → to ✕ 📅 ]`. The two inner fields stay real, typeable
7
+ * `yyyy/MM` inputs (form-submittable via `${name}_from` / `${name}_to`); the Ant-style month grid
8
+ * is the visual affordance.
11
9
  */
12
10
  export declare function MonthRangePicker({ value: valueProp, defaultValue, onValueChange, placeholder, disabled, className, id, name, fromYear, toYear, allowClear, ...ariaProps }: MonthRangePickerProp): React.JSX.Element;
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  import { ArrowRight, CalendarIcon, ChevronLeft, ChevronRight, X } from "lucide-react";
5
5
  import { usePickerLocales, useTranslation } from "../../i18n/use-translation.js";
6
6
  import { useControlledLatch } from "../../lib/hooks.js";
7
- import { pickGroupFieldA11y } from "../../lib/field-a11y.js";
7
+ import { pickGroupFieldA11y, useFieldIdentity } from "../../lib/field-a11y.js";
8
8
  import { cn } from "../../lib/utils.js";
9
9
  import { Button } from "../general/button.js";
10
10
  import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
@@ -40,6 +40,9 @@ function MonthRangePicker({
40
40
  const groupId = id ?? autoId;
41
41
  const fromId = `${groupId}-from`;
42
42
  const toId = `${groupId}-to`;
43
+ const identity = useFieldIdentity({ id: groupId, name, "data-field": groupA11y["data-field"] });
44
+ const rangeField = groupA11y["data-field"] ?? identity["data-field"];
45
+ const rangeName = name ?? identity.name;
43
46
  const isControlled = useControlledLatch(valueProp !== void 0);
44
47
  const [internalValue, setInternalValue] = React.useState(defaultValue);
45
48
  const value = isControlled ? valueProp : internalValue;
@@ -107,12 +110,13 @@ function MonthRangePicker({
107
110
  role: "group",
108
111
  id: groupId,
109
112
  ...groupA11y,
113
+ "data-field": rangeField,
110
114
  "aria-disabled": disabled ? true : void 0,
111
115
  "data-disabled": disabled ? "" : void 0,
116
+ "data-state": open ? "open" : "closed",
112
117
  className: cn(
113
118
  "ui-control ui-control-composite-field",
114
- "focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]",
115
- open && "border-ring ring-ring/50 ring-[3px]",
119
+ "aria-invalid:border-destructive",
116
120
  className
117
121
  ),
118
122
  onClick: () => {
@@ -123,7 +127,8 @@ function MonthRangePicker({
123
127
  "input",
124
128
  {
125
129
  id: fromId,
126
- name: name ? `${name}_from` : void 0,
130
+ "data-field": rangeField ? `${rangeField}_from` : void 0,
131
+ name: rangeName ? `${rangeName}_from` : void 0,
127
132
  value: fromText,
128
133
  disabled,
129
134
  placeholder: resolvedPlaceholder,
@@ -144,7 +149,8 @@ function MonthRangePicker({
144
149
  "input",
145
150
  {
146
151
  id: toId,
147
- name: name ? `${name}_to` : void 0,
152
+ "data-field": rangeField ? `${rangeField}_to` : void 0,
153
+ name: rangeName ? `${rangeName}_to` : void 0,
148
154
  value: toText,
149
155
  disabled,
150
156
  placeholder: resolvedPlaceholder,
@@ -2,11 +2,7 @@ import * as React from "react";
2
2
  export type { NumberInputProp, NumberInputProp as NumberInputProps, } from "../../props/components/data-entry.prop.js";
3
3
  /**
4
4
  * NumberInput — WAI-ARIA spinbutton: a localized numeric `<Input>` with increment/decrement steps.
5
- *
6
- * Composes the real `Input` primitive (no raw `<input>`) plus two icon `Button`s. The text input is
7
- * the `role="spinbutton"` element carrying `aria-valuenow/min/max/text`; type freely, ArrowUp/Down
8
- * (Shift = ×10) step, and the value commits clamped + rounded to `precision` on blur/Enter/step.
9
- * Display formats via `Intl.NumberFormat` at rest, but stays raw and typeable while focused.
5
+ * Composes the real `Input` primitive (no raw `<input>`) plus two icon `Button`s.
10
6
  */
11
7
  export declare const NumberInput: React.ForwardRefExoticComponent<import("../../lib/field-a11y.js").FieldA11yProps & {
12
8
  value?: import("../../props/index.js").ValueProp<number | null>;
@@ -154,6 +154,7 @@ const NumberInput = React.forwardRef(
154
154
  role: "spinbutton",
155
155
  "data-slot": "number-input-field",
156
156
  "data-testid": dataTestId,
157
+ "data-field": ariaProps["data-field"],
157
158
  className: "ui-number-input-field",
158
159
  value: draft,
159
160
  placeholder,
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
5
5
  import { Circle } from "lucide-react";
6
6
  import { cn } from "../../lib/utils.js";
7
- import { pickFieldA11y } from "../../lib/field-a11y.js";
7
+ import { pickFieldA11y, useFieldIdentity } from "../../lib/field-a11y.js";
8
8
  import { Field } from "./field.js";
9
9
  import { choiceGroupClassName } from "./choice-option.js";
10
10
  const RadioGroupRoot = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
@@ -23,7 +23,6 @@ const RadioItem = React.forwardRef(({ className, ...props }, ref) => /* @__PURE_
23
23
  ref,
24
24
  "data-slot": "radio-group-item",
25
25
  className: cn(
26
- // `disabled:cursor-not-allowed disabled:opacity-50` DELETED, not moved (#319):
27
26
  // `.ui-radio:disabled, .ui-radio[data-disabled]` in styles/control.css already declares both
28
27
  // and reads --disabled-opacity. The utility was layered after components, so it silently
29
28
  // outranked that token — a service theme's --disabled-opacity never reached a radio.
@@ -58,6 +57,10 @@ function RadioGroupOptions({
58
57
  }) {
59
58
  const reactId = React.useId();
60
59
  const groupA11y = pickFieldA11y(ariaProps);
60
+ const identity = useFieldIdentity({ id, name, "data-field": groupA11y["data-field"] });
61
+ const resolvedName = name ?? identity.name;
62
+ const resolvedField = groupA11y["data-field"] ?? identity["data-field"];
63
+ const optionDomId = (optionValue, index) => id ? `${id}-${optionValue}` : `${reactId}-${optionValue}-${index}`;
61
64
  if (options && options.length > 0) {
62
65
  return /* @__PURE__ */ jsx(
63
66
  RadioGroupRoot,
@@ -66,14 +69,23 @@ function RadioGroupOptions({
66
69
  defaultValue,
67
70
  onValueChange,
68
71
  disabled,
69
- name,
72
+ name: resolvedName,
70
73
  id,
71
74
  ...groupA11y,
75
+ "data-field": resolvedField,
72
76
  "data-orientation": orientation,
73
77
  className: choiceGroupClassName(orientation, className),
74
78
  children: options.map((opt, index) => {
75
- const id2 = `${reactId}-${opt.value}-${index}`;
76
- return /* @__PURE__ */ jsx(Field, { id: id2, label: opt.label, description: opt.description, children: /* @__PURE__ */ jsx(RadioItem, { id: id2, value: opt.value, disabled: opt.disabled }) }, opt.value);
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,
82
+ {
83
+ id: optionId,
84
+ value: opt.value,
85
+ disabled: opt.disabled,
86
+ "data-field": resolvedField
87
+ }
88
+ ) }, opt.value);
77
89
  })
78
90
  }
79
91
  );
@@ -85,9 +97,10 @@ function RadioGroupOptions({
85
97
  defaultValue,
86
98
  onValueChange,
87
99
  disabled,
88
- name,
100
+ name: resolvedName,
89
101
  id,
90
102
  ...groupA11y,
103
+ "data-field": resolvedField,
91
104
  "data-orientation": orientation,
92
105
  className: choiceGroupClassName(orientation, className),
93
106
  children
@@ -4,9 +4,7 @@ export type { SearchSelectProp, SearchSelectProp as SearchSelectProps, SearchSel
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
- * with `loadOptions({ query, page })` (server search + infinite scroll) OR with a static
8
- * `options` array (client-side filter) — the latter supersedes the legacy `Autocomplete`.
9
- * Custom per-option rendering via `renderOption` (Ant-Design style). Form-submittable via
10
- * `name`; e2e-testable by the trigger's `data-testid` + each option's `${data-testid}-option-${value}`.
7
+ * with `loadOptions({ query, page })` (server search + infinite scroll) OR with a static `options`
8
+ * array (client-side filter) — the latter supersedes the legacy `Autocomplete`.
11
9
  */
12
- 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, "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({ 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;
@@ -3,7 +3,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { ChevronsUpDown, Loader2, X } from "lucide-react";
5
5
  import { useTranslation } from "../../i18n/use-translation.js";
6
- import { useFieldNameFallback } from "../../lib/field-a11y.js";
6
+ import { useFieldIdentity, useFieldNameFallback } from "../../lib/field-a11y.js";
7
7
  import { cn } from "../../lib/utils.js";
8
8
  import { controlOpenRingClass } from "../../lib/control-styles.js";
9
9
  import { Button } from "../general/button.js";
@@ -42,6 +42,7 @@ function SearchSelect({
42
42
  id,
43
43
  className,
44
44
  "data-testid": dataTestId,
45
+ "data-field": dataField,
45
46
  "aria-label": ariaLabel,
46
47
  "aria-labelledby": ariaLabelledby,
47
48
  "aria-describedby": ariaDescribedby,
@@ -54,6 +55,9 @@ function SearchSelect({
54
55
  "aria-label": ariaLabel,
55
56
  "aria-labelledby": ariaLabelledby
56
57
  });
58
+ const identity = useFieldIdentity({ id, name, "data-field": dataField });
59
+ const resolvedName = name ?? identity.name;
60
+ const resolvedField = dataField ?? identity["data-field"];
57
61
  const triggerAriaLabel = ariaLabel ?? nameFallback["aria-label"];
58
62
  const triggerAriaLabelledby = ariaLabelledby ?? nameFallback["aria-labelledby"];
59
63
  const reactId = React.useId();
@@ -254,6 +258,8 @@ function SearchSelect({
254
258
  "aria-readonly": readOnly || void 0,
255
259
  disabled,
256
260
  "data-testid": dataTestId,
261
+ "data-field": resolvedField,
262
+ "data-value": value || void 0,
257
263
  className: cn(
258
264
  "w-full justify-start font-normal",
259
265
  controlOpenRingClass,
@@ -275,7 +281,7 @@ function SearchSelect({
275
281
  )
276
282
  }
277
283
  ) }),
278
- name ? /* @__PURE__ */ jsx("input", { type: "hidden", name, value, readOnly: true }) : null,
284
+ resolvedName ? /* @__PURE__ */ jsx("input", { type: "hidden", name: resolvedName, value, readOnly: true }) : null,
279
285
  /* @__PURE__ */ jsx(
280
286
  PopoverContent,
281
287
  {
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import type { ControlWidthProp } from "../../props/vocabulary/shared.prop.js";
2
3
  import * as SelectPrimitive from "@radix-ui/react-select";
3
4
  import type { FieldA11yProps } from "../../lib/field-a11y.js";
4
5
  import type { SelectDataProp } from "../../props/components/data-entry.prop.js";
@@ -20,13 +21,25 @@ export declare function SelectGroup(props: React.ComponentProps<typeof SelectPri
20
21
  export declare function SelectValue(props: React.ComponentProps<typeof SelectPrimitive.Value>): React.JSX.Element;
21
22
  export declare const SelectTrigger: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & {
22
23
  size?: "sm" | "md";
24
+ /**
25
+ * `full` (default) fills the field column — right inside a FormField. `auto` sizes to the
26
+ * selected label — right in a PageContainer `extra` slot, a toolbar or a footer row, where a
27
+ * full-width trigger swallows the row and starves its siblings (text truncated to "UA…").
28
+ */
29
+ width?: ControlWidthProp;
23
30
  /**
24
31
  * Show the built-in chevron disclosure indicator (default true). Set `false` for specialized
25
32
  * triggers — icon-only, or one that already renders its own affordance — so it isn't
26
- * duplicated. Omits the icon from the DOM entirely (not a CSS hide), so no consumer
27
- * descendant CSS is needed to remove it.
33
+ * duplicated.
28
34
  */
29
35
  showIndicator?: boolean;
36
+ "data-field"?: string;
37
+ /**
38
+ * Normally supplied by `Select` itself — the trigger shows the option's LABEL, and this is the
39
+ * only place the underlying value is readable from the DOM without reaching into Radix's
40
+ * aria-hidden native `<select>`.
41
+ */
42
+ "data-value"?: string;
30
43
  } & React.RefAttributes<HTMLButtonElement>>;
31
44
  export declare const SelectScrollUpButton: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectScrollUpButtonProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
32
45
  export declare const SelectScrollDownButton: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectScrollDownButtonProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
@@ -7,6 +7,7 @@ import { cn } from "../../lib/utils.js";
7
7
  import { controlTriggerClass } from "../../lib/control-styles.js";
8
8
  import {
9
9
  mergeAriaIds,
10
+ useFieldIdentity,
10
11
  omitFieldA11y,
11
12
  pickFieldA11y,
12
13
  useFieldNameFallback
@@ -26,7 +27,36 @@ function Select(props) {
26
27
  function CompoundSelect({ id, ...props }) {
27
28
  const fieldA11y = pickFieldA11y(props);
28
29
  const rootProps = omitFieldA11y(props);
29
- return /* @__PURE__ */ jsx(SelectFieldA11yContext.Provider, { value: { ...fieldA11y, id }, children: /* @__PURE__ */ jsx(SelectPrimitive.Root, { "data-slot": "select", ...rootProps }) });
30
+ const [uncontrolled, setUncontrolled] = React.useState(props.defaultValue);
31
+ const value = props.value ?? uncontrolled;
32
+ const identity = useFieldIdentity({
33
+ id,
34
+ name: props.name,
35
+ "data-field": fieldA11y["data-field"]
36
+ });
37
+ return /* @__PURE__ */ jsx(
38
+ SelectFieldA11yContext.Provider,
39
+ {
40
+ value: {
41
+ ...fieldA11y,
42
+ "data-field": identity["data-field"] ?? fieldA11y["data-field"],
43
+ id,
44
+ value
45
+ },
46
+ children: /* @__PURE__ */ jsx(
47
+ SelectPrimitive.Root,
48
+ {
49
+ "data-slot": "select",
50
+ ...rootProps,
51
+ name: props.name ?? identity.name,
52
+ onValueChange: (next) => {
53
+ setUncontrolled(next);
54
+ props.onValueChange?.(next);
55
+ }
56
+ }
57
+ )
58
+ }
59
+ );
30
60
  }
31
61
  function SelectGroup(props) {
32
62
  return /* @__PURE__ */ jsx(SelectPrimitive.Group, { "data-slot": "select-group", ...props });
@@ -34,7 +64,7 @@ function SelectGroup(props) {
34
64
  function SelectValue(props) {
35
65
  return /* @__PURE__ */ jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
36
66
  }
37
- const SelectTrigger = React.forwardRef(({ className, children, size = "md", showIndicator = true, ...props }, ref) => {
67
+ const SelectTrigger = React.forwardRef(({ className, children, size = "md", width = "full", showIndicator = true, ...props }, ref) => {
38
68
  const field = React.useContext(SelectFieldA11yContext);
39
69
  const ownsName = props["aria-label"] !== void 0 || props["aria-labelledby"] !== void 0;
40
70
  const fieldOwnsName = field?.["aria-label"] !== void 0 || field?.["aria-labelledby"] !== void 0;
@@ -54,21 +84,26 @@ const SelectTrigger = React.forwardRef(({ className, children, size = "md", show
54
84
  field?.["aria-errormessage"]
55
85
  ),
56
86
  "aria-required": props["aria-required"] ?? field?.["aria-required"],
57
- "aria-invalid": props["aria-invalid"] ?? field?.["aria-invalid"]
87
+ "aria-invalid": props["aria-invalid"] ?? field?.["aria-invalid"],
88
+ "data-field": props["data-field"] ?? field?.["data-field"]
58
89
  } : void 0;
90
+ const dataValue = (props["data-value"] ?? field?.value) || void 0;
59
91
  return /* @__PURE__ */ jsxs(
60
92
  SelectPrimitive.Trigger,
61
93
  {
62
94
  ref,
63
95
  "data-slot": "select-trigger",
64
96
  "data-size": size,
97
+ "data-width": width,
65
98
  className: cn(
66
99
  controlTriggerClass,
67
- "aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground w-full whitespace-nowrap transition-[color,box-shadow] outline-none *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center",
100
+ width === "auto" ? "w-auto" : "w-full",
101
+ "aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground whitespace-nowrap transition-[color,box-shadow] outline-none *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center",
68
102
  className
69
103
  ),
70
104
  ...props,
71
105
  ...fieldA11y,
106
+ "data-value": dataValue,
72
107
  children: [
73
108
  children,
74
109
  showIndicator ? /* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(
@@ -212,12 +247,18 @@ function DataSelect({
212
247
  id,
213
248
  className,
214
249
  "data-testid": dataTestId,
250
+ "data-field": dataField,
215
251
  ...rest
216
252
  }) {
217
253
  const ariaProps = Object.fromEntries(
218
254
  Object.entries(rest).filter(([key]) => key.startsWith("aria-"))
219
255
  );
220
256
  const { t } = useTranslation();
257
+ const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);
258
+ const currentValue = value ?? uncontrolledValue;
259
+ const identity = useFieldIdentity({ id, name, "data-field": dataField });
260
+ const resolvedName = name ?? identity.name;
261
+ const resolvedField = dataField ?? identity["data-field"];
221
262
  const searchable = showSearch ?? Boolean(loadOptions);
222
263
  const hasOptions = options.length > 0;
223
264
  if (searchable) {
@@ -250,10 +291,11 @@ function DataSelect({
250
291
  filterOption,
251
292
  renderError,
252
293
  renderLoadMore,
253
- name,
294
+ name: resolvedName,
254
295
  id,
255
296
  className,
256
297
  "data-testid": dataTestId,
298
+ "data-field": resolvedField,
257
299
  ...ariaProps
258
300
  }
259
301
  );
@@ -278,18 +320,23 @@ function DataSelect({
278
320
  "data-slot": "select",
279
321
  value: isControlled ? value : void 0,
280
322
  defaultValue: isControlled ? void 0 : defaultValue || void 0,
281
- onValueChange: (next) => onValueChange?.(
282
- next,
283
- options.find((option) => option.value === next)
284
- ),
323
+ onValueChange: (next) => {
324
+ setUncontrolledValue(next);
325
+ onValueChange?.(
326
+ next,
327
+ options.find((option) => option.value === next)
328
+ );
329
+ },
285
330
  disabled: disabled || !hasOptions,
286
- name,
331
+ name: resolvedName,
287
332
  children: [
288
333
  /* @__PURE__ */ jsx(
289
334
  SelectTrigger,
290
335
  {
291
336
  id,
292
337
  "data-testid": dataTestId,
338
+ "data-field": resolvedField,
339
+ "data-value": currentValue || void 0,
293
340
  className: cn(showClear && "ui-control-trigger-affixed", canClear ? void 0 : className),
294
341
  showIndicator: !showClear,
295
342
  ...ariaProps,
@@ -3,8 +3,15 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as SwitchPrimitive from "@radix-ui/react-switch";
5
5
  import { cn } from "../../lib/utils.js";
6
+ import { useFieldIdentity } from "../../lib/field-a11y.js";
6
7
  const Switch = React.forwardRef(
7
8
  ({ className, size = "md", name, checked, defaultChecked = false, onCheckedChange, ...props }, ref) => {
9
+ const identity = useFieldIdentity({
10
+ id: props.id,
11
+ name,
12
+ "data-field": props["data-field"]
13
+ });
14
+ const resolvedName = name ?? identity.name;
8
15
  const [internalChecked, setInternalChecked] = React.useState(defaultChecked);
9
16
  const isControlled = checked !== void 0;
10
17
  const isChecked = isControlled ? checked : internalChecked;
@@ -15,7 +22,7 @@ const Switch = React.forwardRef(
15
22
  onCheckedChange?.(next);
16
23
  };
17
24
  return /* @__PURE__ */ jsxs(Fragment, { children: [
18
- name ? /* @__PURE__ */ jsx("input", { type: "hidden", name, value: isChecked ? "1" : "0", readOnly: true }) : null,
25
+ resolvedName ? /* @__PURE__ */ jsx("input", { type: "hidden", name: resolvedName, value: isChecked ? "1" : "0", readOnly: true }) : null,
19
26
  /* @__PURE__ */ jsx(
20
27
  SwitchPrimitive.Root,
21
28
  {
@@ -25,7 +32,6 @@ const Switch = React.forwardRef(
25
32
  checked: isChecked,
26
33
  onCheckedChange: handleCheckedChange,
27
34
  className: cn(
28
- // `disabled:cursor-not-allowed disabled:opacity-50` DELETED, not moved (#319):
29
35
  // `.ui-switch:disabled, .ui-switch[data-disabled]` in styles/control.css already
30
36
  // declares both and reads --disabled-opacity. The utility was layered after
31
37
  // components, so it silently outranked that token. Byte-identical: the token
@@ -35,6 +41,7 @@ const Switch = React.forwardRef(
35
41
  className
36
42
  ),
37
43
  ...props,
44
+ "data-field": identity["data-field"] ?? props["data-field"],
38
45
  children: /* @__PURE__ */ jsx(SwitchPrimitive.Thumb, { "data-slot": "switch-thumb", className: "ui-switch-thumb" })
39
46
  }
40
47
  )
@@ -5,20 +5,17 @@ export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> &
5
5
  /** Called after the field is cleared via the inline ✕. */
6
6
  onClear?: () => void;
7
7
  /**
8
- * `ghost` strips the field's own border, background and focus ring, for a textarea embedded
9
- * in a surface that already draws the box (a chat composer inside a Card). The surface then
10
- * owns focus — give it `focus-within`. Default keeps the standalone control chrome.
8
+ * `ghost` strips the field's own border, background and focus ring, for a textarea embedded in a
9
+ * surface that already draws the box (a chat composer inside a Card). The surface then owns
10
+ * focus — give it `focus-within`.
11
11
  */
12
12
  variant?: "default" | "ghost";
13
13
  /**
14
- * Grow the control with its content instead of holding a fixed `rows` height (default false —
15
- * the inert default, so every existing `<Textarea>` keeps the geometry it has today).
16
- *
17
14
  * The floor is `minRows` (or `rows`, when that is the only one given) and never undercuts the
18
15
  * `--control-height` tier; past `maxRows` the control stops growing and scrolls internally.
19
16
  * Sizing is done in CSS by a hidden replica of the text, so it follows a paste, a programmatic
20
17
  * value change, a font swap and a container resize — not just typing — and it never writes
21
- * `style.height` or reads `scrollHeight`. Works controlled and uncontrolled.
18
+ * `style.height` or reads `scrollHeight`.
22
19
  */
23
20
  autoGrow?: boolean;
24
21
  /**
@@ -29,7 +26,7 @@ export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> &
29
26
  /**
30
27
  * Ceiling in text rows while `autoGrow` (theme default `--textarea-autogrow-max-height-rows`,
31
28
  * 8); beyond it the control scrolls internally rather than pushing the page. Pass `0` for no
32
- * ceiling — only correct inside an owning scroll container. Ignored when `autoGrow` is false.
29
+ * ceiling — only correct inside an owning scroll container.
33
30
  */
34
31
  maxRows?: number;
35
32
  };
@@ -39,20 +36,17 @@ export declare const Textarea: React.ForwardRefExoticComponent<React.TextareaHTM
39
36
  /** Called after the field is cleared via the inline ✕. */
40
37
  onClear?: () => void;
41
38
  /**
42
- * `ghost` strips the field's own border, background and focus ring, for a textarea embedded
43
- * in a surface that already draws the box (a chat composer inside a Card). The surface then
44
- * owns focus — give it `focus-within`. Default keeps the standalone control chrome.
39
+ * `ghost` strips the field's own border, background and focus ring, for a textarea embedded in a
40
+ * surface that already draws the box (a chat composer inside a Card). The surface then owns
41
+ * focus — give it `focus-within`.
45
42
  */
46
43
  variant?: "default" | "ghost";
47
44
  /**
48
- * Grow the control with its content instead of holding a fixed `rows` height (default false —
49
- * the inert default, so every existing `<Textarea>` keeps the geometry it has today).
50
- *
51
45
  * The floor is `minRows` (or `rows`, when that is the only one given) and never undercuts the
52
46
  * `--control-height` tier; past `maxRows` the control stops growing and scrolls internally.
53
47
  * Sizing is done in CSS by a hidden replica of the text, so it follows a paste, a programmatic
54
48
  * value change, a font swap and a container resize — not just typing — and it never writes
55
- * `style.height` or reads `scrollHeight`. Works controlled and uncontrolled.
49
+ * `style.height` or reads `scrollHeight`.
56
50
  */
57
51
  autoGrow?: boolean;
58
52
  /**
@@ -63,7 +57,7 @@ export declare const Textarea: React.ForwardRefExoticComponent<React.TextareaHTM
63
57
  /**
64
58
  * Ceiling in text rows while `autoGrow` (theme default `--textarea-autogrow-max-height-rows`,
65
59
  * 8); beyond it the control scrolls internally rather than pushing the page. Pass `0` for no
66
- * ceiling — only correct inside an owning scroll container. Ignored when `autoGrow` is false.
60
+ * ceiling — only correct inside an owning scroll container.
67
61
  */
68
62
  maxRows?: number;
69
63
  } & React.RefAttributes<HTMLTextAreaElement>>;
@@ -4,6 +4,7 @@ import * as React from "react";
4
4
  import { X } from "lucide-react";
5
5
  import { useTranslation } from "../../i18n/use-translation.js";
6
6
  import { cn } from "../../lib/utils.js";
7
+ import { useFieldIdentity } from "../../lib/field-a11y.js";
7
8
  import { controlMultilineClass, controlMultilineGhostClass } from "../../lib/control-styles.js";
8
9
  const UNBOUNDED_ROWS = "infinity";
9
10
  const Textarea = React.forwardRef(
@@ -26,6 +27,11 @@ const Textarea = React.forwardRef(
26
27
  }, ref) => {
27
28
  const { t } = useTranslation();
28
29
  const base = variant === "ghost" ? controlMultilineGhostClass : controlMultilineClass;
30
+ const identity = useFieldIdentity({
31
+ id: props.id,
32
+ name: props.name,
33
+ "data-field": props["data-field"]
34
+ });
29
35
  const innerRef = React.useRef(null);
30
36
  const setRefs = React.useCallback(
31
37
  (node) => {
@@ -110,7 +116,8 @@ const Textarea = React.forwardRef(
110
116
  onCompositionEnd: handleCompositionEnd,
111
117
  style,
112
118
  className: cn(base, showClear && "ui-input--trailing-affix", className),
113
- ...props
119
+ ...props,
120
+ ...identity
114
121
  }
115
122
  );
116
123
  if (!needsWrapper) return field;