themelia-react-ui 2.0.3 → 2.0.5

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 (648) hide show
  1. package/CHANGELOG.md +185 -0
  2. package/README.md +168 -36
  3. package/dist/{accordion-Cjb6sx0G.js → accordion-B9MHG0cT.js} +11 -11
  4. package/dist/accordion-B9MHG0cT.js.map +1 -0
  5. package/dist/action-menu-Dr8K-ghE.js +284 -0
  6. package/dist/action-menu-Dr8K-ghE.js.map +1 -0
  7. package/dist/{affordance-geometry.generated-tF36bREk.js → affordance-geometry.generated-P-aVJisu.js} +42 -36
  8. package/dist/affordance-geometry.generated-P-aVJisu.js.map +1 -0
  9. package/dist/{ai-artifact-DvTwDVyL.js → ai-artifact-C58tQcBy.js} +387 -350
  10. package/dist/ai-artifact-C58tQcBy.js.map +1 -0
  11. package/dist/app-shell-B_IuNWOo.js +321 -0
  12. package/dist/app-shell-B_IuNWOo.js.map +1 -0
  13. package/dist/{attachment-BxDfL2mw.js → attachment-Dg_69lPS.js} +9 -9
  14. package/dist/{attachment-BxDfL2mw.js.map → attachment-Dg_69lPS.js.map} +1 -1
  15. package/dist/{auth-BGua8ouh.js → auth-DTkkshS8.js} +44 -47
  16. package/dist/auth-DTkkshS8.js.map +1 -0
  17. package/dist/{avatar-DAPlDvhJ.js → avatar-CeZaFmNH.js} +8 -8
  18. package/dist/avatar-CeZaFmNH.js.map +1 -0
  19. package/dist/{badge-HpFqoqSY.js → badge-xIiV_E7f.js} +5 -5
  20. package/dist/{badge-HpFqoqSY.js.map → badge-xIiV_E7f.js.map} +1 -1
  21. package/dist/base/accordion.js +1 -1
  22. package/dist/base/action-menu.js +1 -1
  23. package/dist/base/attachment.js +1 -1
  24. package/dist/base/avatar.js +1 -1
  25. package/dist/base/badge.js +1 -1
  26. package/dist/base/batch-action-bar.js +1 -1
  27. package/dist/base/buttons.js +1 -1
  28. package/dist/base/cards.js +2 -2
  29. package/dist/base/carousel.js +3 -3
  30. package/dist/base/cascader.js +2 -372
  31. package/dist/base/chart.js +1 -1
  32. package/dist/base/choice-inputs.js +2 -2
  33. package/dist/base/code-block.js +1 -1
  34. package/dist/base/combobox.js +2 -2
  35. package/dist/base/command.js +1 -1
  36. package/dist/base/copyable.js +1 -1
  37. package/dist/base/date-pickers.js +2 -2
  38. package/dist/base/display.js +6 -6
  39. package/dist/base/feedback.js +3 -3
  40. package/dist/base/forms-numeric.js +1 -1
  41. package/dist/base/forms.js +3 -3
  42. package/dist/base/inline-edit.js +10 -10
  43. package/dist/base/item.js +1 -1
  44. package/dist/base/media-gallery.js +1 -1
  45. package/dist/base/metadata-list.js +1 -1
  46. package/dist/base/navigation.js +7 -7
  47. package/dist/base/popover-menu.js +1 -1
  48. package/dist/base/popover.js +1 -1
  49. package/dist/base/qr-code.js +1 -1
  50. package/dist/base/repeaters.js +12 -12
  51. package/dist/base/repeaters.js.map +1 -1
  52. package/dist/base/sheet.js +1 -1
  53. package/dist/base/sidebar.js +2 -2
  54. package/dist/base/signature-pad.js +7 -7
  55. package/dist/base/signature-pad.js.map +1 -1
  56. package/dist/base/skeleton.js +1 -1
  57. package/dist/base/spinner.js +4 -4
  58. package/dist/base/structure.js +1 -1
  59. package/dist/base/table.js +1 -1
  60. package/dist/base/text-inputs.js +2 -2
  61. package/dist/base/toaster.js +36 -36
  62. package/dist/base/toaster.js.map +1 -1
  63. package/dist/base/tree.js +1 -1
  64. package/dist/base/upload-queue.js +1 -1
  65. package/dist/base/upload.js +3 -3
  66. package/dist/base/value-inputs.js +1 -1
  67. package/dist/{batch-action-bar-DnUJ21NQ.js → batch-action-bar-Cb8cuvyy.js} +6 -6
  68. package/dist/batch-action-bar-Cb8cuvyy.js.map +1 -0
  69. package/dist/blocks/admin.js +23 -23
  70. package/dist/blocks/admin.js.map +1 -1
  71. package/dist/blocks/ai.js +230 -216
  72. package/dist/blocks/ai.js.map +1 -1
  73. package/dist/blocks/analytics/usage-card.js +1 -1
  74. package/dist/blocks/analytics.js +326 -307
  75. package/dist/blocks/analytics.js.map +1 -1
  76. package/dist/blocks/collaboration.js +1 -1
  77. package/dist/blocks/commerce/receipt.js +1 -1
  78. package/dist/blocks/commerce.js +1247 -1169
  79. package/dist/blocks/commerce.js.map +1 -1
  80. package/dist/blocks/data-display.js +2 -2
  81. package/dist/blocks/onboarding.js +6 -6
  82. package/dist/blocks/onboarding.js.map +1 -1
  83. package/dist/blocks/planning.js +11 -11
  84. package/dist/blocks/timelines.js +1 -1
  85. package/dist/{breadcrumbs-C-oqs1sQ.js → breadcrumbs-J-K2kl4c.js} +6 -6
  86. package/dist/{breadcrumbs-C-oqs1sQ.js.map → breadcrumbs-J-K2kl4c.js.map} +1 -1
  87. package/dist/{button-DVzspB_G.js → button-S2Cubiiz.js} +3 -3
  88. package/dist/button-S2Cubiiz.js.map +1 -0
  89. package/dist/{buttons-DPZekJFu.js → buttons-BedGfygC.js} +16 -16
  90. package/dist/buttons-BedGfygC.js.map +1 -0
  91. package/dist/cards-rNX1M4Xn.js +69 -0
  92. package/dist/cards-rNX1M4Xn.js.map +1 -0
  93. package/dist/cascader-B1MiqkBq.js +439 -0
  94. package/dist/cascader-B1MiqkBq.js.map +1 -0
  95. package/dist/chart-Darg_0Kv.js +162 -0
  96. package/dist/chart-Darg_0Kv.js.map +1 -0
  97. package/dist/{checkbox-AWIhNhmo.js → checkbox-fflqmODR.js} +9 -5
  98. package/dist/checkbox-fflqmODR.js.map +1 -0
  99. package/dist/choice-inputs-zUgBZfE4.js +777 -0
  100. package/dist/choice-inputs-zUgBZfE4.js.map +1 -0
  101. package/dist/{code-block-DeneBJR_.js → code-block-BzmM9Eig.js} +9 -9
  102. package/dist/code-block-BzmM9Eig.js.map +1 -0
  103. package/dist/{collapsible-C-_l4hpy.js → collapsible-BkAI_XD4.js} +5 -5
  104. package/dist/{collapsible-C-_l4hpy.js.map → collapsible-BkAI_XD4.js.map} +1 -1
  105. package/dist/{collection-content-By56pLog.js → collection-content-gDh1v6O4.js} +3 -3
  106. package/dist/{collection-content-By56pLog.js.map → collection-content-gDh1v6O4.js.map} +1 -1
  107. package/dist/combobox-BEx0vJgF.js +362 -0
  108. package/dist/combobox-BEx0vJgF.js.map +1 -0
  109. package/dist/{combobox-Dxo2fAYQ.js → combobox-BwzoXFSG.js} +254 -247
  110. package/dist/combobox-BwzoXFSG.js.map +1 -0
  111. package/dist/{command-C25VMRII.js → command-CrlPIL6m.js} +12 -12
  112. package/dist/command-CrlPIL6m.js.map +1 -0
  113. package/dist/{comments-DD0DUPwJ.js → comments-Dmpp0YIc.js} +380 -379
  114. package/dist/comments-Dmpp0YIc.js.map +1 -0
  115. package/dist/components/base/action-menu/action-menu.d.ts +9 -1
  116. package/dist/components/base/buttons/button-group.recipes.d.ts +2 -2
  117. package/dist/components/base/cards/card.recipes.d.ts +16 -7
  118. package/dist/components/base/cards/partials/card-primitives.d.ts +9 -2
  119. package/dist/components/base/cards/partials/smart-card-header-row.d.ts +3 -1
  120. package/dist/components/base/cards/smart-card.types.d.ts +11 -7
  121. package/dist/components/base/cascader/cascader-panel.d.ts +76 -0
  122. package/dist/components/base/chart/chart.d.ts +6 -1
  123. package/dist/components/base/choice-inputs/checkbox.d.ts +7 -2
  124. package/dist/components/base/choice-inputs/choice-types.d.ts +1 -1
  125. package/dist/components/base/choice-inputs/switch-card.d.ts +7 -0
  126. package/dist/components/base/choice-inputs/toggle-field.d.ts +7 -0
  127. package/dist/components/base/combobox/index.d.ts +4 -2
  128. package/dist/components/base/date-pickers/datepicker.types.d.ts +7 -0
  129. package/dist/components/base/feedback/alert.d.ts +1 -1
  130. package/dist/components/base/forms/controlled-form-field.d.ts +6 -6
  131. package/dist/components/base/forms/form-field.d.ts +5 -3
  132. package/dist/components/base/forms/form-sizing.d.ts +7 -7
  133. package/dist/components/base/forms/index.d.ts +1 -0
  134. package/dist/components/base/forms/server-errors.d.ts +16 -0
  135. package/dist/components/base/forms/workflow.d.ts +11 -2
  136. package/dist/components/base/forms-numeric/coordinates-input.d.ts +4 -0
  137. package/dist/components/base/metadata-list/metadata-list.d.ts +3 -1
  138. package/dist/components/base/navigation/dropdown-menu.d.ts +1 -1
  139. package/dist/components/base/navigation/page-header/page-header-commands.d.ts +14 -7
  140. package/dist/components/base/navigation/page-header/page-header.d.ts +13 -4
  141. package/dist/components/base/popover/popover.d.ts +3 -3
  142. package/dist/components/base/popover/popover.recipes.d.ts +10 -6
  143. package/dist/components/base/sheet/sheet.d.ts +2 -0
  144. package/dist/components/base/sidebar/index.d.ts +1 -1
  145. package/dist/components/base/sidebar/sidebar.d.ts +27 -5
  146. package/dist/components/base/structure/composition.recipes.d.ts +17 -0
  147. package/dist/components/base/text-inputs/hooks/use-form-field-state.d.ts +7 -2
  148. package/dist/components/base/text-inputs/input.d.ts +4 -2
  149. package/dist/components/base/text-inputs/textarea.d.ts +4 -2
  150. package/dist/components/base/toaster/index.d.ts +1 -0
  151. package/dist/components/base/value-inputs/date-time-input.d.ts +2 -1
  152. package/dist/components/base/value-inputs/slider.d.ts +5 -1
  153. package/dist/components/base/value-inputs/tags-input.d.ts +5 -1
  154. package/dist/components/blocks/ai/ai-file-tree/types.d.ts +1 -1
  155. package/dist/components/blocks/ai/ai-tool-call/types.d.ts +3 -1
  156. package/dist/components/blocks/ai/ai.strings.d.ts +2 -0
  157. package/dist/components/blocks/analytics/metric-comparison/metric-comparison.d.ts +2 -0
  158. package/dist/components/blocks/analytics/usage-card/usage-card.strings.d.ts +2 -0
  159. package/dist/components/blocks/commerce/cart-summary/cart-summary.d.ts +1 -1
  160. package/dist/components/blocks/commerce/cart-summary/types.d.ts +3 -1
  161. package/dist/components/blocks/commerce/discount-stack/discount-stack.d.ts +1 -1
  162. package/dist/components/blocks/commerce/discount-stack/types.d.ts +3 -1
  163. package/dist/components/blocks/commerce/fulfillment-group/fulfillment-group.d.ts +1 -1
  164. package/dist/components/blocks/commerce/fulfillment-group/types.d.ts +11 -2
  165. package/dist/components/blocks/commerce/index.d.ts +7 -6
  166. package/dist/components/blocks/commerce/inventory-section/inventory-section.d.ts +1 -1
  167. package/dist/components/blocks/commerce/inventory-section/types.d.ts +7 -2
  168. package/dist/components/blocks/commerce/invoice-header/index.d.ts +2 -1
  169. package/dist/components/blocks/commerce/invoice-header/invoice-header.d.ts +1 -1
  170. package/dist/components/blocks/commerce/invoice-header/types.d.ts +20 -6
  171. package/dist/components/blocks/commerce/invoice-line-items/invoice-line-items.d.ts +1 -1
  172. package/dist/components/blocks/commerce/invoice-line-items/types.d.ts +24 -7
  173. package/dist/components/blocks/commerce/invoice-mini/index.d.ts +2 -1
  174. package/dist/components/blocks/commerce/invoice-mini/types.d.ts +7 -1
  175. package/dist/components/blocks/commerce/order-customer/order-customer.d.ts +1 -1
  176. package/dist/components/blocks/commerce/order-customer/types.d.ts +9 -1
  177. package/dist/components/blocks/commerce/refund-status/refund-status.d.ts +1 -1
  178. package/dist/components/blocks/commerce/refund-status/types.d.ts +3 -1
  179. package/dist/components/blocks/commerce/shipment-tracking/shipment-tracking.d.ts +1 -1
  180. package/dist/components/blocks/commerce/shipment-tracking/types.d.ts +3 -1
  181. package/dist/components/blocks/commerce/tax-breakdown/tax-breakdown.d.ts +1 -1
  182. package/dist/components/blocks/commerce/tax-breakdown/types.d.ts +3 -1
  183. package/dist/components/features/activities/activities.types.d.ts +8 -2
  184. package/dist/components/features/activities/partials/activity-marker.d.ts +7 -3
  185. package/dist/components/features/activities/partials/activity-row.d.ts +24 -0
  186. package/dist/components/features/event-calendar/colors.d.ts +2 -2
  187. package/dist/components/features/event-calendar/event-calendar.types.d.ts +4 -0
  188. package/dist/components/features/filters/facets/select-facet.d.ts +2 -1
  189. package/dist/components/features/filters/filters.strings.d.ts +4 -0
  190. package/dist/components/features/filters/filters.types.d.ts +3 -0
  191. package/dist/components/features/filters/partials/filter-editor-header.d.ts +16 -0
  192. package/dist/components/features/filters/partials/filter-popover-content.d.ts +1 -1
  193. package/dist/components/features/filters/partials/nested-filter-options.d.ts +21 -0
  194. package/dist/components/features/filters/partials/regular-filter-content.d.ts +2 -1
  195. package/dist/components/features/filters/utils/filter-utils.d.ts +21 -3
  196. package/dist/components/features/global-search/global-search.types.d.ts +2 -0
  197. package/dist/components/features/global-search/partials/global-search-input.d.ts +10 -0
  198. package/dist/components/features/global-search/partials/global-search-result-row.d.ts +7 -1
  199. package/dist/components/features/media-library/media-library.strings.d.ts +2 -0
  200. package/dist/components/features/media-library/media-library.types.d.ts +14 -4
  201. package/dist/components/features/media-library/partials/media-library-partials.d.ts +1 -1
  202. package/dist/components/features/products/components/product-options-matrix.d.ts +1 -1
  203. package/dist/components/features/products/components/product-variant-editor.d.ts +1 -1
  204. package/dist/components/features/products/components/product-variants-manager.d.ts +1 -1
  205. package/dist/components/features/products/products.strings.d.ts +9 -1
  206. package/dist/components/features/products/products.types.d.ts +43 -6
  207. package/dist/components/features/resource/resource.d.ts +5 -1
  208. package/dist/components/features/resource/resource.types.d.ts +12 -1
  209. package/dist/components/features/rich-text-editor/partials/image-uploads.d.ts +1 -1
  210. package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +12 -2
  211. package/dist/components/features/table/partials/resource-cell.d.ts +22 -5
  212. package/dist/components/features/table/table.types.d.ts +1 -1
  213. package/dist/components/layout/app-shell/app-shell.types.d.ts +35 -6
  214. package/dist/components/layout/app-shell/index.d.ts +1 -1
  215. package/dist/components/layout/app-shell/shell-regions.d.ts +27 -0
  216. package/dist/components/layout/app-shell/sidebar-inset-layout.d.ts +1 -1
  217. package/dist/components/layout/app-shell/stacked-layout.d.ts +1 -1
  218. package/dist/components/layout/app-shell/topbar-sidebar-layout.d.ts +1 -1
  219. package/dist/components/layout/containers/two-column-layout.d.ts +2 -0
  220. package/dist/components/layout/header/header.recipes.d.ts +6 -0
  221. package/dist/components/layout/header/header.types.d.ts +6 -6
  222. package/dist/components/layout/navigation/section-nav/section-nav.d.ts +5 -0
  223. package/dist/components/layout/page/index.d.ts +2 -1
  224. package/dist/components/layout/page/page.d.ts +1 -0
  225. package/dist/components/layout/page/page.strings.d.ts +11 -0
  226. package/dist/components/layout/page/page.types.d.ts +69 -17
  227. package/dist/components/layout/page/partials/page-header.d.ts +1 -1
  228. package/dist/components/layout/settings/settings.d.ts +9 -2
  229. package/dist/components/layout/sidebar/app-sidebar.d.ts +1 -1
  230. package/dist/components/layout/sidebar/components/sidebar-grouped-navigation.d.ts +1 -1
  231. package/dist/components/layout/sidebar/components/sidebar-navigation.d.ts +1 -1
  232. package/dist/components/layout/sidebar/index.d.ts +2 -1
  233. package/dist/components/layout/sidebar/sidebar-navigation-rail.d.ts +36 -0
  234. package/dist/components/layout/sidebar/sidebar.context.d.ts +5 -7
  235. package/dist/components/layout/sidebar/sidebar.types.d.ts +48 -10
  236. package/dist/components/layout/sidebar/sidebar.utils.d.ts +9 -1
  237. package/dist/components/layout/workspace/workspace.types.d.ts +8 -1
  238. package/dist/components/typography/text.styles.d.ts +26 -1
  239. package/dist/components/ui/alert-dialog.d.ts +2 -2
  240. package/dist/components/ui/combobox.d.ts +1 -1
  241. package/dist/components/ui/dialog.d.ts +2 -2
  242. package/dist/components/ui/overlay-layer.d.ts +18 -0
  243. package/dist/components/ui/sheet.d.ts +5 -1
  244. package/dist/components/ui/sidebar-state.d.ts +82 -0
  245. package/dist/components/ui/sidebar.d.ts +5 -17
  246. package/dist/composition.recipes-COdiFhxB.js +19 -0
  247. package/dist/composition.recipes-COdiFhxB.js.map +1 -0
  248. package/dist/containers-CIxwbZt5.js +112 -0
  249. package/dist/containers-CIxwbZt5.js.map +1 -0
  250. package/dist/{control-group-recipes-DBXmfh2E.js → control-group-recipes-fMuFo0H7.js} +6 -6
  251. package/dist/control-group-recipes-fMuFo0H7.js.map +1 -0
  252. package/dist/{copyable-ClBuk_UK.js → copyable-DIznBqiT.js} +7 -7
  253. package/dist/{copyable-ClBuk_UK.js.map → copyable-DIznBqiT.js.map} +1 -1
  254. package/dist/{data-display-DT_khPl_.js → data-display-BdgCAw8T.js} +277 -285
  255. package/dist/data-display-BdgCAw8T.js.map +1 -0
  256. package/dist/{date-DCrsDTZc.js → date-Cq8ioE4o.js} +5 -5
  257. package/dist/{date-DCrsDTZc.js.map → date-Cq8ioE4o.js.map} +1 -1
  258. package/dist/{date-picker-B2K3ucWn.js → date-picker-RlIzKom_.js} +501 -480
  259. package/dist/date-picker-RlIzKom_.js.map +1 -0
  260. package/dist/date-pickers-DY-CpXS1.js +179 -0
  261. package/dist/date-pickers-DY-CpXS1.js.map +1 -0
  262. package/dist/{display-hAc1HjpI.js → display-KsZLw9Ov.js} +9 -9
  263. package/dist/{display-hAc1HjpI.js.map → display-KsZLw9Ov.js.map} +1 -1
  264. package/dist/dropdown-menu-CLs8Lihj.js +194 -0
  265. package/dist/dropdown-menu-CLs8Lihj.js.map +1 -0
  266. package/dist/features/activities.js +302 -253
  267. package/dist/features/activities.js.map +1 -1
  268. package/dist/features/ai-chat.js +15 -14
  269. package/dist/features/ai-chat.js.map +1 -1
  270. package/dist/features/appointment-calendar.js +222 -220
  271. package/dist/features/appointment-calendar.js.map +1 -1
  272. package/dist/features/async-preview.js +11 -10
  273. package/dist/features/async-preview.js.map +1 -1
  274. package/dist/features/combobox.js +1 -1
  275. package/dist/features/comments.js +1 -1
  276. package/dist/features/data-view.js +13 -13
  277. package/dist/features/data-view.js.map +1 -1
  278. package/dist/features/email-composer.js +249 -249
  279. package/dist/features/email-composer.js.map +1 -1
  280. package/dist/features/event-calendar.js +264 -269
  281. package/dist/features/event-calendar.js.map +1 -1
  282. package/dist/features/filters.js +1 -1
  283. package/dist/features/global-search.js +167 -138
  284. package/dist/features/global-search.js.map +1 -1
  285. package/dist/features/kanban.js +6 -7
  286. package/dist/features/kanban.js.map +1 -1
  287. package/dist/features/map.js +269 -260
  288. package/dist/features/map.js.map +1 -1
  289. package/dist/features/media-library.js +827 -777
  290. package/dist/features/media-library.js.map +1 -1
  291. package/dist/features/mentions.js +1 -1
  292. package/dist/features/overlays.js +1 -1
  293. package/dist/features/products.js +1246 -1169
  294. package/dist/features/products.js.map +1 -1
  295. package/dist/features/questionnaire.js +13 -13
  296. package/dist/features/questionnaire.js.map +1 -1
  297. package/dist/features/resource-assignment.js +8 -8
  298. package/dist/features/resource.js +127 -123
  299. package/dist/features/resource.js.map +1 -1
  300. package/dist/features/rich-text-editor.js +2 -2
  301. package/dist/features/schema-form.js +254 -253
  302. package/dist/features/schema-form.js.map +1 -1
  303. package/dist/features/suggestions.js +3 -3
  304. package/dist/features/sync.js +3 -3
  305. package/dist/features/table.js +1 -1
  306. package/dist/features/theme-tweaker.js +95 -96
  307. package/dist/features/theme-tweaker.js.map +1 -1
  308. package/dist/{feedback-BYIhtitP.js → feedback-Dm4izqFn.js} +81 -80
  309. package/dist/feedback-Dm4izqFn.js.map +1 -0
  310. package/dist/{field-affordance-recipes-DZhnIL_Y.js → field-affordance-recipes-DWcNcOjh.js} +4 -4
  311. package/dist/field-affordance-recipes-DWcNcOjh.js.map +1 -0
  312. package/dist/{filters-DJVAveHA.js → filters-DzgSJpMK.js} +693 -645
  313. package/dist/filters-DzgSJpMK.js.map +1 -0
  314. package/dist/{form-field-CwH9y77i.js → form-field-BriWAXyg.js} +14 -8
  315. package/dist/form-field-BriWAXyg.js.map +1 -0
  316. package/dist/{form-sizing-BdP_Mf5p.js → form-sizing-Bs2qFUeE.js} +4 -4
  317. package/dist/form-sizing-Bs2qFUeE.js.map +1 -0
  318. package/dist/forms-C0RGnJTe.js +216 -0
  319. package/dist/forms-C0RGnJTe.js.map +1 -0
  320. package/dist/{forms-numeric-B_jraJaQ.js → forms-numeric-DIhghX1Q.js} +295 -291
  321. package/dist/forms-numeric-DIhghX1Q.js.map +1 -0
  322. package/dist/{header-BSfIEWbI.js → header-DMMxG__r.js} +67 -63
  323. package/dist/header-DMMxG__r.js.map +1 -0
  324. package/dist/header.recipes-BigdJjw1.js +6 -0
  325. package/dist/header.recipes-BigdJjw1.js.map +1 -0
  326. package/dist/hooks/useFormErrors.d.ts +1 -1
  327. package/dist/{hooks-ClH9thn4.js → hooks-DB6CJ4MR.js} +26 -14
  328. package/dist/hooks-DB6CJ4MR.js.map +1 -0
  329. package/dist/{icon-badge-DYKIwvOV.js → icon-badge-DZF-YjQp.js} +4 -4
  330. package/dist/{icon-badge-DYKIwvOV.js.map → icon-badge-DZF-YjQp.js.map} +1 -1
  331. package/dist/index.js +4 -5
  332. package/dist/input-CvyDQlY7.js +289 -0
  333. package/dist/input-CvyDQlY7.js.map +1 -0
  334. package/dist/input-DMBwAZmr.js +21 -0
  335. package/dist/input-DMBwAZmr.js.map +1 -0
  336. package/dist/item-DjCcM18E.js +277 -0
  337. package/dist/item-DjCcM18E.js.map +1 -0
  338. package/dist/layout/app-shell.js +1 -1
  339. package/dist/layout/auth.js +1 -1
  340. package/dist/layout/containers.js +1 -1
  341. package/dist/layout/header.js +1 -1
  342. package/dist/layout/hooks.js +1 -1
  343. package/dist/layout/navigation.js +1 -1
  344. package/dist/layout/page.js +2 -2
  345. package/dist/layout/settings.js +1 -1
  346. package/dist/layout/sidebar.js +3 -3
  347. package/dist/layout/workspace.js +1 -1
  348. package/dist/layout.js +11 -11
  349. package/dist/lib/affordance-geometry.generated.d.ts +41 -35
  350. package/dist/lib/control-group-recipes.d.ts +5 -5
  351. package/dist/lib/field-affordance-recipes.d.ts +2 -2
  352. package/dist/lib/motion-recipes.d.ts +3 -0
  353. package/dist/lib/navigation-row-recipes.d.ts +7 -7
  354. package/dist/lib/overlay-anatomy-recipes.d.ts +3 -3
  355. package/dist/lib/portal-recipes.d.ts +3 -0
  356. package/dist/lib/token-merge.generated.d.ts +13 -10
  357. package/dist/lib/ui-provider/types.d.ts +1 -1
  358. package/dist/lib/utils.js +1 -1
  359. package/dist/map-demo-tile.svg +1 -1
  360. package/dist/{media-gallery-3zIVLMWH.js → media-gallery-C-vChPmE.js} +6 -6
  361. package/dist/{media-gallery-3zIVLMWH.js.map → media-gallery-C-vChPmE.js.map} +1 -1
  362. package/dist/{mentions-CGlEJ15c.js → mentions-0_4nWuI-.js} +10 -10
  363. package/dist/{mentions-CGlEJ15c.js.map → mentions-0_4nWuI-.js.map} +1 -1
  364. package/dist/{message-DZ_ruyUV.js → message-g8p7eVtN.js} +7 -7
  365. package/dist/message-g8p7eVtN.js.map +1 -0
  366. package/dist/metadata-list-C3MkU-Om.js +443 -0
  367. package/dist/metadata-list-C3MkU-Om.js.map +1 -0
  368. package/dist/{motion-recipes-ChBg4HBq.js → motion-recipes-DitYv6P2.js} +10 -2
  369. package/dist/motion-recipes-DitYv6P2.js.map +1 -0
  370. package/dist/navigation-C90-oQFq.js +255 -0
  371. package/dist/navigation-C90-oQFq.js.map +1 -0
  372. package/dist/{navigation-BzhHI3lo.js → navigation-DaRjthVk.js} +101 -82
  373. package/dist/navigation-DaRjthVk.js.map +1 -0
  374. package/dist/{navigation-row-recipes-BFLCk_Aq.js → navigation-row-recipes-BGVLvU_O.js} +9 -9
  375. package/dist/navigation-row-recipes-BGVLvU_O.js.map +1 -0
  376. package/dist/{number-DbV1Dija.js → number-CRU3kGuk.js} +5 -5
  377. package/dist/{number-DbV1Dija.js.map → number-CRU3kGuk.js.map} +1 -1
  378. package/dist/overflow-tab-bar-IVFVQFV6.js +172 -0
  379. package/dist/overflow-tab-bar-IVFVQFV6.js.map +1 -0
  380. package/dist/overlays-BSgCtM2v.js +1013 -0
  381. package/dist/overlays-BSgCtM2v.js.map +1 -0
  382. package/dist/page-DUUKDAjo.js +331 -0
  383. package/dist/page-DUUKDAjo.js.map +1 -0
  384. package/dist/page-header-commands-7P3sfE9u.js +193 -0
  385. package/dist/page-header-commands-7P3sfE9u.js.map +1 -0
  386. package/dist/{pagination-BL25hu2s.js → pagination-CgCjElfu.js} +7 -7
  387. package/dist/{pagination-BL25hu2s.js.map → pagination-CgCjElfu.js.map} +1 -1
  388. package/dist/popover-B85RenIl.js +201 -0
  389. package/dist/popover-B85RenIl.js.map +1 -0
  390. package/dist/{popover-menu-Cn9rUkdc.js → popover-menu-DlnQ2zlR.js} +7 -7
  391. package/dist/{popover-menu-Cn9rUkdc.js.map → popover-menu-DlnQ2zlR.js.map} +1 -1
  392. package/dist/{popover.recipes-D3j8R8Yp.js → popover.recipes-DdiEp0rd.js} +18 -11
  393. package/dist/popover.recipes-DdiEp0rd.js.map +1 -0
  394. package/dist/portal-recipes-BpsV_iRw.js +9 -0
  395. package/dist/portal-recipes-BpsV_iRw.js.map +1 -0
  396. package/dist/{primitives-BFK08r9M.js → primitives-ByWgGUgt.js} +6 -6
  397. package/dist/{primitives-BFK08r9M.js.map → primitives-ByWgGUgt.js.map} +1 -1
  398. package/dist/primitives.js +4 -4
  399. package/dist/{progress-B1VnCT0K.js → progress-BJhQP9WX.js} +9 -9
  400. package/dist/{progress-B1VnCT0K.js.map → progress-BJhQP9WX.js.map} +1 -1
  401. package/dist/{receipt-BVSOH3Xo.js → receipt-tOc7B3hw.js} +7 -7
  402. package/dist/receipt-tOc7B3hw.js.map +1 -0
  403. package/dist/{rich-text-GOUyKQ-s.js → rich-text-Dth5E882.js} +4 -4
  404. package/dist/{rich-text-GOUyKQ-s.js.map → rich-text-Dth5E882.js.map} +1 -1
  405. package/dist/{rich-text-editor-cRLC-eBK.js → rich-text-editor-C1fOjBTd.js} +429 -430
  406. package/dist/rich-text-editor-C1fOjBTd.js.map +1 -0
  407. package/dist/{rich-text-editor-toolbar-DfXg0-VC.js → rich-text-editor-toolbar-laT3tpBT.js} +33 -29
  408. package/dist/rich-text-editor-toolbar-laT3tpBT.js.map +1 -0
  409. package/dist/{scroll-area-DcI-M1UT.js → scroll-area-B0dB2cBi.js} +2 -2
  410. package/dist/{scroll-area-DcI-M1UT.js.map → scroll-area-B0dB2cBi.js.map} +1 -1
  411. package/dist/{separator-Bom7NsGO.js → separator-Bb17I4pu.js} +2 -2
  412. package/dist/{separator-Bom7NsGO.js.map → separator-Bb17I4pu.js.map} +1 -1
  413. package/dist/{separator-BDV-Y648.js → separator-Ct_WSWTJ.js} +3 -3
  414. package/dist/{separator-BDV-Y648.js.map → separator-Ct_WSWTJ.js.map} +1 -1
  415. package/dist/services/actions.js +1 -1
  416. package/dist/settings-Bar5wiSo.js +167 -0
  417. package/dist/settings-Bar5wiSo.js.map +1 -0
  418. package/dist/sheet-BGPERY55.js +250 -0
  419. package/dist/sheet-BGPERY55.js.map +1 -0
  420. package/dist/sidebar-D-JYMMbY.js +686 -0
  421. package/dist/sidebar-D-JYMMbY.js.map +1 -0
  422. package/dist/sidebar-f9gRWXIR.js +1001 -0
  423. package/dist/sidebar-f9gRWXIR.js.map +1 -0
  424. package/dist/skeleton-BapcJd9C.js +265 -0
  425. package/dist/skeleton-BapcJd9C.js.map +1 -0
  426. package/dist/smart-card-CW0hjetE.js +617 -0
  427. package/dist/smart-card-CW0hjetE.js.map +1 -0
  428. package/dist/{structure-BmisBK-3.js → structure-DuxKl954.js} +3 -3
  429. package/dist/{structure-BmisBK-3.js.map → structure-DuxKl954.js.map} +1 -1
  430. package/dist/{structure.recipes-EPz60cU8.js → structure.recipes-BB4-n58V.js} +2 -2
  431. package/dist/{structure.recipes-EPz60cU8.js.map → structure.recipes-BB4-n58V.js.map} +1 -1
  432. package/dist/style.css +1 -1
  433. package/dist/{table-DsfzoUia.js → table-B4TE7iOV.js} +3 -3
  434. package/dist/{table-DsfzoUia.js.map → table-B4TE7iOV.js.map} +1 -1
  435. package/dist/{table-BweFy_P9.js → table-CFOWY9pQ.js} +394 -388
  436. package/dist/table-CFOWY9pQ.js.map +1 -0
  437. package/dist/{tabs-CDocW5D1.js → tabs-e7ko9S2o.js} +11 -11
  438. package/dist/tabs-e7ko9S2o.js.map +1 -0
  439. package/dist/{text-inputs-f9Ia-aCi.js → text-inputs-B1culiSK.js} +107 -104
  440. package/dist/text-inputs-B1culiSK.js.map +1 -0
  441. package/dist/{text.styles-g4He6UIW.js → text.styles-B64My8RZ.js} +25 -10
  442. package/dist/text.styles-B64My8RZ.js.map +1 -0
  443. package/dist/theme.css +192 -149
  444. package/dist/{timelines-CwM_9IhD.js → timelines-D3Sl9ueq.js} +13 -12
  445. package/dist/timelines-D3Sl9ueq.js.map +1 -0
  446. package/dist/tooltip-8wz5S_Zr.js +113 -0
  447. package/dist/tooltip-8wz5S_Zr.js.map +1 -0
  448. package/dist/{tree-WnKQzwbq.js → tree-CzUJHnFs.js} +9 -9
  449. package/dist/{tree-WnKQzwbq.js.map → tree-CzUJHnFs.js.map} +1 -1
  450. package/dist/typography/rich-text.js +1 -1
  451. package/dist/typography-BQnine1k.js +117 -0
  452. package/dist/typography-BQnine1k.js.map +1 -0
  453. package/dist/typography.js +1 -1
  454. package/dist/ui-provider-C-74NVLc.js +178 -0
  455. package/dist/ui-provider-C-74NVLc.js.map +1 -0
  456. package/dist/ui-provider.js +2 -3
  457. package/dist/{upload-CXyxmQBP.js → upload-BOW6U2tI.js} +25 -24
  458. package/dist/upload-BOW6U2tI.js.map +1 -0
  459. package/dist/{upload-queue-Boscubn9.js → upload-queue-qUXn1ykN.js} +16 -14
  460. package/dist/upload-queue-qUXn1ykN.js.map +1 -0
  461. package/dist/{usage-card-BhO5eqkX.js → usage-card-BeSLY0i0.js} +145 -137
  462. package/dist/usage-card-BeSLY0i0.js.map +1 -0
  463. package/dist/{utils-BRhFDwuU.js → utils-B6kKb8jB.js} +303 -144
  464. package/dist/utils-B6kKb8jB.js.map +1 -0
  465. package/dist/value-inputs-skdVB2zh.js +980 -0
  466. package/dist/value-inputs-skdVB2zh.js.map +1 -0
  467. package/dist/{value-typography-BP8OG6h5.js → value-typography-uAmWUAL1.js} +2 -2
  468. package/dist/{value-typography-BP8OG6h5.js.map → value-typography-uAmWUAL1.js.map} +1 -1
  469. package/dist/workspace-DHeHv0qw.js +411 -0
  470. package/dist/workspace-DHeHv0qw.js.map +1 -0
  471. package/docs/consumer-skill/SKILL.md +15 -129
  472. package/docs/consumer-skill/agents/themelia-ui-designer.md +96 -0
  473. package/docs/consumer-skill/examples/app-layout.tsx +74 -13
  474. package/docs/consumer-skill/examples/authentication.tsx +77 -0
  475. package/docs/consumer-skill/examples/commerce-lines.tsx +271 -0
  476. package/docs/consumer-skill/examples/custom-composition.tsx +21 -0
  477. package/docs/consumer-skill/examples/detail.tsx +5 -4
  478. package/docs/consumer-skill/examples/edit.tsx +30 -38
  479. package/docs/consumer-skill/examples/editable-sections.tsx +38 -0
  480. package/docs/consumer-skill/examples/index-table.tsx +4 -4
  481. package/docs/consumer-skill/examples/manifest.json +88 -1
  482. package/docs/consumer-skill/examples/product-media.tsx +41 -0
  483. package/docs/consumer-skill/examples/product-parts.tsx +81 -0
  484. package/docs/consumer-skill/examples/rhf-bindings.tsx +86 -0
  485. package/docs/consumer-skill/examples/rhf-edit-page.tsx +141 -0
  486. package/docs/consumer-skill/examples/rhf-overlay-form.tsx +105 -0
  487. package/docs/consumer-skill/examples/rhf-transport.tsx +28 -0
  488. package/docs/consumer-skill/examples/token-domain-structure.tsx +68 -0
  489. package/docs/consumer-skill/references/agents-md.md +23 -11
  490. package/docs/consumer-skill/references/analytics.md +18 -1
  491. package/docs/consumer-skill/references/authentication.md +42 -0
  492. package/docs/consumer-skill/references/commerce-composition.md +97 -0
  493. package/docs/consumer-skill/references/component-contracts.json +325201 -0
  494. package/docs/consumer-skill/references/composition-mapping.md +106 -0
  495. package/docs/consumer-skill/references/composition.md +198 -46
  496. package/docs/consumer-skill/references/critique-rubric.md +98 -0
  497. package/docs/consumer-skill/references/custom-composition.md +261 -0
  498. package/docs/consumer-skill/references/data-reading.md +79 -0
  499. package/docs/consumer-skill/references/design-contract.md +43 -9
  500. package/docs/consumer-skill/references/discovery.md +109 -8
  501. package/docs/consumer-skill/references/domain-structures.md +124 -0
  502. package/docs/consumer-skill/references/installation.md +51 -36
  503. package/docs/consumer-skill/references/integration.md +41 -2
  504. package/docs/consumer-skill/references/product-composition.md +94 -0
  505. package/docs/consumer-skill/references/public-api.json +4390 -475
  506. package/docs/consumer-skill/references/review.md +47 -5
  507. package/docs/consumer-skill/references/rhf-workflows.md +93 -0
  508. package/docs/consumer-skill/references/screen-archetypes.md +34 -0
  509. package/docs/consumer-skill/references/screen-decisions.md +126 -0
  510. package/docs/consumer-skill/references/theming.md +25 -27
  511. package/docs/consumer-skill/references/tokens.json +20 -11
  512. package/docs/consumer-skill/references/view-craft.md +153 -0
  513. package/docs/consumer-skill/references/view-spec.md +73 -0
  514. package/docs/consumer-skill/references/workflows.md +9 -2
  515. package/docs/consumer-skill/scripts/composition-policy.mjs +39 -3
  516. package/docs/consumer-skill/scripts/composition-schema.d.mts +2 -0
  517. package/docs/consumer-skill/scripts/composition-schema.mjs +32 -0
  518. package/docs/consumer-skill/scripts/composition.mjs +254 -0
  519. package/docs/consumer-skill/scripts/discovery.mjs +96 -10
  520. package/docs/consumer-skill/scripts/inspect-component.mjs +11 -0
  521. package/docs/consumer-skill/scripts/inspect-tokens.mjs +11 -0
  522. package/docs/consumer-skill/scripts/inspection.mjs +193 -0
  523. package/docs/consumer-skill/scripts/map-composition.mjs +12 -0
  524. package/docs/consumer-skill/scripts/setup-skills.mjs +111 -0
  525. package/docs/consumer-skill/scripts/surface-policy.mjs +5 -5
  526. package/docs/consumer-skills/themelia-components/SKILL.md +31 -0
  527. package/docs/consumer-skills/themelia-composition/SKILL.md +34 -0
  528. package/docs/consumer-skills/themelia-design/SKILL.md +55 -0
  529. package/docs/consumer-skills/themelia-forms/SKILL.md +12 -0
  530. package/docs/consumer-skills/themelia-foundation/SKILL.md +15 -0
  531. package/docs/consumer-skills/themelia-tokenization/SKILL.md +42 -0
  532. package/package.json +4 -2
  533. package/templates/README.md +39 -0
  534. package/templates/admin-shell-template.tsx +382 -0
  535. package/templates/analytics-operations-template.tsx +376 -0
  536. package/templates/customers-template.tsx +509 -0
  537. package/templates/index.ts +29 -0
  538. package/templates/orders-template.tsx +1102 -0
  539. package/templates/products-template.tsx +834 -0
  540. package/templates/user-permissions-template.tsx +450 -0
  541. package/dist/accordion-Cjb6sx0G.js.map +0 -1
  542. package/dist/action-menu-CllU52Mm.js +0 -280
  543. package/dist/action-menu-CllU52Mm.js.map +0 -1
  544. package/dist/affordance-geometry.generated-tF36bREk.js.map +0 -1
  545. package/dist/ai-artifact-DvTwDVyL.js.map +0 -1
  546. package/dist/app-shell-C4FhvCqF.js +0 -236
  547. package/dist/app-shell-C4FhvCqF.js.map +0 -1
  548. package/dist/auth-BGua8ouh.js.map +0 -1
  549. package/dist/avatar-DAPlDvhJ.js.map +0 -1
  550. package/dist/base/cascader.js.map +0 -1
  551. package/dist/batch-action-bar-DnUJ21NQ.js.map +0 -1
  552. package/dist/button-DVzspB_G.js.map +0 -1
  553. package/dist/buttons-DPZekJFu.js.map +0 -1
  554. package/dist/cards-BaBZR-AU.js +0 -68
  555. package/dist/cards-BaBZR-AU.js.map +0 -1
  556. package/dist/chart-ZOYyK2xG.js +0 -155
  557. package/dist/chart-ZOYyK2xG.js.map +0 -1
  558. package/dist/checkbox-AWIhNhmo.js.map +0 -1
  559. package/dist/choice-inputs-CNHvARCJ.js +0 -770
  560. package/dist/choice-inputs-CNHvARCJ.js.map +0 -1
  561. package/dist/code-block-DeneBJR_.js.map +0 -1
  562. package/dist/combobox-DaHESuiL.js +0 -355
  563. package/dist/combobox-DaHESuiL.js.map +0 -1
  564. package/dist/combobox-Dxo2fAYQ.js.map +0 -1
  565. package/dist/command-C25VMRII.js.map +0 -1
  566. package/dist/comments-DD0DUPwJ.js.map +0 -1
  567. package/dist/containers-Mu1LMGV1.js +0 -103
  568. package/dist/containers-Mu1LMGV1.js.map +0 -1
  569. package/dist/control-group-recipes-DBXmfh2E.js.map +0 -1
  570. package/dist/data-display-DT_khPl_.js.map +0 -1
  571. package/dist/date-picker-B2K3ucWn.js.map +0 -1
  572. package/dist/date-pickers-Ds8gLaoP.js +0 -175
  573. package/dist/date-pickers-Ds8gLaoP.js.map +0 -1
  574. package/dist/dropdown-menu-Cl4X7L5S.js +0 -193
  575. package/dist/dropdown-menu-Cl4X7L5S.js.map +0 -1
  576. package/dist/feedback-BYIhtitP.js.map +0 -1
  577. package/dist/field-affordance-recipes-DZhnIL_Y.js.map +0 -1
  578. package/dist/filters-DJVAveHA.js.map +0 -1
  579. package/dist/form-field-CwH9y77i.js.map +0 -1
  580. package/dist/form-sizing-BdP_Mf5p.js.map +0 -1
  581. package/dist/forms-B9G_xwzi.js +0 -194
  582. package/dist/forms-B9G_xwzi.js.map +0 -1
  583. package/dist/forms-numeric-B_jraJaQ.js.map +0 -1
  584. package/dist/header-BSfIEWbI.js.map +0 -1
  585. package/dist/hooks-ClH9thn4.js.map +0 -1
  586. package/dist/input-CZw8iU99.js +0 -21
  587. package/dist/input-CZw8iU99.js.map +0 -1
  588. package/dist/input-DQdEd0YD.js +0 -263
  589. package/dist/input-DQdEd0YD.js.map +0 -1
  590. package/dist/item-K5_ghvze.js +0 -275
  591. package/dist/item-K5_ghvze.js.map +0 -1
  592. package/dist/message-DZ_ruyUV.js.map +0 -1
  593. package/dist/metadata-list-8N16ZMW_.js +0 -405
  594. package/dist/metadata-list-8N16ZMW_.js.map +0 -1
  595. package/dist/motion-recipes-ChBg4HBq.js.map +0 -1
  596. package/dist/navigation-Bnotn4AQ.js +0 -145
  597. package/dist/navigation-Bnotn4AQ.js.map +0 -1
  598. package/dist/navigation-BzhHI3lo.js.map +0 -1
  599. package/dist/navigation-row-recipes-BFLCk_Aq.js.map +0 -1
  600. package/dist/overflow-tab-bar-CWY7Nogn.js +0 -282
  601. package/dist/overflow-tab-bar-CWY7Nogn.js.map +0 -1
  602. package/dist/overlays-tMkF-VAN.js +0 -1003
  603. package/dist/overlays-tMkF-VAN.js.map +0 -1
  604. package/dist/page-CL9YeH_V.js +0 -224
  605. package/dist/page-CL9YeH_V.js.map +0 -1
  606. package/dist/page-header-commands-DOb6WsfD.js +0 -126
  607. package/dist/page-header-commands-DOb6WsfD.js.map +0 -1
  608. package/dist/popover-gnTOhbFM.js +0 -198
  609. package/dist/popover-gnTOhbFM.js.map +0 -1
  610. package/dist/popover.recipes-D3j8R8Yp.js.map +0 -1
  611. package/dist/receipt-BVSOH3Xo.js.map +0 -1
  612. package/dist/rich-text-editor-cRLC-eBK.js.map +0 -1
  613. package/dist/rich-text-editor-toolbar-DfXg0-VC.js.map +0 -1
  614. package/dist/settings-ybnjVwbd.js +0 -171
  615. package/dist/settings-ybnjVwbd.js.map +0 -1
  616. package/dist/sheet-ijlsjq-n.js +0 -213
  617. package/dist/sheet-ijlsjq-n.js.map +0 -1
  618. package/dist/sidebar-Db6gkh3U.js +0 -619
  619. package/dist/sidebar-Db6gkh3U.js.map +0 -1
  620. package/dist/sidebar-DkTO4VTO.js +0 -512
  621. package/dist/sidebar-DkTO4VTO.js.map +0 -1
  622. package/dist/skeleton-Byjnt7qr.js +0 -264
  623. package/dist/skeleton-Byjnt7qr.js.map +0 -1
  624. package/dist/smart-card-DiC5aac3.js +0 -604
  625. package/dist/smart-card-DiC5aac3.js.map +0 -1
  626. package/dist/table-BweFy_P9.js.map +0 -1
  627. package/dist/tabs-CDocW5D1.js.map +0 -1
  628. package/dist/text-inputs-f9Ia-aCi.js.map +0 -1
  629. package/dist/text.styles-g4He6UIW.js.map +0 -1
  630. package/dist/theme-scope-BJ6eE2xt.js +0 -50
  631. package/dist/theme-scope-BJ6eE2xt.js.map +0 -1
  632. package/dist/timelines-CwM_9IhD.js.map +0 -1
  633. package/dist/tooltip-yiRJUFjp.js +0 -111
  634. package/dist/tooltip-yiRJUFjp.js.map +0 -1
  635. package/dist/typography-UTnveOEy.js +0 -117
  636. package/dist/typography-UTnveOEy.js.map +0 -1
  637. package/dist/ui-provider-C_U0Xma4.js +0 -136
  638. package/dist/ui-provider-C_U0Xma4.js.map +0 -1
  639. package/dist/upload-CXyxmQBP.js.map +0 -1
  640. package/dist/upload-queue-Boscubn9.js.map +0 -1
  641. package/dist/usage-card-BhO5eqkX.js.map +0 -1
  642. package/dist/use-mobile-vaLKwgyf.js +0 -15
  643. package/dist/use-mobile-vaLKwgyf.js.map +0 -1
  644. package/dist/utils-BRhFDwuU.js.map +0 -1
  645. package/dist/value-inputs-TaX4OjNk.js +0 -963
  646. package/dist/value-inputs-TaX4OjNk.js.map +0 -1
  647. package/dist/workspace-B-OEm3Kf.js +0 -408
  648. package/dist/workspace-B-OEm3Kf.js.map +0 -1
