themelia-react-ui 2.0.4 → 2.0.6

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 (715) hide show
  1. package/CHANGELOG.md +211 -0
  2. package/MIGRATION.md +119 -0
  3. package/README.md +122 -20
  4. package/dist/{accordion-96o0pN62.js → accordion-0tQUZ20r.js} +13 -13
  5. package/dist/accordion-0tQUZ20r.js.map +1 -0
  6. package/dist/{action-menu-CHgs8vmj.js → action-menu-C0gjzLyE.js} +48 -45
  7. package/dist/action-menu-C0gjzLyE.js.map +1 -0
  8. package/dist/{affordance-geometry.generated-B8yGOr8-.js → affordance-geometry.generated-P-aVJisu.js} +36 -36
  9. package/dist/affordance-geometry.generated-P-aVJisu.js.map +1 -0
  10. package/dist/{ai-artifact-BZUGwBq6.js → ai-artifact-CGGpQryR.js} +281 -230
  11. package/dist/ai-artifact-CGGpQryR.js.map +1 -0
  12. package/dist/app-shell-EHuuRDGy.js +321 -0
  13. package/dist/app-shell-EHuuRDGy.js.map +1 -0
  14. package/dist/{attachment-DkoqHPPl.js → attachment-BCpA4e7i.js} +10 -10
  15. package/dist/{attachment-DkoqHPPl.js.map → attachment-BCpA4e7i.js.map} +1 -1
  16. package/dist/{auth-D2FVZ1MH.js → auth-B0girIk_.js} +49 -52
  17. package/dist/auth-B0girIk_.js.map +1 -0
  18. package/dist/{avatar-DWO_HHhB.js → avatar-B9Jnp-T-.js} +8 -8
  19. package/dist/avatar-B9Jnp-T-.js.map +1 -0
  20. package/dist/{badge-DErMA7ul.js → badge-wWauMgAt.js} +5 -5
  21. package/dist/{badge-DErMA7ul.js.map → badge-wWauMgAt.js.map} +1 -1
  22. package/dist/base/accordion.js +1 -1
  23. package/dist/base/action-menu.js +1 -1
  24. package/dist/base/attachment.js +1 -1
  25. package/dist/base/avatar.js +1 -1
  26. package/dist/base/badge.js +1 -1
  27. package/dist/base/batch-action-bar.js +1 -1
  28. package/dist/base/buttons.js +1 -1
  29. package/dist/base/cards.js +2 -2
  30. package/dist/base/carousel.js +3 -3
  31. package/dist/base/cascader.js +2 -372
  32. package/dist/base/chart.js +1 -1
  33. package/dist/base/choice-inputs.js +2 -2
  34. package/dist/base/code-block.js +1 -1
  35. package/dist/base/combobox.js +2 -2
  36. package/dist/base/command.js +1 -1
  37. package/dist/base/copyable.js +1 -1
  38. package/dist/base/date-pickers.js +2 -2
  39. package/dist/base/display.js +6 -6
  40. package/dist/base/feedback.js +4 -4
  41. package/dist/base/forms-numeric.js +1 -1
  42. package/dist/base/forms.js +2 -2
  43. package/dist/base/inline-edit.js +10 -10
  44. package/dist/base/item.js +1 -1
  45. package/dist/base/media-gallery.js +1 -1
  46. package/dist/base/metadata-list.js +1 -1
  47. package/dist/base/navigation.js +7 -7
  48. package/dist/base/popover-menu.js +1 -1
  49. package/dist/base/popover.js +1 -1
  50. package/dist/base/qr-code.js +1 -1
  51. package/dist/base/repeaters.js +200 -193
  52. package/dist/base/repeaters.js.map +1 -1
  53. package/dist/base/sheet.js +1 -1
  54. package/dist/base/sidebar.js +2 -2
  55. package/dist/base/signature-pad.js +8 -8
  56. package/dist/base/signature-pad.js.map +1 -1
  57. package/dist/base/skeleton.js +1 -1
  58. package/dist/base/spinner.js +6 -6
  59. package/dist/base/spinner.js.map +1 -1
  60. package/dist/base/structure.js +1 -1
  61. package/dist/base/table.js +1 -1
  62. package/dist/base/text-inputs.js +2 -2
  63. package/dist/base/toaster.js +36 -36
  64. package/dist/base/toaster.js.map +1 -1
  65. package/dist/base/tree.js +1 -1
  66. package/dist/base/upload-queue.js +1 -1
  67. package/dist/base/upload.js +3 -3
  68. package/dist/base/value-inputs.js +1 -1
  69. package/dist/{batch-action-bar-CdfIkCsV.js → batch-action-bar-BoqWIIpV.js} +7 -7
  70. package/dist/batch-action-bar-BoqWIIpV.js.map +1 -0
  71. package/dist/blocks/admin.js +21 -21
  72. package/dist/blocks/admin.js.map +1 -1
  73. package/dist/blocks/ai.js +267 -247
  74. package/dist/blocks/ai.js.map +1 -1
  75. package/dist/blocks/analytics/usage-card.js +1 -1
  76. package/dist/blocks/analytics.js +537 -543
  77. package/dist/blocks/analytics.js.map +1 -1
  78. package/dist/blocks/collaboration.js +1 -1
  79. package/dist/blocks/commerce/receipt.js +1 -1
  80. package/dist/blocks/commerce.js +1330 -1250
  81. package/dist/blocks/commerce.js.map +1 -1
  82. package/dist/blocks/data-display.js +2 -2
  83. package/dist/blocks/onboarding.js +6 -6
  84. package/dist/blocks/onboarding.js.map +1 -1
  85. package/dist/blocks/planning.js +11 -11
  86. package/dist/blocks/timelines.js +1 -1
  87. package/dist/{breadcrumbs-B-WFKecD.js → breadcrumbs-Bp9Ke7kd.js} +7 -7
  88. package/dist/breadcrumbs-Bp9Ke7kd.js.map +1 -0
  89. package/dist/{button-DkmK-z8E.js → button-ChBovTx0.js} +3 -3
  90. package/dist/button-ChBovTx0.js.map +1 -0
  91. package/dist/{buttons-BbfzgczK.js → buttons-DeW0bQeK.js} +16 -16
  92. package/dist/buttons-DeW0bQeK.js.map +1 -0
  93. package/dist/cards-CNXnmvV5.js +69 -0
  94. package/dist/cards-CNXnmvV5.js.map +1 -0
  95. package/dist/cascader-CrAl9zD5.js +439 -0
  96. package/dist/cascader-CrAl9zD5.js.map +1 -0
  97. package/dist/chart-I7ROnsl8.js +162 -0
  98. package/dist/chart-I7ROnsl8.js.map +1 -0
  99. package/dist/{checkbox-CzYUTPeJ.js → checkbox-MoyHIAPs.js} +3 -3
  100. package/dist/{checkbox-CzYUTPeJ.js.map → checkbox-MoyHIAPs.js.map} +1 -1
  101. package/dist/choice-inputs-DHGtx0QV.js +789 -0
  102. package/dist/choice-inputs-DHGtx0QV.js.map +1 -0
  103. package/dist/{code-block-CGNaUtAE.js → code-block-BSJyq9e-.js} +9 -9
  104. package/dist/code-block-BSJyq9e-.js.map +1 -0
  105. package/dist/{collapsible-Do4G0zcC.js → collapsible-BzJ91LUG.js} +5 -5
  106. package/dist/{collapsible-Do4G0zcC.js.map → collapsible-BzJ91LUG.js.map} +1 -1
  107. package/dist/{collection-content-C0e8SsTm.js → collection-content-CSnwtOTH.js} +3 -3
  108. package/dist/{collection-content-C0e8SsTm.js.map → collection-content-CSnwtOTH.js.map} +1 -1
  109. package/dist/combobox-Bcvu5J8O.js +363 -0
  110. package/dist/combobox-Bcvu5J8O.js.map +1 -0
  111. package/dist/combobox-C2JiSQPc.js +915 -0
  112. package/dist/combobox-C2JiSQPc.js.map +1 -0
  113. package/dist/{command-D8NrBj-b.js → command-9e52NPgK.js} +11 -11
  114. package/dist/command-9e52NPgK.js.map +1 -0
  115. package/dist/{comments-Di4w0H_S.js → comments-BsgErEqd.js} +44 -39
  116. package/dist/comments-BsgErEqd.js.map +1 -0
  117. package/dist/components/base/action-menu/action-menu.d.ts +7 -1
  118. package/dist/components/base/buttons/button-group.recipes.d.ts +2 -2
  119. package/dist/components/base/cards/card.recipes.d.ts +6 -4
  120. package/dist/components/base/cards/partials/card-primitives.d.ts +9 -2
  121. package/dist/components/base/cards/partials/smart-card-header-row.d.ts +3 -1
  122. package/dist/components/base/cards/smart-card.types.d.ts +3 -4
  123. package/dist/components/base/cascader/cascader-panel.d.ts +76 -0
  124. package/dist/components/base/chart/chart.d.ts +6 -1
  125. package/dist/components/base/choice-inputs/choice-types.d.ts +5 -1
  126. package/dist/components/base/choice-inputs/pill-radio-group.d.ts +7 -6
  127. package/dist/components/base/combobox/combobox-field.d.ts +2 -2
  128. package/dist/components/base/combobox/index.d.ts +4 -2
  129. package/dist/components/base/date-pickers/date-picker-internals.d.ts +3 -1
  130. package/dist/components/base/date-pickers/datepicker.types.d.ts +10 -4
  131. package/dist/components/base/date-pickers/time-picker.d.ts +17 -3
  132. package/dist/components/base/feedback/alert.d.ts +1 -1
  133. package/dist/components/base/feedback/state-display.d.ts +5 -1
  134. package/dist/components/base/feedback/state-display.strings.d.ts +9 -0
  135. package/dist/components/base/forms/form-field.d.ts +7 -2
  136. package/dist/components/base/forms/form-sizing.d.ts +7 -7
  137. package/dist/components/base/forms/workflow.d.ts +7 -1
  138. package/dist/components/base/forms-numeric/coordinates-input.d.ts +8 -1
  139. package/dist/components/base/forms-numeric/decimal-input.d.ts +2 -2
  140. package/dist/components/base/forms-numeric/dimensions-input.d.ts +4 -1
  141. package/dist/components/base/forms-numeric/numeric-composite-field.d.ts +12 -0
  142. package/dist/components/base/forms-numeric/weight-input.d.ts +6 -1
  143. package/dist/components/base/metadata-list/metadata-list.d.ts +1 -1
  144. package/dist/components/base/navigation/dropdown-menu.d.ts +1 -1
  145. package/dist/components/base/navigation/language-switcher.d.ts +12 -4
  146. package/dist/components/base/navigation/page-header/page-header-commands.d.ts +14 -7
  147. package/dist/components/base/navigation/page-header/page-header.d.ts +10 -3
  148. package/dist/components/base/popover/popover.d.ts +3 -3
  149. package/dist/components/base/popover/popover.recipes.d.ts +10 -6
  150. package/dist/components/base/repeaters/key-value-editor.d.ts +2 -1
  151. package/dist/components/base/sheet/sheet.d.ts +2 -0
  152. package/dist/components/base/sidebar/index.d.ts +1 -1
  153. package/dist/components/base/sidebar/sidebar.d.ts +29 -5
  154. package/dist/components/base/toaster/index.d.ts +1 -0
  155. package/dist/components/base/upload/avatar-upload.d.ts +2 -1
  156. package/dist/components/base/upload/image-upload.d.ts +2 -1
  157. package/dist/components/blocks/ai/ai-citation/types.d.ts +2 -0
  158. package/dist/components/blocks/ai/ai-file-tree/types.d.ts +1 -1
  159. package/dist/components/blocks/ai/ai-reasoning/types.d.ts +2 -0
  160. package/dist/components/blocks/ai/ai-sources/types.d.ts +2 -0
  161. package/dist/components/blocks/ai/ai-tool-call/types.d.ts +5 -1
  162. package/dist/components/blocks/ai/ai.strings.d.ts +2 -0
  163. package/dist/components/blocks/analytics/metric/metric.d.ts +4 -0
  164. package/dist/components/blocks/analytics/metric-comparison/metric-comparison.d.ts +4 -0
  165. package/dist/components/blocks/analytics/metric-grid/metric-grid.d.ts +4 -5
  166. package/dist/components/blocks/analytics/types.d.ts +2 -2
  167. package/dist/components/blocks/analytics/usage-card/usage-card.strings.d.ts +2 -0
  168. package/dist/components/blocks/commerce/cart-summary/cart-summary.d.ts +1 -1
  169. package/dist/components/blocks/commerce/cart-summary/types.d.ts +3 -1
  170. package/dist/components/blocks/commerce/discount-stack/discount-stack.d.ts +1 -1
  171. package/dist/components/blocks/commerce/discount-stack/types.d.ts +3 -1
  172. package/dist/components/blocks/commerce/fulfillment-group/fulfillment-group.d.ts +1 -1
  173. package/dist/components/blocks/commerce/fulfillment-group/types.d.ts +11 -2
  174. package/dist/components/blocks/commerce/index.d.ts +7 -6
  175. package/dist/components/blocks/commerce/inventory-section/inventory-section.d.ts +1 -1
  176. package/dist/components/blocks/commerce/inventory-section/types.d.ts +7 -2
  177. package/dist/components/blocks/commerce/invoice-header/index.d.ts +2 -1
  178. package/dist/components/blocks/commerce/invoice-header/invoice-header.d.ts +1 -1
  179. package/dist/components/blocks/commerce/invoice-header/types.d.ts +20 -6
  180. package/dist/components/blocks/commerce/invoice-line-items/invoice-line-items.d.ts +1 -1
  181. package/dist/components/blocks/commerce/invoice-line-items/types.d.ts +24 -7
  182. package/dist/components/blocks/commerce/invoice-mini/index.d.ts +2 -1
  183. package/dist/components/blocks/commerce/invoice-mini/types.d.ts +7 -1
  184. package/dist/components/blocks/commerce/order-customer/order-customer.d.ts +1 -1
  185. package/dist/components/blocks/commerce/order-customer/types.d.ts +9 -1
  186. package/dist/components/blocks/commerce/order-status/types.d.ts +4 -0
  187. package/dist/components/blocks/commerce/refund-status/refund-status.d.ts +1 -1
  188. package/dist/components/blocks/commerce/refund-status/types.d.ts +3 -1
  189. package/dist/components/blocks/commerce/shipment-tracking/shipment-tracking.d.ts +1 -1
  190. package/dist/components/blocks/commerce/shipment-tracking/types.d.ts +3 -1
  191. package/dist/components/blocks/commerce/tax-breakdown/tax-breakdown.d.ts +1 -1
  192. package/dist/components/blocks/commerce/tax-breakdown/types.d.ts +3 -1
  193. package/dist/components/blocks/data-display/empty-state/empty-state.types.d.ts +4 -3
  194. package/dist/components/features/activities/activities.types.d.ts +26 -13
  195. package/dist/components/features/activities/hooks/use-activity-resources.d.ts +2 -1
  196. package/dist/components/features/activities/partials/activity-marker.d.ts +7 -3
  197. package/dist/components/features/activities/partials/activity-row.d.ts +24 -0
  198. package/dist/components/features/ai-chat/hooks/use-ai-chat-scroll.d.ts +1 -1
  199. package/dist/components/features/appointment-calendar/appointment-calendar.d.ts +1 -1
  200. package/dist/components/features/appointment-calendar/appointment-calendar.types.d.ts +4 -2
  201. package/dist/components/features/combobox/async-resource-combobox.d.ts +2 -2
  202. package/dist/components/features/combobox/combobox.d.ts +2 -2
  203. package/dist/components/features/combobox/hooks/use-combobox-core.d.ts +2 -1
  204. package/dist/components/features/combobox/hooks/use-combobox-state.d.ts +1 -0
  205. package/dist/components/features/combobox/hooks/use-load-more.d.ts +1 -0
  206. package/dist/components/features/combobox/types.d.ts +37 -8
  207. package/dist/components/features/email-composer/types.d.ts +3 -1
  208. package/dist/components/features/event-calendar/colors.d.ts +2 -2
  209. package/dist/components/features/event-calendar/event-calendar.types.d.ts +4 -0
  210. package/dist/components/features/filters/facets/date-facet.d.ts +4 -2
  211. package/dist/components/features/filters/facets/range-facet.d.ts +12 -0
  212. package/dist/components/features/filters/facets/select-facet.d.ts +2 -1
  213. package/dist/components/features/filters/filters.strings.d.ts +4 -0
  214. package/dist/components/features/filters/filters.types.d.ts +6 -3
  215. package/dist/components/features/filters/partials/date-filter-content.d.ts +3 -2
  216. package/dist/components/features/filters/partials/filter-editor-header.d.ts +16 -0
  217. package/dist/components/features/filters/partials/filter-popover-content.d.ts +5 -3
  218. package/dist/components/features/filters/partials/nested-filter-options.d.ts +21 -0
  219. package/dist/components/features/filters/partials/range-filter-content.d.ts +12 -0
  220. package/dist/components/features/filters/partials/regular-filter-content.d.ts +2 -1
  221. package/dist/components/features/filters/utils/filter-utils.d.ts +25 -3
  222. package/dist/components/features/global-search/global-search.types.d.ts +2 -0
  223. package/dist/components/features/global-search/partials/global-search-input.d.ts +10 -0
  224. package/dist/components/features/global-search/partials/global-search-result-row.d.ts +7 -1
  225. package/dist/components/features/media-library/hooks/use-media-library.d.ts +1 -1
  226. package/dist/components/features/media-library/media-library.d.ts +1 -1
  227. package/dist/components/features/media-library/media-library.strings.d.ts +8 -0
  228. package/dist/components/features/media-library/media-library.types.d.ts +50 -12
  229. package/dist/components/features/media-library/partials/media-library-partials.d.ts +4 -4
  230. package/dist/components/features/mentions/hooks/use-mentions.d.ts +16 -1
  231. package/dist/components/features/mentions/partials/mention-inline-suggestions.d.ts +5 -1
  232. package/dist/components/features/mentions/utils/split-html-by-mentions.d.ts +1 -7
  233. package/dist/components/features/overlays/hooks/use-overlay-visibility.d.ts +2 -2
  234. package/dist/components/features/products/components/product-options-matrix.d.ts +1 -1
  235. package/dist/components/features/products/components/product-variant-editor.d.ts +1 -1
  236. package/dist/components/features/products/components/product-variants-manager.d.ts +1 -1
  237. package/dist/components/features/products/products.strings.d.ts +9 -1
  238. package/dist/components/features/products/products.types.d.ts +45 -8
  239. package/dist/components/features/questionnaire/questionnaire.types.d.ts +3 -0
  240. package/dist/components/features/resource/resource.d.ts +6 -2
  241. package/dist/components/features/resource/resource.types.d.ts +14 -1
  242. package/dist/components/features/rich-text-editor/form-rich-text-editor.d.ts +1 -1
  243. package/dist/components/features/rich-text-editor/partials/caret-helpers.d.ts +1 -1
  244. package/dist/components/features/rich-text-editor/partials/editor-field-aria.d.ts +14 -0
  245. package/dist/components/features/rich-text-editor/partials/image-uploads.d.ts +1 -1
  246. package/dist/components/features/rich-text-editor/partials/rich-text-editor-toolbar.d.ts +3 -1
  247. package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +12 -2
  248. package/dist/components/features/rich-text-editor/rich-text-editor.types.d.ts +17 -3
  249. package/dist/components/features/schema-form/hooks/use-schema-form.d.ts +5 -1
  250. package/dist/components/features/schema-form/partials/schema-form-field.d.ts +3 -1
  251. package/dist/components/features/schema-form/schema-form.utils.d.ts +1 -1
  252. package/dist/components/features/suggestions/suggestions.types.d.ts +1 -1
  253. package/dist/components/features/table/data-table.d.ts +1 -1
  254. package/dist/components/features/table/index.d.ts +1 -0
  255. package/dist/components/features/table/partials/resource-cell.d.ts +22 -5
  256. package/dist/components/features/table/table-body.d.ts +1 -1
  257. package/dist/components/features/table/table-helpers.d.ts +6 -3
  258. package/dist/components/features/table/table.strings.d.ts +3 -0
  259. package/dist/components/features/table/table.types.d.ts +18 -2
  260. package/dist/components/layout/app-shell/app-shell.types.d.ts +35 -6
  261. package/dist/components/layout/app-shell/index.d.ts +1 -1
  262. package/dist/components/layout/app-shell/shell-regions.d.ts +27 -0
  263. package/dist/components/layout/app-shell/sidebar-inset-layout.d.ts +1 -1
  264. package/dist/components/layout/app-shell/stacked-layout.d.ts +1 -1
  265. package/dist/components/layout/app-shell/topbar-sidebar-layout.d.ts +1 -1
  266. package/dist/components/layout/containers/two-column-layout.d.ts +2 -0
  267. package/dist/components/layout/header/header.recipes.d.ts +6 -0
  268. package/dist/components/layout/header/header.types.d.ts +9 -8
  269. package/dist/components/layout/layout.types.d.ts +5 -3
  270. package/dist/components/layout/navigation/section-nav/section-nav.d.ts +5 -0
  271. package/dist/components/layout/navigation/side-nav.d.ts +3 -2
  272. package/dist/components/layout/normalize-layout-path.d.ts +1 -0
  273. package/dist/components/layout/page/index.d.ts +2 -1
  274. package/dist/components/layout/page/page.d.ts +1 -0
  275. package/dist/components/layout/page/page.strings.d.ts +11 -0
  276. package/dist/components/layout/page/page.types.d.ts +69 -17
  277. package/dist/components/layout/page/partials/page-header.d.ts +1 -1
  278. package/dist/components/layout/settings/settings.d.ts +10 -3
  279. package/dist/components/layout/sidebar/app-sidebar.d.ts +1 -1
  280. package/dist/components/layout/sidebar/components/sidebar-grouped-navigation.d.ts +1 -1
  281. package/dist/components/layout/sidebar/components/sidebar-navigation.d.ts +1 -1
  282. package/dist/components/layout/sidebar/index.d.ts +2 -1
  283. package/dist/components/layout/sidebar/sidebar-navigation-rail.d.ts +38 -0
  284. package/dist/components/layout/sidebar/sidebar.context.d.ts +6 -7
  285. package/dist/components/layout/sidebar/sidebar.types.d.ts +50 -10
  286. package/dist/components/layout/sidebar/sidebar.utils.d.ts +9 -1
  287. package/dist/components/layout/workspace/workspace.types.d.ts +8 -1
  288. package/dist/components/primitives/link.d.ts +3 -2
  289. package/dist/components/primitives/money.d.ts +1 -1
  290. package/dist/components/primitives/number.d.ts +1 -1
  291. package/dist/components/typography/rich-text/rich-text-tree.d.ts +7 -5
  292. package/dist/components/ui/alert-dialog.d.ts +2 -2
  293. package/dist/components/ui/combobox.d.ts +1 -1
  294. package/dist/components/ui/dialog.d.ts +2 -2
  295. package/dist/components/ui/overlay-layer.d.ts +18 -0
  296. package/dist/components/ui/sheet.d.ts +5 -1
  297. package/dist/components/ui/sidebar-state.d.ts +82 -0
  298. package/dist/components/ui/sidebar.d.ts +5 -17
  299. package/dist/{containers-CRmHf7GP.js → containers-CSdc32h9.js} +26 -18
  300. package/dist/containers-CSdc32h9.js.map +1 -0
  301. package/dist/{control-group-recipes-DBXmfh2E.js → control-group-recipes-fMuFo0H7.js} +6 -6
  302. package/dist/control-group-recipes-fMuFo0H7.js.map +1 -0
  303. package/dist/{copyable-CnGCZdX4.js → copyable-3fdHfMR3.js} +7 -7
  304. package/dist/{copyable-CnGCZdX4.js.map → copyable-3fdHfMR3.js.map} +1 -1
  305. package/dist/{data-display-D4oujtx0.js → data-display-Cmj-xZYl.js} +271 -279
  306. package/dist/data-display-Cmj-xZYl.js.map +1 -0
  307. package/dist/{date-Q7jnXxpk.js → date-Br0FicVv.js} +5 -5
  308. package/dist/{date-Q7jnXxpk.js.map → date-Br0FicVv.js.map} +1 -1
  309. package/dist/date-picker-CyQlFYsP.js +1617 -0
  310. package/dist/date-picker-CyQlFYsP.js.map +1 -0
  311. package/dist/date-pickers-tj2MXmXd.js +185 -0
  312. package/dist/date-pickers-tj2MXmXd.js.map +1 -0
  313. package/dist/{display-BB4BL_-K.js → display-CT_N2a3w.js} +9 -9
  314. package/dist/{display-BB4BL_-K.js.map → display-CT_N2a3w.js.map} +1 -1
  315. package/dist/dropdown-menu-C08iIugv.js +194 -0
  316. package/dist/dropdown-menu-C08iIugv.js.map +1 -0
  317. package/dist/features/activities.js +388 -326
  318. package/dist/features/activities.js.map +1 -1
  319. package/dist/features/ai-chat.js +46 -32
  320. package/dist/features/ai-chat.js.map +1 -1
  321. package/dist/features/appointment-calendar.js +130 -130
  322. package/dist/features/appointment-calendar.js.map +1 -1
  323. package/dist/features/async-preview.js +11 -10
  324. package/dist/features/async-preview.js.map +1 -1
  325. package/dist/features/combobox.js +1 -1
  326. package/dist/features/comments.js +1 -1
  327. package/dist/features/data-view.js +13 -13
  328. package/dist/features/data-view.js.map +1 -1
  329. package/dist/features/email-composer.js +243 -239
  330. package/dist/features/email-composer.js.map +1 -1
  331. package/dist/features/event-calendar.js +197 -199
  332. package/dist/features/event-calendar.js.map +1 -1
  333. package/dist/features/filters.js +2 -2
  334. package/dist/features/global-search.js +168 -143
  335. package/dist/features/global-search.js.map +1 -1
  336. package/dist/features/kanban.js +19 -30
  337. package/dist/features/kanban.js.map +1 -1
  338. package/dist/features/map/style.css +15 -0
  339. package/dist/features/map.js +369 -343
  340. package/dist/features/map.js.map +1 -1
  341. package/dist/features/media-library.js +1202 -975
  342. package/dist/features/media-library.js.map +1 -1
  343. package/dist/features/mentions.js +2 -2
  344. package/dist/features/overlays.js +1 -1
  345. package/dist/features/products.js +1270 -1183
  346. package/dist/features/products.js.map +1 -1
  347. package/dist/features/questionnaire.js +160 -153
  348. package/dist/features/questionnaire.js.map +1 -1
  349. package/dist/features/resource-assignment.js +8 -8
  350. package/dist/features/resource.js +119 -113
  351. package/dist/features/resource.js.map +1 -1
  352. package/dist/features/rich-text-editor.js +28 -19
  353. package/dist/features/rich-text-editor.js.map +1 -1
  354. package/dist/features/schema-form.js +297 -256
  355. package/dist/features/schema-form.js.map +1 -1
  356. package/dist/features/suggestions.js +57 -50
  357. package/dist/features/suggestions.js.map +1 -1
  358. package/dist/features/sync.js +3 -3
  359. package/dist/features/table.js +1 -1
  360. package/dist/features/theme-tweaker.js +470 -470
  361. package/dist/features/theme-tweaker.js.map +1 -1
  362. package/dist/feedback-Dzo1xtAU.js +246 -0
  363. package/dist/feedback-Dzo1xtAU.js.map +1 -0
  364. package/dist/{field-affordance-recipes-DjwGx8eM.js → field-affordance-recipes-D6H7tVJi.js} +5 -5
  365. package/dist/field-affordance-recipes-D6H7tVJi.js.map +1 -0
  366. package/dist/field-control-attributes-B6i335wr.js +18 -0
  367. package/dist/field-control-attributes-B6i335wr.js.map +1 -0
  368. package/dist/{field-state-recipes-BVA2CWHo.js → field-state-recipes-7sza8QbC.js} +4 -2
  369. package/dist/{field-state-recipes-BVA2CWHo.js.map → field-state-recipes-7sza8QbC.js.map} +1 -1
  370. package/dist/filters-Dl80yYtN.js +2415 -0
  371. package/dist/filters-Dl80yYtN.js.map +1 -0
  372. package/dist/form-field-CAPdwdnZ.js +74 -0
  373. package/dist/form-field-CAPdwdnZ.js.map +1 -0
  374. package/dist/{form-sizing-NXgjkmBG.js → form-sizing-CgcrUbLU.js} +5 -5
  375. package/dist/form-sizing-CgcrUbLU.js.map +1 -0
  376. package/dist/{forms-BV5m5aQF.js → forms-B3W8CH7-.js} +17 -13
  377. package/dist/forms-B3W8CH7-.js.map +1 -0
  378. package/dist/forms-numeric-CwjQJe-O.js +991 -0
  379. package/dist/forms-numeric-CwjQJe-O.js.map +1 -0
  380. package/dist/{header-BA697l4a.js → header-ZIIsRKxP.js} +145 -141
  381. package/dist/header-ZIIsRKxP.js.map +1 -0
  382. package/dist/header.recipes-BigdJjw1.js +6 -0
  383. package/dist/header.recipes-BigdJjw1.js.map +1 -0
  384. package/dist/hooks/use-files.d.ts +2 -0
  385. package/dist/{hooks-BQ-L7Uu2.js → hooks-BitHSh-Y.js} +27 -15
  386. package/dist/hooks-BitHSh-Y.js.map +1 -0
  387. package/dist/{icon-badge-COWbCCWu.js → icon-badge-npxF1SLX.js} +4 -4
  388. package/dist/{icon-badge-COWbCCWu.js.map → icon-badge-npxF1SLX.js.map} +1 -1
  389. package/dist/index.js +4 -5
  390. package/dist/{input-Cdw4k0fb.js → input-7KAc7XQL.js} +9 -9
  391. package/dist/{input-Cdw4k0fb.js.map → input-7KAc7XQL.js.map} +1 -1
  392. package/dist/input-DIREVYHs.js +21 -0
  393. package/dist/input-DIREVYHs.js.map +1 -0
  394. package/dist/{interaction-recipes-XR9ZpVYL.js → interaction-recipes-4wZ2tvfb.js} +2 -2
  395. package/dist/{interaction-recipes-XR9ZpVYL.js.map → interaction-recipes-4wZ2tvfb.js.map} +1 -1
  396. package/dist/item-FfWnaYST.js +278 -0
  397. package/dist/item-FfWnaYST.js.map +1 -0
  398. package/dist/layout/app-shell.js +1 -1
  399. package/dist/layout/auth.js +1 -1
  400. package/dist/layout/containers.js +1 -1
  401. package/dist/layout/header.js +1 -1
  402. package/dist/layout/hooks.js +1 -1
  403. package/dist/layout/navigation.js +1 -1
  404. package/dist/layout/page.js +2 -2
  405. package/dist/layout/settings.js +1 -1
  406. package/dist/layout/sidebar.js +3 -3
  407. package/dist/layout/workspace.js +1 -1
  408. package/dist/layout.js +12 -12
  409. package/dist/layout.types-E_GAApzO.js +30 -0
  410. package/dist/layout.types-E_GAApzO.js.map +1 -0
  411. package/dist/lib/affordance-geometry.generated.d.ts +35 -35
  412. package/dist/lib/control-group-recipes.d.ts +5 -5
  413. package/dist/lib/field-affordance-recipes.d.ts +2 -2
  414. package/dist/lib/field-control-attributes.d.ts +11 -0
  415. package/dist/lib/field-state-recipes.d.ts +2 -0
  416. package/dist/lib/format.d.ts +1 -0
  417. package/dist/lib/motion-recipes.d.ts +3 -0
  418. package/dist/lib/navigation-row-recipes.d.ts +7 -7
  419. package/dist/lib/overlay-anatomy-recipes.d.ts +3 -3
  420. package/dist/lib/portal-recipes.d.ts +3 -0
  421. package/dist/lib/surface-recipes.d.ts +1 -1
  422. package/dist/lib/token-merge.generated.d.ts +18 -15
  423. package/dist/lib/utils.js +1 -1
  424. package/dist/map-demo-tile.svg +1 -1
  425. package/dist/{media-gallery-CSl5W1Fy.js → media-gallery-C81DAnKI.js} +6 -6
  426. package/dist/{media-gallery-CSl5W1Fy.js.map → media-gallery-C81DAnKI.js.map} +1 -1
  427. package/dist/{mentions-RKOQaaIB.js → mentions-qOnedSt4.js} +237 -168
  428. package/dist/mentions-qOnedSt4.js.map +1 -0
  429. package/dist/message-BJHnn43M.js +135 -0
  430. package/dist/message-BJHnn43M.js.map +1 -0
  431. package/dist/{metadata-list-qVV7AVxa.js → metadata-list-XkqZ_UXH.js} +64 -64
  432. package/dist/metadata-list-XkqZ_UXH.js.map +1 -0
  433. package/dist/{motion-recipes-ChBg4HBq.js → motion-recipes-DitYv6P2.js} +10 -2
  434. package/dist/motion-recipes-DitYv6P2.js.map +1 -0
  435. package/dist/navigation-BgtPJAhi.js +288 -0
  436. package/dist/navigation-BgtPJAhi.js.map +1 -0
  437. package/dist/navigation-Bt-v7rWP.js +261 -0
  438. package/dist/navigation-Bt-v7rWP.js.map +1 -0
  439. package/dist/{navigation-row-recipes-WZEs-hYo.js → navigation-row-recipes-BGVLvU_O.js} +9 -9
  440. package/dist/navigation-row-recipes-BGVLvU_O.js.map +1 -0
  441. package/dist/normalize-layout-path-BmEgg6fu.js +14 -0
  442. package/dist/normalize-layout-path-BmEgg6fu.js.map +1 -0
  443. package/dist/{number-E_OiIfJz.js → number-CYqBcrSj.js} +79 -87
  444. package/dist/number-CYqBcrSj.js.map +1 -0
  445. package/dist/overflow-tab-bar-BQCA2Zn2.js +172 -0
  446. package/dist/overflow-tab-bar-BQCA2Zn2.js.map +1 -0
  447. package/dist/overlays-CC8zI3Du.js +1017 -0
  448. package/dist/overlays-CC8zI3Du.js.map +1 -0
  449. package/dist/page-BoQ1VaFJ.js +331 -0
  450. package/dist/page-BoQ1VaFJ.js.map +1 -0
  451. package/dist/page-header-commands-DIKspJfx.js +193 -0
  452. package/dist/page-header-commands-DIKspJfx.js.map +1 -0
  453. package/dist/{pagination-Ch8X_47u.js → pagination-Br8TdV9A.js} +7 -7
  454. package/dist/{pagination-Ch8X_47u.js.map → pagination-Br8TdV9A.js.map} +1 -1
  455. package/dist/popover-k8TdUcAt.js +201 -0
  456. package/dist/popover-k8TdUcAt.js.map +1 -0
  457. package/dist/{popover-menu-BYaCdFhf.js → popover-menu-yn-o0kyA.js} +7 -7
  458. package/dist/{popover-menu-BYaCdFhf.js.map → popover-menu-yn-o0kyA.js.map} +1 -1
  459. package/dist/{popover.recipes-D3j8R8Yp.js → popover.recipes-DJ0AkUan.js} +19 -12
  460. package/dist/popover.recipes-DJ0AkUan.js.map +1 -0
  461. package/dist/portal-recipes-DyUXqUtD.js +9 -0
  462. package/dist/portal-recipes-DyUXqUtD.js.map +1 -0
  463. package/dist/{primitives-Du64iDbb.js → primitives-BkkQjYl7.js} +23 -18
  464. package/dist/primitives-BkkQjYl7.js.map +1 -0
  465. package/dist/primitives.js +4 -4
  466. package/dist/{progress-BvF2oCdV.js → progress-DZFXXzPs.js} +9 -9
  467. package/dist/{progress-BvF2oCdV.js.map → progress-DZFXXzPs.js.map} +1 -1
  468. package/dist/{receipt-D789Jwyy.js → receipt-C7LhOg7Q.js} +7 -7
  469. package/dist/receipt-C7LhOg7Q.js.map +1 -0
  470. package/dist/rich-text-BnTzZjIo.js +45 -0
  471. package/dist/rich-text-BnTzZjIo.js.map +1 -0
  472. package/dist/{rich-text-editor-Cm1dpUpQ.js → rich-text-editor-CAurDwT5.js} +501 -424
  473. package/dist/rich-text-editor-CAurDwT5.js.map +1 -0
  474. package/dist/rich-text-editor-toolbar-DbXig7Jk.js +99 -0
  475. package/dist/rich-text-editor-toolbar-DbXig7Jk.js.map +1 -0
  476. package/dist/rich-text-tree-BqyQ_7-R.js +66 -0
  477. package/dist/rich-text-tree-BqyQ_7-R.js.map +1 -0
  478. package/dist/{sanitize-html-DsQmI48u.js → sanitize-html-BWkH4dLM.js} +29 -16
  479. package/dist/sanitize-html-BWkH4dLM.js.map +1 -0
  480. package/dist/{scroll-area-La5RXsEk.js → scroll-area-Bj6CRUif.js} +2 -2
  481. package/dist/{scroll-area-La5RXsEk.js.map → scroll-area-Bj6CRUif.js.map} +1 -1
  482. package/dist/{separator-DAEV0w65.js → separator-B9ewiCGO.js} +2 -2
  483. package/dist/{separator-DAEV0w65.js.map → separator-B9ewiCGO.js.map} +1 -1
  484. package/dist/{separator-GNfPG-90.js → separator-DM6gs2vu.js} +3 -3
  485. package/dist/{separator-GNfPG-90.js.map → separator-DM6gs2vu.js.map} +1 -1
  486. package/dist/services/actions.js +1 -1
  487. package/dist/settings-DZPHgpx4.js +155 -0
  488. package/dist/settings-DZPHgpx4.js.map +1 -0
  489. package/dist/sheet-C4DHsgLk.js +250 -0
  490. package/dist/sheet-C4DHsgLk.js.map +1 -0
  491. package/dist/sidebar-C8BnDwTH.js +709 -0
  492. package/dist/sidebar-C8BnDwTH.js.map +1 -0
  493. package/dist/sidebar-CmD6a-HK.js +1004 -0
  494. package/dist/sidebar-CmD6a-HK.js.map +1 -0
  495. package/dist/skeleton-DDgdhmu9.js +265 -0
  496. package/dist/skeleton-DDgdhmu9.js.map +1 -0
  497. package/dist/smart-card-B6vLxqa_.js +617 -0
  498. package/dist/smart-card-B6vLxqa_.js.map +1 -0
  499. package/dist/{structure-C0V0_Fyf.js → structure-DZJ2wbAU.js} +2 -2
  500. package/dist/{structure-C0V0_Fyf.js.map → structure-DZJ2wbAU.js.map} +1 -1
  501. package/dist/style.css +1 -1
  502. package/dist/{surface-recipes-BKRVW8Os.js → surface-recipes-C8mNycaY.js} +2 -2
  503. package/dist/{surface-recipes-BKRVW8Os.js.map → surface-recipes-C8mNycaY.js.map} +1 -1
  504. package/dist/{table-DH7rozUv.js → table-CBonSdTp.js} +573 -519
  505. package/dist/table-CBonSdTp.js.map +1 -0
  506. package/dist/{table-CpvnzJn9.js → table-CXSPHH25.js} +75 -71
  507. package/dist/table-CXSPHH25.js.map +1 -0
  508. package/dist/tabs-C4Kr_hCr.js +192 -0
  509. package/dist/tabs-C4Kr_hCr.js.map +1 -0
  510. package/dist/{text-inputs-DXItiR0O.js → text-inputs-jdkS3ReG.js} +18 -18
  511. package/dist/text-inputs-jdkS3ReG.js.map +1 -0
  512. package/dist/theme.css +40 -37
  513. package/dist/{timelines-DmtztAY_.js → timelines-CoPwdJP0.js} +13 -12
  514. package/dist/timelines-CoPwdJP0.js.map +1 -0
  515. package/dist/tooltip-31NwIpTo.js +113 -0
  516. package/dist/tooltip-31NwIpTo.js.map +1 -0
  517. package/dist/{tree-CV11PURP.js → tree-CeYVzdFE.js} +9 -9
  518. package/dist/{tree-CV11PURP.js.map → tree-CeYVzdFE.js.map} +1 -1
  519. package/dist/typography/rich-text.js +1 -1
  520. package/dist/{typography-CSyJrh28.js → typography-C7-YMW1S.js} +12 -12
  521. package/dist/{typography-CSyJrh28.js.map → typography-C7-YMW1S.js.map} +1 -1
  522. package/dist/typography.js +1 -1
  523. package/dist/ui-provider-C-74NVLc.js +178 -0
  524. package/dist/ui-provider-C-74NVLc.js.map +1 -0
  525. package/dist/ui-provider.js +2 -3
  526. package/dist/{upload-C9SA0X-8.js → upload-Hdm5gObf.js} +309 -296
  527. package/dist/upload-Hdm5gObf.js.map +1 -0
  528. package/dist/{upload-queue-DhQJiSRc.js → upload-queue-D0sYPuqo.js} +16 -14
  529. package/dist/upload-queue-D0sYPuqo.js.map +1 -0
  530. package/dist/{usage-card-DVTRDmGz.js → usage-card-9s8hLDfn.js} +24 -17
  531. package/dist/usage-card-9s8hLDfn.js.map +1 -0
  532. package/dist/{utils-CF3c95Io.js → utils-DhuoqFy4.js} +255 -165
  533. package/dist/utils-DhuoqFy4.js.map +1 -0
  534. package/dist/value-inputs-D3aPgq9H.js +980 -0
  535. package/dist/value-inputs-D3aPgq9H.js.map +1 -0
  536. package/dist/{value-typography-ClupF0Gz.js → value-typography-uSzzG9Gf.js} +32 -26
  537. package/dist/value-typography-uSzzG9Gf.js.map +1 -0
  538. package/dist/{workspace-9EFVXUyk.js → workspace-CC8Vchiu.js} +51 -50
  539. package/dist/workspace-CC8Vchiu.js.map +1 -0
  540. package/docs/consumer-skill/SKILL.md +4 -3
  541. package/docs/consumer-skill/agents/themelia-ui-designer.md +96 -0
  542. package/docs/consumer-skill/examples/app-layout.tsx +52 -1
  543. package/docs/consumer-skill/examples/commerce-lines.tsx +271 -0
  544. package/docs/consumer-skill/examples/custom-composition.tsx +21 -0
  545. package/docs/consumer-skill/examples/detail.tsx +5 -4
  546. package/docs/consumer-skill/examples/edit.tsx +3 -3
  547. package/docs/consumer-skill/examples/editable-sections.tsx +38 -0
  548. package/docs/consumer-skill/examples/index-table.tsx +4 -4
  549. package/docs/consumer-skill/examples/manifest.json +38 -1
  550. package/docs/consumer-skill/examples/product-media.tsx +41 -0
  551. package/docs/consumer-skill/examples/product-parts.tsx +81 -0
  552. package/docs/consumer-skill/examples/rhf-edit-page.tsx +1 -1
  553. package/docs/consumer-skill/examples/rhf-overlay-form.tsx +24 -11
  554. package/docs/consumer-skill/examples/token-domain-structure.tsx +68 -0
  555. package/docs/consumer-skill/references/agents-md.md +21 -19
  556. package/docs/consumer-skill/references/analytics.md +33 -1
  557. package/docs/consumer-skill/references/commerce-composition.md +97 -0
  558. package/docs/consumer-skill/references/component-contracts.json +21249 -14205
  559. package/docs/consumer-skill/references/composition-mapping.md +17 -3
  560. package/docs/consumer-skill/references/composition.md +177 -32
  561. package/docs/consumer-skill/references/critique-rubric.md +98 -0
  562. package/docs/consumer-skill/references/custom-composition.md +261 -0
  563. package/docs/consumer-skill/references/data-reading.md +79 -0
  564. package/docs/consumer-skill/references/design-contract.md +12 -9
  565. package/docs/consumer-skill/references/discovery.md +27 -3
  566. package/docs/consumer-skill/references/domain-structures.md +124 -0
  567. package/docs/consumer-skill/references/installation.md +62 -8
  568. package/docs/consumer-skill/references/integration.md +59 -1
  569. package/docs/consumer-skill/references/product-composition.md +94 -0
  570. package/docs/consumer-skill/references/public-api.json +3044 -445
  571. package/docs/consumer-skill/references/review.md +87 -10
  572. package/docs/consumer-skill/references/rhf-workflows.md +79 -0
  573. package/docs/consumer-skill/references/screen-archetypes.md +19 -7
  574. package/docs/consumer-skill/references/screen-decisions.md +126 -0
  575. package/docs/consumer-skill/references/theming.md +24 -20
  576. package/docs/consumer-skill/references/tokens.json +9 -9
  577. package/docs/consumer-skill/references/view-craft.md +153 -0
  578. package/docs/consumer-skill/references/view-spec.md +73 -0
  579. package/docs/consumer-skill/references/workflows.md +7 -1
  580. package/docs/consumer-skill/scripts/composition-policy.mjs +176 -26
  581. package/docs/consumer-skill/scripts/composition-schema.mjs +1 -1
  582. package/docs/consumer-skill/scripts/composition.mjs +61 -5
  583. package/docs/consumer-skill/scripts/discovery.mjs +54 -0
  584. package/docs/consumer-skill/scripts/inspect-component.mjs +1 -1
  585. package/docs/consumer-skill/scripts/inspection.mjs +73 -18
  586. package/docs/consumer-skill/scripts/setup-skills.mjs +79 -7
  587. package/docs/consumer-skill/scripts/surface-policy.mjs +5 -5
  588. package/docs/consumer-skills/themelia-components/SKILL.md +14 -13
  589. package/docs/consumer-skills/themelia-composition/SKILL.md +16 -17
  590. package/docs/consumer-skills/themelia-design/SKILL.md +55 -0
  591. package/docs/consumer-skills/themelia-foundation/SKILL.md +2 -1
  592. package/docs/consumer-skills/themelia-tokenization/SKILL.md +24 -17
  593. package/package.json +4 -2
  594. package/templates/admin-shell-template.tsx +1 -2
  595. package/templates/customers-template.tsx +18 -16
  596. package/dist/accordion-96o0pN62.js.map +0 -1
  597. package/dist/action-menu-CHgs8vmj.js.map +0 -1
  598. package/dist/affordance-geometry.generated-B8yGOr8-.js.map +0 -1
  599. package/dist/ai-artifact-BZUGwBq6.js.map +0 -1
  600. package/dist/app-shell-D63ATkIK.js +0 -237
  601. package/dist/app-shell-D63ATkIK.js.map +0 -1
  602. package/dist/auth-D2FVZ1MH.js.map +0 -1
  603. package/dist/avatar-DWO_HHhB.js.map +0 -1
  604. package/dist/base/cascader.js.map +0 -1
  605. package/dist/batch-action-bar-CdfIkCsV.js.map +0 -1
  606. package/dist/breadcrumbs-B-WFKecD.js.map +0 -1
  607. package/dist/button-DkmK-z8E.js.map +0 -1
  608. package/dist/buttons-BbfzgczK.js.map +0 -1
  609. package/dist/cards-4JTWqvVe.js +0 -68
  610. package/dist/cards-4JTWqvVe.js.map +0 -1
  611. package/dist/chart-C19flDQb.js +0 -155
  612. package/dist/chart-C19flDQb.js.map +0 -1
  613. package/dist/choice-inputs-JLtij2y4.js +0 -776
  614. package/dist/choice-inputs-JLtij2y4.js.map +0 -1
  615. package/dist/code-block-CGNaUtAE.js.map +0 -1
  616. package/dist/combobox-CBJDs6w_.js +0 -877
  617. package/dist/combobox-CBJDs6w_.js.map +0 -1
  618. package/dist/combobox-hbhSS18O.js +0 -355
  619. package/dist/combobox-hbhSS18O.js.map +0 -1
  620. package/dist/command-D8NrBj-b.js.map +0 -1
  621. package/dist/comments-Di4w0H_S.js.map +0 -1
  622. package/dist/containers-CRmHf7GP.js.map +0 -1
  623. package/dist/control-group-recipes-DBXmfh2E.js.map +0 -1
  624. package/dist/data-display-D4oujtx0.js.map +0 -1
  625. package/dist/date-picker-zOt1oNss.js +0 -1542
  626. package/dist/date-picker-zOt1oNss.js.map +0 -1
  627. package/dist/date-pickers-cj8IXbDC.js +0 -179
  628. package/dist/date-pickers-cj8IXbDC.js.map +0 -1
  629. package/dist/dropdown-menu-CjY8Vt7W.js +0 -193
  630. package/dist/dropdown-menu-CjY8Vt7W.js.map +0 -1
  631. package/dist/feedback-DZNL5Lg1.js +0 -239
  632. package/dist/feedback-DZNL5Lg1.js.map +0 -1
  633. package/dist/field-affordance-recipes-DjwGx8eM.js.map +0 -1
  634. package/dist/filters-BcT-uoFy.js +0 -2209
  635. package/dist/filters-BcT-uoFy.js.map +0 -1
  636. package/dist/form-field-CsgRmdit.js +0 -63
  637. package/dist/form-field-CsgRmdit.js.map +0 -1
  638. package/dist/form-sizing-NXgjkmBG.js.map +0 -1
  639. package/dist/forms-BV5m5aQF.js.map +0 -1
  640. package/dist/forms-numeric-Cd33AKbD.js +0 -906
  641. package/dist/forms-numeric-Cd33AKbD.js.map +0 -1
  642. package/dist/header-BA697l4a.js.map +0 -1
  643. package/dist/hooks-BQ-L7Uu2.js.map +0 -1
  644. package/dist/input-DOPL5_QE.js +0 -21
  645. package/dist/input-DOPL5_QE.js.map +0 -1
  646. package/dist/item-BvZ2DR_x.js +0 -277
  647. package/dist/item-BvZ2DR_x.js.map +0 -1
  648. package/dist/layout.types-Cn7aUzJp.js +0 -20
  649. package/dist/layout.types-Cn7aUzJp.js.map +0 -1
  650. package/dist/mentions-RKOQaaIB.js.map +0 -1
  651. package/dist/message-INU2xsxu.js +0 -128
  652. package/dist/message-INU2xsxu.js.map +0 -1
  653. package/dist/metadata-list-qVV7AVxa.js.map +0 -1
  654. package/dist/motion-recipes-ChBg4HBq.js.map +0 -1
  655. package/dist/navigation-BQNcg1jT.js +0 -269
  656. package/dist/navigation-BQNcg1jT.js.map +0 -1
  657. package/dist/navigation-DLF3E1IC.js +0 -145
  658. package/dist/navigation-DLF3E1IC.js.map +0 -1
  659. package/dist/navigation-row-recipes-WZEs-hYo.js.map +0 -1
  660. package/dist/number-E_OiIfJz.js.map +0 -1
  661. package/dist/overflow-tab-bar-CrbqMteP.js +0 -284
  662. package/dist/overflow-tab-bar-CrbqMteP.js.map +0 -1
  663. package/dist/overlays-BlKynmde.js +0 -1004
  664. package/dist/overlays-BlKynmde.js.map +0 -1
  665. package/dist/page-CIwNUtGr.js +0 -227
  666. package/dist/page-CIwNUtGr.js.map +0 -1
  667. package/dist/page-header-commands-DFMlNYzN.js +0 -128
  668. package/dist/page-header-commands-DFMlNYzN.js.map +0 -1
  669. package/dist/popover-uwzX2vo7.js +0 -198
  670. package/dist/popover-uwzX2vo7.js.map +0 -1
  671. package/dist/popover.recipes-D3j8R8Yp.js.map +0 -1
  672. package/dist/primitives-Du64iDbb.js.map +0 -1
  673. package/dist/receipt-D789Jwyy.js.map +0 -1
  674. package/dist/rich-text-CLJEf76s.js +0 -78
  675. package/dist/rich-text-CLJEf76s.js.map +0 -1
  676. package/dist/rich-text-editor-Cm1dpUpQ.js.map +0 -1
  677. package/dist/rich-text-editor-toolbar-L__e4x47.js +0 -94
  678. package/dist/rich-text-editor-toolbar-L__e4x47.js.map +0 -1
  679. package/dist/safe-image-src-C6kQSMBZ.js +0 -17
  680. package/dist/safe-image-src-C6kQSMBZ.js.map +0 -1
  681. package/dist/sanitize-html-DsQmI48u.js.map +0 -1
  682. package/dist/settings-BA2iboic.js +0 -174
  683. package/dist/settings-BA2iboic.js.map +0 -1
  684. package/dist/sheet-DoAxTb2J.js +0 -213
  685. package/dist/sheet-DoAxTb2J.js.map +0 -1
  686. package/dist/sidebar-ByqKR_W5.js +0 -512
  687. package/dist/sidebar-ByqKR_W5.js.map +0 -1
  688. package/dist/sidebar-D2iSnGJ7.js +0 -619
  689. package/dist/sidebar-D2iSnGJ7.js.map +0 -1
  690. package/dist/skeleton-CUj8O5Bd.js +0 -264
  691. package/dist/skeleton-CUj8O5Bd.js.map +0 -1
  692. package/dist/smart-card-CqkzQsK-.js +0 -614
  693. package/dist/smart-card-CqkzQsK-.js.map +0 -1
  694. package/dist/table-CpvnzJn9.js.map +0 -1
  695. package/dist/table-DH7rozUv.js.map +0 -1
  696. package/dist/tabs-eqVsJZWO.js +0 -191
  697. package/dist/tabs-eqVsJZWO.js.map +0 -1
  698. package/dist/text-inputs-DXItiR0O.js.map +0 -1
  699. package/dist/theme-scope-BJ6eE2xt.js +0 -50
  700. package/dist/theme-scope-BJ6eE2xt.js.map +0 -1
  701. package/dist/timelines-DmtztAY_.js.map +0 -1
  702. package/dist/tooltip-B4hjKtoV.js +0 -111
  703. package/dist/tooltip-B4hjKtoV.js.map +0 -1
  704. package/dist/ui-provider-CQCuCBcy.js +0 -136
  705. package/dist/ui-provider-CQCuCBcy.js.map +0 -1
  706. package/dist/upload-C9SA0X-8.js.map +0 -1
  707. package/dist/upload-queue-DhQJiSRc.js.map +0 -1
  708. package/dist/usage-card-DVTRDmGz.js.map +0 -1
  709. package/dist/use-mobile-vaLKwgyf.js +0 -15
  710. package/dist/use-mobile-vaLKwgyf.js.map +0 -1
  711. package/dist/utils-CF3c95Io.js.map +0 -1
  712. package/dist/value-inputs-C0o70p-U.js +0 -980
  713. package/dist/value-inputs-C0o70p-U.js.map +0 -1
  714. package/dist/value-typography-ClupF0Gz.js.map +0 -1
  715. package/dist/workspace-9EFVXUyk.js.map +0 -1
