@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
@@ -0,0 +1,105 @@
1
+ import { useState } from "react";
2
+
3
+ import { Field, FormField, Input, Select, Switch, Textarea } from "@godxjp/ui/data-entry";
4
+ import { Button } from "@godxjp/ui/general";
5
+ import { Avatar, AvatarFallback } from "@godxjp/ui/data-display";
6
+ import {
7
+ AppShell,
8
+ Flex,
9
+ PageContainer,
10
+ Sidebar,
11
+ type SidebarSectionProp,
12
+ Topbar,
13
+ } from "@godxjp/ui/layout";
14
+ import { BookOpen, FileText, LayoutDashboard, ReceiptText, Users } from "lucide-react";
15
+
16
+ /**
17
+ * Create form — a real screen: FormField wraps each stacked control (Input /
18
+ * Select / Textarea), Field pairs the Switch with its label, and the page's
19
+ * footer holds the primary submit + outline cancel. The canonical data-entry
20
+ * page, composed only from real @godxjp/ui components.
21
+ */
22
+ const sections: SidebarSectionProp[] = [
23
+ {
24
+ label: "会計",
25
+ items: [
26
+ { id: "dashboard", label: "ダッシュボード", icon: LayoutDashboard },
27
+ { id: "journal", label: "仕訳", icon: FileText },
28
+ { id: "invoices", label: "請求書", icon: ReceiptText },
29
+ { id: "partners", label: "取引先", icon: BookOpen },
30
+ ],
31
+ },
32
+ { label: "管理", items: [{ id: "users", label: "ユーザー", icon: Users }] },
33
+ ];
34
+
35
+ export default function Demo() {
36
+ const [type, setType] = useState("corp");
37
+
38
+ return (
39
+ <AppShell
40
+ sidebar={
41
+ <Sidebar
42
+ activeId="partners"
43
+ sections={sections}
44
+ onSelect={() => {}}
45
+ product={{ name: "CoreBooks", role: "管理コンソール", color: "hsl(var(--primary))" }}
46
+ />
47
+ }
48
+ topbar={
49
+ <Topbar
50
+ start={
51
+ <Avatar className="rounded-md">
52
+ <AvatarFallback className="bg-primary text-primary-foreground font-bold">
53
+ C
54
+ </AvatarFallback>
55
+ </Avatar>
56
+ }
57
+ />
58
+ }
59
+ >
60
+ <PageContainer
61
+ title="取引先を作成"
62
+ breadcrumb={[{ label: "取引先", to: "#" }, { label: "新規" }]}
63
+ footer={
64
+ <Flex direction="row" wrap gap="sm" justify="end">
65
+ <Button variant="outline" type="button">
66
+ キャンセル
67
+ </Button>
68
+ <Button type="submit">作成</Button>
69
+ </Flex>
70
+ }
71
+ >
72
+ <Flex direction="col" gap="md" className="max-w-2xl">
73
+ <FormField id="cf-name" label="取引先名" required helper="最大50文字">
74
+ <Input id="cf-name" placeholder="株式会社ベトヤ" />
75
+ </FormField>
76
+ <FormField id="cf-code" label="取引先コード" required helper="一意のコードを入力">
77
+ <Input id="cf-code" placeholder="BTY-0012" />
78
+ </FormField>
79
+ <FormField id="cf-type" label="区分">
80
+ <Select
81
+ id="cf-type"
82
+ name="type"
83
+ value={type}
84
+ onValueChange={setType}
85
+ options={[
86
+ { value: "corp", label: "法人" },
87
+ { value: "indiv", label: "個人事業主" },
88
+ ]}
89
+ />
90
+ </FormField>
91
+ <FormField id="cf-memo" label="メモ" helper="任意">
92
+ <Textarea id="cf-memo" placeholder="例: 4月分から取引開始" />
93
+ </FormField>
94
+ <Field
95
+ id="cf-active"
96
+ label="取引を有効にする"
97
+ description="無効にすると新規取引を登録できません"
98
+ >
99
+ <Switch id="cf-active" defaultChecked />
100
+ </Field>
101
+ </Flex>
102
+ </PageContainer>
103
+ </AppShell>
104
+ );
105
+ }
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Overview
3
+ ---
4
+
5
+ The labelled-field wrapper for every stacked control — it renders the label, a required
6
+ asterisk, a helper hint or a role="alert" error, and wires `aria-describedby` /
7
+ `aria-invalid` onto the single child control. Use `Field` instead for a checkbox/switch
8
+ beside its label. See Examples for a full create form.
@@ -0,0 +1,326 @@
1
+ import { useState } from "react";
2
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display";
3
+ import { Checkbox, Form, FormField, Input, Select } from "@godxjp/ui/data-entry";
4
+ import {
5
+ Dialog,
6
+ DialogBody,
7
+ DialogContent,
8
+ DialogHeader,
9
+ DialogTitle,
10
+ Sheet,
11
+ SheetContent,
12
+ SheetHeader,
13
+ SheetTitle,
14
+ } from "@godxjp/ui/feedback";
15
+ import { Button } from "@godxjp/ui/general";
16
+ import { Flex, PageContainer } from "@godxjp/ui/layout";
17
+
18
+ /**
19
+ * FormField — wraps one control with a label, helper, and error, and wires
20
+ * aria-describedby / aria-invalid onto the child. Use it for every stacked
21
+ * labelled control (Input/Textarea/Select/DatePicker…); use Field for a
22
+ * checkbox/switch beside its label. Composed only from real @godxjp/ui components.
23
+ */
24
+ export default function Demo() {
25
+ const [dialogOpen, setDialogOpen] = useState(false);
26
+ const [sheetOpen, setSheetOpen] = useState(false);
27
+ return (
28
+ <PageContainer
29
+ title="FormField"
30
+ subtitle="Label · helper · required · error · a11y wired for the control"
31
+ >
32
+ <Flex direction="col" gap="lg">
33
+ <Card>
34
+ <CardHeader>
35
+ <CardTitle level={2}>States</CardTitle>
36
+ <CardDescription>
37
+ required adds a red asterisk; helper is a muted hint; error (role=alert) overrides it.
38
+ </CardDescription>
39
+ </CardHeader>
40
+ <CardContent>
41
+ <Flex direction="col" gap="md">
42
+ <FormField id="ff-name" label="取引先名" required helper="最大50文字">
43
+ <Input id="ff-name" placeholder="株式会社..." />
44
+ </FormField>
45
+ <FormField
46
+ id="ff-email"
47
+ label="メール"
48
+ error="メールアドレスの形式が正しくありません"
49
+ >
50
+ <Input id="ff-email" type="email" defaultValue="invalid@" />
51
+ </FormField>
52
+ <FormField id="ff-status" label="状態" helper="未選択の場合は下書きになります">
53
+ <Select
54
+ id="ff-status"
55
+ name="status"
56
+ value="paid"
57
+ onValueChange={() => {}}
58
+ options={[
59
+ { value: "draft", label: "下書き" },
60
+ { value: "paid", label: "入金済" },
61
+ ]}
62
+ />
63
+ </FormField>
64
+ <FormField
65
+ id="ff-required-status"
66
+ label="承認状態"
67
+ required
68
+ helper="承認ワークフローで使用します"
69
+ error="承認状態を選択してください"
70
+ >
71
+ <Select
72
+ id="ff-required-status"
73
+ name="approval_status"
74
+ value=""
75
+ onValueChange={() => {}}
76
+ placeholder="状態を選択"
77
+ options={[
78
+ { value: "pending", label: "承認待ち" },
79
+ { value: "approved", label: "承認済み" },
80
+ ]}
81
+ />
82
+ </FormField>
83
+ </Flex>
84
+ </CardContent>
85
+ </Card>
86
+
87
+ <Card>
88
+ <CardHeader>
89
+ <CardTitle level={2}>Complete field contract</CardTitle>
90
+ <CardDescription>
91
+ Auto id, label addon, every layout, per-field widths, className and grid span are
92
+ rendered explicitly.
93
+ </CardDescription>
94
+ </CardHeader>
95
+ <CardContent>
96
+ <Form columns={2}>
97
+ <FormField
98
+ label="自動ID"
99
+ helper="id を省略すると control に生成IDを注入"
100
+ labelAddon={<Button aria-label="自動IDの説明">?</Button>}
101
+ className="contract-auto-id"
102
+ >
103
+ <Input defaultValue="自動関連付け" />
104
+ </FormField>
105
+ <FormField
106
+ id="contract-horizontal"
107
+ label="Horizontal"
108
+ layout="horizontal"
109
+ labelWidth="8rem"
110
+ controlWidth="16rem"
111
+ required={false}
112
+ >
113
+ <Input defaultValue="有効" />
114
+ </FormField>
115
+ <FormField id="contract-vertical" label="Vertical" layout="vertical" required>
116
+ <Input aria-invalid defaultValue="不正な値" />
117
+ </FormField>
118
+ <FormField
119
+ id="contract-inline"
120
+ label="Inline"
121
+ layout="inline"
122
+ error="入力内容を確認してください"
123
+ colSpan={2}
124
+ >
125
+ <Input defaultValue="invalid@example" />
126
+ </FormField>
127
+ </Form>
128
+ </CardContent>
129
+ </Card>
130
+
131
+ <Card>
132
+ <CardHeader>
133
+ <CardTitle level={2}>Field identity · data-field (gh#337)</CardTitle>
134
+ <CardDescription>
135
+ 項目キーを control の data-field に出す。既定は id から導出。id が DOM
136
+ 一意化のためのもので項目キーと違う場合だけ field を明示する。AppProvider
137
+ emitFieldNames を立てたアプリでは同じキーが name にも出る。
138
+ </CardDescription>
139
+ </CardHeader>
140
+ <CardContent>
141
+ <Form columns={2}>
142
+ <FormField id="project_name" label="案件名" helper="data-field は id から導出">
143
+ <Input defaultValue="ABC商事 更新案件" />
144
+ </FormField>
145
+ <FormField
146
+ id="source_slip_field"
147
+ field="source_slip_id"
148
+ label="ソース伝票番号"
149
+ helper="id は枠の一意化用。項目キーは field で明示"
150
+ >
151
+ <Input defaultValue="2024-00871" />
152
+ </FormField>
153
+ <FormField
154
+ id="fax_field"
155
+ label="FAX"
156
+ helper="ラッパー越しでも各控えが自分の id で名乗る"
157
+ >
158
+ <Flex gap="sm" align="center">
159
+ <Input id="fax" defaultValue="03-1234-5678" />
160
+ <Checkbox id="fax_unknown" aria-label="不明" />
161
+ </Flex>
162
+ </FormField>
163
+ <FormField id="branch_cd" label="拠点" helper="trigger は data-value に選択コード">
164
+ <Select
165
+ options={[
166
+ { value: "52", label: "東京本社" },
167
+ { value: "53", label: "大阪支社" },
168
+ ]}
169
+ value="52"
170
+ onValueChange={() => undefined}
171
+ />
172
+ </FormField>
173
+ </Form>
174
+ </CardContent>
175
+ </Card>
176
+
177
+ <Card>
178
+ <CardHeader>
179
+ <CardTitle level={2}>Static value · mixed with editable fields (gh#294)</CardTitle>
180
+ <CardDescription>
181
+ staticText renders a read-only VALUE as a FormField itself: Descriptions.Item's exact
182
+ value typography, no control, no id/aria-* wiring. An immutable name/email row and an
183
+ editable role Select then share the same Form context · label column · labelAlign ·
184
+ row-to-row gap, with nothing to reconcile by hand.
185
+ </CardDescription>
186
+ </CardHeader>
187
+ <CardContent>
188
+ <Form layout="horizontal" labelWidth="8rem" controlWidth="20rem">
189
+ <FormField label="名前" staticText="山田 太郎" />
190
+ <FormField label="メールアドレス" staticText="yamada@example.jp" />
191
+ <FormField id="static-role" label="ロール" required>
192
+ <Select
193
+ id="static-role"
194
+ name="role"
195
+ value="member"
196
+ onValueChange={() => {}}
197
+ options={[
198
+ { value: "member", label: "Member" },
199
+ { value: "admin", label: "Admin" },
200
+ ]}
201
+ />
202
+ </FormField>
203
+ </Form>
204
+ </CardContent>
205
+ </Card>
206
+
207
+ <Card>
208
+ <CardHeader>
209
+ <CardTitle level={2}>
210
+ Layout matrix · widths / breakpoints / long locale / RTL
211
+ </CardTitle>
212
+ <CardDescription>
213
+ horizontal は md 未満で vertical に collapse。field 単位の width override と 320px
214
+ 相当の長文を同時確認する。
215
+ </CardDescription>
216
+ </CardHeader>
217
+ <CardContent>
218
+ <div className="max-w-3xl">
219
+ <Form layout="horizontal" labelWidth="12rem" controlWidth="28rem">
220
+ <FormField
221
+ id="matrix-ja"
222
+ label="請求書の送付先メールアドレス"
223
+ required
224
+ helper="確認メールを送信します"
225
+ >
226
+ <Input id="matrix-ja" defaultValue="billing@example.jp" />
227
+ </FormField>
228
+ <FormField
229
+ id="matrix-vi"
230
+ label="Địa chỉ email nhận hóa đơn và thông báo"
231
+ controlWidth="20rem"
232
+ >
233
+ <Input id="matrix-vi" defaultValue="ketoan@example.vn" />
234
+ </FormField>
235
+ </Form>
236
+ </div>
237
+ <div className="mt-6 max-w-80 border p-3" dir="rtl" lang="ar">
238
+ <FormField
239
+ id="matrix-rtl"
240
+ label="البريد الإلكتروني لاستلام الفاتورة"
241
+ helper="سيتم إرسال رسالة تأكيد"
242
+ >
243
+ <Input id="matrix-rtl" type="email" placeholder="name@example.com" />
244
+ </FormField>
245
+ </div>
246
+ </CardContent>
247
+ </Card>
248
+
249
+ <Card>
250
+ <CardHeader>
251
+ <CardTitle level={2}>State contract · supported and untested gaps</CardTitle>
252
+ <CardDescription>
253
+ FormField supports helper, required and error. warning, pending, touched/submitted
254
+ timing, server-error mapping and form-summary focus are not FormField props; those
255
+ remain UNTESTED and belong to the form controller/application flow.
256
+ </CardDescription>
257
+ </CardHeader>
258
+ <CardContent>
259
+ <Flex direction="col" gap="md">
260
+ <FormField id="state-readonly" label="作成者" helper="システム管理項目">
261
+ <Input id="state-readonly" readOnly defaultValue="山田 太郎" />
262
+ </FormField>
263
+ <FormField id="state-disabled" label="契約番号">
264
+ <Input id="state-disabled" disabled defaultValue="CTR-2026-0042" />
265
+ </FormField>
266
+ <FormField
267
+ id="state-server"
268
+ label="組織名"
269
+ error="保存できませんでした。しばらくしてから再試行してください。"
270
+ >
271
+ <Input id="state-server" defaultValue="株式会社アクメ" />
272
+ </FormField>
273
+ </Flex>
274
+ </CardContent>
275
+ </Card>
276
+
277
+ <Card>
278
+ <CardHeader>
279
+ <CardTitle level={2}>Composition · Dialog / Sheet</CardTitle>
280
+ <CardDescription>同じ bounded form を overlay 内で確認する。</CardDescription>
281
+ </CardHeader>
282
+ <CardContent>
283
+ <Flex gap="sm" wrap>
284
+ <Button onClick={() => setDialogOpen(true)}>Dialog form</Button>
285
+ <Button variant="outline" onClick={() => setSheetOpen(true)}>
286
+ Sheet form
287
+ </Button>
288
+ </Flex>
289
+ <Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
290
+ <DialogContent className="max-w-lg">
291
+ <DialogHeader>
292
+ <DialogTitle>取引先を追加</DialogTitle>
293
+ </DialogHeader>
294
+ <DialogBody>
295
+ <Form>
296
+ <FormField id="dialog-name" label="取引先名" required>
297
+ <Input id="dialog-name" />
298
+ </FormField>
299
+ <FormField id="dialog-email" label="メール" helper="任意">
300
+ <Input id="dialog-email" type="email" />
301
+ </FormField>
302
+ </Form>
303
+ </DialogBody>
304
+ </DialogContent>
305
+ </Dialog>
306
+ <Sheet open={sheetOpen} onOpenChange={setSheetOpen}>
307
+ <SheetContent>
308
+ <SheetHeader>
309
+ <SheetTitle>請求先設定</SheetTitle>
310
+ </SheetHeader>
311
+ <Form className="mt-4">
312
+ <FormField id="sheet-name" label="宛名" required>
313
+ <Input id="sheet-name" />
314
+ </FormField>
315
+ <FormField id="sheet-note" label="備考">
316
+ <Input id="sheet-note" />
317
+ </FormField>
318
+ </Form>
319
+ </SheetContent>
320
+ </Sheet>
321
+ </CardContent>
322
+ </Card>
323
+ </Flex>
324
+ </PageContainer>
325
+ );
326
+ }
@@ -0,0 +1,80 @@
1
+ import { useState } from "react";
2
+ import { Input } from "@godxjp/ui/data-entry";
3
+ import { Button } from "@godxjp/ui/general";
4
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display";
5
+ import { PageContainer } from "@godxjp/ui/layout";
6
+ import { FormFieldControl, FormRoot, useFormSubmitting } from "@godxjp/ui/form";
7
+ import { inertiaAdapter } from "@godxjp/ui/inertia";
8
+
9
+ // Stand-in for Inertia's useForm() — the real hook from @inertiajs/react has this exact shape, so a
10
+ // page passes it straight to inertiaAdapter (the library never imports @inertiajs). Here a tiny local
11
+ // mock drives the demo: server-style state + errors + processing, no react-hook-form.
12
+ function useMockInertiaForm(initial: Record<string, string>) {
13
+ const [data, setData] = useState(initial);
14
+ const [errors, setErrors] = useState<Record<string, string>>({});
15
+ const [processing, setProcessing] = useState(false);
16
+ return {
17
+ data,
18
+ errors,
19
+ processing,
20
+ setData: (key: string, value: unknown) => {
21
+ setData((d) => ({ ...d, [key]: String(value) }));
22
+ setErrors((e) => ({ ...e, [key]: "" })); // clear the field error on edit (Inertia behaviour)
23
+ },
24
+ post: () => {
25
+ setProcessing(true);
26
+ window.setTimeout(() => {
27
+ setProcessing(false);
28
+ // Simulate a Laravel FormRequest validation error landing in form.errors.
29
+ setErrors({ email: "このメールアドレスは登録されていません。" });
30
+ }, 600);
31
+ },
32
+ };
33
+ }
34
+
35
+ // The submit button reads processing via useFormSubmitting() — app code, not a library component.
36
+ function SubmitButton() {
37
+ return (
38
+ <Button type="submit" loading={useFormSubmitting()}>
39
+ サインイン
40
+ </Button>
41
+ );
42
+ }
43
+
44
+ /**
45
+ * FormRoot with an Inertia adapter — server-driven form binding. inertiaAdapter(form) lets Inertia's
46
+ * useForm drive FormFieldControl with the SAME auto-binding as the react-hook-form path: no manual
47
+ * value/onChange/error/aria-invalid per field; server errors surface on the right field and clear on
48
+ * edit; processing flows to the submit button via useFormSubmitting(). Composed of real @godxjp/ui.
49
+ */
50
+ export default function Demo() {
51
+ const form = useMockInertiaForm({ email: "", password: "" });
52
+
53
+ return (
54
+ <PageContainer
55
+ title="FormRoot with Inertia"
56
+ subtitle="Server-driven form binding via inertiaAdapter · no per-field wiring"
57
+ >
58
+ <Card className="max-w-xl">
59
+ <CardHeader>
60
+ <CardTitle level={2}>サインイン</CardTitle>
61
+ <CardDescription>
62
+ Inertia の useForm を inertiaAdapter でラップし、FormRoot に渡すだけ。value / onChange /
63
+ error / aria は name から自動でバインドされる。
64
+ </CardDescription>
65
+ </CardHeader>
66
+ <CardContent>
67
+ <FormRoot adapter={inertiaAdapter(form)} onSubmit={() => form.post()}>
68
+ <FormFieldControl name="email" label="メールアドレス" required>
69
+ {(field) => <Input {...field} type="email" value={String(field.value ?? "")} />}
70
+ </FormFieldControl>
71
+ <FormFieldControl name="password" label="パスワード" required>
72
+ {(field) => <Input {...field} type="password" value={String(field.value ?? "")} />}
73
+ </FormFieldControl>
74
+ <SubmitButton />
75
+ </FormRoot>
76
+ </CardContent>
77
+ </Card>
78
+ </PageContainer>
79
+ );
80
+ }
@@ -0,0 +1,102 @@
1
+ import { useState } from "react";
2
+ import { z } from "zod";
3
+ import { Alert, AlertDescription } from "@godxjp/ui/feedback";
4
+ import { Input } from "@godxjp/ui/data-entry";
5
+ import { Button } from "@godxjp/ui/general";
6
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display";
7
+ import { Flex, PageContainer } from "@godxjp/ui/layout";
8
+ import { FormFieldControl, FormRoot, useZodForm } from "@godxjp/ui/form";
9
+
10
+ const schema = z.object({
11
+ name: z.string().min(1, "組織名を入力してください"),
12
+ email: z.string().email("有効なメールアドレスを入力してください"),
13
+ });
14
+
15
+ export default function Demo() {
16
+ const [status, setStatus] = useState<"idle" | "pending" | "success" | "server-error">("idle");
17
+ const form = useZodForm(schema, {
18
+ defaultValues: { name: "株式会社アクメ", email: "billing@example.jp" },
19
+ });
20
+
21
+ async function submit() {
22
+ setStatus("pending");
23
+ await new Promise((resolve) => window.setTimeout(resolve, 500));
24
+ setStatus("success");
25
+ }
26
+
27
+ return (
28
+ <PageContainer
29
+ title="FormRoot"
30
+ subtitle="Zod + React Hook Form · validation timing / reset / pending / summary"
31
+ >
32
+ <Card className="max-w-2xl">
33
+ <CardHeader>
34
+ <CardTitle level={2}>送付先設定</CardTitle>
35
+ <CardDescription>
36
+ Submit 後に field error を表示し、最初の invalid field へ focus。reset は defaultValues
37
+ を復元する。server error summary は application が管理する。
38
+ </CardDescription>
39
+ </CardHeader>
40
+ <CardContent>
41
+ <FormRoot form={form} onSubmit={submit}>
42
+ {status === "server-error" && (
43
+ <Alert tone="destructive">
44
+ <AlertDescription>
45
+ 保存できませんでした。接続を確認して再試行してください。
46
+ </AlertDescription>
47
+ </Alert>
48
+ )}
49
+ {status === "success" && (
50
+ <Alert tone="success">
51
+ <AlertDescription>保存しました。</AlertDescription>
52
+ </Alert>
53
+ )}
54
+ <FormFieldControl name="name" label="組織名" required helper="請求書に表示します">
55
+ {(field) => (
56
+ <Input
57
+ {...field}
58
+ disabled={status === "pending"}
59
+ value={String(field.value ?? "")}
60
+ />
61
+ )}
62
+ </FormFieldControl>
63
+ <FormFieldControl name="email" label="送付先メール" required>
64
+ {(field) => (
65
+ <Input
66
+ {...field}
67
+ type="email"
68
+ disabled={status === "pending"}
69
+ value={String(field.value ?? "")}
70
+ />
71
+ )}
72
+ </FormFieldControl>
73
+ <Flex gap="sm" wrap>
74
+ <Button type="submit" loading={status === "pending"}>
75
+ 保存
76
+ </Button>
77
+ <Button
78
+ type="button"
79
+ variant="outline"
80
+ disabled={status === "pending"}
81
+ onClick={() => {
82
+ form.reset();
83
+ setStatus("idle");
84
+ }}
85
+ >
86
+ リセット
87
+ </Button>
88
+ <Button type="button" variant="ghost" onClick={() => setStatus("server-error")}>
89
+ Server error を表示
90
+ </Button>
91
+ </Flex>
92
+ </FormRoot>
93
+ </CardContent>
94
+ </Card>
95
+ <p className="text-muted-foreground mt-4 text-sm">
96
+ warning state、form-level error-summary から field への focus link、touched-only timing は
97
+ public wrapper API では未提供。React Hook Form の設定または consumer composition として
98
+ UNTESTED。
99
+ </p>
100
+ </PageContainer>
101
+ );
102
+ }