@@ -1,7 +1,8 @@
1
- import { useId, useRef, useState, type FormEvent } from 'react';
1
+ import { useRef, useState } from 'react';
2
+ import { useForm } from 'react-hook-form';
2
3
  import { Button } from 'themelia-react-ui/base/buttons';
3
4
  import { Card } from 'themelia-react-ui/base/cards';
4
- import { FormField } from 'themelia-react-ui/base/forms';
5
+ import { ControlledFormField, DirtyStateBanner, ErrorSummary, FormActionsBar, SubmitStateButton } from 'themelia-react-ui/base/forms';
5
6
  import { Stack } from 'themelia-react-ui/base/structure';
6
7
  import { Input } from 'themelia-react-ui/base/text-inputs';
7
8
  import { Text } from 'themelia-react-ui/typography';
@@ -9,52 +10,43 @@ import { Text } from 'themelia-react-ui/typography';
9
10
  export interface AccountEditValue { id: string; name: string; }
10
11
  export interface AccountEditProps {
11
12
  initial: AccountEditValue;
12
- // Resolve with the authoritative saved value; reject if persistence failed.
13
13
  onSave: (value: AccountEditValue) => Promise<AccountEditValue>;
14
14
  onCancel: () => void;
15
15
  }
16
16
 
17
- // Mount with key={initial.id} when switching records. Draft state belongs to this mount.
17
+ /** Small embedded subject; full routes start from rhf-edit-page.tsx. */
18
18
  export function AccountEdit({ initial, onSave, onCancel }: AccountEditProps) {
19
- const id = useId();
20
- const input = useRef<HTMLInputElement>(null);
21
- const inFlight = useRef(false);
22
- const [name, setName] = useState(initial.name);
23
- const [validation, setValidation] = useState<string>();
24
- const [error, setError] = useState<string>();
25
- const [pending, setPending] = useState(false);
19
+ const lock = useRef(false);
26
20
  const [saved, setSaved] = useState(false);
27
- async function submit(event: FormEvent<HTMLFormElement>) {
28
- event.preventDefault();
29
- if (inFlight.current) return;
30
- setError(undefined); setSaved(false);
31
- const trimmed = name.trim();
32
- if (trimmed.length < 2) {
33
- setValidation('Enter at least two characters.'); input.current?.focus(); return;
34
- }
35
- setValidation(undefined); inFlight.current = true; setPending(true);
21
+ const form = useForm<AccountEditValue>({ defaultValues: initial });
22
+ const { isDirty, isSubmitting, errors } = form.formState;
23
+ const submit = form.handleSubmit(async values => {
24
+ if (lock.current) return;
25
+ lock.current = true;
26
+ setSaved(false);
27
+ form.clearErrors('root.server');
36
28
  try {
37
- const result = await onSave({ id: initial.id, name: trimmed });
38
- setName(result.name); setSaved(true);
29
+ form.reset(await onSave({ ...values, name: values.name.trim() }));
30
+ setSaved(true);
39
31
  } catch {
40
- setError('Saving failed. Your draft is kept; retry Save account.');
41
- } finally { inFlight.current = false; setPending(false); }
42
- }
32
+ form.setError('root.server', { type: 'transport', message: 'Saving failed. Your draft is kept; retry Save account.' });
33
+ } finally { lock.current = false; }
34
+ });
43
35
  return <Card title="Edit account" surface="card">