@@ -0,0 +1,153 @@
1
+ # View craft
2
+
3
+ Themelia already sets type, colour, spacing and surfaces. Craft is what remains:
4
+ deciding what a view shows, how much emphasis each part gets and how the parts
5
+ are arranged, so the user understands the screen at a glance. Each rule below is
6
+ a decision you can explain and check on the rendered result. Most improvements
7
+ remove something.
8
+
9
+ Start from the [data brief](data-reading.md#write-the-data-brief). Owner
10
+ selection, surfaces and inset ownership follow
11
+ [screen decisions](screen-decisions.md); this reference does not restate them.
12
+
13
+ ## One focal point
14
+
15
+ Each view, and each region in it, has one thing the eye reaches first: the
16
+ figure that answers the question, the subject's identity and state, or the queue
17
+ of records that need action. Choose it from the brief. When two things compete,
18
+ demote one: a smaller text role, secondary tone, or a supporting region.
19
+
20
+ Check it by looking at a reduced screenshot: the focal point is still the
21
+ strongest mass. It sits in the first viewport at both 390 and 1440 wide.
22
+
23
+ ## Spend emphasis on purpose
24
+
25
+ Emphasis works only by contrast, so it is a budget:
26
+
27
+ - **Commands.** One solid primary command per page or surface. Other commands
28
+ are outline or ghost, or sit in the same scope's overflow menu.
29
+ - **Text.** At most three levels in a region: title (`Heading`), body and values
30
+ (`Text`), supporting copy (`Text` secondary, smaller size). A fourth level
31
+ signals a hierarchy problem, not a missing style.
32
+ - **Tone.** `success`, `warning`, `destructive` and `info` mark a status that
33
+ changes what the user does. Kinds, categories and counts stay neutral. When
34
+ everything is coloured, nothing reads as status.
35
+ - **Size.** One hero figure size per region; peer figures share one size.
36
+
37
+ Adding emphasis in one place means removing it from another.
38
+
39
+ ## Choose the encoding from the fact
40
+
41
+ | The fact | Encoding | Owner family (confirm with the finder and inspector) |
42
+ | --- | --- | --- |
43
+ | A figure the user must judge | Figure with its baseline delta; a sparkline when the path matters | `Metric`, `MetricTrendChip`, `MetricSparkline`; `MetricComparison` for current versus previous |
44
+ | Several peer figures for one period | One strip, not a grid of identical cards | `MetricBar`; `MetricGrid` with a quiet variant inside one surface |
45
+ | A series whose shape is the message | Chart with one emphasised series and minimal axes | `ChartCard` with Recharts children |
46
+ | Part of a whole, or use against a limit | Bar with the figure as its label | `Progress`, `UsageCard` |
47
+ | Facts about one record | Label and value list; one inline line for two to four short facts | `MetadataList` (inline or stacked), `InlineStat` |
48
+ | A lifecycle with a current stage | Steps with only the current stage emphasised | `StepsHorizontal`, `Timeline` |
49
+ | Events and history | Newest first, grouped by day | `Timeline`, `features/activities` |
50
+ | Many records compared on shared columns | Table whose columns are what users compare or sort | `DataTable`, `DataView` |
51
+ | Records that differ in shape | List rows: identity, one line of context, state, action | `Item`, `ItemGroup` |
52
+ | A money ledger | Right-aligned amounts, one rule above the grand total | `SummaryPanel` with `AmountRow`, `OrderSummary` |
53
+ | Nothing to show yet | What is missing and the next action | `EmptyState` |
54
+
55
+ Read [metrics and statistics](analytics.md) for the exact metric owner. A chart
56
+ must answer a question you can write in one sentence; otherwise show the figure.
57
+ Do not chart three values. Prefer a sparkline in a strip to a large chart that
58
+ repeats what the figures already say.
59
+
60
+ ## Spend words carefully
61
+
62
+ - Label a value only when it is ambiguous. A ledger amount needs "Total"; an
63
+ order number in a header does not need "Order number".
64
+ - Do not repeat a column header inside its cells or a section title in each row.
65
+ - State a unit once, in the header or the value.
66
+ - A sentence fragment often reads better than three label and value pairs:
67
+ "2 of 3 shipped · 1 reserved at Plovdiv".
68
+ - Omit zero and not-applicable counters, or collapse them into one "Nothing
69
+ outstanding" line.
70
+ - Do not explain the interface on the page. A description states scope or
71
+ as-of time, not instructions.
72
+
73
+ ## Density follows the audience
74
+
75
+ - **Queues** for operators: compact rows, more records per screen, identity,
76
+ state and amount; detail on open.
77
+ - **Overviews**: fewer, larger figures with room around them, each answering a
78
+ question.
79
+ - **Records**: the subject leads; evidence and history follow.
80
+
81
+ Change global density through the provider and density roots described in
82
+ [theming](theming.md). Do not shrink text roles to fit more data; remove
83
+ low-value content first.
84
+
85
+ ## Rhythm groups content
86
+
87
+ - Gaps grow outward: within a group, between groups, between sections. Equal
88
+ gaps everywhere mean nothing groups. Use `Stack` and `Grid` gap roles.
89
+ - Few edges: peer regions share content start edges; numbers right-align on one
90
+ axis; labels share one axis.
91
+ - Few frames: one `Card` per independent subject. Continuous sections of one
92
+ subject share one surface and are separated by space, not rules or nested
93
+ boxes.
94
+ - Narrow widths keep the decision content first in reading order. Only data
95
+ tables that own horizontal scrolling may scroll sideways.
96
+
97
+ ## Numbers and copy
98
+
99
+ - Numbers use tabular figures through the value primitives (`Money`, `Number`,
100
+ `Percent`, `Date`, `RelativeTime`) with one precision per column.
101
+ - Recency reads as relative time with the exact date available; documents show
102
+ absolute dates.
103
+ - A delta states direction and baseline: "↓ 0.9% vs September".
104
+ - Sentence case everywhere. Buttons are a verb and an object ("Record payment").
105
+ Empty states say what is missing and what to do. Errors say what happened and
106
+ how to recover.
107
+
108
+ ## Modern patterns and their owners
109
+
110
+ - **Overview.** A header with the period control, one figure strip (three to
111
+ five figures with deltas or sparklines), one chart answering the main
112
+ question, and a "needs attention" list that links to records. Not a wall of
113
+ identical cards.
114
+ - **Index.** Search plus the work queues users actually work; rows lead with
115
+ identity and the deciding column; bulk actions appear with a selection;
116
+ export states how many rows match.
117
+ - **Record.** The page header carries identity, status badges in `titleSuffix`,
118
+ one metadata line (date · channel · customer) and the primary command. The
119
+ main column holds the subject's working content, an aside holds context
120
+ (customer, payment, notes) and history comes last.
121
+ - **Editing.** `InlineEdit` for one field; `ActionDrawer` for a focused
122
+ multi-field edit that keeps the record visible; `ActionDialog` for short
123
+ creation; `ConfirmDialog` for destructive commands.
124
+ - **Progressive disclosure.** `Collapsible` or `Accordion` for evidence and
125
+ technical detail; overflow menus for rare commands.
126
+ - **Loading.** Owners' loading states and `Skeleton` shaped like the content,
127
+ not spinners in empty boxes.
128
+
129
+ Inspect each owner's declaration before using it; a pattern names a direction,
130
+ not a prop list.
131
+
132
+ ## Anti-patterns seen in trials
133
+
134
+ - A grid of identical metric cards whose figures have no baseline.
135
+ - A facts card that repeats the header's identifier, status and date.
136
+ - Every lifecycle counter on every line, zeros included.
137
+ - Column headers repeated in cells; units on every value.
138
+ - Filler cards added to balance a column's whitespace.
139
+ - Decorative icons on titles, rows or badges; tinted icon tiles.
140
+ - Status tones on kinds or categories; three badges on one row saying related
141
+ things.
142
+ - A storefront hero image inside an operational editor.
143
+ - A framed box inside a card for sub-content that is not a distinct object.
144
+ - A chart of three values, or a chart whose question cannot be stated.
145
+ - Prose explaining what the screen does.
146
+
147
+ ## When an owner limits the view
148
+
149
+ When an owner cannot express the hierarchy the data needs, compose its public
150
+ parts or app markup with token-backed utilities
151
+ ([domain structures](domain-structures.md)) and report the gap by owner and
152
+ prop. Never override anatomy classes, add colours or add tokens to make a view
153
+ look designed.
@@ -0,0 +1,73 @@
1
+ # View spec
2
+
3
+ Write this before JSX for a new view or a substantial redesign. Keep it short
4
+ enough to read in a minute; it is a working note, not an approval document. Every
5
+ line should change a later decision. Save it beside the app's other design notes
6
+ so a reviewer can compare the result with the intent.
7
+
8
+ ```md
9
+ # <View name> (<route>)
10
+
11
+ ## Decision
12
+ <who> decides <what>, <how often>. Success: <what they can do faster or with more confidence>.
13
+
14
+ ## Data brief
15
+ <the data brief from data-reading.md>
16
+
17
+ ## Ranked information
18
+ - Must (first viewport at 390 and 1440): …
19
+ - Should (visible without interaction): …
20
+ - Could (behind disclosure, overflow or a detail view): …
21
+ - Omit: … (why: zero, not applicable, duplicated elsewhere, not used for this decision)
22
+
23
+ ## Focal point
24
+ <the one element the eye reaches first, and why>
25
+
26
+ ## Wireframes
27
+ 1440:
28
+ ┌──────────────────────────────────────────────┐
29
+ │ Title · status [secondary] [Primary]│
30
+ │ meta · meta · meta │
31
+ ├──────────────────────────────┬───────────────┤
32
+ │ main subject │ context │
33
+ │ … │ … │
34
+ └──────────────────────────────┴───────────────┘
35
+
36
+ 390:
37
+ ┌────────────────────┐
38
+ │ Title · status │
39
+ │ [Primary] [⋯] │
40
+ │ main subject │
41
+ │ context │
42
+ └────────────────────┘
43
+
44
+ ## Encodings
45
+ | Fact | Encoding | Why |
46
+ | --- | --- | --- |
47
+
48
+ ## Owners
49
+ | Region | Owner | Exact import | Verified with |
50
+ | --- | --- | --- | --- |
51
+ (found with find-components.mjs and map-composition.mjs; props checked with inspect-component.mjs)
52
+
53
+ ## Commands
54
+ <command: scope, emphasis (primary, secondary, overflow), eligibility and disabled reason>
55
+
56
+ ## States
57
+ Loading: … Empty: … Error and retry: … Accepted: … Long text and narrow parent: …
58
+
59
+ ## Open questions and data gaps
60
+ …
61
+ ```
62
+
63
+ ## Notes
64
+
65
+ - Draw wireframes in text so they survive any editor and diff. Boxes show
66
+ regions and order, not pixel sizes.
67
+ - The ranked list is where most quality comes from. If "must" has more than
68
+ five items, the decision is not specific enough yet.
69
+ - Fill "Owners" only after running the finder and inspector. An owner that does
70
+ not fit is recorded with the reason, and the region becomes app markup over
71
+ public parts.
72
+ - After building, score the result with the [critique rubric](critique-rubric.md)
73
+ and note any departure from this spec with its reason.
@@ -124,7 +124,13 @@ back navigation, content bounds, commands and section tabs. Pass the record's
124
124
  main command as `header.primaryAction`, supporting commands as
125
125
  `header.secondaryActions` and separately selected/routed sections as `header.tabs`;
126
126
  continuous sections can stay in the body. One status badge goes in
127
- `header.titleBadges`. `PageHeader` serves a custom shell; `PageActions` is
127
+ `header.slots.titleSuffix` as a composed Badge. Place supporting facts in
128
+ `header.slots.afterDescription` as a MetadataList when useful. The four header
129
+ slots (`beforeTitle`, `titleSuffix`, `afterDescription`, `actions`) accept content
130
+ or a callback receiving `{ renderLink, defaultContent }`; an actions callback
131
+ can wrap or return `defaultContent` to retain responsive commands. A replacement
132
+ owns its behavior. Below 40rem of actual header width, all commands, including
133
+ primary, share one More actions trigger. `PageHeader` serves a custom shell; `PageActions` is
128
134
  deprecated. The [layout recipe](../examples/app-layout.tsx) demonstrates that
129
135
  route boundary; the [detail recipe](../examples/detail.tsx) demonstrates the
130
136
  record route and an independently framed subject with MetadataList and value
@@ -44,6 +44,8 @@ export function analyzeComposition(text, { filename, index, ts }) {
44
44
  const families = new Map(index.families.map(owner => [owner.import, owner]));
45
45
  const bindings = new Map();
46
46
  const namespaces = new Map();
47
+ const portalBindings = new Set();
48
+ const portalNamespaces = new Set();
47
49
  const declarations = new Map();
48
50
  const findings = [];
49
51
  const unresolved = [];
@@ -135,14 +137,23 @@ export function analyzeComposition(text, { filename, index, ts }) {
135
137
  if (names && ts.isNamespaceImport(names)) namespaces.set(symbolFor(names.name), specifier);
136
138
  }
137
139
  function gather(node) {
140
+ if (ts.isImportDeclaration(node) && ts.isStringLiteralLike(node.moduleSpecifier) && node.moduleSpecifier.text === 'react-dom') {
141
+ const names = node.importClause?.namedBindings;
142
+ if (names && ts.isNamedImports(names)) for (const item of names.elements) if ((item.propertyName ?? item.name).text === 'createPortal') portalBindings.add(symbolFor(item.name));
143
+ if (names && ts.isNamespaceImport(names)) portalNamespaces.add(symbolFor(names.name));
144
+ if (node.importClause?.name) portalNamespaces.add(symbolFor(node.importClause.name));
145
+ }
138
146
  if (ts.isImportDeclaration(node) && ts.isStringLiteralLike(node.moduleSpecifier) && importsModal(node, ts)) add(node, 'raw-overlay-primitive', 'warning', `${node.moduleSpecifier.text} builds a second dialog system. ${overlayRemedy}`);
139
147
  if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) declarations.set(symbolFor(node.name), node.initializer);
148
+ if (ts.isFunctionDeclaration(node) && node.name && node.body) declarations.set(symbolFor(node.name), node);
140
149
  if ((ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) && node.moduleSpecifier && ts.isStringLiteralLike(node.moduleSpecifier)) importOwner(node, node.moduleSpecifier.text);
141
150
  if (ts.isImportTypeNode(node) && ts.isLiteralTypeNode(node.argument) && ts.isStringLiteralLike(node.argument.literal)) importOwner(node, node.argument.literal.text);
142
151
  if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword && ts.isStringLiteralLike(node.arguments[0])) importOwner(node, node.arguments[0].text);
143
152
  ts.forEachChild(node, gather);
144
153
  }
