@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
@@ -35,10 +35,7 @@ export interface EmailShellTokens {
35
35
  /** Tight rhythm (heading ↔ lede). */
36
36
  readonly gapSm: string;
37
37
  readonly gapSmPx: number;
38
- /**
39
- * Height the canonical invitation reference card measures at this geometry (480×407). A
40
- * visual-regression target, NOT a layout input — never set a fixed height on an email card.
41
- */
38
+ /** Height the canonical invitation reference card measures at this geometry (480×407). */
42
39
  readonly referenceHeight: string;
43
40
  readonly referenceHeightPx: number;
44
41
  }
@@ -47,11 +44,10 @@ export declare const EMAIL_SHELL: EmailShellTokens;
47
44
  export interface EmailTypographyTokens {
48
45
  /**
49
46
  * The canonical DXS stack, Noto Sans JP first (product override, direct instruction). Web-font
50
- * `@font-face` is unavailable in most clients, so this NAMES the face and degrades: a client with
51
- * Noto Sans JP installed (or a webmail that already loaded it) renders the canonical face;
47
+ * `@font-face` is unavailable in most clients, so this NAMES the face and degrades: a client
48
+ * with Noto Sans JP installed (or a webmail that already loaded it) renders the canonical face;
52
49
  * everything else falls to Hiragino (macOS/iOS) → Yu Gothic (Windows) → M PLUS 2 → Meiryo → the
53
- * system UI face → Arial → `sans-serif`. Family names are SINGLE-quoted so the value drops
54
- * straight into a double-quoted `style="…"` attribute.
50
+ * system UI face → Arial → `sans-serif`.
55
51
  */
56
52
  readonly fontFamily: string;
57
53
  /** Mono stack for invoice ids, masked card numbers, ISO dates and amounts. */
@@ -1,53 +1,9 @@
1
1
  /**
2
- * `@godxjp/ui/email` — the email-safe design-token contract for transactional templates (issue #227).
3
- *
4
- * ## Why this exists
5
- *
6
- * A transactional email is rendered by Blade/Twig/MJML, not React, and by clients that strip
7
- * `<style>`, ignore CSS custom properties, refuse relative units and block remote images. So the
8
- * two things a template usually reaches for — the component library and the CSS token file — are
9
- * both unavailable, and templates end up hand-copying hex and hand-drawing the logo. That is
2
+ * So the two things a template usually reaches for — the component library and the CSS token file
3
+ * — are both unavailable, and templates end up hand-copying hex and hand-drawing the logo. That is
10
4
  * exactly the drift this module removes: it is a FRAMEWORK-NEUTRAL, zero-dependency, React-free
11
- * data export of literal `#rrggbb` / `px` values plus the canonical brand-mark markup.
12
- *
13
- * ## The no-drift guarantee
14
- *
15
- * Nothing here is hand-typed. `src/tokens/foundation.css` (colour roles) and
16
- * `src/tokens/components/email.css` (geometry/typography) are read by
17
- * `scripts/gen-email-tokens.mjs` into `tokens.generated.ts`, and the HSL→hex conversion runs at
18
- * module load. There is no hex literal anywhere in `src/email/`, so an email palette that diverges
19
- * from the web palette is not something a maintainer can accidentally write.
20
- * `src/email/__tests__/email-tokens.test.ts` re-derives every value straight from the CSS and
21
- * asserts equality, and `pnpm check:email-token-sync` fails CI if the generated file goes stale.
22
- *
23
- * ## Usage
24
- *
25
- * ```ts
26
- * import { EMAIL_COLORS, EMAIL_URGENCY, EMAIL_SHELL, EMAIL_CTA, EMAIL_BRAND_MARK, emailInlineStyle } from "@godxjp/ui/email";
27
- *
28
- * const card = emailInlineStyle({
29
- * width: EMAIL_SHELL.width,
30
- * padding: EMAIL_SHELL.padding,
31
- * backgroundColor: EMAIL_COLORS.surface,
32
- * border: `${EMAIL_SHELL.borderWidth} solid ${EMAIL_COLORS.border}`,
33
- * borderTopColor: EMAIL_URGENCY.accent,
34
- * borderRadius: EMAIL_SHELL.radius,
35
- * });
36
- * ```
37
- *
38
- * A non-JS template engine (Blade, Twig, Liquid) consumes the same values through
39
- * `EMAIL_TOKENS_JSON` — dump it once in the build step and read the JSON from PHP:
40
- *
41
- * ```sh
42
- * node --input-type=module -e \
43
- * 'import("@godxjp/ui/email").then(m => process.stdout.write(m.EMAIL_TOKENS_JSON))' \
44
- * > resources/design/email-tokens.json
45
- * ```
46
- *
47
- * ## Scope
48
- *
49
- * Tokens, geometry and brand markup only. Copy, recipients, links, locale, triggers and queue
50
- * behaviour belong to the sending application — this module knows nothing about them.
5
+ * data export of literal `#rrggbb` / `px` values plus the canonical brand-mark markup. ## The
6
+ * no-drift guarantee Nothing here is hand-typed.
51
7
  */
52
8
  export { hslToHex, EMAIL_COLORS, EMAIL_COLORS_DARK, type EmailColorToken, type EmailHex, } from "./color.js";
53
9
  export { EMAIL_SHELL, EMAIL_TYPOGRAPHY, EMAIL_CTA, EMAIL_FOOTER, EMAIL_FOCUS, EMAIL_MOBILE, type EmailTokenName, type EmailShellTokens, type EmailTypographyTokens, type EmailCtaTokens, type EmailFooterTokens, type EmailFocusTokens, type EmailMobileTokens, } from "./geometry.js";
@@ -1,13 +1,7 @@
1
1
  /**
2
- * Inline-style serialisation for HTML email.
3
- *
4
- * Email clients do not run the cascade: Gmail strips `<style>`, Outlook resolves no custom
5
- * property, and only the `style=""` attribute on the painting element is universally honoured.
6
- * `emailInlineStyle` turns a declaration map into that attribute value AND enforces the three rules
7
- * that silently break templates — no `var()` (nothing resolves it), no `calc()` (Outlook's Word
8
- * renderer drops the whole declaration) and no `"` (it closes the `style="…"` attribute mid-value,
9
- * which is how a double-quoted font family corrupts a whole tag). Failing loudly at template-build
10
- * time beats a broken layout discovered in Mailpit.
2
+ * Inline-style serialisation for HTML email. Email clients do not run the cascade: Gmail strips
3
+ * `<style>`, Outlook resolves no custom property, and only the `style=""` attribute on the
4
+ * painting element is universally honoured.
11
5
  */
12
6
  /** A declaration map. Numbers are emitted verbatim (already-unitless values like `font-weight`). */
13
7
  export type EmailStyleDeclarations = Record<string, string | number | null | undefined>;
@@ -1,12 +1,7 @@
1
1
  import { type EmailHex } from "./color.js";
2
2
  /**
3
- * Semantic action-required styling for transactional email.
4
- *
5
- * `accent` is the non-text rail/border color painted on the normal email surface. The solid pair
6
- * is safe for icons and large or bold labels that satisfy the 3:1 contrast floor; it is not a
7
- * replacement for normal body copy, which remains `EMAIL_COLORS.foreground` on
8
- * `EMAIL_COLORS.surface`. This deliberately narrow contract prevents urgency from becoming an
9
- * undocumented second CTA or a component-local palette.
3
+ * Semantic action-required styling for transactional email. `accent` is the non-text rail/border
4
+ * color painted on the normal email surface.
10
5
  */
11
6
  export interface EmailUrgencyTokens {
12
7
  /** Non-text action-required rail or border on the standard email surface. */
@@ -9,15 +9,12 @@ export declare const FormAdapterContext: import("react").Context<FormStateAdapte
9
9
  export declare function useFormAdapter(): FormStateAdapter | null;
10
10
  /**
11
11
  * Whether the surrounding `FormRoot` is currently submitting — works for BOTH paths: the adapter's
12
- * `isSubmitting` (e.g. Inertia's `processing`) or react-hook-form's `formState.isSubmitting`. Spread
13
- * onto a submit button so `processing` drives its loading state automatically:
14
- * `<Button type="submit" loading={useFormSubmitting()}>`.
12
+ * `isSubmitting` (e.g. Inertia's `processing`) or react-hook-form's `formState.isSubmitting`.
15
13
  */
16
14
  export declare function useFormSubmitting(): boolean;
17
15
  /**
18
16
  * Normalise a control's change payload to a bare value. The `FormFieldControl` render-prop spreads
19
17
  * `onChange` onto a control that may call it with a DOM `ChangeEvent` (native `<Input>`) OR a raw
20
- * value (a `Select`'s `onValueChange`). Mirror react-hook-form's own event unwrapping so the adapter
21
- * path binds identically for every control kind.
18
+ * value (a `Select`'s `onValueChange`).
22
19
  */
23
20
  export declare function extractControlValue(arg: unknown): unknown;
@@ -4,7 +4,6 @@ export type { FormRootProp } from "../props/components/form.prop.js";
4
4
  /**
5
5
  * FormRoot — the form shell. Provide EITHER `form` (built-in react-hook-form + Zod, client-side
6
6
  * validation) OR `adapter` (a framework-agnostic {@link FormStateAdapter} for a server-driven form
7
- * library — Inertia's `useForm` via `@godxjp/ui/inertia`, formik, TanStack Form). Both drive the same
8
- * `FormFieldControl` auto-binding; the core keeps ZERO dependency on any non-RHF form library.
7
+ * library — Inertia's `useForm` via `@godxjp/ui/inertia`, formik, TanStack Form).
9
8
  */
10
9
  export declare function FormRoot<TFieldValues extends FieldValues>({ form, adapter, onSubmit, children, className, id, }: FormRootProp<TFieldValues>): import("react").JSX.Element;
@@ -17,6 +17,10 @@
17
17
  "typeToConfirm": "Type {phrase} to confirm"
18
18
  },
19
19
  "dataEntry": {
20
+ "calendar": {
21
+ "today": "Today",
22
+ "close": "Close"
23
+ },
20
24
  "datePicker": {
21
25
  "placeholder": "Select date",
22
26
  "openCalendar": "Open calendar"
@@ -17,6 +17,10 @@
17
17
  "typeToConfirm": "確認のため {phrase} と入力"
18
18
  },
19
19
  "dataEntry": {
20
+ "calendar": {
21
+ "today": "今日",
22
+ "close": "閉じる"
23
+ },
20
24
  "datePicker": {
21
25
  "placeholder": "日付を選択",
22
26
  "openCalendar": "カレンダーを開く"
@@ -17,6 +17,10 @@
17
17
  "typeToConfirm": "Nhập {phrase} để xác nhận"
18
18
  },
19
19
  "dataEntry": {
20
+ "calendar": {
21
+ "today": "Hôm nay",
22
+ "close": "Đóng"
23
+ },
20
24
  "datePicker": {
21
25
  "placeholder": "Chọn ngày",
22
26
  "openCalendar": "Mở lịch"
@@ -1,11 +1,7 @@
1
1
  import type { ComponentType, ReactNode } from "react";
2
2
  import type { FormStateAdapter } from "../props/components/form.prop.js";
3
3
  import type { SidebarLinkComponentProp } from "../props/components/layout.prop.js";
4
- /**
5
- * Structural shape of Inertia's `useForm` return that the adapter needs. Duck-typed on purpose —
6
- * `@godxjp/ui` keeps ZERO dependency on `@inertiajs/react`; the real `useForm()` object satisfies
7
- * this shape, so a consumer passes it directly with no import from this package.
8
- */
4
+ /** Structural shape of Inertia's `useForm` return that the adapter needs. */
9
5
  export interface InertiaFormLike<TData extends Record<string, unknown> = Record<string, unknown>> {
10
6
  /** Current form values (server-driven state). */
11
7
  data: TData;
@@ -65,11 +61,7 @@ export declare function useInertiaField<TData extends Record<string, unknown>>(f
65
61
  };
66
62
  }) => void;
67
63
  };
68
- /**
69
- * Structural shape of Inertia's `<Link>` that the Sidebar adapter needs. Duck-typed on purpose —
70
- * `@godxjp/ui` keeps ZERO dependency on `@inertiajs/react`; the real `Link` satisfies this shape,
71
- * so a consumer passes it directly with no import from this package.
72
- */
64
+ /** Structural shape of Inertia's `<Link>` that the Sidebar adapter needs. */
73
65
  export interface InertiaLinkLike {
74
66
  href: string;
75
67
  className?: string;
@@ -1,29 +1,18 @@
1
1
  /** Shared control sizing — reads `--control-height`, `--font-size-*` from density / theme. */
2
- export declare const controlFieldClass = "ui-control w-full rounded-[var(--control-radius)] border border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 disabled:cursor-not-allowed disabled:opacity-50";
3
- export declare const controlMultilineClass = "ui-control-multiline w-full rounded-[var(--control-radius)] border border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 disabled:cursor-not-allowed disabled:opacity-50";
2
+ export declare const controlMultilineClass = "ui-control-multiline aria-invalid:border-destructive w-full rounded-[var(--control-radius)] border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none";
4
3
  /**
5
- * Multiline control with its own chrome removed, for a textarea EMBEDDED in a surface that
6
- * already draws the box — a chat composer inside a Card, an inline edit cell, a comment box in
7
- * a panel. Two nested rounded borders is the tell that this was missing.
8
- *
9
- * These are utilities, not tokens, ON PURPOSE. `.ui-control-multiline` reads
10
- * `--control-border-width` / `--control-shadow` from `@layer components`, but the default class
11
- * ALSO carries Tailwind's `border` in `@layer utilities`, which wins whatever the token says —
12
- * the same structural inertness gh#260 found on Badge's font size. So the variant cannot be a
13
- * token override by a consumer; it has to drop the utilities here.
14
- *
15
- * The focus ring goes with them: the surface owns focus, via `focus-within` on the wrapper.
4
+ * Multiline control with its own chrome removed, for a textarea EMBEDDED in a surface that already
5
+ * draws the box — a chat composer inside a Card, an inline edit cell, a comment box in a panel.
6
+ * Two nested rounded borders is the tell that this was missing.
16
7
  */
17
- export declare const controlMultilineGhostClass = "ui-control-multiline w-full min-h-0 border-0 bg-transparent shadow-none placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 disabled:cursor-not-allowed disabled:opacity-50";
8
+ export declare const controlMultilineGhostClass = "ui-control-multiline w-full min-h-0 border-0 bg-transparent shadow-none placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0";
18
9
  /**
19
- * Open-state ring for popup-style triggers (Select / Cascader / TreeSelect / SearchSelect).
20
- * Radix moves focus INTO the popup on open, so the trigger loses `:focus-visible` and — without
21
- * this — an open popover shows only a border change (no ring), inconsistent with a focused Input.
22
- * Opacity `/50` matches the real focus ring used by Button / Input / Select. Apply alongside
23
- * `focus-visible:ring-*` on any trigger that toggles `data-state="open"`.
10
+ * Open-state ring for popup-style triggers (Select / Cascader / TreeSelect / SearchSelect). Radix
11
+ * moves focus INTO the popup on open, so the trigger loses `:focus-visible` and — without this —
12
+ * an open popover shows only a border change (no ring), inconsistent with a focused Input.
24
13
  */
25
- export declare const controlOpenRingClass = "data-[state=open]:border-ring data-[state=open]:ring-ring/50 data-[state=open]:ring-[3px]";
26
- export declare const controlTriggerClass = "ui-control flex w-full items-center justify-between gap-2 whitespace-nowrap rounded-[var(--control-radius)] border border-input bg-background shadow-sm transition-[color,box-shadow] focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 data-[state=open]:border-ring data-[state=open]:ring-ring/50 data-[state=open]:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1";
14
+ export declare const controlOpenRingClass = "ui-control-trigger";
15
+ export declare const controlTriggerClass = "ui-control ui-control-trigger flex items-center justify-between gap-2 whitespace-nowrap rounded-[var(--control-radius)] border-input bg-background transition-[color,box-shadow] focus-visible:outline-none [&>span]:line-clamp-1";
27
16
  export declare const controlIconClass = "size-[length:var(--control-height)] shrink-0";
28
17
  export declare const controlIconSmClass = "size-[calc(var(--control-height)-0.5rem)] shrink-0";
29
18
  /** Leading/affix icon inside an input row (search, command) — sized to `--control-icon-size`. */
@@ -1,8 +1,7 @@
1
- const controlFieldClass = "ui-control w-full rounded-[var(--control-radius)] border border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 disabled:cursor-not-allowed disabled:opacity-50";
2
- const controlMultilineClass = "ui-control-multiline w-full rounded-[var(--control-radius)] border border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 disabled:cursor-not-allowed disabled:opacity-50";
3
- const controlMultilineGhostClass = "ui-control-multiline w-full min-h-0 border-0 bg-transparent shadow-none placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 disabled:cursor-not-allowed disabled:opacity-50";
4
- const controlOpenRingClass = "data-[state=open]:border-ring data-[state=open]:ring-ring/50 data-[state=open]:ring-[3px]";
5
- const controlTriggerClass = "ui-control flex w-full items-center justify-between gap-2 whitespace-nowrap rounded-[var(--control-radius)] border border-input bg-background shadow-sm transition-[color,box-shadow] focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/25 data-[state=open]:border-ring data-[state=open]:ring-ring/50 data-[state=open]:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1";
1
+ const controlMultilineClass = "ui-control-multiline aria-invalid:border-destructive w-full rounded-[var(--control-radius)] border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none";
2
+ const controlMultilineGhostClass = "ui-control-multiline w-full min-h-0 border-0 bg-transparent shadow-none placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0";
3
+ const controlOpenRingClass = "ui-control-trigger";
4
+ const controlTriggerClass = "ui-control ui-control-trigger flex items-center justify-between gap-2 whitespace-nowrap rounded-[var(--control-radius)] border-input bg-background transition-[color,box-shadow] focus-visible:outline-none [&>span]:line-clamp-1";
6
5
  const controlIconClass = "size-[length:var(--control-height)] shrink-0";
7
6
  const controlIconSmClass = "size-[calc(var(--control-height)-0.5rem)] shrink-0";
8
7
  const controlIconLeadingClass = "size-[length:var(--control-icon-size)] shrink-0";
@@ -17,7 +16,6 @@ const toneDestructiveClass = "border-destructive/30 bg-destructive/10 text-error
17
16
  const toneMutedClass = "border-border bg-muted text-muted-foreground";
18
17
  const toneNeutralClass = "border-border bg-muted text-muted-foreground";
19
18
  export {
20
- controlFieldClass,
21
19
  controlIconClass,
22
20
  controlIconLeadingClass,
23
21
  controlIconSmClass,
@@ -1,10 +1,7 @@
1
1
  import { type FormatDatetimeOptions } from "./format.js";
2
2
  import { type FormatDateKind } from "./detect.js";
3
3
  export type FormatDateOptions = FormatDatetimeOptions & {
4
- /**
5
- * Output preset. Default `auto` detects ISO date / HH:mm / instant.
6
- * Locale, timezone, and 12h|24h fall back to AppProvider when omitted.
7
- */
4
+ /** Output preset. Default `auto` detects ISO date / HH:mm / instant. */
8
5
  kind?: FormatDateKind;
9
6
  /** Treat `Date` as calendar pick (react-day-picker) — not an instant. */
10
7
  calendar?: boolean;
@@ -3,16 +3,7 @@ import * as React from "react";
3
3
  * The accessible-name / description / validation contract that {@link FormField} injects onto its
4
4
  * single control child (via `cloneElement`). EVERY form-capable `@godxjp/ui` component accepts
5
5
  * these props and forwards them to its **semantic focus target** — the real `<input>` / combobox /
6
- * trigger the user tabs to, never a presentational wrapper `<div>`. Without this forwarding the
7
- * visible label / helper / error rendered by FormField is silently disconnected from the control
8
- * for assistive technology (issue #164).
9
- *
10
- * These are the standard WAI-ARIA field relationships:
11
- * - `aria-labelledby` — points at the FormField label → the control's accessible **name**.
12
- * - `aria-describedby` — points at helper text → the control's **description**.
13
- * - `aria-errormessage` + `aria-invalid` — the validation message, announced when invalid.
14
- * - `aria-required` — required-field semantics.
15
- * - `aria-label` — a name supplied directly (used when there is no visible label element).
6
+ * trigger the user tabs to, never a presentational wrapper `<div>`.
16
7
  */
17
8
  export interface FieldA11yProps {
18
9
  "aria-label"?: string;
@@ -21,6 +12,7 @@ export interface FieldA11yProps {
21
12
  "aria-errormessage"?: string;
22
13
  "aria-invalid"?: React.AriaAttributes["aria-invalid"];
23
14
  "aria-required"?: React.AriaAttributes["aria-required"];
15
+ "data-field"?: string;
24
16
  }
25
17
  /**
26
18
  * Merge one or more space-separated id-reference lists (`aria-describedby`, `aria-labelledby`,
@@ -32,18 +24,12 @@ export declare function mergeAriaIds(...values: Array<string | undefined>): stri
32
24
  * Extract ONLY the defined field-a11y attributes from a props bag, ready to spread onto a
33
25
  * component's semantic focus target. Undefined entries are dropped so a forwarded contract never
34
26
  * clobbers a control's own intrinsic `aria-label` / `aria-invalid`.
35
- *
36
- * ```tsx
37
- * const fieldA11y = pickFieldA11y(props);
38
- * return <input {...fieldA11y} />; // the real focus target owns the relationship
39
- * ```
40
27
  */
41
28
  export declare function pickFieldA11y(props: FieldA11yProps): FieldA11yProps;
42
29
  /**
43
30
  * The inverse of {@link pickFieldA11y}: everything EXCEPT the field-a11y attributes. Use it when a
44
31
  * component must route the contract somewhere other than the element the remaining props land on —
45
- * e.g. `Select`'s compound API, where the props bag belongs to `SelectPrimitive.Root` (a
46
- * context-only component that renders no DOM) while the accessible name has to reach the trigger.
32
+ * e.g.
47
33
  */
48
34
  export declare function omitFieldA11y<T extends FieldA11yProps>(props: T): Omit<T, keyof FieldA11yProps>;
49
35
  /**
@@ -54,19 +40,10 @@ export declare function omitFieldA11y<T extends FieldA11yProps>(props: T): Omit<
54
40
  */
55
41
  export declare function resolveFieldA11y(props: FieldA11yProps, intrinsicAriaLabel?: string): FieldA11yProps;
56
42
  /**
57
- * The FormField label made reachable by NESTED controls (gh#303).
58
- *
59
43
  * `cloneElement` can only wire the field-a11y contract onto FormField's single direct child. When
60
44
  * that child is a layout wrapper (a `Flex` holding a range from/to pair, a 年/月 input+select
61
45
  * combo), the naming attributes stop on the wrapper `div` and every control inside is left with no
62
46
  * accessible name at all (axe: `label` on the inputs, `button-name` on select/combobox triggers).
63
- *
64
- * FormField therefore also publishes its label through this context, and each control's semantic
65
- * focus target picks it up as a LAST-RESORT name via {@link useFieldNameFallback}: a control that
66
- * already has a name — its own `aria-label`/`aria-labelledby`, or the one FormField cloned onto it
67
- * as the direct child — keeps it untouched. Multiple nested controls then all announce the field's
68
- * label; a consumer wanting distinct names (e.g. "開始日" / "終了日") sets `aria-label` per
69
- * control, which always wins.
70
47
  */
71
48
  export interface FieldNameContextValue {
72
49
  /** DOM id of FormField's visible label element (the `aria-labelledby` target). */
@@ -81,21 +58,39 @@ export declare const FieldNameContext: React.Context<FieldNameContextValue | nul
81
58
  * inside a FormField AND still nameless after its own props and the cloned contract are applied.
82
59
  */
83
60
  export declare function useFieldNameFallback(name: Pick<FieldA11yProps, "aria-label" | "aria-labelledby">): Pick<FieldA11yProps, "aria-label" | "aria-labelledby">;
61
+ /**
62
+ * `cloneElement` reaches FormField's single DIRECT child only. In the real screens this library
63
+ * serves, 322 of 1,410 controls (23%) sit one level deeper — the direct child is a `Flex` holding
64
+ * a from/to pair, a 年/月 combo, or a value + 「不明」 checkbox — so the machine key stopped on the
65
+ * wrapper `div` and the controls inside stayed anonymous.
66
+ */
67
+ export interface FieldIdentityContextValue {
68
+ /** Whether the app opted into a native `name` (@see AppProviderProp.emitFieldNames). */
69
+ emitName: boolean;
70
+ }
71
+ export declare const FieldIdentityContext: React.Context<FieldIdentityContextValue | null>;
72
+ /**
73
+ * Resolve `data-field` / `name` for a control nested under a `FormField` (see {@link
74
+ * FieldIdentityContext}). Returns `{}` — adding nothing — in every case but the one it exists for,
75
+ * which is what keeps it safe to call from every control: - **outside a FormField** → `{}`.
76
+ */
77
+ export declare function useFieldIdentity(own: {
78
+ id?: string;
79
+ name?: string;
80
+ "data-field"?: string;
81
+ }): {
82
+ "data-field"?: string;
83
+ name?: string;
84
+ };
84
85
  /**
85
86
  * The field-a11y attributes valid on a **group container** (`role="group"`), used by composite
86
87
  * controls that have no single labelable focus target — CheckboxGroup, and the two-input range
87
- * pickers / Transfer shuttle.
88
- *
89
- * Per WAI-ARIA 1.2 only `aria-labelledby` and `aria-describedby` are globally allowed on
90
- * `role="group"`; `aria-invalid` / `aria-errormessage` / `aria-required` are widget-only and would
91
- * be an invalid-ARIA violation on a group. So the validation message id (`aria-errormessage`) is
92
- * **folded into `aria-describedby`** — the error text is still announced as part of the group's
93
- * description, and FormField's `role="alert"` error node announces it live regardless.
94
- *
95
- * `role="radiogroup"` IS a widget and supports the full validation set — those groups use
96
- * {@link pickFieldA11y} directly, not this helper.
88
+ * pickers / Transfer shuttle. Per WAI-ARIA 1.2 only `aria-labelledby` and `aria-describedby` are
89
+ * globally allowed on `role="group"`; `aria-invalid` / `aria-errormessage` / `aria-required` are
90
+ * widget-only and would be an invalid-ARIA violation on a group.
97
91
  */
98
92
  export declare function pickGroupFieldA11y(props: FieldA11yProps): {
99
93
  "aria-labelledby"?: string;
100
94
  "aria-describedby"?: string;
95
+ "data-field"?: string;
101
96
  };
@@ -6,7 +6,8 @@ const FIELD_A11Y_KEYS = [
6
6
  "aria-describedby",
7
7
  "aria-errormessage",
8
8
  "aria-invalid",
9
- "aria-required"
9
+ "aria-required",
10
+ "data-field"
10
11
  ];
11
12
  function mergeAriaIds(...values) {
12
13
  return Array.from(new Set(values.flatMap((value) => value?.split(/\s+/).filter(Boolean) ?? []))).join(
@@ -47,19 +48,32 @@ function useFieldNameFallback(name) {
47
48
  ...field.label !== void 0 ? { "aria-label": field.label } : {}
48
49
  };
49
50
  }
51
+ const FieldIdentityContext = React.createContext(null);
52
+ function useFieldIdentity(own) {
53
+ const ctx = React.useContext(FieldIdentityContext);
54
+ if (!ctx || own["data-field"] !== void 0 || own.id === void 0) return {};
55
+ return {
56
+ "data-field": own.id,
57
+ ...ctx.emitName && own.name === void 0 ? { name: own.id } : {}
58
+ };
59
+ }
50
60
  function pickGroupFieldA11y(props) {
51
61
  const describedBy = mergeAriaIds(props["aria-describedby"], props["aria-errormessage"]);
52
62
  return {
53
63
  ...props["aria-labelledby"] !== void 0 ? { "aria-labelledby": props["aria-labelledby"] } : {},
54
- ...describedBy !== void 0 ? { "aria-describedby": describedBy } : {}
64
+ ...describedBy !== void 0 ? { "aria-describedby": describedBy } : {},
65
+ // Not an ARIA attribute and so not subject to the role="group" restriction above — a group
66
+ ...props["data-field"] !== void 0 ? { "data-field": props["data-field"] } : {}
55
67
  };
56
68
  }
57
69
  export {
70
+ FieldIdentityContext,
58
71
  FieldNameContext,
59
72
  mergeAriaIds,
60
73
  omitFieldA11y,
61
74
  pickFieldA11y,
62
75
  pickGroupFieldA11y,
63
76
  resolveFieldA11y,
77
+ useFieldIdentity,
64
78
  useFieldNameFallback
65
79
  };
@@ -1,15 +1,11 @@
1
1
  /**
2
- * Bytes → size with conventional binary units (B/KB/MB/GB) and a locale-correct number,
3
- * e.g. "2.0 KB" (en) / "2,0 KB" (vi). The numeric part is formatted via `Intl.NumberFormat`
4
- * (locale decimal/grouping separators — no hardcoded "."); an optional `locale` overrides the
5
- * module-synced active locale.
2
+ * Bytes → size with conventional binary units (B/KB/MB/GB) and a locale-correct number, e.g. "2.0
3
+ * KB" (en) / "2,0 KB" (vi).
6
4
  */
7
5
  export declare function formatBytes(n: number | null | undefined, locale?: string): string;
8
6
  /**
9
- * ISO 4217 minor units → locale-formatted currency, e.g. (1995, "USD") → "$19.95" (en) /
10
- * "19,95 $" (vi). The active locale (or an explicit `locale`) drives grouping/symbol placement;
11
- * the currency's minor-unit scale comes from CLDR via `resolvedOptions().maximumFractionDigits`
12
- * — no hand-maintained zero-decimal list.
7
+ * ISO 4217 minor units → locale-formatted currency, e.g. (1995, "USD") → "$19.95" (en) / "19,95 $"
8
+ * (vi).
13
9
  */
14
10
  export declare function formatCurrency(amountMinor: number | null | undefined, currency: string, locale?: string): string;
15
11
  /** UUIDv7 / UUIDv4 → first 8 chars + ellipsis. Pair with a Tooltip showing full. */
@@ -12,18 +12,12 @@ export declare function useDebouncedValue<T>(value: T, delay?: number): T;
12
12
  */
13
13
  export declare function useTimeoutFlag(signal: unknown, ms?: number): boolean;
14
14
  /**
15
- * Controlled-ness latch for `value`/`defaultValue`/`onValueChange` controls
16
- * whose empty state is `undefined` (pickers carrying `Date`/`DateRange`).
17
- *
18
- * A control counts as controlled once a DEFINED `value` has EVER been passed:
19
- * - mounted with a defined `value`controlled, and a later `value={undefined}`
20
- * stays controlled-EMPTY (not mistaken for uncontrolled);
21
- * - mounted with `value={undefined}` (an empty form that later restores a
22
- * saved value) → uncontrolled until the first defined value arrives, then
23
- * PROMOTES to controlled for good.
24
- *
25
- * Fixing controlled-ness at mount (the previous behaviour) silently ignored
26
- * every later controlled value in the second case.
15
+ * Controlled-ness latch for `value`/`defaultValue`/`onValueChange` controls whose empty state is
16
+ * `undefined` (pickers carrying `Date`/`DateRange`). A control counts as controlled once a DEFINED
17
+ * `value` has EVER been passed: - mounted with a defined `value` → controlled, and a later
18
+ * `value={undefined}` stays controlled-EMPTY (not mistaken for uncontrolled); - mounted with
19
+ * `value={undefined}` (an empty form that later restores a saved value)uncontrolled until the
20
+ * first defined value arrives, then PROMOTES to controlled for good.
27
21
  */
28
22
  export declare function useControlledLatch(valueIsDefined: boolean): boolean;
29
23
  export declare function useMediaQuery(query: string): boolean;
@@ -1,22 +1,7 @@
1
1
  /**
2
- * permission-grid — pure, render-neutral helpers for RBAC role × permission
3
- * matrices.
4
- *
5
- * A permission matrix maps a set of PERMISSION rows against a set of ROLE
6
- * columns; each (role, permission) pair is either granted or not. A "permission
7
- * matrix" is NOT a framework component — it is a COMPOSITION of `Table`/
8
- * `DataTable` + `Badge` + tokens (see `docs/COMPOSITION-VS-COMPONENT.md`, Gate 0:
9
- * fails C2/C3/C7). What it DOES need is a single, tested source of truth for the
10
- * non-trivial data logic every consumer would otherwise re-derive: grant lookup,
11
- * the per-permission diff between two roles (compare mode), and the row set that
12
- * survives a "differences only" (差分のみ) filter.
13
- *
14
- * These functions are framework-neutral (no React) and locale-neutral (no
15
- * strings) so the showcase — and any RBAC admin — composes UI on top of them.
16
- *
17
- * Grants are modelled as a flat `Set` of composite keys for O(1) membership,
18
- * which mirrors how an authz decision cache (`role:permission` tuples) is
19
- * typically held in memory.
2
+ * permission-grid — pure, render-neutral helpers for RBAC role × permission matrices. A permission
3
+ * matrix maps a set of PERMISSION rows against a set of ROLE columns; each (role, permission) pair
4
+ * is either granted or not.
20
5
  */
21
6
  /** Any object addressable by a stable string `id` (a role or a permission). */
22
7
  export interface GridEntity {
@@ -8,9 +8,9 @@ export type QueryErrorInfo = {
8
8
  retryable: boolean;
9
9
  };
10
10
  /**
11
- * Classify a query/API error into a recovery-relevant category. Status codes win; message
12
- * keywords are the fallback for transport layers that only surface a string (e.g. an SDK that
13
- * throws `new Error("Access token invalid")` with no status). Never exposes the raw message.
11
+ * Classify a query/API error into a recovery-relevant category. Status codes win; message keywords
12
+ * are the fallback for transport layers that only surface a string (e.g. an SDK that throws `new
13
+ * Error("Access token invalid")` with no status).
14
14
  */
15
15
  export declare function classifyQueryError(error: unknown): QueryErrorInfo;
16
16
  /** `true` when repeating the same request can plausibly resolve the error. */
@@ -15,23 +15,20 @@ export type AppProviderProp = {
15
15
  defaultTimezone?: AppTimezoneDefault;
16
16
  /** Backend/system timezone when `defaultTimezone` is `system`. */
17
17
  systemTimezone?: AppTimezone;
18
- /** Initial clock format. `"locale"` derives from `defaultLocale`. Default: `"locale"`. */
18
+ /** Initial clock format. `"locale"` derives from `defaultLocale`. */
19
19
  defaultTimeFormat?: AppTimeFormat | "locale";
20
- /** Initial date display format. `"locale"` derives from `defaultLocale`. Default: `"locale"`. */
20
+ /** Initial date display format. `"locale"` derives from `defaultLocale`. */
21
21
  defaultDateFormat?: AppDateFormat | "locale";
22
22
  /**
23
- * IANA ids offered by the timezone-picker recipe (`useAppContext().timezoneOptions`).
24
- * Omit for the full IANA list; set to restrict (e.g. `APP_TIMEZONE_PRESET`).
23
+ * IANA ids offered by the timezone-picker recipe (`useAppContext().timezoneOptions`). Omit for
24
+ * the full IANA list; set to restrict (e.g.
25
25
  */
26
26
  timezoneOptions?: readonly AppTimezone[];
27
27
  /** localStorage key. Default: `godxjp.app`. */
28
28
  storageKey?: string;
29
29
  /** Persist user choices. Default: true. */
30
30
  persist?: boolean;
31
- /**
32
- * Initial light/dark theme — written to `<html data-theme>`. Default: `"light"`.
33
- * (The legacy `.dark` class still works as an equal alias.)
34
- */
31
+ /** Initial light/dark theme — written to `<html data-theme>`. Default: `"light"`. */
35
32
  theme?: AppTheme;
36
33
  /**
37
34
  * Initial brand palette preset — written to `<html data-brand>`. OPT-IN: omit
@@ -43,12 +40,16 @@ export type AppProviderProp = {
43
40
  /** Initial base type size — written to `<html data-font-size>`. Default: `"default"`. */
44
41
  fontSize?: AppFontSize;
45
42
  /**
46
- * Continuous global size multiplier — sets inline `--scaling` on `<html>`. Every
47
- * size token (spacing, control/table/checkbox/switch heights, radius) rescales in
48
- * proportion (Radix-style). `null` (default) defers to the `density` preset; a
49
- * number (e.g. `0.95`) overrides it. Type is a separate axis — not scaled.
43
+ * Continuous global size multiplier — sets inline `--scaling` on `<html>`. Every size token
44
+ * (spacing, control/table/checkbox/switch heights, radius) rescales in proportion (Radix-style).
50
45
  */
51
46
  scaling?: number | null;
47
+ /**
48
+ * Emit a native `name` on every control a `FormField` wraps, taken from the field's key (`field`
49
+ * → `name` → `id`). `data-field` is inert metadata and is always emitted; `name` is NOT — it
50
+ * changes what a native `<form>` submit sends.
51
+ */
52
+ emitFieldNames?: boolean;
52
53
  onLocaleChange?: (locale: AppLocale) => void;
53
54
  onTimezoneChange?: (timezone: AppTimezone) => void;
54
55
  onTimeFormatChange?: (timeFormat: AppTimeFormat) => void;
@@ -70,24 +71,13 @@ export type AppSettingPickerProp = {
70
71
  kind: AppSettingKind;
71
72
  /**
72
73
  * Trigger presentation. `"labeled"` shows the leading icon + the selected value in a control
73
- * sized to the setting. `"icon"` renders a supported square, icon-only topbar trigger (e.g. a
74
- * globe language switcher): it structurally drops the value text and the picker's owned width —
75
- * no descendant-selector CSS overrides needed — while always keeping the localized `aria-label`,
76
- * so an icon-only trigger can never ship without an accessible name. `"inline"` renders the
77
- * selected value as a compact text trigger for legal/auth footers without a field-like box.
78
- *
79
- * Default is kind-dependent: `kind="locale"` defaults to `"icon"` (its product contract is the
80
- * compact language switcher); every other kind defaults to `"labeled"`. Override explicitly for
81
- * e.g. a labeled locale row inside a settings form (`appearance="labeled"`).
74
+ * sized to the setting.
82
75
  */
83
76
  appearance?: AppSettingPickerAppearanceProp;
84
77
  /**
85
- * Compact presentation (gh#217) re-tiers the trigger box to `--control-height-sm` and drops the
86
- * picker's owned per-kind width so a LABELLED trigger hugs its value. Use it for an auth/legal
87
- * footer locale switch (`kind="locale" appearance="labeled" compact`), where the square icon-only
88
- * default reads as a stray button and the full labelled trigger is too tall. All geometry is
89
- * tokenized (`--app-setting-picker-compact-*`). No effect on `appearance="inline"`, which is
90
- * already chrome-less. Default `false`.
78
+ * Use it for an auth/legal footer locale switch (`kind="locale" appearance="labeled" compact`),
79
+ * where the square icon-only default reads as a stray button and the full labelled trigger is
80
+ * too tall. All geometry is tokenized (`--app-setting-picker-compact-*`).
91
81
  */
92
82
  compact?: boolean;
93
83
  className?: ClassNameProp;
@@ -117,6 +107,8 @@ export type AppContextValue = {
117
107
  density: AppDensity;
118
108
  fontSize: AppFontSize;
119
109
  scaling: number | null;
110
+ /** Default `false`. */
111
+ emitFieldNames: boolean;
120
112
  setLocale: (locale: AppLocale) => void;
121
113
  setTimezone: (timezone: AppTimezone) => void;
122
114
  setTimeFormat: (timeFormat: AppTimeFormat) => void;