44
- <form onSubmit={submit} noValidate aria-busy={pending}>
36
+ <form onSubmit={submit} noValidate aria-busy={isSubmitting}>
45
37
  <Stack gap="lg">
46
- <FormField label="Account name" htmlFor={id} required error={validation}
47
- hint="At least two characters." supportingTextId={`${id}-help`}>
48
- <Input ref={input} id={id} value={name} required disabled={pending}
49
- aria-invalid={Boolean(validation)} aria-describedby={`${id}-help`}
50
- onChange={event => { setName(event.target.value); setValidation(undefined); setError(undefined); setSaved(false); }} />
51
- </FormField>
52
- {error && <Text role="alert" type="error">{error}</Text>}
53
- {saved && <Text role="status">Account saved.</Text>}
54
- <Stack direction={{ base: 'vertical', sm: 'horizontal' }} gap="sm">
55
- <Button tone="primary" type="submit" loading={pending} strings={{ loading: 'Saving account…' }}>Save account</Button>
56
- <Button type="button" disabled={pending} onClick={onCancel}>Cancel edit</Button>
57
- </Stack>
38
+ {isDirty && <DirtyStateBanner title="Unsaved changes" />}
39
+ {errors.root?.server?.message && <ErrorSummary title="Account could not be saved" errors={[errors.root.server.message]} />}
40
+ <ControlledFormField control={form.control} name="name" label="Account name" required
41
+ hint="At least two characters." rules={{ validate: value => value.trim().length >= 2 || 'Enter at least two characters.' }}>
42
+ {(field, _error, invalid) => <Input ref={field.ref} name={field.name} value={field.value}
43
+ onValueChange={value => field.onChange(value)} onBlur={field.onBlur} invalid={invalid} disabled={isSubmitting} />}
44
+ </ControlledFormField>
45
+ {saved && !isDirty && <Text role="status">Account saved.</Text>}
46
+ <FormActionsBar>
47
+ <Button type="button" disabled={isSubmitting} onClick={onCancel}>Cancel edit</Button>
48
+ <SubmitStateButton dirty={isDirty} disableWhenPristine submitting={isSubmitting}>Save account</SubmitStateButton>
49
+ </FormActionsBar>
58
50
  </Stack>