145
154
  gather(source);
155
+ const portalCall = node => ts.isCallExpression(node) && (ts.isIdentifier(node.expression) && portalBindings.has(symbolFor(node.expression))
156
+ || ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === 'createPortal' && ts.isIdentifier(node.expression.expression) && portalNamespaces.has(symbolFor(node.expression.expression)));
146
157
  for (const diagnostic of source.parseDiagnostics) add(source, 'syntax', 'error', ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'));
147
158
  const ownerFor = tag => {
148
159
  if (ts.isIdentifier(tag)) return bindings.get(symbolFor(tag));
@@ -157,16 +168,23 @@ export function analyzeComposition(text, { filename, index, ts }) {
157
168
  const expression = ts.isJsxExpression(attribute.initializer) ? attribute.initializer.expression : attribute.initializer;
158
169
  return [[attribute.name.getText(source), expression]];
159
170
  });
171
+ const unknownSpread = (expression, visiting = new Set()) => {
172
+ const value = resolve(expression);
173
+ if (!value || !ts.isObjectLiteralExpression(value) || visiting.has(value)) return true;
174
+ const next = new Set(visiting).add(value);
175
+ return value.properties.some(property => ts.isSpreadAssignment(property) && unknownSpread(property.expression, next));
176
+ };
160
177
  const isOwner = (owner, suffix, names) => owner?.import === `${index.package}/${suffix}` && names.includes(owner.symbol);
161
178
  const framedOwner = (owner, props) => {
162
- if (literal(props.get('surface')) === 'flat') return false;
163
- if (isOwner(owner, 'base/cards', ['Card', 'SmartCard']) || isOwner(owner, 'features/table', ['DataTable']) || isOwner(owner, 'features/data-view', ['DataView'])) return true;
179
+ if (props.has('surface') && (literal(props.get('surface')) === undefined || literal(props.get('surface')) === 'flat')) return false;
180
+ if (isOwner(owner, 'base/cards', ['Card', 'SmartCard']) || isOwner(owner, 'base/forms', ['FormSection']) || isOwner(owner, 'features/table', ['DataTable']) || isOwner(owner, 'features/data-view', ['DataView'])) return true;
181
+ if (isOwner(owner, 'blocks/analytics', ['ChartCard']) || isOwner(owner, 'base/display', ['ContentBlock'])) return props.has('surface');
164
182
  if (isOwner(owner, 'blocks/analytics', ['Metric'])) return literal(props.get('variant')) === 'card';
165
183
  if (isOwner(owner, 'blocks/analytics', ['MetricGrid'])) return !props.has('variant') || literal(props.get('variant')) === 'card';
166
184
  return isOwner(owner, 'blocks/analytics/usage-card', ['UsageCard']) || isOwner(owner, 'blocks/analytics', ['UsageCard']) || isOwner(owner, 'blocks/planning', ['TaskCard']);
167
185
  };
168
186
  // Examine lexical JSX only. Names ending in Card are not evidence of framing;
169
- // ChartCard is card-free; Receipt's flat paper has no ordinary Card frame.
187
+ // ChartCard is card-free by default; Receipt's paper has no ordinary Card frame.
170
188
  const contentElements = element => {
171
189
  const found = [];
172
190
  function collect(child) {
@@ -184,6 +202,25 @@ export function analyzeComposition(text, { filename, index, ts }) {
184
202
  if (ts.isJsxElement(element.parent)) element.parent.children.forEach(collect);
185
203
  return found;
186
204
  };
205
+ // Static region children only: inspect known passive wrappers and providers,
206
+ // never assume an opaque app component renders its lexical children.
207
+ const regionElements = (opening, deep = false) => {
208
+ const found = [];
209
+ const collect = (child, scope = opening, subject) => {
210
+ if (ts.isJsxFragment(child)) { child.children.forEach(item => collect(item, scope, subject)); return; }
211
+ if (ts.isJsxExpression(child)) { const value = resolve(child.expression); if (value) collect(value, scope, subject); return; }
212
+ const node = ts.isJsxElement(child) ? child.openingElement : ts.isJsxSelfClosingElement(child) ? child : undefined;
213
+ if (!node) return;
214
+ const owner = ownerFor(node.tagName);
215
+ found.push({node, owner, tag: node.tagName.getText(source), scope, subject});
216
+ const provider = isOwner(owner, 'features/filters', ['FilterProvider']);
217
+ const card = isOwner(owner, 'base/cards', ['Card', 'SmartCard']);
218
+ // Cards delimit independent subjects; providers delimit query state.
219
+ if (deep && ts.isJsxElement(child) && (/^(div|section|form)$/.test(node.tagName.getText(source)) || isOwner(owner, 'base/structure', ['Stack', 'Grid', 'AdaptiveGrid', 'GridCell']) || card || provider)) child.children.forEach(item => collect(item, provider ? node : scope, card ? node : subject));
220
+ };
221
+ if (ts.isJsxElement(opening.parent)) opening.parent.children.forEach(child => collect(child));
222
+ return found;
223
+ };
187
224
  const renderedText = element => ts.isJsxElement(element) ? element.children.map(child => ts.isJsxText(child) ? child.text : ts.isJsxExpression(child) ? literal(child.expression) ?? '' : '').join(' ').trim() : '';
188
225
  const slotBadge = expression => {
189
226
  const node = resolve(expression);
@@ -241,25 +278,43 @@ export function analyzeComposition(text, { filename, index, ts }) {
241
278
  };
242
279
  // tone="primary" is solid unless a buttonStyle says otherwise; untoned Buttons are neutral.
243
280
  const solidPrimary = (opening, owner) => {
244
- if (!isOwner(owner, 'base/buttons', ['Button'])) return false;
281
+ const submit = isOwner(owner, 'base/forms', ['SubmitStateButton']);
282
+ if (!submit && !isOwner(owner, 'base/buttons', ['Button'])) return false;
245
283
  const props = new Map(attributes(opening));
246
284
  const style = props.has('buttonStyle') ? literal(props.get('buttonStyle')) : 'solid';
247
- return literal(props.get('tone')) === 'primary' && style === 'solid';
285
+ return (literal(props.get('tone')) ?? (submit && !props.has('tone') ? 'primary' : undefined)) === 'primary' && style === 'solid';
286
+ };
287
+ const formRoot = opening => {
288
+ if (opening.tagName.getText(source) === 'form') return true;
289
+ const render = resolve(new Map(attributes(opening)).get('render'));
290
+ return render && (ts.isJsxElement(render) ? render.openingElement : ts.isJsxSelfClosingElement(render) ? render : undefined)?.tagName.getText(source) === 'form';
248
291
  };
249
- // Overlays are separate surfaces with their own primary command.
292
+ // A form owns its submit command; overlays and exclusive branches are not
293
+ // simultaneously competing page commands. Follow same-file slot values only.
250
294
  const solidPrimaryCount = root => {
251
- let count = 0;
252
- const walk = child => {
295
+ const count = (expression, visiting = new Set()) => {
296
+ if (!expression) return 0;
297
+ const child = resolve(expression) ?? expression;
298
+ if (visiting.has(child)) return 0;
299
+ const next = new Set(visiting).add(child);
300
+ if (portalCall(child)) return 0;
301
+ if (ts.isConditionalExpression(child)) return Math.max(count(child.whenTrue, next), count(child.whenFalse, next));
302
+ if (ts.isBinaryExpression(child) && [ts.SyntaxKind.BarBarToken, ts.SyntaxKind.QuestionQuestionToken].includes(child.operatorToken.kind)) return Math.max(count(child.left, next), count(child.right, next));
253
303
  if (ts.isJsxElement(child) || ts.isJsxSelfClosingElement(child)) {
254
304
  const opening = ts.isJsxElement(child) ? child.openingElement : child;
255
305
  const owner = ownerFor(opening.tagName);
256
- if (isOwner(owner, 'features/overlays', overlayOwners)) return;
257
- if (solidPrimary(opening, owner)) count++;
306
+ if (isOwner(owner, 'features/overlays', overlayOwners) || formRoot(opening) || !owner && /^[A-Z]/.test(opening.tagName.getText(source))) return 0;
307
+ const props = new Map(attributes(opening));
308
+ if (resolve(props.get('hidden'))?.kind === ts.SyntaxKind.TrueKeyword || props.has('hidden') && props.get('hidden') === undefined) return 0;
309
+ const children = ts.isJsxElement(child) ? child.children.reduce((total, item) => total + count(item, next), 0) : 0;
310
+ const slots = [...props].filter(([name]) => !['header', 'render'].includes(name)).reduce((total, [, value]) => total + count(value, next), 0);
311
+ return Number(solidPrimary(opening, owner)) + children + slots;
258
312
  }
259
- ts.forEachChild(child, walk);
313
+ let total = 0;
314
+ ts.forEachChild(child, item => { total += count(item, next); });
315
+ return total;
260
316
  };
261
- ts.forEachChild(root, walk);
262
- return count;
317
+ return count(root);
263
318
  };
264
319
  const peerCards = element => {
265
320
  if (!ts.isJsxElement(element.parent)) return new Set();
@@ -303,18 +358,78 @@ export function analyzeComposition(text, { filename, index, ts }) {
303
358
  return smallPeerGaps.has(row ?? gap) || smallPeerGaps.has(column ?? gap);
304
359
  });
305
360
  };
306
- function visit(node, parents = []) {
361
+ const separateRegion = owner => isOwner(owner, 'features/overlays', overlayOwners)
362
+ || isOwner(owner, 'base/popover', ['PopoverContent'])
363
+ || isOwner(owner, 'base/navigation', ['DropdownMenuContent', 'DropdownMenuSubContent', 'ContextMenuContent', 'ContextMenuSubContent'])
364
+ || isOwner(owner, 'base/combobox', ['ComboboxContent', 'ComboboxPopup'])
365
+ || isOwner(owner, 'base/choice-inputs', ['SelectPopupContent']);
366
+ function regionParents(element, parents, context, slot) {
367
+ if (slot === 'render') return parents;
368
+ if (separateRegion(context?.owner) || !context && /^[A-Z]/.test(element.tagName.getText(source))) parents = [];
369
+ return context ? [...parents, { ...context, slot }] : parents;
370
+ }
371
+ function visitValue(value, parents, visiting) {
372
+ if (value) visit(resolve(value) ?? value, parents, visiting);
373
+ }
374
+ function visit(node, parents = [], visiting = new Set()) {
375
+ if (visiting.has(node)) return;
376
+ const next = new Set(visiting).add(node);
307
377
  if (ts.isJsxElement(node)) {
308
378
  const element = node.openingElement;
309
379
  const context = inspect(element, parents);
310
- for (const child of node.children) visit(child, context ? [...parents, context] : parents);
311
- // JSX in props is a separate region, not a child frame.
312
- for (const attribute of element.attributes.properties) ts.forEachChild(attribute, child => visit(child, parents));
380
+ for (const child of node.children) visit(child, regionParents(element, parents, context, 'children'), next);
381
+ for (const [slot, value] of attributes(element)) visitValue(value, regionParents(element, parents, context, slot), next);
382
+ return;
383
+ }
384
+ if (ts.isJsxSelfClosingElement(node)) {
385
+ const context = inspect(node, parents);
386
+ for (const [slot, value] of attributes(node)) visitValue(value, regionParents(node, parents, context, slot), next);
387
+ return;
388
+ }
389
+ if (ts.isJsxExpression(node)) { visitValue(node.expression, parents, next); return; }
390
+ if (ts.isPropertyAssignment(node) || ts.isShorthandPropertyAssignment(node) || ts.isMethodDeclaration(node)) {
391
+ const member = ts.isIdentifier(node.name) || ts.isStringLiteralLike(node.name) ? node.name.text : undefined;
392
+ // columns contains header/footer renderers as well as cells. Only a cell
393
+ // owns the table-row height addressed by heavy-cell-disclosure.
394
+ const nextParents = parents.map(parent => parent.slot === 'columns' && ['cell', 'header', 'footer'].includes(member) ? {...parent, member} : parent);
395
+ if (ts.isMethodDeclaration(node)) { if (node.body) visit(node.body, nextParents, next); }
396
+ else visitValue(ts.isShorthandPropertyAssignment(node) ? node.name : node.initializer, nextParents, next);
313
397
  return;
314
398
  }
315
- if (ts.isJsxSelfClosingElement(node)) inspect(node, parents);
316
- ts.forEachChild(node, child => visit(child, parents));
399
+ if (portalCall(node)) {
400
+ for (const [index, value] of node.arguments.entries()) visitValue(value, index === 0 ? [] : parents, next);
401
+ return;
402
+ }
403
+ ts.forEachChild(node, child => visit(child, parents, next));
317
404
  }
405
+ const surfaceOwner = owner => isOwner(owner, 'base/cards', ['Card', 'SmartCard', 'CardFooter']) || isOwner(owner, 'base/forms', ['FormSection']) || isOwner(owner, 'blocks/analytics', ['ChartCard']) || isOwner(owner, 'base/display', ['ContentBlock']);
406
+ const footerRegion = parent => surfaceOwner(parent.owner) && (['footerSlot', 'footer'].includes(parent.slot) || parent.owner.symbol === 'CardFooter');
407
+ const paddedRegion = parent => {
408
+ if (!surfaceOwner(parent.owner) || parent.unknownProps) return false;
409
+ if (parent.props.has('padding')) {
410
+ const padding = literal(parent.props.get('padding'));
411
+ return padding !== undefined && padding !== 'none';
412
+ }
413
+ // Flat removes the frame, not Card/FormSection's ordinary region insets.
414
+ // ChartCard and ContentBlock instead default to no inset when card-free.
415
+ return isOwner(parent.owner, 'base/cards', ['Card', 'SmartCard', 'CardFooter']) || isOwner(parent.owner, 'base/forms', ['FormSection']) || parent.framed;
416
+ };
417
+ const remoteSubmit = expression => {
418
+ const calls = new Set();
419
+ const walk = (node, visiting = new Set()) => {
420
+ if (!node) return;
421
+ const value = resolve(node) ?? node;
422
+ if (visiting.has(value)) return;
423
+ const next = new Set(visiting).add(value);
424
+ if (ts.isCallExpression(value) && ts.isPropertyAccessExpression(value.expression)) {
425
+ if (value.expression.name.text === 'requestSubmit') calls.add('submit');
426
+ if (value.expression.name.text === 'getElementById' && value.expression.expression.getText(source) === 'document' && !symbolFor(value.expression.expression)) calls.add('lookup');
427
+ }
428
+ ts.forEachChild(value, child => walk(child, next));
429
+ };
430
+ walk(expression);
431
+ return calls.size === 2;
432
+ };
318
433
  // A native element passed as a package owner's `render` is that owner's root, such as
319
434
  // an Item row rendered as a button; the owner keeps its focus, hover and row anatomy.
320
435
  const renderRoots = new Set();
@@ -342,7 +457,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
342
457
  if (modalRole || scrim) add(node, 'raw-overlay-primitive', 'warning', `A hand-rolled ${modalRole ? 'dialog' : 'full-screen layer'} must own focus, dismissal, pending state and theming itself. ${overlayRemedy}`);
343
458
  if (/^(?:input|textarea)$/.test(node.tagName.getText(source))) {
344
459
  const props = new Map(attributes(node));
345
- if (props.has('className') && classStrings(props.get('className')).flatMap(value=>value.split(/\s+/)).some(value=>replacesSharedRadius(value,'inner'))) add(node,'shared-radius','error','Native editable controls follow bounded rounded-inner; change the global theme root, not per-field corners.');
460
+ if (props.has('className') && classStrings(props.get('className')).flatMap(value=>value.split(/\s+/)).some(value=>replacesSharedRadius(value,'radius'))) add(node,'shared-radius','error','Native editable controls follow bounded rounded-radius; change the global theme root, not per-field corners.');
346
461
  if (props.has('style') && properties(props.get('style')).some(([name])=>radiusProperty.test(name))) add(node,'shared-radius','error','Native editable corners belong to the global radius root, not inline styles.');
347
462
  }
348
463
  if (nativeDisplayNames.test(node.tagName.getText(source))) {
@@ -356,9 +471,10 @@ export function analyzeComposition(text, { filename, index, ts }) {
356
471
  add(node, 'public-symbol', 'error', `${owner.import} does not export ${owner.symbol}.`);
357
472
  return;
358
473
  }
359
- const unresolvedBeforeProps = unresolved.length;
360
474
  const props = new Map(attributes(node));
361
- const unknownProps = unresolved.length !== unresolvedBeforeProps;
475
+ // Other reviews can have already disclosed this spread. Deduplication of
476
+ // unresolved output must not turn an unknown value into a known default.
477
+ const unknownProps = node.attributes.properties.some(attribute => ts.isJsxSpreadAttribute(attribute) && unknownSpread(attribute.expression));
362
478
  const family = owner.import.split('/base/')[1];
363
479
  const anatomy = surfaceParts[family]?.test(owner.symbol);
364
480
  const forwarder = surfaceForwarders[family] === owner.symbol;
@@ -375,7 +491,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
375
491
  const focusDrift = focusRingDrift(tokens);
376
492
  if ((anatomy || forwarder && name === 'contentClassName') && classes.some(value => paddingClass.test(value))) add(node, 'surface-padding', 'error', `${owner.symbol}: use inset/type/density and public regions; padding overrides replace owned anatomy.`);
377
493
  if (control && name === 'className' && classes.some(value => fixedControlClass.test(value))) add(node, 'control-anatomy', 'error', `${owner.symbol}: use its size/variant props; preserve shared control height, inset, corners and typography.`);
378
- if ((name === 'className' && (control || sharedCorners) || name === 'contentClassName' && forwarder) && classes.some(value=>replacesSharedRadius(value, control && name === 'className' ? 'inner' : cornerRole(family,owner.symbol)))) add(node,'shared-radius','error',`${owner.symbol}: outer shells use rounded-radius; controls and collection rows use bounded rounded-inner. Preserve the owning role and joined-edge resets.`);
494
+ if ((name === 'className' && (control || sharedCorners) || name === 'contentClassName' && forwarder) && classes.some(value=>replacesSharedRadius(value, control && name === 'className' ? 'radius' : cornerRole(family,owner.symbol)))) add(node,'shared-radius','error',`${owner.symbol}: outer shells use rounded-surface; controls and collection rows use bounded rounded-radius. Preserve the owning role and joined-edge resets.`);
379
495
  if (display && classes.some(addsCopyMargin)) add(node,'copy-margin','error',`${owner.symbol}: typography is margin-free; use textGap on the headed owner or gap on Stack/Grid.`);
380
496
  if (textContent && name === 'className' && tokens.some(token=>fadedText(token)||textOpacityDrift(token))) add(node,'faded-text','error',`${owner.symbol}: use its semantic type instead of adding an opacity tier to the text. Presence endpoints and shared disabled state remain valid.`);
381
497
  if ((control || family === 'buttons' && owner.symbol === 'TextButton') && name === 'className' && focusDrift.length) add(node, 'focus-ring-recipe', 'error', `${owner.symbol}: keep the shared focus indicator (a ring-3 halo of ring-ring/50 around a full-strength ring edge); ${[...new Set(focusDrift)].join(', ')} redraws it.`);
@@ -391,7 +507,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
391
507
  if ((isOwner(owner, 'base/cards', ['Card', 'SmartCard']) || isOwner(owner, 'base/display', ['ContentBlock'])) && props.get('icon')) add(node, 'decorative-icon', 'warning', `${owner.symbol}: a title icon is decoration unless it encodes state or a brand; let the title name the subject.`);
392
508
  const facts = isOwner(owner, 'base/metadata-list', ['MetadataList']) || isOwner(owner, 'blocks/data-display', ['MetadataList']) ? resolve(props.get('items')) : undefined;
393
509
  if (facts && ts.isArrayLiteralExpression(facts) && facts.elements.filter(item => properties(item, false).some(([name]) => name === 'icon')).length > 1) add(node, 'decorative-icon', 'warning', 'MetadataList: an icon on every fact repeats what its label says; keep labels and drop the icons.');
394
- const framed = framedOwner(owner, props);
510
+ const framed = !unknownProps && framedOwner(owner, props);
395
511
  if (isOwner(owner, 'base/cards', ['Card', 'SmartCard'])) {
396
512
  for (const slot of ['headerAction', 'headerStart']) if (slotBadge(props.get(slot))) add(node, 'card-badge-placement', 'error', `${owner.symbol}: put status/count/version badges in titleSuffix; ${slot} owns ${slot === 'headerAction' ? 'commands' : 'pre-title context'}.`);
397
513
  const contents = contentElements(node);
@@ -404,6 +520,37 @@ export function analyzeComposition(text, { filename, index, ts }) {
404
520
  }
405
521
  if (isOwner(owner, 'base/feedback', ['Empty'])) add(node, 'reinvented-empty-state', 'warning', 'Empty exposes lower-level anatomy. Compare EmptyState from blocks/data-display for a routine no-data/no-results region; keep Empty when custom anatomy is required.');
406
522
  if (isOwner(owner, 'base/sheet', ['Sheet', 'SheetContent']) || isOwner(owner, 'base/display', ['Dialog', 'DialogContent', 'AlertDialog', 'AlertDialogContent'])) add(node, 'raw-overlay-primitive', 'warning', 'This lower-level modal needs application lifecycle coordination. Prefer ActionDialog, ConfirmDialog or ActionDrawer from features/overlays when their workflow fits.');
523
+ if (isOwner(owner, 'base/forms', ['FormActionsBar'])) {
524
+ const footer = parents.findLast(footerRegion);
525
+ const padded = parents.findLast(paddedRegion);
526
+ if (footer || padded) add(node, 'form-actions-bar-placement', 'warning', `FormActionsBar owns a divider, background and inset; ${footer ? `${footer.owner.symbol}.${footer.slot} already owns footer geometry` : `${padded.owner.symbol} already owns body padding`}. Put action buttons directly in the footer slot, or place the bar at the end of the form inside Card padding="none" with flat FormSection siblings. Review intentional custom hosts.`);
527
+ }
528
+ if (isOwner(owner, 'features/table', ['DataTable']) || isOwner(owner, 'base/table', ['Table'])) {
529
+ const footer = parents.findLast(footerRegion);
530
+ const padded = parents.findLast(paddedRegion);
531
+ if (footer || padded) add(node, 'uncontained-table-in-card', 'warning', `${owner.symbol} is inside ${footer ? `${footer.owner.symbol}.${footer.slot}` : `a padded ${padded.owner.symbol}`}. Keep substantial tables in a body or peer region; a deliberate Card host uses padding="none" with a flat table. Review the actual surface and inset ownership.`);
532
+ }
533
+ if ((isOwner(owner, 'base/accordion', ['Accordion', 'SmartAccordion']) || isOwner(owner, 'features/table', ['DataTable']) || isOwner(owner, 'base/code-block', ['CodeBlock'])) && parents.some(parent => isOwner(parent.owner, 'features/table', ['DataTable']) && parent.slot === 'columns' && parent.member === 'cell')) {
534
+ add(node, 'heavy-cell-disclosure', 'warning', `${owner.symbol} in a DataTable cell can disrupt row scanning. Prefer a compact summary with rowActions opening an ActionDrawer, ActionDialog or detail route; retain an intentional inline disclosure after checking expanded rows and keyboard access.`);
535
+ }
536
+ if (isOwner(owner, 'base/choice-inputs', ['CardCheckboxGroup', 'CardRadioGroup', 'ListRadioGroup', 'PillRadioGroup'])) {
537
+ const options = resolve(props.get('options'));
538
+ if (options && ts.isArrayLiteralExpression(options) && options.elements.length === 1 && !ts.isSpreadElement(options.elements[0])) add(node, 'single-option-choice-group', 'warning', `${owner.symbol} has one static option. For a boolean setting prefer Checkbox, Switch, ToggleField or SwitchCard; retain a genuine choice set whose available options happen to contain one item.`);
539
+ }
540
+ const routeOwner = isOwner(owner, 'layout/page', ['Page']) || isOwner(owner, 'layout', ['Page']);
541
+ if (routeOwner) {
542
+ for (const name of ['narrow', 'maxWidth']) {
543
+ const value = resolve(props.get(name));
544
+ if (value && (ts.isConditionalExpression(value) || ts.isBinaryExpression(value) || ts.isPrefixUnaryExpression(value))) add(props.get(name), 'dynamic-page-measure', 'warning', `Page ${name} depends on an expression and may resize the header and tabs when sections change. Keep the route measure stable and constrain a focused tab panel with Container maxWidth="md" gutter="none"; responsive route sizing can be intentional.`);
545
+ }
546
+ const children = regionElements(node);
547
+ const contents = regionElements(node, true);
548
+ const tables = contents.filter(child => isOwner(child.owner, 'features/table', ['DataTable']));
549
+ for (const child of contents) if (isOwner(child.owner, 'features/filters', ['FilterLayout']) && tables.some(table => table.scope === child.scope && (!child.subject || table.subject === child.subject))) add(child.node, 'detached-filter-layout', 'warning', 'Pass FilterLayout into DataTable topbarContent with variant="compact", or use DataView so filters and table chrome share one surface.');
550
+ const hasAsideSlot = properties(props.get('slots'), false).some(([name]) => name === 'aside');
551
+ const onlyForms = children.length > 0 && children.every(child => child.tag === 'form' || isOwner(child.owner, 'base/forms', ['FormSection']));
552
+ if (onlyForms && !unknownProps && !['narrow', 'maxWidth', 'aside'].some(name => props.has(name)) && !hasAsideSlot) add(node, 'wide-single-column-form', 'warning', 'Review this single-column form measure: a focused form can use Page narrow (48rem centered), an explicit maxWidth, or a supporting aside. In a mixed/tabbed route, keep Page stable and constrain only the form panel with Container maxWidth="md" gutter="none".');
553
+ }
407
554
  if (owner.symbol === 'Page' && literal(props.get('gutter')) === 'none' && !parents.some(parent => parent.framed)) add(node, 'page-gutter', 'warning', 'Page gutter="none" delegates inline padding to a real parent. PageViewport owns scrolling, not padding; verify the parent inset.');
408
555
  if (owner.symbol === 'Card' && framed && literal(props.get('padding')) === 'sm' && !parents.some(parent => parent.framed)) add(node, 'compact-card', 'warning', 'Standalone Card padding="sm" halves the normal inset. Omit padding for ordinary subjects; retain sm only for an intentional compact composition.');
409
556
  const peers = parents.findLast(parent => parent.structure);
@@ -411,6 +558,8 @@ export function analyzeComposition(text, { filename, index, ts }) {
411
558
  if (framed && parents.some(parent => parent.framed)) add(node, 'nested-surface', 'warning', `${owner.symbol} is inside a framed owner. Review subject boundaries; use surface="flat" when the parent owns the frame.`);
412
559
  const header = properties(props.get('header'), false);
413
560
  const pageOwner = owner.import === `${index.package}/layout/page` || owner.import === `${index.package}/layout`;
561
+ const headerValue = resolve(props.get('header'));
562
+ if (routeOwner && props.has('header') && headerValue && !ts.isObjectLiteralExpression(headerValue)) unknown(props.get('header'));
414
563
  // Every header owner takes role-based commands; its free-form regions hold
415
564
  // non-command controls only.
416
565
  const commandHeader = (pageOwner && owner.symbol === 'PageHeader') || isOwner(owner, 'base/navigation', ['PageHeading']) || isOwner(owner, 'features/resource', ['ResourceHeader', 'ResourceIndexShell', 'ResourceShowShell', 'TabbedResourceShell']) || isOwner(owner, 'layout/settings', ['SettingsShell', 'AsideNavShell']) || isOwner(owner, 'layout', ['SettingsShell', 'AsideNavShell']) || isOwner(owner, 'layout/workspace', ['WorkspaceRecordHeader']);
@@ -418,11 +567,12 @@ export function analyzeComposition(text, { filename, index, ts }) {
418
567
  const elementSecondary = isOwner(owner, 'layout/workspace', ['WorkspaceRecordHeader']) ? props.get('secondaryActions') : undefined;
419
568
  if (pageOwner && owner.symbol === 'Page') {
420
569
  const primaries = solidPrimaryCount(ts.isJsxSelfClosingElement(node) ? node : node.parent) + (new Map(header).has('primaryAction') ? 1 : 0);
421
- if (primaries > 1) add(node, 'multiple-primary-commands', 'warning', `Page has ${primaries} solid primary commands. Keep one primary per page as header.primaryAction; leave other commands untoned (the neutral button) or list them in secondaryActions.`);
570
+ if (primaries > 1) add(node, 'multiple-primary-commands', 'warning', `Page has ${primaries} solid primary commands in the same task scope. Keep one leading command per task/surface; forms keep their local SubmitStateButton or FormActionsBar. Use header.primaryAction for route-level commands and secondaryActions for supporting route commands.`);
422
571
  }
423
572
  if ((headerActions && commandButtons(headerActions)) || (elementSecondary && commandButtons(elementSecondary))) add(node, 'page-command-roles', 'warning', `${owner.symbol}: buttons, command rows and menus in the header actions region choose their own emphasis, order and overflow. Pass commands as primaryAction (one) and ordered secondaryActions; keep actions for non-command controls.`);
424
573
  const headerProps = pageOwner && owner.symbol === 'Page' ? new Map(header) : pageOwner && owner.symbol === 'PageHeader' ? props : undefined;
425
574
  if (headerProps) {
575
+ for (const name of ['primaryAction', 'secondaryActions']) if (headerProps.has(name) && remoteSubmit(headerProps.get(name))) add(headerProps.get(name), 'remote-header-form-submit', 'warning', `${owner.symbol}: ${name} submits a form through document.getElementById(...).requestSubmit(). Keep task-local submission beside its fields or in the form footer. A single full-page editor can deliberately own a header submit; preserve native validation and avoid duplicate commands.`);
426
576
  if (headerProps.has('titleIcon') && !headerProps.has('titleIconHref') && !headerProps.has('onTitleIconClick')) add(headerProps.get('titleIcon') ?? node, 'decorative-icon', 'warning', `${owner.symbol}: titleIcon decorates the page title; let the title name the page, or link the icon with titleIconHref.`);
427
577
  const hasIcon = action => properties(action, false).some(([name]) => name === 'icon');
428
578
  const secondary = resolve(headerProps.get('secondaryActions'));
@@ -432,7 +582,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
432
582
  const title = literal(props.get('title')) ?? literal(new Map(header).get('title'));
433
583
  if (title && parents.some(parent => parent.title === title)) add(node, 'duplicate-heading', 'warning', `The heading "${title}" repeats its ancestor. Keep one route/subject title unless a distinct task warrants repetition.`);
434
584
  const structure = owner.import === `${index.package}/base/structure` && Object.hasOwn(structureDefaults, owner.symbol);
435
- return { framed, title, structure, cards: structure ? peerCards(node) : new Set(), smallGap: structure ? smallGap(props, owner.symbol, unknownProps) : false };
585
+ return { owner, props, unknownProps, framed, title, structure, cards: structure ? peerCards(node) : new Set(), smallGap: structure ? smallGap(props, owner.symbol, unknownProps) : false };
436
586
  }
437
587
  visit(source);
438
588
  return { findings, unresolved };
@@ -4,7 +4,7 @@ const name = value => typeof value === 'string' && /^[A-Za-z][A-Za-z0-9]*$/.test
4
4
  const uniqueList = (value, valid, maximum) => Array.isArray(value) && value.length <= maximum && value.every(valid) && new Set(value).size === value.length;
5
5
  const scalar = value => value === null || typeof value === 'boolean' || (typeof value === 'string' && value.length <= 500) || (typeof value === 'number' && Number.isFinite(value));
6
6
  const kinds = ['shell', 'page', 'layout', 'surface', 'content', 'workflow'];
7
- const placements = ['region', 'cell', 'overlay'];
7
+ const placements = ['region', 'toolbar', 'cell', 'overlay'];
8
8
  const surfaces = ['none', 'parent', 'self', 'variant'];
9
9
 
10
10
  /** One literal metadata shape shared by authored catalogue and copied tools. */