59
51
  </form>
60
52
  </Card>;
@@ -0,0 +1,38 @@
1
+ import type { ReactNode } from 'react';
2
+ import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from 'themelia-react-ui/base/accordion';
3
+ import { Badge } from 'themelia-react-ui/base/badge';
4
+ import { Stack } from 'themelia-react-ui/base/structure';
5
+ import { Heading, Text } from 'themelia-react-ui/typography';
6
+
7
+ export interface EditableSection {
8
+ id: string;
9
+ title: string;
10
+ content: ReactNode;
11
+ /** App-localized validation status, e.g. "2 errors"; omit when valid. */
12
+ validationMessage?: string;
13
+ }
14
+
15
+ /** Place inside the app's one form. Closing a panel retains the same field DOM. */
16
+ export function EditableSections({title, sections, openSections, onOpenSectionsChange}: {
17
+ title: string;
18
+ sections: EditableSection[];
19
+ openSections: string[];
20
+ onOpenSectionsChange: (values: string[]) => void;
21
+ }) {
22
+ return <Stack gap="xl">
23
+ <Heading tag="h2" size="base">{title}</Heading>
24
+ <Accordion multiple value={openSections} onValueChange={onOpenSectionsChange} aria-label={title}>
25
+ {sections.map(section => <AccordionItem key={section.id} value={section.id}>
26
+ <AccordionTrigger>
27
+ <Stack render={<span />} direction="horizontal" gap="md" className="min-w-0">
28
+ <Text tag="span" size="inherit" type="inherit" weight="medium">{section.title}</Text>
29
+ {section.validationMessage && <>{' '}<Badge tone="destructive">{section.validationMessage}</Badge></>}
30
+ </Stack>
31
+ </AccordionTrigger>
32
+ <AccordionContent keepMounted>
33
+ <Stack gap="xl">{section.content}</Stack>
34
+ </AccordionContent>
35
+ </AccordionItem>)}
36
+ </Accordion>
37
+ </Stack>;
38
+ }
@@ -1,5 +1,5 @@
1
1
  import { Button } from 'themelia-react-ui/base/buttons';
2
- import { Card } from 'themelia-react-ui/base/cards';
2
+ import { Page } from 'themelia-react-ui/layout/page';
3
3
  import { Stack } from 'themelia-react-ui/base/structure';
4
4
  import { DataTable, type DataTableProps } from 'themelia-react-ui/features/table';
5
5
  import { Email, Name } from 'themelia-react-ui/primitives';
@@ -23,14 +23,14 @@ export function AccountIndex({ state, onRetry, hrefFor, onNavigate }: AccountInd
23
23
  { accessorKey: 'name', header: 'Name', cell: ({ row }) => <Name value={row.original.name} /> },
24
24
  { accessorKey: 'email', header: 'Email', cell: ({ row }) => <Email value={row.original.email} /> },
25
25
  ];
26
- return <Card title="Accounts" surface="card">
26
+ return <Page header={{ title: 'Accounts' }}>
27
27
  {state.status === 'loading' ? <Text role="status">Loading accounts…</Text> :
28
28
  state.status === 'error' ? <Stack gap="md">
29
29
  <Text role="alert" type="error">{state.message}</Text>
30
30
  <Button onClick={onRetry}>Retry loading</Button>
31
- </Stack> : <DataTable columns={columns} data={state.records} surface="flat"
31
+ </Stack> : <DataTable columns={columns} data={state.records}
32
32
  getRowId={account => account.id} enablePagination={false} showFullscreenToggle={false}
33
33
  emptyStateMessage="No accounts yet." emptyStateAction={<Button onClick={onRetry}>Refresh accounts</Button>}
34
34
  rowActions={[{ id: 'open', label: 'Open account', onClick: account => onNavigate(hrefFor(account)) }]} />}
35
- </Card>;
35
+ </Page>;
36
36
  }
@@ -1,6 +1,42 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "examples": [
4
+ {
5
+ "file": "product-parts.tsx",
6
+ "exports": ["ProductOptionDefinitions", "ProductVariantManagement", "VariantComparison", "VariantInspectionAndEditor"],
7
+ "phase": "optional",
8
+ "optionalPeers": ["@tanstack/react-table", "react-hook-form"]
9
+ },
10
+ {
11
+ "file": "product-media.tsx",
12
+ "exports": ["LocalProductImages", "AttachedProductImages", "MediaOnlyProductOverview"],
13
+ "phase": "optional",
14
+ "optionalPeers": ["@dnd-kit/core", "@dnd-kit/sortable", "@dnd-kit/utilities", "@tanstack/react-table", "react-hook-form"]
15
+ },
16
+ {
17
+ "file": "token-domain-structure.tsx",
18
+ "exports": ["AllocationByLocation", "AllocationSubjectExample"],
19
+ "phase": "basic",
20
+ "optionalPeers": []
21
+ },
22
+ {
23
+ "file": "commerce-lines.tsx",
24
+ "exports": ["SoldProductWithSummary", "CustomServiceInvoice", "OrderFulfillmentDetail", "ReceivableInvoiceDetail"],
25
+ "phase": "optional",
26
+ "optionalPeers": ["react-day-picker", "react-hook-form", "sonner"]
27
+ },
28
+ {
29
+ "file": "editable-sections.tsx",
30
+ "exports": ["EditableSections"],
31
+ "phase": "basic",
32
+ "optionalPeers": []
33
+ },
34
+ {
35
+ "file": "custom-composition.tsx",
36
+ "exports": ["AssessmentComparison"],
37
+ "phase": "basic",
38
+ "optionalPeers": []
39
+ },
4
40
  {
5
41
  "file": "website.tsx",
6
42
  "exports": [
@@ -105,7 +141,8 @@
105
141
  {
106
142
  "file": "app-layout.tsx",
107
143
  "exports": [
108
- "WorkspaceLayout"
144
+ "WorkspaceLayout",
145
+ "WorkspaceExamplePage"
109
146
  ],
110
147
  "phase": "basic",
111
148
  "optionalPeers": []
@@ -137,6 +174,56 @@
137
174
  ],
138
175
  "phase": "basic",
139
176
  "optionalPeers": []
177
+ },
178
+ {
179
+ "file": "authentication.tsx",
180
+ "exports": [
181
+ "PasswordSignIn"
182
+ ],
183
+ "phase": "optional",
184
+ "optionalPeers": [
185
+ "react-hook-form"
186
+ ]
187
+ },
188
+ {
189
+ "file": "rhf-edit-page.tsx",
190
+ "exports": [
191
+ "RHFEditPage"
192
+ ],
193
+ "phase": "optional",
194
+ "optionalPeers": [
195
+ "react-hook-form"
196
+ ]
197
+ },
198
+ {
199
+ "file": "rhf-overlay-form.tsx",
200
+ "exports": [
201
+ "RHFOverlayForm",
202
+ "RHFDialogForm"
203
+ ],
204
+ "phase": "optional",
205
+ "optionalPeers": [
206
+ "react-hook-form"
207
+ ]
208
+ },
209
+ {
210
+ "file": "rhf-bindings.tsx",
211
+ "exports": [
212
+ "TypedControlBindings"
213
+ ],
214
+ "phase": "optional",
215
+ "optionalPeers": [
216
+ "react-day-picker",
217
+ "react-hook-form"
218
+ ]
219
+ },
220
+ {
221
+ "file": "rhf-transport.tsx",
222
+ "exports": [
223
+ "awaitCallbackSave"
224
+ ],
225
+ "phase": "basic",
226
+ "optionalPeers": []
140
227
  }
141
228
  ]
142
229
  }
@@ -0,0 +1,41 @@
1
+ import { FormField } from 'themelia-react-ui/base/forms';
2
+ import { MediaGallery } from 'themelia-react-ui/base/media-gallery';
3
+ import { MediaResourceGallery, type MediaLibraryAccessors } from 'themelia-react-ui/features/media-library';
4
+ import { ProductOverview } from 'themelia-react-ui/features/products';
5
+
6
+ /** New local files remain File[]; the caller owns transfer and persistence. */
7
+ export function LocalProductImages({ files, onFilesChange }: { files: File[]; onFilesChange: (files: File[]) => void }) {
8
+ return <FormField label="New product images" hint="The first image is the cover. Drag or use the keyboard to change order.">
9
+ <MediaGallery value={files} onValueChange={onFilesChange} accept="image/*" maxFiles={6} />
10
+ </FormField>;
11
+ }
12
+
13
+ export interface ProductAsset { key: string; filename: string; url: string; altText: string; }
14
+ const accessors: MediaLibraryAccessors<ProductAsset> = {
15
+ getId: item => item.key, getName: item => item.filename, getType: () => 'image',
16
+ getSrc: item => item.url, getAlt: item => item.altText,
17
+ };
18
+
19
+ /** Existing records stay records; callbacks propose resource attachment changes. */
20
+ export function AttachedProductImages({ assets, primaryId, onAssetsChange, onPrimaryChange, onAdd }: {
21
+ assets: ProductAsset[];
22
+ primaryId?: string;
23
+ onAssetsChange: (assets: ProductAsset[]) => void;
24
+ onPrimaryChange: (id: string | undefined) => void;
25
+ onAdd?: () => void;
26
+ }) {
27
+ return <MediaResourceGallery items={assets} accessors={accessors} title="Product media" layout="grid"
28
+ primaryId={primaryId} onPrimaryChange={id => onPrimaryChange(id)} onAdd={onAdd}
29
+ onReorder={(_ids, next) => onAssetsChange(next)} onRemove={id => {
30
+ const next = assets.filter(asset => asset.key !== id);
31
+ onAssetsChange(next);
32
+ if (id === (primaryId ?? assets[0]?.key)) onPrimaryChange(next[0]?.key);
33
+ }} />;
34
+ }
35
+
36
+ /** ProductOverview owns the subject; media enters through details.media, not a top-level media prop. */
37
+ export function MediaOnlyProductOverview({ assets }: { assets: ProductAsset[] }) {
38
+ return <ProductOverview details={{ title: 'Product media', description: false,
39
+ media: <MediaResourceGallery items={assets} accessors={accessors} readOnly layout="field" />,
40
+ }} />;
41
+ }
@@ -0,0 +1,81 @@
1
+ import { useState, type ReactNode } from 'react';
2
+ import { Alert, AlertDescription } from 'themelia-react-ui/base/feedback';
3
+ import { Stack } from 'themelia-react-ui/base/structure';
4
+ import {
5
+ ProductOptionsMatrix, ProductVariantDetails, ProductVariantEditor,
6
+ ProductVariantsBulkTable, ProductVariantsManager,
7
+ type ProductOptionEditDraft, type ProductOptionGroup,
8
+ type ProductVariantEditorValues, type ProductVariantRow,
9
+ } from 'themelia-react-ui/features/products';
10
+ import { Money } from 'themelia-react-ui/primitives';
11
+
12
+ const colors: ProductOptionGroup[] = [{
13
+ id: 'color', name: 'Color', values: [{ id: 'olive', label: 'Olive' }, { id: 'natural', label: 'Natural' }],
14
+ }];
15
+ const rows: ProductVariantRow[] = [
16
+ { id: 'weekender-olive', name: 'Olive', sku: 'WEEK-OLIVE', price: '€68.00', inventory: '7 available', status: 'Active', optionValueIds: { color: 'olive' } },
17
+ { id: 'weekender-natural', name: 'Natural', sku: 'WEEK-NATURAL', price: '€68.00', inventory: '12 available', status: 'Active', optionValueIds: { color: 'natural' } },
18
+ ];
19
+
20
+ /** Local definition-editing example. Variant reconciliation is a separate app rule. */
21
+ export function ProductOptionDefinitions() {
22
+ const [groups, setGroups] = useState(colors);
23
+ const [editingId, setEditingId] = useState<string | null>(null);
24
+ return <ProductOptionsMatrix optionGroups={groups} editingOptionId={editingId}
25
+ onEditingOptionIdChange={setEditingId} showVariantToggle={false}
26
+ onSaveEditingOption={(option, draft) => {
27
+ setGroups(current => current.map(group => group.id === option.id ? { ...group, name: draft.name, values: draft.values } : group));
28
+ }} />;
29
+ }
30
+
31
+ /** Callbacks apply app-owned accepted definitions/rows; the manager does not generate business data. */
32
+ export function ProductVariantManagement({ optionGroups, variants, onSaveOption, onInspectVariant }: {
33
+ optionGroups: ProductOptionGroup[];
34
+ variants: ProductVariantRow[];
35
+ onSaveOption: (option: ProductOptionGroup, draft: ProductOptionEditDraft) => void | Promise<void>;
36
+ onInspectVariant: (variant: ProductVariantRow) => void;
37
+ }) {
38
+ const [editingId, setEditingId] = useState<string | null>(null);
39
+ return <ProductVariantsManager optionGroups={optionGroups} variants={variants}
40
+ editingOptionId={editingId} onEditingOptionIdChange={setEditingId}
41
+ onSaveEditingOption={onSaveOption}
42
+ onSelectVariant={onInspectVariant} groupByOptionId={null}
43
+ visibleColumns={['variant', 'sku', 'price', 'inventory', 'status']} selectionMode="none" cellDisplay="text" />;
44
+ }
45
+
46
+ /** A comparison can use the table independently from option-definition editing. */
47
+ export function VariantComparison({ onInspectVariant }: { onInspectVariant: (variant: ProductVariantRow) => void }) {
48
+ return <ProductVariantsBulkTable variants={rows} optionGroups={colors} groupByOptionId={null}
49
+ visibleColumns={['variant', 'sku', 'price', 'inventory', 'status']} selectionMode="none"
50
+ cellDisplay="text" onSelectVariant={onInspectVariant} />;
51
+ }
52
+
53
+ /** The caller validates/persists and returns accepted fields; a failed save keeps the editor draft. */
54
+ export function VariantInspectionAndEditor({ id, initialValue, media, detailFooter, onSave }: {
55
+ id: string;
56
+ initialValue: ProductVariantEditorValues;
57
+ media?: ReactNode;
58
+ detailFooter?: ReactNode;
59
+ onSave: (draft: ProductVariantEditorValues) => Promise<ProductVariantEditorValues>;
60
+ }) {
61
+ const [accepted, setAccepted] = useState(initialValue);
62
+ const [draft, setDraft] = useState(initialValue);
63
+ const [editing, setEditing] = useState(false);
64
+ const [error, setError] = useState('');
65
+ return <Stack gap="2xl">
66
+ <ProductVariantDetails variant={{ id, name: accepted.name || 'Variant', sku: accepted.sku,
67
+ price: accepted.price ? <Money amount={Number(accepted.price)} currency="EUR" /> : undefined,
68
+ inventory: accepted.inventory, status: accepted.status,
69
+ options: Object.values(accepted.options ?? {}).filter((value): value is string => value !== undefined),
70
+ }} media={media} footerSlot={detailFooter} onEditVariant={() => {
71
+ setDraft(accepted); setError(''); setEditing(true);
72
+ }} />
73
+ {editing && <Stack gap="xl">
74
+ {error && <Alert tone="destructive"><AlertDescription>{error}</AlertDescription></Alert>}
75
+ <ProductVariantEditor value={draft} onValueChange={setDraft}
76
+ onSubmit={async value => { const saved = await onSave(value); setAccepted(saved); setEditing(false); }}
77
+ onError={() => setError('Variant could not be saved. Your draft is kept; retry Save variant.')}
78
+ onCancel={() => setEditing(false)} />
79
+ </Stack>}
80
+ </Stack>;
81
+ }
@@ -0,0 +1,86 @@
1
+ import { useId } from 'react';
2
+ import { useForm } from 'react-hook-form';
3
+ import { ControlledFormField } from 'themelia-react-ui/base/forms';
4
+ import { Input, Textarea } from 'themelia-react-ui/base/text-inputs';
5
+ import { Checkbox, Select, Switch, SwitchCard, ToggleField } from 'themelia-react-ui/base/choice-inputs';
6
+ import { DatePicker } from 'themelia-react-ui/base/date-pickers';
7
+ import { ColorInput, DateTimeInput, PhoneInput, SliderField, TagsInput } from 'themelia-react-ui/base/value-inputs';
8
+ import { Stack } from 'themelia-react-ui/base/structure';
9
+ import { Text } from 'themelia-react-ui/typography';
10
+
11
+ export interface BindingValues {
12
+ title: string; description: string; category: string;
13
+ enabled: boolean; accepted: boolean; notifications: boolean; automation: boolean;
14
+ dueDate: Date | null; appointment: string; phone: string; tags: string[];
15
+ threshold: number; color: string;
16
+ }
17
+
18
+ /** Each binding follows the public control's actual value contract. */
19
+ export function TypedControlBindings() {
20
+ const id = useId();
21
+ const { control } = useForm<BindingValues>({ defaultValues: {
22
+ title: '', description: '', category: 'standard', enabled: false, accepted: false,
23
+ notifications: true, automation: false, dueDate: null, appointment: '', phone: '',
24
+ tags: [], threshold: 50, color: '#335577',
25
+ } });
26
+ return <Stack gap="xl">
27
+ <ControlledFormField control={control} name="title" label="Title">
28
+ {(field, _error, invalid) => <Input ref={field.ref} name={field.name}
29
+ value={field.value} onValueChange={value => field.onChange(value)} onBlur={field.onBlur} invalid={invalid} />}
30
+ </ControlledFormField>
31
+ <ControlledFormField control={control} name="description" label="Description">
32
+ {(field, _error, invalid) => <Textarea ref={field.ref} name={field.name}
33
+ value={field.value} onValueChange={value => field.onChange(value)} onBlur={field.onBlur} invalid={invalid} />}
34
+ </ControlledFormField>
35
+ <ControlledFormField control={control} name="category" label="Category">
36
+ {(field, _error, invalid) => <Select ref={field.ref} name={field.name}
37
+ value={field.value} onValueChange={value => field.onChange(value ?? '')} onBlur={field.onBlur}
38
+ invalid={invalid} options={[{ value: 'standard', label: 'Standard' }, { value: 'priority', label: 'Priority' }]} />}
39
+ </ControlledFormField>
40
+ <ControlledFormField control={control} name="enabled" label="Enabled">
41
+ {(field, _error, invalid) => <Switch ref={field.ref} name={field.name}
42
+ checked={field.value} onValueChange={checked => field.onChange(checked)} onBlur={field.onBlur} invalid={invalid} />}
43
+ </ControlledFormField>
44
+ <ControlledFormField control={control} name="accepted" label="Accept terms" rules={{ validate: value => value || 'Accept the terms.' }}>
45
+ {(field, _error, invalid) => <Checkbox ref={field.ref} name={field.name}
46
+ checked={field.value} onValueChange={checked => field.onChange(checked)} onBlur={field.onBlur} invalid={invalid} />}
47
+ </ControlledFormField>
48
+ <ControlledFormField control={control} name="notifications">
49
+ {(field, _error, invalid) => <ToggleField label="Email notifications" name={field.name}
50
+ value={field.value} controlRef={field.ref} onBlur={field.onBlur} onValueChange={checked => field.onChange(checked)}
51
+ invalid={invalid} />}
52
+ </ControlledFormField>
53
+ <ControlledFormField control={control} name="automation">
54
+ {(field, _error, invalid) => <SwitchCard label="Automatic processing" name={field.name}
55
+ value={field.value} controlRef={field.ref} onBlur={field.onBlur} onValueChange={checked => field.onChange(checked)}
56
+ invalid={invalid} />}
57
+ </ControlledFormField>
58
+ <ControlledFormField control={control} name="dueDate" label="Due date">
59
+ {(field, _error, invalid) => <DatePicker mode="single" value={field.value ?? undefined}
60
+ triggerRef={field.ref} onBlur={field.onBlur} onValueChange={output => field.onChange(output.date ?? null)} invalid={invalid} />}
61
+ </ControlledFormField>
62
+ <ControlledFormField control={control} name="appointment" label="Appointment">
63
+ {(field, _error, invalid) => <DateTimeInput value={field.value || undefined}
64
+ triggerRef={field.ref} onBlur={field.onBlur} onValueChange={value => field.onChange(value ?? '')} invalid={invalid} />}
65
+ </ControlledFormField>
66
+ <ControlledFormField control={control} name="phone" label="Phone">
67
+ {(field, _error, invalid) => <PhoneInput ref={field.ref} name={field.name}
68
+ value={field.value} onChange={event => field.onChange(event.target.value)} onBlur={field.onBlur} invalid={invalid} />}
69
+ </ControlledFormField>
70
+ <ControlledFormField control={control} name="tags" label="Tags">
71
+ {(field, _error, invalid) => <TagsInput<string> name={field.name} value={field.value}
72
+ inputRef={field.ref} onBlur={field.onBlur} onValueChange={value => field.onChange(value)} aria-invalid={invalid} />}
73
+ </ControlledFormField>
74
+ <ControlledFormField control={control} name="threshold" hint="Choose a value between 0 and 100." supportingTextId={`${id}-threshold-help`}>
75
+ {(field, _error, invalid) => <Stack gap="xs">
76
+ <Text tag="span" id={`${id}-threshold-label`} weight="medium">Threshold</Text>
77
+ <SliderField name={field.name} value={field.value} aria-labelledby={`${id}-threshold-label`} aria-describedby={`${id}-threshold-help`}
78
+ onValueChange={value => field.onChange(value)} inputRef={field.ref} onBlur={field.onBlur} invalid={invalid} showValue />
79
+ </Stack>}
80
+ </ControlledFormField>
81
+ <ControlledFormField control={control} name="color" label="Brand color">
82
+ {(field, _error, invalid) => <ColorInput ref={field.ref} name={field.name}
83
+ value={field.value} onValueChange={value => field.onChange(value)} onBlur={field.onBlur} invalid={invalid} />}
84
+ </ControlledFormField>
85
+ </Stack>;
86
+ }
@@ -0,0 +1,141 @@
1
+ import { useEffect, useId, useRef, useState } from 'react';
2
+ import { useFieldArray, useForm, useWatch, type FieldErrors } from 'react-hook-form';
3
+ import { Button } from 'themelia-react-ui/base/buttons';
4
+ import { ControlledFormField, DirtyStateBanner, ErrorSummary, FormActionsBar, FormSection, SubmitStateButton } from 'themelia-react-ui/base/forms';
5
+ import { Select, ToggleField } from 'themelia-react-ui/base/choice-inputs';
6
+ import { Input, Textarea } from 'themelia-react-ui/base/text-inputs';
7
+ import { Stack } from 'themelia-react-ui/base/structure';
8
+ import { MetadataList } from 'themelia-react-ui/base/metadata-list';
9
+ import { TwoColumnLayout } from 'themelia-react-ui/layout/containers';
10
+ import { Page } from 'themelia-react-ui/layout/page';
11
+ import { Money } from 'themelia-react-ui/primitives';
12
+ import { Text } from 'themelia-react-ui/typography';
13
+
14
+ export interface OrderEditValues {
15
+ reference: string; email: string; notes: string; priority: string; notify: boolean;
16
+ lines: { product: string; quantity: number; priceMinor: number }[];
17
+ }
18
+ export type OrderSaveResult =
19
+ | { ok: true; values: OrderEditValues }
20
+ | { ok: false; errors: Partial<Record<'reference' | 'email' | 'notes' | 'lines', string>>; message?: string };
21
+ export interface RHFEditPageProps {
22
+ initial: OrderEditValues;
23
+ /** Await the complete request and return the accepted server representation. */
24
+ onSave: (values: OrderEditValues) => Promise<OrderSaveResult>;
25
+ onCancel: () => void;
26
+ }
27
+
28
+ function messages(errors: FieldErrors<OrderEditValues>): string[] {
29
+ const result: string[] = [];
30
+ for (const error of [errors.reference, errors.email, errors.notes, errors.priority, errors.lines, errors.lines?.root, errors.root?.server]) {
31
+ if (typeof error?.message === 'string') result.push(error.message);
32
+ }
33
+ for (const line of Array.isArray(errors.lines) ? errors.lines : []) for (const error of [line?.product, line?.quantity, line?.priceMinor]) {
34
+ if (typeof error?.message === 'string') result.push(error.message);
35
+ }
36
+ return result;
37
+ }
38
+
39
+ /** Mount with key={record.id}; background revalidation must not reset a dirty draft. */
40
+ export function RHFEditPage({ initial, onSave, onCancel }: RHFEditPageProps) {
41
+ const id = useId();
42
+ const lock = useRef(false);
43
+ const pendingFocus = useRef<'reference' | 'email' | 'notes' | 'lines.0.product' | undefined>(undefined);
44
+ const [saved, setSaved] = useState(false);
45
+ const form = useForm<OrderEditValues>({ defaultValues: initial, mode: 'onBlur' });
46
+ const lines = useFieldArray({ control: form.control, name: 'lines', rules: { minLength: { value: 1, message: 'Keep at least one line item.' } } });
47
+ const draftLines = useWatch({ control: form.control, name: 'lines' });
48
+ const totalMinor = draftLines.reduce((sum, line) => sum + (line.quantity || 0) * (line.priceMinor || 0), 0);
49
+ const { isDirty, isSubmitting, errors } = form.formState;
50
+ const summary = messages(errors);
51
+ const { setFocus } = form;
52
+ useEffect(() => {
53
+ if (!isSubmitting && pendingFocus.current) {
54
+ setFocus(pendingFocus.current);
55
+ pendingFocus.current = undefined;
56
+ }
57
+ }, [isSubmitting, setFocus]);
58
+ const submit = form.handleSubmit(async values => {
59
+ if (lock.current) return;
60
+ lock.current = true;
61
+ setSaved(false);
62
+ pendingFocus.current = undefined;
63
+ form.clearErrors();
64
+ try {
65
+ const result = await onSave(values);
66
+ if (!result.ok) {
67
+ let focused = false;
68
+ for (const name of ['reference', 'email', 'notes', 'lines'] as const) {
69
+ const message = result.errors[name];
70
+ if (message) {
71
+ form.setError(name, { type: 'server', message });
72
+ if (!focused) pendingFocus.current = name === 'lines' ? (values.lines.length ? 'lines.0.product' : undefined) : name;
73
+ focused = true;
74
+ }
75
+ }
76
+ form.setError('root.server', { type: 'server', message: result.message ?? 'Review the highlighted fields. Your draft is kept.' });
77
+ return;
78
+ }
79
+ form.reset(result.values);
80
+ setSaved(true);
81
+ } catch {
82
+ form.setError('root.server', { type: 'transport', message: 'Saving failed. Your draft is kept; retry Save order.' });
83
+ } finally { lock.current = false; }
84
+ });
85
+ return <Page maxWidth="xl"
86
+ render={<form id={`${id}-form`} onSubmit={submit} noValidate aria-busy={isSubmitting} />}
87
+ header={{ title: 'Edit order', description: 'Update customer, fulfillment and line items.' }}>
88
+ {isDirty && <DirtyStateBanner title="Unsaved changes" description="Save to commit this draft, or discard to restore the last saved version." />}
89
+ {summary.length > 0 && <ErrorSummary title="Order could not be saved" errors={summary} />}
90
+ {saved && !isDirty && <Text role="status">Order saved.</Text>}
91
+ <TwoColumnLayout adaptTo="container" main={<>
92
+ <FormSection title="Customer" description="The customer receives order updates at this address.">
93
+ <ControlledFormField control={form.control} name="reference" label="Order reference" required rules={{ required: 'Enter an order reference.' }}>
94
+ {(field, _error, invalid) => <Input ref={field.ref} name={field.name} value={field.value} onValueChange={value => field.onChange(value)} onBlur={field.onBlur} invalid={invalid} disabled={isSubmitting} />}
95
+ </ControlledFormField>
96
+ <ControlledFormField control={form.control} name="email" label="Customer email" required rules={{ required: 'Enter an email.', pattern: { value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: 'Enter a valid email.' } }}>
97
+ {(field, _error, invalid) => <Input type="email" ref={field.ref} name={field.name} value={field.value} onValueChange={value => field.onChange(value)} onBlur={field.onBlur} invalid={invalid} disabled={isSubmitting} />}
98
+ </ControlledFormField>
99
+ </FormSection>
100
+ <FormSection title="Line items" actions={<Button type="button" disabled={isSubmitting} onClick={() => lines.append({ product: '', quantity: 1, priceMinor: 0 })}>Add item</Button>}>
101
+ {lines.fields.map((line, index) => <Stack key={line.id} gap="md">
102
+ <ControlledFormField control={form.control} name={`lines.${index}.product`} label={`Item ${index + 1}`} rules={{ required: 'Enter a product.' }}>
103
+ {(field, _error, invalid) => <Input ref={field.ref} name={field.name} value={field.value} onValueChange={value => field.onChange(value)} onBlur={field.onBlur} invalid={invalid} disabled={isSubmitting} />}
104
+ </ControlledFormField>
105
+ <Stack direction={{ base: 'vertical', sm: 'horizontal' }} gap="md" align="end">
106
+ <ControlledFormField control={form.control} name={`lines.${index}.quantity`} label="Quantity" rules={{ validate: value => (Number.isFinite(value) && Number.isInteger(value) && value >= 1) || 'Enter a whole quantity of at least one.' }}>
107
+ {(field, _error, invalid) => <Input ref={field.ref} type="number" name={field.name} min={1} value={Number.isNaN(field.value) ? '' : String(field.value)} onChange={event => field.onChange(event.target.valueAsNumber)} onBlur={field.onBlur} invalid={invalid} disabled={isSubmitting} />}
108
+ </ControlledFormField>
109
+ <ControlledFormField control={form.control} name={`lines.${index}.priceMinor`} label="Unit price (cents)" rules={{ validate: value => (Number.isFinite(value) && Number.isInteger(value) && value >= 0) || 'Enter a whole price in cents of zero or more.' }}>
110
+ {(field, _error, invalid) => <Input ref={field.ref} type="number" name={field.name} min={0} value={Number.isNaN(field.value) ? '' : String(field.value)} onChange={event => field.onChange(event.target.valueAsNumber)} onBlur={field.onBlur} invalid={invalid} disabled={isSubmitting} />}
111
+ </ControlledFormField>
112
+ <Button type="button" disabled={isSubmitting || lines.fields.length < 2} onClick={() => lines.remove(index)}>Remove item {index + 1}</Button>
113
+ </Stack>
114
+ </Stack>)}
115
+ </FormSection>
116
+ <FormSection title="Internal notes">
117
+ <ControlledFormField control={form.control} name="notes" label="Notes" hint="Visible to your team only.">
118
+ {(field, _error, invalid) => <Textarea ref={field.ref} name={field.name} value={field.value} onValueChange={value => field.onChange(value)} onBlur={field.onBlur} invalid={invalid} disabled={isSubmitting} />}
119
+ </ControlledFormField>
120
+ </FormSection>
121
+ </>} aside={<>
122
+ <FormSection title="Fulfillment">
123
+ <ControlledFormField control={form.control} name="priority" label="Priority">
124
+ {(field, _error, invalid) => <Select ref={field.ref} name={field.name} value={field.value} onValueChange={value => field.onChange(value ?? '')} onBlur={field.onBlur} invalid={invalid} disabled={isSubmitting} options={[{ value: 'standard', label: 'Standard' }, { value: 'express', label: 'Express' }]} />}
125
+ </ControlledFormField>
126
+ <ControlledFormField control={form.control} name="notify">
127
+ {(field, _error, invalid) => <ToggleField label="Email customer on save" name={field.name} value={field.value} controlRef={field.ref} onBlur={field.onBlur} onValueChange={value => field.onChange(value)} invalid={invalid} disabled={isSubmitting} />}
128
+ </ControlledFormField>
129
+ </FormSection>
130
+ <FormSection title="Summary"><MetadataList items={[
131
+ { id: 'items', label: 'Line items', value: lines.fields.length },
132
+ { id: 'total', label: 'Draft total', value: <Money amount={totalMinor} currency="USD" unit="minor" /> },
133
+ ]} /></FormSection>
134
+ </>} />
135
+ <FormActionsBar sticky leading={isDirty ? 'Changes are not saved yet.' : 'All changes saved.'}>
136
+ <Button type="button" disabled={isSubmitting} onClick={onCancel}>Cancel</Button>
137
+ <Button type="button" disabled={isSubmitting || !isDirty} onClick={() => { form.reset(); setSaved(false); }}>Discard changes</Button>
138
+ <SubmitStateButton dirty={isDirty} disableWhenPristine submitting={isSubmitting}>Save order</SubmitStateButton>
139
+ </FormActionsBar>
140
+ </Page>;
141
+ }