themelia-react-ui 2.0.0 → 2.0.2

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 (707) hide show
  1. package/CHANGELOG.md +527 -0
  2. package/README.md +47 -14
  3. package/THIRD_PARTY_NOTICES.md +13 -0
  4. package/dist/accordion-Cjb6sx0G.js +208 -0
  5. package/dist/accordion-Cjb6sx0G.js.map +1 -0
  6. package/dist/action-menu-CllU52Mm.js +280 -0
  7. package/dist/action-menu-CllU52Mm.js.map +1 -0
  8. package/dist/affordance-geometry.generated-tF36bREk.js +140 -0
  9. package/dist/affordance-geometry.generated-tF36bREk.js.map +1 -0
  10. package/dist/ai-artifact-DvTwDVyL.js +1148 -0
  11. package/dist/ai-artifact-DvTwDVyL.js.map +1 -0
  12. package/dist/{app-shell-BE_j8-AT.js → app-shell-C4FhvCqF.js} +5 -5
  13. package/dist/{app-shell-BE_j8-AT.js.map → app-shell-C4FhvCqF.js.map} +1 -1
  14. package/dist/attachment-BxDfL2mw.js +246 -0
  15. package/dist/attachment-BxDfL2mw.js.map +1 -0
  16. package/dist/{auth-M3vGMgDR.js → auth-ax2BqjrI.js} +241 -235
  17. package/dist/auth-ax2BqjrI.js.map +1 -0
  18. package/dist/{avatar-djdaaQ_s.js → avatar-DAPlDvhJ.js} +67 -66
  19. package/dist/avatar-DAPlDvhJ.js.map +1 -0
  20. package/dist/badge-HpFqoqSY.js +93 -0
  21. package/dist/badge-HpFqoqSY.js.map +1 -0
  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 +3 -0
  28. package/dist/base/buttons.js +2 -3
  29. package/dist/base/cards.js +2 -2
  30. package/dist/base/carousel.js +50 -46
  31. package/dist/base/carousel.js.map +1 -1
  32. package/dist/base/cascader.js +69 -81
  33. package/dist/base/cascader.js.map +1 -1
  34. package/dist/base/chart.js +1 -1
  35. package/dist/base/choice-inputs.js +3 -3
  36. package/dist/base/code-block.js +1 -1
  37. package/dist/base/combobox.js +2 -2
  38. package/dist/base/command.js +1 -1
  39. package/dist/base/copyable.js +1 -1
  40. package/dist/base/date-pickers.js +2 -2
  41. package/dist/base/display.js +7 -7
  42. package/dist/base/feedback.js +3 -3
  43. package/dist/base/forms-numeric.js +1 -1
  44. package/dist/base/forms.js +2 -2
  45. package/dist/base/inline-edit.js +20 -20
  46. package/dist/base/inline-edit.js.map +1 -1
  47. package/dist/base/item.js +1 -1
  48. package/dist/base/media-gallery.js +1 -1
  49. package/dist/base/metadata-list.js +3 -0
  50. package/dist/base/navigation.js +7 -7
  51. package/dist/base/popover-menu.js +1 -1
  52. package/dist/base/popover.js +1 -1
  53. package/dist/base/qr-code.js +1 -1
  54. package/dist/base/repeaters.js +216 -220
  55. package/dist/base/repeaters.js.map +1 -1
  56. package/dist/base/sheet.js +1 -1
  57. package/dist/base/sidebar.js +1 -1
  58. package/dist/base/signature-pad.js +147 -137
  59. package/dist/base/signature-pad.js.map +1 -1
  60. package/dist/base/skeleton.js +1 -1
  61. package/dist/base/spinner.js +79 -2
  62. package/dist/base/spinner.js.map +1 -0
  63. package/dist/base/structure.js +1 -1
  64. package/dist/base/table.js +1 -1
  65. package/dist/base/text-inputs.js +2 -2
  66. package/dist/base/toaster.js +46 -45
  67. package/dist/base/toaster.js.map +1 -1
  68. package/dist/base/tree.js +1 -1
  69. package/dist/base/upload-queue.js +1 -1
  70. package/dist/base/upload.js +3 -3
  71. package/dist/base/value-inputs.js +2 -2
  72. package/dist/batch-action-bar-DnUJ21NQ.js +105 -0
  73. package/dist/batch-action-bar-DnUJ21NQ.js.map +1 -0
  74. package/dist/blocks/admin.js +171 -169
  75. package/dist/blocks/admin.js.map +1 -1
  76. package/dist/blocks/ai.js +308 -285
  77. package/dist/blocks/ai.js.map +1 -1
  78. package/dist/blocks/analytics/usage-card.js +1 -1
  79. package/dist/blocks/analytics.js +626 -589
  80. package/dist/blocks/analytics.js.map +1 -1
  81. package/dist/blocks/collaboration.js +1 -1
  82. package/dist/blocks/commerce/receipt.js +1 -1
  83. package/dist/blocks/commerce.js +2051 -1329
  84. package/dist/blocks/commerce.js.map +1 -1
  85. package/dist/blocks/data-display.js +3 -2
  86. package/dist/blocks/onboarding.js +68 -58
  87. package/dist/blocks/onboarding.js.map +1 -1
  88. package/dist/blocks/planning.js +27 -26
  89. package/dist/blocks/planning.js.map +1 -1
  90. package/dist/blocks/timelines.js +1 -1
  91. package/dist/breadcrumbs-C-oqs1sQ.js +129 -0
  92. package/dist/breadcrumbs-C-oqs1sQ.js.map +1 -0
  93. package/dist/{button-R9CCoH7A.js → button-DVzspB_G.js} +15 -14
  94. package/dist/button-DVzspB_G.js.map +1 -0
  95. package/dist/{button-BS3KDg00.js → buttons-DPZekJFu.js} +208 -216
  96. package/dist/buttons-DPZekJFu.js.map +1 -0
  97. package/dist/cards-BaBZR-AU.js +68 -0
  98. package/dist/cards-BaBZR-AU.js.map +1 -0
  99. package/dist/{chart-DwYRKKc-.js → chart-ZOYyK2xG.js} +58 -55
  100. package/dist/chart-ZOYyK2xG.js.map +1 -0
  101. package/dist/checkbox-AWIhNhmo.js +36 -0
  102. package/dist/checkbox-AWIhNhmo.js.map +1 -0
  103. package/dist/choice-inputs-CNHvARCJ.js +770 -0
  104. package/dist/choice-inputs-CNHvARCJ.js.map +1 -0
  105. package/dist/code-block-DeneBJR_.js +185 -0
  106. package/dist/code-block-DeneBJR_.js.map +1 -0
  107. package/dist/{collapsible-oMUGM4tr.js → collapsible-C-_l4hpy.js} +4 -4
  108. package/dist/{collapsible-oMUGM4tr.js.map → collapsible-C-_l4hpy.js.map} +1 -1
  109. package/dist/{collection-content-Ys-OZOkY.js → collection-content-By56pLog.js} +3 -3
  110. package/dist/{collection-content-Ys-OZOkY.js.map → collection-content-By56pLog.js.map} +1 -1
  111. package/dist/combobox-C0EQW6dr.js +875 -0
  112. package/dist/combobox-C0EQW6dr.js.map +1 -0
  113. package/dist/combobox-xCQ2RMNE.js +309 -0
  114. package/dist/combobox-xCQ2RMNE.js.map +1 -0
  115. package/dist/{command-kPMPjIxJ.js → command-C25VMRII.js} +7 -7
  116. package/dist/{command-kPMPjIxJ.js.map → command-C25VMRII.js.map} +1 -1
  117. package/dist/{comments-You0Bzbr.js → comments-BYYlTA8E.js} +390 -379
  118. package/dist/comments-BYYlTA8E.js.map +1 -0
  119. package/dist/components/base/action-menu/action-menu.d.ts +21 -4
  120. package/dist/components/base/action-menu/action-menu.recipes.d.ts +21 -0
  121. package/dist/components/base/action-menu/index.d.ts +1 -0
  122. package/dist/components/base/badge/badge.recipes.d.ts +5 -5
  123. package/dist/components/base/batch-action-bar/batch-action-bar.d.ts +50 -0
  124. package/dist/components/base/batch-action-bar/batch-action-bar.strings.d.ts +20 -0
  125. package/dist/components/base/batch-action-bar/index.d.ts +8 -0
  126. package/dist/components/base/buttons/button-group.recipes.d.ts +1 -1
  127. package/dist/components/base/buttons/button.recipes.d.ts +2 -2
  128. package/dist/components/base/buttons/loader-button.d.ts +2 -1
  129. package/dist/components/base/cards/card.recipes.d.ts +2 -3
  130. package/dist/components/base/cards/partials/smart-card-skeleton.d.ts +3 -13
  131. package/dist/components/base/cards/smart-card.types.d.ts +11 -4
  132. package/dist/components/base/chart/chart.d.ts +2 -5
  133. package/dist/components/base/choice-inputs/checkbox.d.ts +2 -2
  134. package/dist/components/base/choice-inputs/choice-types.d.ts +18 -6
  135. package/dist/components/base/combobox/combobox.strings.d.ts +7 -0
  136. package/dist/components/base/combobox/index.d.ts +30 -4
  137. package/dist/components/base/display/alert-dialog.d.ts +6 -5
  138. package/dist/components/base/display/dialog.d.ts +4 -8
  139. package/dist/components/base/display/icon-badge/icon-badge.d.ts +1 -1
  140. package/dist/components/base/forms/form-sizing.d.ts +26 -15
  141. package/dist/components/base/metadata-list/index.d.ts +12 -0
  142. package/dist/components/{blocks/data-display/metadata → base/metadata-list}/metadata-list.d.ts +28 -25
  143. package/dist/components/{blocks/data-display/metadata → base/metadata-list}/metadata-value.d.ts +2 -2
  144. package/dist/components/base/navigation/index.d.ts +1 -1
  145. package/dist/components/base/navigation/page-header/index.d.ts +1 -0
  146. package/dist/components/base/navigation/page-header/page-header-commands.d.ts +73 -0
  147. package/dist/components/base/navigation/page-header/page-header.d.ts +26 -3
  148. package/dist/components/base/navigation/pagination.d.ts +5 -2
  149. package/dist/components/base/popover/popover.recipes.d.ts +15 -1
  150. package/dist/components/base/sheet/sheet.d.ts +4 -8
  151. package/dist/components/base/signature-pad/signature-pad.types.d.ts +5 -1
  152. package/dist/components/base/signature-pad/signature-pad.utils.d.ts +11 -3
  153. package/dist/components/base/table/index.d.ts +9 -2
  154. package/dist/components/base/text-inputs/field-clear-button.d.ts +6 -0
  155. package/dist/components/base/text-inputs/input-group.d.ts +2 -2
  156. package/dist/components/base/upload/upload.recipes.d.ts +25 -3
  157. package/dist/components/base/value-inputs/index.d.ts +5 -5
  158. package/dist/components/base/value-inputs/tags-input.d.ts +36 -12
  159. package/dist/components/blocks/ai/ai-shimmer/ai-shimmer.d.ts +1 -1
  160. package/dist/components/blocks/ai/ai-shimmer/types.d.ts +3 -0
  161. package/dist/components/blocks/commerce/address-card/address-card.d.ts +1 -1
  162. package/dist/components/blocks/commerce/address-card/types.d.ts +2 -1
  163. package/dist/components/blocks/commerce/cart-summary/cart-summary.d.ts +3 -1
  164. package/dist/components/blocks/commerce/cart-summary/index.d.ts +2 -2
  165. package/dist/components/blocks/commerce/cart-summary/types.d.ts +6 -1
  166. package/dist/components/blocks/commerce/discount-stack/discount-stack.d.ts +3 -1
  167. package/dist/components/blocks/commerce/discount-stack/index.d.ts +2 -2
  168. package/dist/components/blocks/commerce/discount-stack/types.d.ts +16 -4
  169. package/dist/components/blocks/commerce/fulfillment-group/fulfillment-group.d.ts +5 -0
  170. package/dist/components/blocks/commerce/fulfillment-group/index.d.ts +2 -0
  171. package/dist/components/blocks/commerce/fulfillment-group/types.d.ts +45 -0
  172. package/dist/components/blocks/commerce/index.d.ts +13 -5
  173. package/dist/components/blocks/commerce/invoice-header/invoice-header.d.ts +1 -1
  174. package/dist/components/blocks/commerce/invoice-header/types.d.ts +4 -2
  175. package/dist/components/blocks/commerce/invoice-mini/invoice-mini.d.ts +1 -1
  176. package/dist/components/blocks/commerce/invoice-mini/types.d.ts +2 -1
  177. package/dist/components/blocks/commerce/order-customer/index.d.ts +2 -0
  178. package/dist/components/blocks/commerce/order-customer/order-customer.d.ts +5 -0
  179. package/dist/components/blocks/commerce/order-customer/types.d.ts +48 -0
  180. package/dist/components/blocks/commerce/order-header/index.d.ts +2 -0
  181. package/dist/components/blocks/commerce/order-header/order-header.d.ts +5 -0
  182. package/dist/components/blocks/commerce/order-header/types.d.ts +37 -0
  183. package/dist/components/blocks/commerce/order-line-item/index.d.ts +2 -0
  184. package/dist/components/blocks/commerce/order-line-item/order-line-item.d.ts +5 -0
  185. package/dist/components/blocks/commerce/order-line-item/types.d.ts +46 -0
  186. package/dist/components/blocks/commerce/order-summary/index.d.ts +2 -0
  187. package/dist/components/blocks/commerce/order-summary/order-summary.d.ts +5 -0
  188. package/dist/components/blocks/commerce/order-summary/types.d.ts +42 -0
  189. package/dist/components/blocks/commerce/order-transactions/index.d.ts +2 -0
  190. package/dist/components/blocks/commerce/order-transactions/order-transactions.d.ts +5 -0
  191. package/dist/components/blocks/commerce/order-transactions/types.d.ts +46 -0
  192. package/dist/components/blocks/commerce/payment-method/index.d.ts +2 -2
  193. package/dist/components/blocks/commerce/payment-method/payment-method.d.ts +9 -1
  194. package/dist/components/blocks/commerce/payment-method/types.d.ts +12 -1
  195. package/dist/components/blocks/commerce/refund-status/index.d.ts +2 -2
  196. package/dist/components/blocks/commerce/refund-status/refund-status.d.ts +3 -1
  197. package/dist/components/blocks/commerce/refund-status/types.d.ts +6 -3
  198. package/dist/components/blocks/commerce/shared/address-lines.d.ts +21 -0
  199. package/dist/components/blocks/commerce/shared/line-thumbnail.d.ts +9 -0
  200. package/dist/components/blocks/commerce/shared/order-status.d.ts +51 -0
  201. package/dist/components/blocks/commerce/shipment-tracking/shipment-tracking.d.ts +1 -1
  202. package/dist/components/blocks/commerce/shipment-tracking/types.d.ts +27 -6
  203. package/dist/components/blocks/commerce/summary-panel/amount-row.d.ts +2 -0
  204. package/dist/components/blocks/commerce/summary-panel/index.d.ts +3 -0
  205. package/dist/components/blocks/commerce/summary-panel/summary-panel.d.ts +2 -0
  206. package/dist/components/blocks/commerce/summary-panel/types.d.ts +26 -0
  207. package/dist/components/blocks/commerce/tax-breakdown/tax-breakdown.d.ts +1 -1
  208. package/dist/components/blocks/commerce/tax-breakdown/types.d.ts +2 -1
  209. package/dist/components/blocks/data-display/inline-stat/inline-stat.d.ts +16 -8
  210. package/dist/components/blocks/data-display/metadata/index.d.ts +30 -4
  211. package/dist/components/features/activities/partials/activity-marker.d.ts +6 -3
  212. package/dist/components/features/activities/partials/activity-row.d.ts +6 -2
  213. package/dist/components/features/activities/partials/tone-tokens.d.ts +0 -6
  214. package/dist/components/features/appointment-calendar/appointment-calendar.d.ts +5 -0
  215. package/dist/components/features/appointment-calendar/appointment-calendar.types.d.ts +220 -0
  216. package/dist/components/features/appointment-calendar/appointment-calendar.utils.d.ts +41 -0
  217. package/dist/components/features/appointment-calendar/index.d.ts +3 -0
  218. package/dist/components/features/appointment-calendar/partials/appointment-agenda.d.ts +32 -0
  219. package/dist/components/features/appointment-calendar/partials/appointment-month.d.ts +13 -0
  220. package/dist/components/features/combobox/combobox.strings.d.ts +15 -1
  221. package/dist/components/features/combobox/types.d.ts +4 -0
  222. package/dist/components/features/global-search/partials/global-search-group-heading.d.ts +15 -0
  223. package/dist/components/features/global-search/partials/tone-palettes.d.ts +0 -5
  224. package/dist/components/features/kanban/kanban.d.ts +1 -1
  225. package/dist/components/features/kanban/kanban.strings.d.ts +1 -1
  226. package/dist/components/features/kanban/kanban.types.d.ts +2 -2
  227. package/dist/components/features/media-library/hooks/use-media-library.d.ts +1 -1
  228. package/dist/components/features/media-library/index.d.ts +1 -1
  229. package/dist/components/features/media-library/media-library.d.ts +1 -1
  230. package/dist/components/features/media-library/media-library.strings.d.ts +6 -0
  231. package/dist/components/features/media-library/media-library.types.d.ts +74 -1
  232. package/dist/components/features/media-library/partials/media-library-partials.d.ts +3 -3
  233. package/dist/components/features/mentions/partials/mention-kind-toggles.d.ts +16 -0
  234. package/dist/components/features/overlays/alert-dialog.d.ts +1 -1
  235. package/dist/components/features/overlays/dialog.d.ts +1 -1
  236. package/dist/components/features/overlays/index.d.ts +1 -1
  237. package/dist/components/features/overlays/overlay-tone-icon.d.ts +3 -3
  238. package/dist/components/features/overlays/overlays.types.d.ts +20 -0
  239. package/dist/components/features/products/components/product-contract-overview.d.ts +5 -0
  240. package/dist/components/features/products/components/product-details-card.d.ts +5 -0
  241. package/dist/components/features/products/components/product-operations-card.d.ts +5 -0
  242. package/dist/components/features/products/components/product-option-action-menu.d.ts +5 -0
  243. package/dist/components/features/products/components/product-options-summary.d.ts +5 -0
  244. package/dist/components/features/products/components/product-policies-card.d.ts +5 -0
  245. package/dist/components/features/products/components/product-quote-preview-card.d.ts +5 -0
  246. package/dist/components/features/products/components/product-readiness-card.d.ts +5 -0
  247. package/dist/components/features/products/components/product-structure-card.d.ts +5 -0
  248. package/dist/components/features/products/components/product-variant-action-menu.d.ts +23 -1
  249. package/dist/components/features/products/products.types.d.ts +9 -2
  250. package/dist/components/features/resource/index.d.ts +1 -1
  251. package/dist/components/features/resource/resource.d.ts +1 -1
  252. package/dist/components/features/resource/resource.types.d.ts +34 -6
  253. package/dist/components/features/rich-text-editor/index.d.ts +2 -1
  254. package/dist/components/features/rich-text-editor/partials/image-nodes.d.ts +13 -0
  255. package/dist/components/features/rich-text-editor/partials/image-uploads.d.ts +66 -0
  256. package/dist/components/features/rich-text-editor/partials/inline-reference-node.d.ts +19 -0
  257. package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +7 -1
  258. package/dist/components/features/rich-text-editor/rich-text-editor.strings.d.ts +14 -0
  259. package/dist/components/features/rich-text-editor/rich-text-editor.types.d.ts +54 -1
  260. package/dist/components/features/rich-text-editor/use-rich-text-images.d.ts +18 -0
  261. package/dist/components/features/sync/index.d.ts +26 -3
  262. package/dist/components/features/table/data-table.d.ts +1 -1
  263. package/dist/components/features/table/table-header.d.ts +1 -1
  264. package/dist/components/features/table/table.strings.d.ts +55 -1
  265. package/dist/components/features/table/table.types.d.ts +49 -11
  266. package/dist/components/features/theme-tweaker/theme-tweaker.types.d.ts +5 -0
  267. package/dist/components/layout/page/index.d.ts +1 -1
  268. package/dist/components/layout/page/page.types.d.ts +33 -36
  269. package/dist/components/layout/page/partials/page-actions.d.ts +1 -0
  270. package/dist/components/layout/page/partials/page-header.d.ts +1 -1
  271. package/dist/components/layout/settings/settings.d.ts +16 -2
  272. package/dist/components/layout/workspace/workspace.types.d.ts +21 -4
  273. package/dist/components/primitives/number.d.ts +4 -2
  274. package/dist/components/primitives/value.d.ts +3 -1
  275. package/dist/components/typography/rich-text/index.d.ts +1 -1
  276. package/dist/components/typography/rich-text/rich-text-tree.d.ts +19 -0
  277. package/dist/components/typography/rich-text/rich-text.d.ts +16 -0
  278. package/dist/components/typography/text-link.d.ts +8 -3
  279. package/dist/components/ui/checkbox.d.ts +4 -3
  280. package/dist/components/ui/combobox.d.ts +6 -2
  281. package/dist/components/ui/item.d.ts +8 -8
  282. package/dist/components/ui/overlay.recipes.d.ts +0 -9
  283. package/dist/components/ui/switch.d.ts +2 -2
  284. package/dist/components/ui/tabs.d.ts +1 -1
  285. package/dist/{containers-D_L4mTVb.js → containers-Mu1LMGV1.js} +36 -35
  286. package/dist/containers-Mu1LMGV1.js.map +1 -0
  287. package/dist/{copyable-DDjTeW_j.js → copyable-ClBuk_UK.js} +6 -6
  288. package/dist/{copyable-DDjTeW_j.js.map → copyable-ClBuk_UK.js.map} +1 -1
  289. package/dist/data-display-DT_khPl_.js +971 -0
  290. package/dist/data-display-DT_khPl_.js.map +1 -0
  291. package/dist/{date-uf3z37Nm.js → date-DCrsDTZc.js} +5 -5
  292. package/dist/{date-uf3z37Nm.js.map → date-DCrsDTZc.js.map} +1 -1
  293. package/dist/date-picker-ay0Pha_a.js +1530 -0
  294. package/dist/date-picker-ay0Pha_a.js.map +1 -0
  295. package/dist/date-pickers-Ccw8DL2b.js +175 -0
  296. package/dist/date-pickers-Ccw8DL2b.js.map +1 -0
  297. package/dist/display-hAc1HjpI.js +344 -0
  298. package/dist/display-hAc1HjpI.js.map +1 -0
  299. package/dist/dropdown-menu-Cl4X7L5S.js +193 -0
  300. package/dist/dropdown-menu-Cl4X7L5S.js.map +1 -0
  301. package/dist/editable-text-recipe-Cn61kEcv.js +10 -0
  302. package/dist/editable-text-recipe-Cn61kEcv.js.map +1 -0
  303. package/dist/features/activities.js +478 -542
  304. package/dist/features/activities.js.map +1 -1
  305. package/dist/features/ai-chat.js +209 -199
  306. package/dist/features/ai-chat.js.map +1 -1
  307. package/dist/features/appointment-calendar.js +683 -0
  308. package/dist/features/appointment-calendar.js.map +1 -0
  309. package/dist/features/async-preview.js +109 -107
  310. package/dist/features/async-preview.js.map +1 -1
  311. package/dist/features/combobox.js +1 -1
  312. package/dist/features/comments.js +1 -1
  313. package/dist/features/data-view.js +30 -29
  314. package/dist/features/data-view.js.map +1 -1
  315. package/dist/features/email-composer/engine.js +1 -1
  316. package/dist/features/email-composer.js +285 -283
  317. package/dist/features/email-composer.js.map +1 -1
  318. package/dist/features/event-calendar.js +282 -273
  319. package/dist/features/event-calendar.js.map +1 -1
  320. package/dist/features/filters.js +1 -1
  321. package/dist/features/global-search.js +318 -318
  322. package/dist/features/global-search.js.map +1 -1
  323. package/dist/features/kanban.js +146 -147
  324. package/dist/features/kanban.js.map +1 -1
  325. package/dist/features/map.js +269 -268
  326. package/dist/features/map.js.map +1 -1
  327. package/dist/features/media-library.js +970 -863
  328. package/dist/features/media-library.js.map +1 -1
  329. package/dist/features/mentions.js +1 -1
  330. package/dist/features/overlays.js +1 -1
  331. package/dist/features/products.js +1137 -1124
  332. package/dist/features/products.js.map +1 -1
  333. package/dist/features/questionnaire.js +206 -194
  334. package/dist/features/questionnaire.js.map +1 -1
  335. package/dist/features/resource-assignment.js +24 -21
  336. package/dist/features/resource-assignment.js.map +1 -1
  337. package/dist/features/resource.js +77 -69
  338. package/dist/features/resource.js.map +1 -1
  339. package/dist/features/rich-text-editor.js +30 -11
  340. package/dist/features/rich-text-editor.js.map +1 -1
  341. package/dist/features/schema-form.js +35 -33
  342. package/dist/features/schema-form.js.map +1 -1
  343. package/dist/features/suggestions.js +3 -3
  344. package/dist/features/sync.js +11 -5
  345. package/dist/features/sync.js.map +1 -1
  346. package/dist/features/table.js +1 -1
  347. package/dist/features/theme-tweaker.js +501 -496
  348. package/dist/features/theme-tweaker.js.map +1 -1
  349. package/dist/feedback-BYIhtitP.js +239 -0
  350. package/dist/feedback-BYIhtitP.js.map +1 -0
  351. package/dist/field-affordance-recipes-DZhnIL_Y.js +41 -0
  352. package/dist/field-affordance-recipes-DZhnIL_Y.js.map +1 -0
  353. package/dist/field-state-recipes-BVA2CWHo.js +12 -0
  354. package/dist/field-state-recipes-BVA2CWHo.js.map +1 -0
  355. package/dist/{filters-Da-gNPsE.js → filters-BGfvjP4d.js} +483 -472
  356. package/dist/filters-BGfvjP4d.js.map +1 -0
  357. package/dist/focus-recipes-B653VaLq.js +12 -0
  358. package/dist/focus-recipes-B653VaLq.js.map +1 -0
  359. package/dist/{form-field-VZRULhUK.js → form-field-CwH9y77i.js} +6 -5
  360. package/dist/form-field-CwH9y77i.js.map +1 -0
  361. package/dist/{form-sizing-uWP4lzVh.js → form-sizing-BdP_Mf5p.js} +45 -46
  362. package/dist/form-sizing-BdP_Mf5p.js.map +1 -0
  363. package/dist/{forms-DDeEnXSY.js → forms-B9G_xwzi.js} +22 -22
  364. package/dist/{forms-DDeEnXSY.js.map → forms-B9G_xwzi.js.map} +1 -1
  365. package/dist/forms-numeric-B_jraJaQ.js +906 -0
  366. package/dist/forms-numeric-B_jraJaQ.js.map +1 -0
  367. package/dist/{header-2ycNqGOR.js → header-CGXuhcRm.js} +164 -161
  368. package/dist/header-CGXuhcRm.js.map +1 -0
  369. package/dist/{hooks-DQ5SPwZw.js → hooks-Dkz0K2WT.js} +2 -2
  370. package/dist/{hooks-DQ5SPwZw.js.map → hooks-Dkz0K2WT.js.map} +1 -1
  371. package/dist/{http-CdEIHyQf.js → http-D_6rOnzU.js} +2 -2
  372. package/dist/{http-CdEIHyQf.js.map → http-D_6rOnzU.js.map} +1 -1
  373. package/dist/icon-badge-DYKIwvOV.js +55 -0
  374. package/dist/icon-badge-DYKIwvOV.js.map +1 -0
  375. package/dist/index.js +7 -7
  376. package/dist/input-CZw8iU99.js +21 -0
  377. package/dist/input-CZw8iU99.js.map +1 -0
  378. package/dist/input-DQdEd0YD.js +263 -0
  379. package/dist/input-DQdEd0YD.js.map +1 -0
  380. package/dist/interaction-recipes-XR9ZpVYL.js +25 -0
  381. package/dist/interaction-recipes-XR9ZpVYL.js.map +1 -0
  382. package/dist/item-K5_ghvze.js +275 -0
  383. package/dist/item-K5_ghvze.js.map +1 -0
  384. package/dist/layer-recipes-CCpklYME.js +13 -0
  385. package/dist/layer-recipes-CCpklYME.js.map +1 -0
  386. package/dist/layout/app-shell.js +1 -1
  387. package/dist/layout/auth.js +1 -1
  388. package/dist/layout/containers.js +1 -1
  389. package/dist/layout/header.js +1 -1
  390. package/dist/layout/hooks.js +1 -1
  391. package/dist/layout/navigation.js +1 -1
  392. package/dist/layout/page.js +1 -1
  393. package/dist/layout/settings.js +1 -1
  394. package/dist/layout/sidebar.js +2 -2
  395. package/dist/layout/workspace.js +1 -1
  396. package/dist/layout.js +10 -10
  397. package/dist/lib/affordance-geometry.generated.d.ts +72 -0
  398. package/dist/lib/editable-text-recipe.d.ts +4 -4
  399. package/dist/lib/field-affordance-recipes.d.ts +8 -3
  400. package/dist/lib/field-state-recipes.d.ts +9 -8
  401. package/dist/lib/focus-recipes.d.ts +24 -0
  402. package/dist/lib/interaction-recipes.d.ts +40 -0
  403. package/dist/lib/layer-recipes.d.ts +19 -0
  404. package/dist/lib/motion-recipes.d.ts +1 -0
  405. package/dist/lib/overlay-anatomy-recipes.d.ts +1 -0
  406. package/dist/lib/safe-image-src.d.ts +10 -0
  407. package/dist/lib/sanitize-html.d.ts +15 -3
  408. package/dist/lib/surface-recipes.d.ts +47 -7
  409. package/dist/lib/theme-mode-css.d.ts +7 -0
  410. package/dist/lib/token-merge.generated.d.ts +9 -6
  411. package/dist/lib/tone-recipes.d.ts +87 -0
  412. package/dist/lib/ui-provider/hooks.d.ts +2 -1
  413. package/dist/lib/ui-provider/index.d.ts +2 -2
  414. package/dist/lib/ui-provider/types.d.ts +11 -2
  415. package/dist/lib/utils.js +1 -1
  416. package/dist/media-gallery-3zIVLMWH.js +203 -0
  417. package/dist/media-gallery-3zIVLMWH.js.map +1 -0
  418. package/dist/mentions-utuUvH1K.js +570 -0
  419. package/dist/mentions-utuUvH1K.js.map +1 -0
  420. package/dist/{message-YfFmbXNP.js → message-DZ_ruyUV.js} +7 -6
  421. package/dist/message-DZ_ruyUV.js.map +1 -0
  422. package/dist/metadata-list-8N16ZMW_.js +405 -0
  423. package/dist/metadata-list-8N16ZMW_.js.map +1 -0
  424. package/dist/{motion-recipes-B6jKXEcN.js → motion-recipes-ChBg4HBq.js} +3 -2
  425. package/dist/{motion-recipes-B6jKXEcN.js.map → motion-recipes-ChBg4HBq.js.map} +1 -1
  426. package/dist/navigation-Bnotn4AQ.js +145 -0
  427. package/dist/navigation-Bnotn4AQ.js.map +1 -0
  428. package/dist/navigation-BzhHI3lo.js +269 -0
  429. package/dist/navigation-BzhHI3lo.js.map +1 -0
  430. package/dist/{navigation-row-recipes-DlU-4QYO.js → navigation-row-recipes-BFLCk_Aq.js} +2 -2
  431. package/dist/{navigation-row-recipes-DlU-4QYO.js.map → navigation-row-recipes-BFLCk_Aq.js.map} +1 -1
  432. package/dist/{number-CKRBYmZK.js → number-DbV1Dija.js} +36 -34
  433. package/dist/{number-CKRBYmZK.js.map → number-DbV1Dija.js.map} +1 -1
  434. package/dist/overflow-tab-bar-CWY7Nogn.js +282 -0
  435. package/dist/overflow-tab-bar-CWY7Nogn.js.map +1 -0
  436. package/dist/overlay.recipes-8GHqmlb4.js +6 -0
  437. package/dist/overlay.recipes-8GHqmlb4.js.map +1 -0
  438. package/dist/overlays-DNWmZrJ4.js +1001 -0
  439. package/dist/overlays-DNWmZrJ4.js.map +1 -0
  440. package/dist/page-Bgl1F560.js +224 -0
  441. package/dist/page-Bgl1F560.js.map +1 -0
  442. package/dist/page-header-commands-DOb6WsfD.js +126 -0
  443. package/dist/page-header-commands-DOb6WsfD.js.map +1 -0
  444. package/dist/pagination-BL25hu2s.js +158 -0
  445. package/dist/pagination-BL25hu2s.js.map +1 -0
  446. package/dist/{popover-Dcv_9jxr.js → popover-7_m66eYW.js} +11 -10
  447. package/dist/popover-7_m66eYW.js.map +1 -0
  448. package/dist/popover-menu-B9WWygpa.js +100 -0
  449. package/dist/popover-menu-B9WWygpa.js.map +1 -0
  450. package/dist/{popover.recipes-wmbvL8Ah.js → popover.recipes-D3j8R8Yp.js} +18 -11
  451. package/dist/popover.recipes-D3j8R8Yp.js.map +1 -0
  452. package/dist/{primitives-BHrwQXFC.js → primitives-BFK08r9M.js} +45 -44
  453. package/dist/primitives-BFK08r9M.js.map +1 -0
  454. package/dist/primitives.js +4 -4
  455. package/dist/{progress-Br9WTFya.js → progress-B1VnCT0K.js} +9 -9
  456. package/dist/{progress-Br9WTFya.js.map → progress-B1VnCT0K.js.map} +1 -1
  457. package/dist/{receipt-CV89q1fs.js → receipt-BVSOH3Xo.js} +9 -6
  458. package/dist/{receipt-CV89q1fs.js.map → receipt-BVSOH3Xo.js.map} +1 -1
  459. package/dist/rich-text-GOUyKQ-s.js +78 -0
  460. package/dist/rich-text-GOUyKQ-s.js.map +1 -0
  461. package/dist/rich-text-editor-cRLC-eBK.js +1196 -0
  462. package/dist/rich-text-editor-cRLC-eBK.js.map +1 -0
  463. package/dist/rich-text-editor-toolbar-DfXg0-VC.js +94 -0
  464. package/dist/rich-text-editor-toolbar-DfXg0-VC.js.map +1 -0
  465. package/dist/rich-text-editor.strings-CB59ekH2.js +38 -0
  466. package/dist/rich-text-editor.strings-CB59ekH2.js.map +1 -0
  467. package/dist/safe-image-src-C6kQSMBZ.js +17 -0
  468. package/dist/safe-image-src-C6kQSMBZ.js.map +1 -0
  469. package/dist/sanitize-html-DsQmI48u.js +92 -0
  470. package/dist/sanitize-html-DsQmI48u.js.map +1 -0
  471. package/dist/scroll-area-DcI-M1UT.js +48 -0
  472. package/dist/scroll-area-DcI-M1UT.js.map +1 -0
  473. package/dist/{separator-Do5GWDYi.js → separator-BDV-Y648.js} +3 -3
  474. package/dist/{separator-Do5GWDYi.js.map → separator-BDV-Y648.js.map} +1 -1
  475. package/dist/{separator-BMEvwnSX.js → separator-Bom7NsGO.js} +2 -2
  476. package/dist/{separator-BMEvwnSX.js.map → separator-Bom7NsGO.js.map} +1 -1
  477. package/dist/services/actions/action-adapters.d.ts +18 -0
  478. package/dist/services/actions/index.d.ts +1 -1
  479. package/dist/services/actions.js +16 -4
  480. package/dist/services/actions.js.map +1 -1
  481. package/dist/settings-ybnjVwbd.js +171 -0
  482. package/dist/settings-ybnjVwbd.js.map +1 -0
  483. package/dist/sheet-CGpB3omz.js +211 -0
  484. package/dist/sheet-CGpB3omz.js.map +1 -0
  485. package/dist/{sidebar-Cb8WzOvE.js → sidebar-A0ElHINE.js} +17 -16
  486. package/dist/sidebar-A0ElHINE.js.map +1 -0
  487. package/dist/{sidebar-Crc9M9JV.js → sidebar-CPx_7YBa.js} +205 -203
  488. package/dist/sidebar-CPx_7YBa.js.map +1 -0
  489. package/dist/{skeleton-DVMXr15h.js → skeleton-Byjnt7qr.js} +9 -9
  490. package/dist/{skeleton-DVMXr15h.js.map → skeleton-Byjnt7qr.js.map} +1 -1
  491. package/dist/smart-card-DiC5aac3.js +604 -0
  492. package/dist/smart-card-DiC5aac3.js.map +1 -0
  493. package/dist/{structure-hzCW-XsV.js → structure-BmisBK-3.js} +2 -2
  494. package/dist/{structure-hzCW-XsV.js.map → structure-BmisBK-3.js.map} +1 -1
  495. package/dist/style.css +1 -1
  496. package/dist/surface-recipes-BKRVW8Os.js +43 -0
  497. package/dist/surface-recipes-BKRVW8Os.js.map +1 -0
  498. package/dist/table-BweFy_P9.js +1530 -0
  499. package/dist/table-BweFy_P9.js.map +1 -0
  500. package/dist/table-DsfzoUia.js +175 -0
  501. package/dist/table-DsfzoUia.js.map +1 -0
  502. package/dist/tabs-CDocW5D1.js +191 -0
  503. package/dist/tabs-CDocW5D1.js.map +1 -0
  504. package/dist/text-inputs-f9Ia-aCi.js +353 -0
  505. package/dist/text-inputs-f9Ia-aCi.js.map +1 -0
  506. package/dist/theme-mode-css-BB-_RYab.js +14 -0
  507. package/dist/theme-mode-css-BB-_RYab.js.map +1 -0
  508. package/dist/theme-scope-BJ6eE2xt.js +50 -0
  509. package/dist/theme-scope-BJ6eE2xt.js.map +1 -0
  510. package/dist/theme.css +285 -228
  511. package/dist/themes/green.css +16 -12
  512. package/dist/timelines-CwM_9IhD.js +457 -0
  513. package/dist/timelines-CwM_9IhD.js.map +1 -0
  514. package/dist/tone-recipes-BPsRAvhu.js +73 -0
  515. package/dist/tone-recipes-BPsRAvhu.js.map +1 -0
  516. package/dist/tooltip-yiRJUFjp.js +111 -0
  517. package/dist/tooltip-yiRJUFjp.js.map +1 -0
  518. package/dist/{tree-BotPlyiD.js → tree-WnKQzwbq.js} +69 -67
  519. package/dist/tree-WnKQzwbq.js.map +1 -0
  520. package/dist/typography/rich-text.js +1 -1
  521. package/dist/typography-UTnveOEy.js +117 -0
  522. package/dist/typography-UTnveOEy.js.map +1 -0
  523. package/dist/typography.js +2 -2
  524. package/dist/{ui-provider-D2_TeLqw.js → ui-provider-C_U0Xma4.js} +13 -5
  525. package/dist/ui-provider-C_U0Xma4.js.map +1 -0
  526. package/dist/ui-provider.js +3 -3
  527. package/dist/{upload-B0WHW7ak.js → upload-CXyxmQBP.js} +210 -209
  528. package/dist/upload-CXyxmQBP.js.map +1 -0
  529. package/dist/{upload-queue-BHZ_wBfd.js → upload-queue-Boscubn9.js} +111 -111
  530. package/dist/upload-queue-Boscubn9.js.map +1 -0
  531. package/dist/upload.recipes-BbxTqrCT.js +61 -0
  532. package/dist/upload.recipes-BbxTqrCT.js.map +1 -0
  533. package/dist/{usage-card-U0YBLTNT.js → usage-card-BhO5eqkX.js} +45 -29
  534. package/dist/usage-card-BhO5eqkX.js.map +1 -0
  535. package/dist/{utils-Cospvlj1.js → utils-BRhFDwuU.js} +114 -67
  536. package/dist/utils-BRhFDwuU.js.map +1 -0
  537. package/dist/value-inputs-DXPDjvBU.js +963 -0
  538. package/dist/value-inputs-DXPDjvBU.js.map +1 -0
  539. package/dist/{value-typography-Deb3yQZg.js → value-typography-BP8OG6h5.js} +2 -2
  540. package/dist/{value-typography-Deb3yQZg.js.map → value-typography-BP8OG6h5.js.map} +1 -1
  541. package/dist/workspace-Cdrg7k9f.js +408 -0
  542. package/dist/workspace-Cdrg7k9f.js.map +1 -0
  543. package/docs/consumer-skill/SKILL.md +21 -22
  544. package/docs/consumer-skill/examples/app-layout.tsx +1 -1
  545. package/docs/consumer-skill/examples/composition.tsx +3 -3
  546. package/docs/consumer-skill/examples/detail.tsx +59 -12
  547. package/docs/consumer-skill/examples/edit.tsx +1 -1
  548. package/docs/consumer-skill/examples/receipt.tsx +2 -2
  549. package/docs/consumer-skill/examples/scoped-directory.tsx +1 -1
  550. package/docs/consumer-skill/examples/website.tsx +1 -1
  551. package/docs/consumer-skill/references/agents-md.md +33 -0
  552. package/docs/consumer-skill/references/analytics.md +1 -1
  553. package/docs/consumer-skill/references/composition.md +58 -13
  554. package/docs/consumer-skill/references/design-contract.md +12 -3
  555. package/docs/consumer-skill/references/installation.md +11 -1
  556. package/docs/consumer-skill/references/integration.md +4 -3
  557. package/docs/consumer-skill/references/public-api.json +956 -453
  558. package/docs/consumer-skill/references/review.md +32 -5
  559. package/docs/consumer-skill/references/theming.md +78 -9
  560. package/docs/consumer-skill/references/tokens.json +1 -1
  561. package/docs/consumer-skill/references/workflows.md +54 -10
  562. package/docs/consumer-skill/scripts/composition-policy.mjs +42 -11
  563. package/docs/consumer-skill/scripts/surface-policy.mjs +150 -5
  564. package/package.json +17 -5
  565. package/dist/accordion-CQXVcd7Q.js +0 -205
  566. package/dist/accordion-CQXVcd7Q.js.map +0 -1
  567. package/dist/action-menu-BTpyPWJ2.js +0 -264
  568. package/dist/action-menu-BTpyPWJ2.js.map +0 -1
  569. package/dist/affordance-geometry.generated-CCIXb2A1.js +0 -68
  570. package/dist/affordance-geometry.generated-CCIXb2A1.js.map +0 -1
  571. package/dist/ai-artifact-2PQ2fItc.js +0 -1112
  572. package/dist/ai-artifact-2PQ2fItc.js.map +0 -1
  573. package/dist/attachment-q69dlt5Y.js +0 -244
  574. package/dist/attachment-q69dlt5Y.js.map +0 -1
  575. package/dist/auth-M3vGMgDR.js.map +0 -1
  576. package/dist/avatar-djdaaQ_s.js.map +0 -1
  577. package/dist/badge-0tATj-tW.js +0 -92
  578. package/dist/badge-0tATj-tW.js.map +0 -1
  579. package/dist/breadcrumbs-BG_FfMK4.js +0 -128
  580. package/dist/breadcrumbs-BG_FfMK4.js.map +0 -1
  581. package/dist/button-BS3KDg00.js.map +0 -1
  582. package/dist/button-R9CCoH7A.js.map +0 -1
  583. package/dist/buttons-DS0ZIwJ_.js +0 -99
  584. package/dist/buttons-DS0ZIwJ_.js.map +0 -1
  585. package/dist/cards-QoJ4syG9.js +0 -66
  586. package/dist/cards-QoJ4syG9.js.map +0 -1
  587. package/dist/chart-DwYRKKc-.js.map +0 -1
  588. package/dist/checkbox-B7ygNTYp.js +0 -35
  589. package/dist/checkbox-B7ygNTYp.js.map +0 -1
  590. package/dist/choice-inputs-DrJ17tpL.js +0 -752
  591. package/dist/choice-inputs-DrJ17tpL.js.map +0 -1
  592. package/dist/code-block-CD0B7M93.js +0 -183
  593. package/dist/code-block-CD0B7M93.js.map +0 -1
  594. package/dist/combobox-6dvVny2q.js +0 -272
  595. package/dist/combobox-6dvVny2q.js.map +0 -1
  596. package/dist/combobox-CB7039j7.js +0 -865
  597. package/dist/combobox-CB7039j7.js.map +0 -1
  598. package/dist/comments-You0Bzbr.js.map +0 -1
  599. package/dist/components/layout/page/partials/page-header-commands.d.ts +0 -13
  600. package/dist/containers-D_L4mTVb.js.map +0 -1
  601. package/dist/data-display-3xWQUnMA.js +0 -1335
  602. package/dist/data-display-3xWQUnMA.js.map +0 -1
  603. package/dist/date-picker-DrDFj8Lo.js +0 -1527
  604. package/dist/date-picker-DrDFj8Lo.js.map +0 -1
  605. package/dist/date-pickers-CnFCb0n2.js +0 -174
  606. package/dist/date-pickers-CnFCb0n2.js.map +0 -1
  607. package/dist/display-DrdvPwF0.js +0 -343
  608. package/dist/display-DrdvPwF0.js.map +0 -1
  609. package/dist/dropdown-menu-CURh59jb.js +0 -193
  610. package/dist/dropdown-menu-CURh59jb.js.map +0 -1
  611. package/dist/editable-text-recipe-Bkm6wKHp.js +0 -10
  612. package/dist/editable-text-recipe-Bkm6wKHp.js.map +0 -1
  613. package/dist/feedback-C7nR0UtT.js +0 -232
  614. package/dist/feedback-C7nR0UtT.js.map +0 -1
  615. package/dist/field-affordance-recipes-CkOCdE2y.js +0 -46
  616. package/dist/field-affordance-recipes-CkOCdE2y.js.map +0 -1
  617. package/dist/field-state-recipes-C-MFBX_8.js +0 -11
  618. package/dist/field-state-recipes-C-MFBX_8.js.map +0 -1
  619. package/dist/filters-Da-gNPsE.js.map +0 -1
  620. package/dist/form-field-VZRULhUK.js.map +0 -1
  621. package/dist/form-sizing-uWP4lzVh.js.map +0 -1
  622. package/dist/forms-numeric-D3CO60IF.js +0 -905
  623. package/dist/forms-numeric-D3CO60IF.js.map +0 -1
  624. package/dist/header-2ycNqGOR.js.map +0 -1
  625. package/dist/icon-badge-DKlaKXoo.js +0 -53
  626. package/dist/icon-badge-DKlaKXoo.js.map +0 -1
  627. package/dist/input-BoLm9Hks.js +0 -20
  628. package/dist/input-BoLm9Hks.js.map +0 -1
  629. package/dist/input-DhQdBnV3.js +0 -255
  630. package/dist/input-DhQdBnV3.js.map +0 -1
  631. package/dist/item-xzh8Df65.js +0 -264
  632. package/dist/item-xzh8Df65.js.map +0 -1
  633. package/dist/media-gallery-DQUQ0m3O.js +0 -201
  634. package/dist/media-gallery-DQUQ0m3O.js.map +0 -1
  635. package/dist/mentions-DwnO1hh4.js +0 -564
  636. package/dist/mentions-DwnO1hh4.js.map +0 -1
  637. package/dist/message-YfFmbXNP.js.map +0 -1
  638. package/dist/navigation-Cbp5V8gG.js +0 -264
  639. package/dist/navigation-Cbp5V8gG.js.map +0 -1
  640. package/dist/navigation-Cs1npsPm.js +0 -300
  641. package/dist/navigation-Cs1npsPm.js.map +0 -1
  642. package/dist/overlay.recipes-CNO2S9V6.js +0 -34
  643. package/dist/overlay.recipes-CNO2S9V6.js.map +0 -1
  644. package/dist/overlays-DhZO7N-I.js +0 -994
  645. package/dist/overlays-DhZO7N-I.js.map +0 -1
  646. package/dist/page-C6R_8jFt.js +0 -325
  647. package/dist/page-C6R_8jFt.js.map +0 -1
  648. package/dist/page-header-hUTzcRZX.js +0 -112
  649. package/dist/page-header-hUTzcRZX.js.map +0 -1
  650. package/dist/pagination-Cm0jqa3I.js +0 -149
  651. package/dist/pagination-Cm0jqa3I.js.map +0 -1
  652. package/dist/popover-Dcv_9jxr.js.map +0 -1
  653. package/dist/popover-menu-DnRFKnHP.js +0 -99
  654. package/dist/popover-menu-DnRFKnHP.js.map +0 -1
  655. package/dist/popover.recipes-wmbvL8Ah.js.map +0 -1
  656. package/dist/primitives-BHrwQXFC.js.map +0 -1
  657. package/dist/rich-text-editor-CF8QYt5p.js +0 -574
  658. package/dist/rich-text-editor-CF8QYt5p.js.map +0 -1
  659. package/dist/rich-text-editor.recipes-CnrbmTS1.js +0 -81
  660. package/dist/rich-text-editor.recipes-CnrbmTS1.js.map +0 -1
  661. package/dist/rich-text-editor.strings-BpnIQgMl.js +0 -25
  662. package/dist/rich-text-editor.strings-BpnIQgMl.js.map +0 -1
  663. package/dist/rich-text-j-FGAeZW.js +0 -32
  664. package/dist/rich-text-j-FGAeZW.js.map +0 -1
  665. package/dist/sanitize-html-BG9FGe-j.js +0 -64
  666. package/dist/sanitize-html-BG9FGe-j.js.map +0 -1
  667. package/dist/scroll-area-DRdr16Pt.js +0 -47
  668. package/dist/scroll-area-DRdr16Pt.js.map +0 -1
  669. package/dist/settings-DHk0L2MF.js +0 -161
  670. package/dist/settings-DHk0L2MF.js.map +0 -1
  671. package/dist/sheet-DRFNY1_D.js +0 -207
  672. package/dist/sheet-DRFNY1_D.js.map +0 -1
  673. package/dist/sidebar-Cb8WzOvE.js.map +0 -1
  674. package/dist/sidebar-Crc9M9JV.js.map +0 -1
  675. package/dist/smart-card-Bek-TwUp.js +0 -599
  676. package/dist/smart-card-Bek-TwUp.js.map +0 -1
  677. package/dist/spinner-CmTAbEp0.js +0 -80
  678. package/dist/spinner-CmTAbEp0.js.map +0 -1
  679. package/dist/surface-recipes-DOdoBXGm.js +0 -28
  680. package/dist/surface-recipes-DOdoBXGm.js.map +0 -1
  681. package/dist/table-D6zKeYQX.js +0 -162
  682. package/dist/table-D6zKeYQX.js.map +0 -1
  683. package/dist/table-Dn4XSrSB.js +0 -1444
  684. package/dist/table-Dn4XSrSB.js.map +0 -1
  685. package/dist/tabs-Dk8E_knt.js +0 -189
  686. package/dist/tabs-Dk8E_knt.js.map +0 -1
  687. package/dist/text-inputs-BFpku0Qd.js +0 -331
  688. package/dist/text-inputs-BFpku0Qd.js.map +0 -1
  689. package/dist/theme-scope-kStaAer0.js +0 -39
  690. package/dist/theme-scope-kStaAer0.js.map +0 -1
  691. package/dist/timelines-CxuAFIc2.js +0 -439
  692. package/dist/timelines-CxuAFIc2.js.map +0 -1
  693. package/dist/tree-BotPlyiD.js.map +0 -1
  694. package/dist/typography-CAr3dQhX.js +0 -116
  695. package/dist/typography-CAr3dQhX.js.map +0 -1
  696. package/dist/ui-provider-D2_TeLqw.js.map +0 -1
  697. package/dist/upload-B0WHW7ak.js.map +0 -1
  698. package/dist/upload-queue-BHZ_wBfd.js.map +0 -1
  699. package/dist/usage-card-U0YBLTNT.js.map +0 -1
  700. package/dist/use-file-drop-target-BX7GnhoQ.js +0 -39
  701. package/dist/use-file-drop-target-BX7GnhoQ.js.map +0 -1
  702. package/dist/utils-Cospvlj1.js.map +0 -1
  703. package/dist/value-inputs-CjfzGMsN.js +0 -854
  704. package/dist/value-inputs-CjfzGMsN.js.map +0 -1
  705. package/dist/workspace-YoFjXi6i.js +0 -394
  706. package/dist/workspace-YoFjXi6i.js.map +0 -1
  707. /package/dist/components/{blocks/data-display/metadata → base/metadata-list}/metadata-list.strings.d.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  # Composition review and checks
2
2
 
3
- Use after selecting owners, or when auditing a screen. Read only the relevant
4
- workflow/declarations; this is a review aid, not a new design system.
3
+ Use after selecting owners, when auditing a screen, and before handing back UI
4
+ work. Read only the relevant workflow/declarations; this is not a new design system.
5
5
 
6
6
  ## Review the task and hierarchy
7
7
 
@@ -22,7 +22,25 @@ These criteria allow different product layouts. Do not impose a universal card
22
22
  count, row-line limit or one-column form rule. Emphasis is the exception: keep
23
23
  one solid primary command per page or surface, so the next action stays obvious.
24
24
 
25
- ## Optional source checker
25
+ ## Done means
26
+
27
+ UI work is done when the source checker below reports no errors on the files you
28
+ changed, and the app's typecheck, lint and tests then pass. Run the checker, fix
29
+ the owner or prop each finding names, and run it again; after three rounds, stop
30
+ and report what remains. Warnings are review findings: fix each one or keep it
31
+ with a reason. This is the agent's completion condition, not the build's; app CI
32
+ may stay non-blocking on warnings. The [project instructions
33
+ block](agents-md.md) states the same condition in the app's `AGENTS.md`.
34
+
35
+ Hand back five lines, so a skipped check is visible:
36
+
37
+ 1. Owners used for the route, its commands and each data region.
38
+ 2. Checker: run or not run, with its error and warning counts.
39
+ 3. Typecheck, lint and tests: each run or not run, and why.
40
+ 4. Kept warnings, each with file:line and its reason.
41
+ 5. States covered or missing: loading, empty, error, disabled and validation.
42
+
43
+ ## Source checker
26
44
 
27
45
  The package ships a read-only script, not an npm bin/global CLI. It needs the
28
46
  consumer's TypeScript development dependency and Node matching the package engine:
@@ -41,7 +59,7 @@ Errors cover unknown package entrypoints/symbols and statically detected overrid
41
59
  of protected Card/popup insets, Card badges in headerAction/headerStart rather
42
60
  than titleSuffix, control geometry/typography, fixed DisplayLabel/Badge
43
61
  roles, cross-role shell/inner radius replacements, display-copy margins, or
44
- attenuated shared focus rings on imported controls. Intentional nested bodies,
62
+ redrawn focus indicators (another ring width, offset or halo strength) on imported controls. Intentional nested bodies,
45
63
  circular owners and joined-edge corner resets retain their roles. Import ownership
46
64
  follows lexical bindings, preserving locally shadowed application components. Imports of
47
65
  symbols the public index marks deprecated, nested framed subjects and repeated
@@ -49,6 +67,13 @@ literal headings produce review warnings; warnings alone do not fail CI. Message
49
67
  identify the owner and remedy. Dialog-like UI outside the overlay owners warns
50
68
  too: native elements with `role="dialog"`/`"alertdialog"` or `aria-modal`, a
51
69
  `fixed inset-0` layer, and imports of another modal library.
70
+
71
+ The checker also rejects faded semantic text colors and partial opacity on
72
+ imported typography/value primitives, including aliases and namespace imports.
73
+ Use the shared secondary/status role. Presence endpoints (0/100) and the shared
74
+ disabled 50% treatment remain valid; component disabled props keep that dimming
75
+ with its owner.
76
+
52
77
  Standalone compact Cards and Page gutter removal also produce review warnings.
53
78
  Buttons placed in a Page or PageHeader `actions` region warn as well: pass
54
79
  commands as `primaryAction` and ordered `secondaryActions` so the header owns
@@ -61,7 +86,9 @@ semantic surface/foreground pair or a status tone. A Card title icon and an icon
61
86
  more than one MetadataList fact warn as decoration; keep a glyph only when it
62
87
  encodes state or a brand. Native `<button>` and
63
88
  `<h1>`–`<h6>` elements warn in favour of Button/TextButton and Heading, which
64
- own focus, loading and disabled states or margins and the heading scale.
89
+ own focus, loading and disabled states or margins and the heading scale. A
90
+ native button passed as a package owner's `render`, such as an Item row
91
+ rendered as a button, is that owner's root and does not warn.
65
92
  Verified Card-owning Metric/card-grid, UsageCard and TaskCard compositions also
66
93
  participate in nested-surface and peer-gap review. Metric without its card variant,
67
94
  compact MetricGrid, flat TaskCard, ChartCard and Receipt do not establish a frame.
@@ -4,10 +4,20 @@ The [design contract](design-contract.md) records which geometry changes togethe
4
4
  and which variant choices remain independent. Retheme shared responsibilities;
5
5
  avoid overriding individual components to imitate another density or inset.
6
6
 
7
- Use shadcn semantic surfaces/foregrounds: background, card, popover, primary, secondary, muted, accent, destructive, border, input, ring, charts and sidebar. Central success/info/warning foreground pairs express states; never overload primary or statuses as decoration. `--input` is the control boundary and keeps 3:1 against every surface (WCAG 1.4.11); `--border` is for dividers and surface edges. Keep that split when rebranding.
7
+ Use shadcn semantic surfaces/foregrounds: background, card, popover, primary, secondary, muted, accent, destructive, border, input, ring, charts and sidebar. Central success/info/warning foreground pairs express states; never overload primary or statuses as decoration. `--input` is the one resting control boundary: fields, select and date triggers, checkboxes, radios, switch tracks and outline buttons all draw it, so adjoining controls read as one family. It provides at least 3:1 contrast on the declared background, card, popover, muted, accent and secondary surfaces in both modes. Focus and invalid edges retain their separate 3:1 contract. `--border` is for quieter dividers and surface edges. When rebranding, check resting controls as well as focused controls, including the outside edge of fields with their own fill.
8
8
 
9
9
  tokens.json distinguishes 23 structural roots, advanced typography/status settings, and derived utility spellings. A utility is not another public variable. Keep overrides in one stylesheet at root or ThemeScope, without copying computed CSS into JavaScript.
10
10
 
11
+ Pair each painted surface with its intended ink: `bg-card text-card-foreground`
12
+ and `bg-popover text-popover-foreground` are matching pairs. Flat sections inherit
13
+ the containing surface. For app-owned primary copy in a differently colored
14
+ surface, use Text/Value `type="inherit"` and Label `className="text-inherit"`;
15
+ standalone typography keeps its documented defaults. Keep secondary, link, status
16
+ and inverse roles explicit, and use a secondary text role instead of fading text
17
+ with opacity. Component disabled props own dimming; an extra faded wrapper can
18
+ multiply it. Brand colors alone do not guarantee input/focus contrast: retain the
19
+ central `--input`/`--ring` roles or verify their replacements on every host surface.
20
+
11
21
  The default `--radius` is 0.75rem (12px). One public root drives two shared
12
22
  roles; component owners choose the role, so ordinary callers add no radius class.
13
23
 
@@ -47,6 +57,14 @@ replacing individual components' owned corners.
47
57
 
48
58
  Action and editable-control heights are separate roles; keep roots equal for adjoining alignment. `--space-scale` multiplies structural gaps, inline insets and surface padding. `--density-scale` multiplies action/control height and collection block padding. Roots are unscaled measurements; do not pre-multiply and then apply the utility again.
49
59
 
60
+ Control heights are nominal floors when custom typography needs more room.
61
+ Native fields, Select and InputGroup frames fit their editable line plus the
62
+ border, and cap vertical padding to the space remaining in the nominal height.
63
+ The default 32/36/40px sizes and radius roles stay unchanged. Text actions grow
64
+ under their intentionally tighter leading, so independently enlarged type can
65
+ produce different fitted heights even with equal action/control roots. Check
66
+ type size, leading and height roots together when exact custom pairing matters.
67
+
50
68
  Both surface roots default to 1.25rem. At a 16px root font and space-scale 1,
51
69
  ordinary surface insets are 20px, compact insets are 10px and large insets are
52
70
  36px. Page's default large gutters inherit that same recipe. Row insets,
@@ -65,11 +83,58 @@ Use discrete inset, density and size props for the component responsibility desc
65
83
 
66
84
  The default primary is near-black so success and other status colors never compete
67
85
  with it. `themelia-react-ui/themes/green.css`, imported after `style.css`, is the
68
- opt-in Themelia green brand (primary, its foreground, the dark accent and the first
69
- chart series). Rebrand by setting `--primary` and `--primary-foreground` in both
70
- `:root` and `.dark`; keep the brand hue clear of the status hues and check 4.5:1.
86
+ opt-in Themelia green brand (primary, its foreground and the dark accent; the first
87
+ chart series is already that green). Rebrand by setting `--primary` and
88
+ `--primary-foreground` in both `:root` and `.dark`; the sidebar's primary follows
89
+ them in both modes. Keep the brand hue clear of the status hues and check 4.5:1.
90
+
91
+ Root overrides reach body portals. Scoped themes use ThemeScope from ui-provider.
92
+ The nearest explicit `.light` or `.dark` boundary governs the palette and dark
93
+ utilities, including repeated nesting and scoped portals. This uses inherited
94
+ custom-property container style queries, supported in Chromium 111+, Safari 18.1+
95
+ and Firefox 151+. The internal mode marker is state derived from those classes;
96
+ it is not another customization setting.
97
+
98
+ When ThemeScope's `style` supplies `--primary`, its default `--primary-accent`
99
+ and `--sidebar-primary` references resolve at that scope. The same applies to
100
+ `--primary-foreground` / `--sidebar-primary-foreground`, `--foreground` /
101
+ `--popover-foreground`, and `--font-sans` / `--font-heading`. Explicit local role
102
+ overrides in CSS or `style` win. A child scope with no new source override
103
+ inherits independent roles unchanged. Mode-dependent roles such as the elevated
104
+ dark `--popover` stay owned by the palette.
105
+
106
+ Package defaults and these alias references live in the `theme` cascade layer.
107
+ Explicit Tailwind utility overrides therefore win on plain scopes and scopes
108
+ with a mode class, as do unlayered consumer CSS and inline overrides. Keep the
109
+ standard `theme, base, components, utilities` layer order when composing your
110
+ application stylesheet.
111
+
112
+ CSS class themes declare their source roots and dependent aliases together:
113
+ CSS resolves aliases at their declaration boundary, and a scope cannot infer
114
+ which declarations an arbitrary consumer stylesheet supplied.
115
+
116
+ ```css
117
+ .tenant-theme {
118
+ --primary: oklch(0.45 0.12 250);
119
+ --primary-accent: var(--primary);
120
+ --sidebar-primary: var(--primary);
121
+ --primary-foreground: oklch(0.99 0 0);
122
+ --sidebar-primary-foreground: var(--primary-foreground);
123
+ --font-sans: Georgia, serif;
124
+ --font-heading: var(--font-sans);
125
+ }
126
+ ```
127
+
128
+ Advanced editing uses the theme-tweaker public API, editing CSS rather than
129
+ adding another JavaScript styling system.
71
130
 
72
- Root overrides reach body portals. Scoped themes use ThemeScope from ui-provider. Advanced editing uses the theme-tweaker public API, editing CSS rather than adding another JavaScript styling system.
131
+ For tenant exports, pass the whole result of
132
+ `createScopedAdminUIThemeSelectors(scopeSelector)` to `serializeAdminUITheme`.
133
+ Its additive `modeScope` metadata selects light/dark values by the nearest mode
134
+ boundary, including complex selector lists. The existing `shared`, `light` and
135
+ `dark` strings remain available; manually supplied selectors without `modeScope`
136
+ are emitted literally. Mode-specific ChartStyle series use the same boundary
137
+ policy, while a fixed single-color series remains independent of mode.
73
138
 
74
139
  Explicit portal containers take precedence over the nearest ThemeScope. Place those containers inside the intended theme boundary; a portal deliberately moved outside it cannot inherit that boundary automatically. Test the opened popup, not only its trigger.
75
140
 
@@ -77,9 +142,13 @@ Apps using semantic utilities in their own JSX process themelia-react-ui/theme.c
77
142
 
78
143
  The package class merger recognizes token overrides only for advertised utilities and exact class spellings emitted by the library stylesheet, including their negative, important and responsive forms. A valid Tailwind alias such as `m-space-2xl` can still be absent from that stylesheet. Unshipped aliases preserve existing fallback classes; they do not receive package override semantics merely because an app's separate Tailwind build can generate them. Use the app's own merge configuration for additional app-compiled aliases.
79
144
 
80
- `ring` and `sidebar-ring` are focus roles tested at full strength. Preserve that
81
- strength and verify at least 3:1 against adjacent surfaces when overriding the
82
- theme; adding opacity can invalidate contrast even when the root color passes.
145
+ `ring` and `sidebar-ring` are the focus roles. Every focused element draws one
146
+ indicator: a 1px edge in the role at full strength (the control's own border, an
147
+ inset edge on borderless rows, or an outline just outside link text) inside a
148
+ soft 3px halo of the role at 50%. The edge carries the tested 3:1 contrast
149
+ against adjacent surfaces, so keep the root color at that strength when
150
+ overriding the theme; the halo makes focus stand out without reading as a
151
+ heavier border.
83
152
 
84
153
  ## Extend without drift
85
154
 
@@ -104,4 +173,4 @@ heights. `--icon` and `--avatar` set media dimensions independently. Component
104
173
  Test these choices separately and in combination. Tables follow row insets,
105
174
  Cards and code/message bodies follow surfaces, and image containment uses generic
106
175
  spacing. Foundation directional spacing utilities ship with style.css and use
107
- the same seven steps as gaps; generated spellings are not new theme roots.
176
+ the same eight steps as gaps; generated spellings are not new theme roots.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "themelia-react-ui",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "structural": [
5
5
  {
6
6
  "name": "--space-scale",
@@ -18,6 +18,14 @@ and explicit maximums from your column definitions. The table owns its one named
18
18
  scroll region. Verify grouped widths, sticky header rows and first-column behavior
19
19
  with real overflow in both directions, rather than adding another focusable wrapper.
20
20
 
21
+ ## Media selection
22
+
23
+ For a browsing `MediaLibrary` with `bulkActions`, localize the selected-assets
24
+ region through `strings.batchActionsLabel` (English default: `Batch actions`).
25
+ The visible selection summary and Clear action stay in
26
+ `strings.footer.selectedCount` and `strings.footer.clear`. The native
27
+ `BatchActionBar` owns the region and its dismissal/focus behavior.
28
+
21
29
  ## Comment attachments
22
30
 
23
31
  `Comments` and `CommentComposer` announce attachment validation/upload errors.
@@ -28,9 +36,23 @@ Reset/removal aborts pending uploads; the app owns transport and persistence.
28
36
 
29
37
  ## Detail and framing
30
38
 
31
- [AccountDetail](../examples/detail.tsx) exports `AccountDetail`, `AccountDetailProps` and `AccountDetailRecord`. Supply `account`, `onEdit(id)` and `onBack()`. Card owns the frame/header/body/footer; Name, Email, Date, Money and Value own formatting and missing-value fallbacks. `balanceMinor` uses `Money unit="minor"`; currency and date values come from the app.
32
-
33
- No optional peers are needed. The app supplies the loaded record and owns navigation, locale/provider defaults and permissions. Verify missing email/date/balance, a real minor-unit amount, Edit/Back callbacks, and the one-column mobile/two-column desktop composition in light/dark themes.
39
+ [The detail recipe](../examples/detail.tsx) exports two owners.
40
+ `AccountDetailPage` is the record route: Page owns the title, one status badge,
41
+ the commands and the section tabs. `primaryAction` is Edit account,
42
+ `secondaryActions` holds Send statement and a `destructive` Delete account that
43
+ opens ConfirmDialog, and `header.tabs` carries Overview, Invoices with its count
44
+ badge, and Activity. The header renders `[secondary…] [primary] [⋯]`; destructive
45
+ and overflow commands live in the More actions menu. `AccountDetail` is the same
46
+ facts as one framed subject for a drawer or dashboard, with Edit as its one quick
47
+ `headerAction`. Name, Email, Date, Money and Value own formatting and
48
+ missing-value fallbacks; `balanceMinor` uses `Money unit="minor"`.
49
+
50
+ No optional peers are needed. The app supplies the loaded record, the section
51
+ content and the delete transport, and owns navigation, locale/provider defaults
52
+ and permissions (`visible: false` hides a command). Verify missing
53
+ email/date/balance, a rejected delete that keeps the confirmation open, tab
54
+ selection with keyboard arrows, the narrow layout where secondary commands
55
+ collapse into the menu, and light/dark themes.
34
56
 
35
57
  ## Scoped directory
36
58
 
@@ -58,6 +80,23 @@ in pagination URLs. A criteria-driven business selector would be a different
58
80
  product contract. The recipe's English labels are example copy: adapt labels,
59
81
  criteria and component `strings` for app translation and permissions.
60
82
 
83
+ DataTable accessibility copy also belongs to `strings`: use
84
+ `accessibility.sortColumn(columnLabel)` and `accessibility.resizeColumn(columnLabel)`
85
+ for column controls, `emptyState.ariaLabel` for the empty-result status and
86
+ `selection.label` for the selected-row action region. Partial overrides preserve
87
+ the other English defaults.
88
+
89
+ For searchable selection, `Combobox` uses `strings.clear` and `strings.toggle`;
90
+ both single and multiple recipes use `strings.dismiss` for the two screen-reader
91
+ dismissal controls. `MultiCombobox` uses `strings.removeSelection(itemLabel)` for
92
+ each removal button.
93
+ Custom base anatomy exposes `ComboboxInputTrigger` strings `{ clear, toggle }`,
94
+ `ComboboxClear` strings `{ clear }` and `ComboboxChip` strings `{ remove }`.
95
+ `ComboboxRoot` preserves the supported upstream `dismissLabel` prop. This private
96
+ build requires the companion Base UI `1.8.0-kpo.2` archive. It includes that public seam
97
+ and preserves an existing focus target inside a parent popup during nested
98
+ popup dismissal.
99
+
61
100
  Strict imported declarations require the manifest's optional peers. DataTable
62
101
  sorting is disabled because the app's server owns query order. Loading/error
63
102
  feedback occupies the empty result region while query context remains mounted;
@@ -80,13 +119,15 @@ definitions; the app then chooses appropriate destination focus.
80
119
  ## Single resource page
81
120
 
82
121
  Use `Page` from `themelia-react-ui/layout/page` for the record route's identity,
83
- back navigation, content bounds and commands. Pass the record's main command as
84
- `header.primaryAction` and supporting commands as `header.secondaryActions`;
85
- `PageHeader` and `PageActions` remain for custom shells and toolbars.
86
- The [layout recipe](../examples/app-layout.tsx) demonstrates that route boundary;
87
- the [detail recipe](../examples/detail.tsx) demonstrates an independently framed
88
- record subject with MetadataList and value primitives. Decide whether the record
89
- needs that independent Card before nesting it under Page. Avoid repeating the
122
+ back navigation, content bounds, commands and section tabs. Pass the record's
123
+ main command as `header.primaryAction`, supporting commands as
124
+ `header.secondaryActions` and sections as `header.tabs`; one status badge goes in
125
+ `header.titleBadges`. `PageHeader` serves a custom shell; `PageActions` is
126
+ deprecated. The [layout recipe](../examples/app-layout.tsx) demonstrates that
127
+ route boundary; the [detail recipe](../examples/detail.tsx) demonstrates the
128
+ record route and an independently framed subject with MetadataList and value
129
+ primitives. Decide whether the record needs that independent Card before nesting
130
+ it under Page. Avoid repeating the
90
131
  route heading just to frame the same facts. Page owns gutters; PageViewport owns
91
132
  scrolling only. App navigation, record loading/missing/error/retry, permissions,
92
133
  edit and delete callbacks remain application responsibilities.
@@ -94,6 +135,9 @@ edit and delete callbacks remain application responsibilities.
94
135
  Use `WorkspaceLayout` from `themelia-react-ui/layout/workspace` when independently composed record header,
95
136
  sidebar/main/rail regions are needed; inspect `features/resource` for complete
96
137
  resource coordination. A single record does not automatically need either.
138
+ Their headers (`WorkspaceRecordHeader`, `ResourceHeader` and the resource shells)
139
+ take the same `primaryAction` and `secondaryActions` as Page; keep their
140
+ `actions` for non-command controls.
97
141
  Read [layout composition](composition.md#application-layouts) for boundary and
98
142
  parent-width behavior, then the exact selected declaration for its current props.
99
143
 
@@ -1,4 +1,4 @@
1
- import { surfaceParts, surfaceForwarders, paddingClass, paddingProperty, utility, attenuatedFocusRing, sharedCornerParts, displayNames, nativeDisplayNames, marginProperty, radiusProperty, replacesSharedRadius, cornerRole, addsCopyMargin } from './surface-policy.mjs';
1
+ import { surfaceParts, surfaceForwarders, paddingClass, paddingProperty, utility, focusRingDrift, fadedText, textOpacityDrift, textContentNames, sharedCornerParts, displayNames, nativeDisplayNames, marginProperty, radiusProperty, replacesSharedRadius, cornerRole, addsCopyMargin } from './surface-policy.mjs';
2
2
 
3
3
  const controlNames = /^(?:Base)?(?:Button|ButtonLink|IconButton)$|^(Input|InputGroup|InputGroupInput|InputGroupTextarea|Textarea|PasswordInput|Select|SelectTrigger|ComboboxInput|ComboboxInputTrigger|ComboboxTrigger)$/;
4
4
  const controlFamilies = new Set(['buttons', 'text-inputs', 'choice-inputs', 'combobox']);
@@ -200,15 +200,16 @@ export function analyzeComposition(text, { filename, index, ts }) {
200
200
  if (ts.isJsxExpression(node)) return slotBadge(node.expression);
201
201
  return false;
202
202
  };
203
- // Buttons placed directly, conditionally or inside a passive row of a page
204
- // header's actions region. Unknown local components are custom controls.
203
+ // Buttons, command rows and command menus placed directly, conditionally or
204
+ // inside a passive row of a page header's actions region. Unknown local
205
+ // components are custom controls.
205
206
  const commandButtons = expression => {
206
207
  const node = resolve(expression);
207
208
  if (!node) return false;
208
209
  if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node)) {
209
210
  const opening = ts.isJsxElement(node) ? node.openingElement : node;
210
211
  const owner = ownerFor(opening.tagName);
211
- if (isOwner(owner, 'base/buttons', ['Button', 'TextButton', 'BaseButton', 'BaseButtonLink']) || isOwner(owner, 'base/forms', ['SubmitStateButton']) || opening.tagName.getText(source) === 'button') return true;
212
+ if (isOwner(owner, 'base/buttons', ['Button', 'TextButton', 'BaseButton', 'BaseButtonLink']) || isOwner(owner, 'base/forms', ['SubmitStateButton']) || isOwner(owner, 'base/action-menu', ['ActionMenu', 'ActionButtons']) || isOwner(owner, 'layout/page', ['PageActions']) || isOwner(owner, 'layout', ['PageActions']) || opening.tagName.getText(source) === 'button') return true;
212
213
  if (!/^(div|span)$/.test(opening.tagName.getText(source)) && !isOwner(owner, 'base/structure', ['Stack', 'Grid'])) return false;
213
214
  return ts.isJsxElement(node) && node.children.some(commandButtons);
214
215
  }
@@ -314,12 +315,26 @@ export function analyzeComposition(text, { filename, index, ts }) {
314
315
  if (ts.isJsxSelfClosingElement(node)) inspect(node, parents);
315
316
  ts.forEachChild(node, child => visit(child, parents));
316
317
  }
318
+ // A native element passed as a package owner's `render` is that owner's root, such as
319
+ // an Item row rendered as a button; the owner keeps its focus, hover and row anatomy.
320
+ const renderRoots = new Set();
321
+ const collectRenderRoots = expression => {
322
+ if (!expression) return;
323
+ if (ts.isJsxSelfClosingElement(expression)) renderRoots.add(expression);
324
+ else if (ts.isJsxElement(expression)) renderRoots.add(expression.openingElement);
325
+ else if (ts.isParenthesizedExpression(expression) || ts.isAsExpression(expression)) collectRenderRoots(expression.expression);
326
+ else if (ts.isConditionalExpression(expression)) { collectRenderRoots(expression.whenTrue); collectRenderRoots(expression.whenFalse); }
327
+ else if (ts.isBinaryExpression(expression)) collectRenderRoots(expression.right);
328
+ else if (ts.isArrowFunction(expression) && !ts.isBlock(expression.body)) collectRenderRoots(expression.body);
329
+ };
317
330
  function inspect(node, parents) {
318
331
  const owner = ownerFor(node.tagName);
332
+ const render = owner && node.attributes.properties.find(attribute => ts.isJsxAttribute(attribute) && attribute.name.getText(source) === 'render');
333
+ if (render?.initializer) collectRenderRoots(ts.isJsxExpression(render.initializer) ? render.initializer.expression : render.initializer);
319
334
  if (classTokens(node).some(token => rawPaletteClass.test(token))) add(node, 'raw-palette-color', 'warning', 'Raw palette colors bypass the theme and dark mode. Use semantic classes such as bg-primary, bg-muted, text-muted-foreground, border-border or a status tone (text-destructive, bg-success/10).');
320
335
  if (!owner) {
321
336
  const tag = node.tagName.getText(source);
322
- if (tag === 'button') add(node, 'raw-button', 'warning', 'Use Button or TextButton from themelia-react-ui/base/buttons: they own size, focus ring, loading and disabled states.');
337
+ if (tag === 'button' && !renderRoots.has(node)) add(node, 'raw-button', 'warning', 'Use Button or TextButton from themelia-react-ui/base/buttons: they own size, focus ring, loading and disabled states.');
323
338
  if (/^h[1-6]$/.test(tag)) add(node, 'raw-heading', 'warning', 'Use Heading from themelia-react-ui/typography (tag for the level, size for emphasis): it resets native margins and keeps the shared heading scale.');
324
339
  const nativeProps = new Map(attributes(node));
325
340
  const modalRole = /^(?:dialog|alertdialog)$/.test(literal(nativeProps.get('role')) ?? '') || nativeProps.has('aria-modal');
@@ -350,16 +365,20 @@ export function analyzeComposition(text, { filename, index, ts }) {
350
365
  const control = controlFamilies.has(family) && controlNames.test(owner.symbol);
351
366
  const sharedCorners = sharedCornerParts[family]?.test(owner.symbol);
352
367
  const display = owner.import === `${index.package}/typography` && displayNames.test(owner.symbol);
368
+ const textContent = display || owner.import === `${index.package}/primitives` && textContentNames.test(owner.symbol);
353
369
  const fixedText = owner.import === `${index.package}/typography` && owner.symbol === 'DisplayLabel' || family === 'badge' && owner.symbol === 'Badge';
354
370
  const badge = family === 'badge' && owner.symbol === 'Badge';
355
371
  for (const name of ['className', 'headerClassName', 'contentClassName', 'footerClassName', 'subHeadingClassName']) {
356
372
  if (!props.has(name)) continue;
357
- const classes = classStrings(props.get(name)).flatMap(value => value.split(/\s+/)).map(utility);
373
+ const tokens = classStrings(props.get(name)).flatMap(value => value.split(/\s+/)).filter(Boolean);
374
+ const classes = tokens.map(utility);
375
+ const focusDrift = focusRingDrift(tokens);
358
376
  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.`);
359
377
  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.`);
360
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.`);
361
379
  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.`);
362
- if ((control || family === 'buttons' && owner.symbol === 'TextButton') && name === 'className' && classes.some(attenuatedFocusRing)) add(node, 'focus-ring-contrast', 'error', `${owner.symbol}: keep the shared ring-ring/sidebar-ring focus color at full strength; numeric opacity weakens its tested contrast.`);
380
+ 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
+ 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.`);
363
382
  if (fixedText && name === 'className' && classes.some(value => fixedTextClass.test(value) || badge && /^rounded(?:-|$)/.test(value))) add(node, 'fixed-text-role', 'error', `${owner.symbol}: preserve its shared typography${badge ? ' and radius' : ''}; use its public variants and className for placement.`);
364
383
  }
365
384
  if (props.has('style')) for (const [name,value] of properties(props.get('style'))) {
@@ -370,7 +389,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
370
389
  if (fixedText && (textStyle.test(name) || badge && /^border.*Radius$/.test(name))) add(node, 'fixed-text-role', 'error', `${owner.symbol}: ${name} replaces its shared text/radius recipe.`);
371
390
  }
372
391
  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.`);
373
- const facts = isOwner(owner, 'blocks/data-display', ['MetadataList']) ? resolve(props.get('items')) : undefined;
392
+ const facts = isOwner(owner, 'base/metadata-list', ['MetadataList']) || isOwner(owner, 'blocks/data-display', ['MetadataList']) ? resolve(props.get('items')) : undefined;
374
393
  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.');
375
394
  const framed = framedOwner(owner, props);
376
395
  if (isOwner(owner, 'base/cards', ['Card', 'SmartCard'])) {
@@ -380,7 +399,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
380
399
  const valueHeading = contents.some(item => role(item, ['Heading']) && /[$€£¥]|\d/.test(renderedText(item.element)));
381
400
  if (valueHeading && contents.some(item => role(item, ['Text', 'DisplayLabel'])) && contents.some(item => isOwner(item.owner, 'base/badge', ['Badge']) && /[%+−-]|\d/.test(renderedText(item.element)))) add(node, 'reinvented-metric-card', 'warning', 'This label/value/change composition resembles a KPI. Compare Metric/MetricGrid from blocks/analytics or InlineStat from blocks/data-display; retain a custom subject when their metric lifecycle does not fit.');
382
401
  const factRows = contents.filter(item => isOwner(item.owner, 'base/structure', ['Stack']) && literal(item.props.get('direction')) === 'horizontal' && literal(item.props.get('justify')) === 'between' && contentElements(item.opening).filter(child => role(child, ['Text', 'DisplayLabel'])).length >= 2);
383
- if (factRows.length >= 2) add(node, 'reinvented-metadata-list', 'warning', 'Repeated label/value rows resemble record facts. Compare MetadataList or InlineStat from blocks/data-display; preserve custom rows when they own distinct interactions or content.');
402
+ if (factRows.length >= 2) add(node, 'reinvented-metadata-list', 'warning', 'Repeated label/value rows resemble record facts. Compare MetadataList from base/metadata-list or InlineStat from blocks/data-display; preserve custom rows when they own distinct interactions or content.');
384
403
  if (contents.some(item => role(item, ['Heading']) && /^(?:no\b|nothing\b|empty\b)/i.test(renderedText(item.element))) && contents.some(item => isOwner(item.owner, 'base/structure', ['Stack']) && literal(item.props.get('align')) === 'center') && contents.some(item => isOwner(item.owner, 'base/buttons', ['Button', 'ButtonLink']))) add(node, 'reinvented-empty-state', 'warning', 'This centered empty region may fit EmptyState from blocks/data-display, with media, title, description and actions. Review the product state before choosing the complete owner.');
385
404
  }
386
405
  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.');
@@ -392,12 +411,24 @@ export function analyzeComposition(text, { filename, index, ts }) {
392
411
  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.`);
393
412
  const header = properties(props.get('header'), false);
394
413
  const pageOwner = owner.import === `${index.package}/layout/page` || owner.import === `${index.package}/layout`;
395
- const headerActions = pageOwner && owner.symbol === 'Page' ? new Map(header).get('actions') : pageOwner && owner.symbol === 'PageHeader' ? props.get('actions') : undefined;
414
+ // Every header owner takes role-based commands; its free-form regions hold
415
+ // non-command controls only.
416
+ 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']);
417
+ const headerActions = pageOwner && owner.symbol === 'Page' ? new Map(header).get('actions') : commandHeader ? props.get('actions') : undefined;
418
+ const elementSecondary = isOwner(owner, 'layout/workspace', ['WorkspaceRecordHeader']) ? props.get('secondaryActions') : undefined;
396
419
  if (pageOwner && owner.symbol === 'Page') {
397
420
  const primaries = solidPrimaryCount(ts.isJsxSelfClosingElement(node) ? node : node.parent) + (new Map(header).has('primaryAction') ? 1 : 0);
398
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.`);
399
422
  }
400
- if (headerActions && commandButtons(headerActions)) add(node, 'page-command-roles', 'warning', `${owner.symbol}: buttons in the header actions region choose their own emphasis, size and overflow. Pass commands as primaryAction (one) and ordered secondaryActions; keep actions for non-command controls.`);
423
+ 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
+ const headerProps = pageOwner && owner.symbol === 'Page' ? new Map(header) : pageOwner && owner.symbol === 'PageHeader' ? props : undefined;
425
+ if (headerProps) {
426
+ 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
+ const hasIcon = action => properties(action, false).some(([name]) => name === 'icon');
428
+ const secondary = resolve(headerProps.get('secondaryActions'));
429
+ const iconCommands = (headerProps.has('primaryAction') && hasIcon(headerProps.get('primaryAction')) ? 1 : 0) + (secondary && ts.isArrayLiteralExpression(secondary) ? secondary.elements.filter(hasIcon).length : 0);
430
+ if (iconCommands > 1) add(headerProps.get('secondaryActions') ?? node, 'decorative-icon', 'warning', `${owner.symbol}: ${iconCommands} page commands carry icons that repeat their labels. Keep the labels; reserve an icon for + on an add command or an external link.`);
431
+ }
401
432
  const title = literal(props.get('title')) ?? literal(new Map(header).get('title'));
402
433
  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.`);
403
434
  const structure = owner.import === `${index.package}/base/structure` && Object.hasOwn(structureDefaults, owner.symbol);
@@ -25,6 +25,7 @@ export const sharedCornerParts = {
25
25
  sheet: /^SheetContent$/,
26
26
  };
27
27
  export const displayNames = /^(?:Text|Heading|DisplayLabel|Label|TextLink)$/;
28
+ export const textContentNames = /^(?:Value|SecondaryValue|MutedValue|MonoValue|EmptyValue|Number|Percent|Money|Date|DateTime|Time|Duration|Name|Email|Phone|Link|FileSize|Dimensions|DateRange|RelativeTime|Url|Initials)$/;
28
29
  export const nativeDisplayNames = /^(?:p|h[1-6])$/;
29
30
  export const marginProperty = /^margin(?:Inline|Block)?(?:Start|End)?$|^margin(?:Top|Right|Bottom|Left)$|^margin-(?:(?:inline|block)(?:-(?:start|end))?|top|right|bottom|left)$/;
30
31
  export const radiusProperty = /^border(?:(?:Top|Bottom)(?:Left|Right)|(?:Start|End)(?:Start|End))?Radius$|^border-(?:(?:top|bottom)-(?:left|right)-|(?:start|end)-(?:start|end)-)?radius$/;
@@ -57,10 +58,154 @@ export function utility(token) {
57
58
  return token.slice(start).replace(/^!|!$/g, '');
58
59
  }
59
60
 
60
- /** Shared focus roles are contrast-tested at full strength, unlike status tints. */
61
- export function attenuatedFocusRing(token) {
62
- const match = utility(token).match(/^ring-(?:ring|sidebar-ring)\/(?:(\d+(?:\.\d+)?|\.\d+)|\[(\d+(?:\.\d+)?|\.\d+)(%)?\])$/);
61
+ export function variants(token) {
62
+ return token.slice(0, token.length - utility(token).length - (/!$/.test(token) ? 1 : 0)).replace(/!$/, '');
63
+ }
64
+
65
+ // Text and icon colours are typography roles. Opacity on a role adds a tier under
66
+ // the tested 4.5:1, so only the sidebar keeps its one secondary tier.
67
+ const textRole = /^text-(?:foreground|muted-foreground|card-foreground|popover-foreground|accent-foreground|secondary-foreground|primary-foreground|primary-accent|warning-accent|link-color|success|info|warning|destructive|sidebar-foreground|sidebar-accent-foreground|sidebar-primary-foreground)\/.+$/;
68
+ export function fadedText(token) {
69
+ const value = utility(token);
70
+ return value !== 'text-sidebar-foreground/70' && textRole.test(value);
71
+ }
72
+
73
+ /** Separate opacity on an owned text node changes its semantic ink as well. */
74
+ export function textOpacityDrift(token) {
75
+ const value = utility(token);
76
+ const match = value.match(/^opacity-(?:(\d+(?:\.\d+)?)|\[(\d*\.?\d+)(%)?\])$/);
63
77
  if (!match) return false;
64
- const opacity = Number(match[1] ?? match[2]);
65
- return opacity < (match[1] !== undefined || match[3] ? 100 : 1);
78
+ const opacity = match[1] !== undefined ? Number(match[1]) : Number(match[2]) * (match[3] ? 1 : 100);
79
+ if (!(opacity > 0 && opacity < 100)) return false;
80
+ return !(opacity === 50 && variantSegments(variants(token)).some(segment => disabledSegment.test(segment)));
81
+ }
82
+
83
+ // Interaction fills come from one recipe owner: accent for rows, muted for toggle
84
+ // hover, a lifted card segment and the table ladder. A neutral fill with opacity or
85
+ // a primary tint under hover, highlight, selection, current or pressed state is a
86
+ // second definition of that state.
87
+ const interactionSegment = /^(?:group-|peer-)?(?:hover|focus|focus-visible|focus-within|active|data-highlighted|data-selected|data-active|data-current|data-pressed|aria-selected|aria-current|aria-pressed|aria-checked|data-\[(?:highlighted|selected|active|current|pressed|checked|state=[^\]]+)[^\]]*\])(?:\/[\w-]+)?$/;
88
+ function variantSegments(variant) {
89
+ const segments = [];
90
+ let depth = 0, start = 0;
91
+ for (let i = 0; i < variant.length; i++) {
92
+ if ('[('.includes(variant[i])) depth++;
93
+ else if ('])'.includes(variant[i])) depth--;
94
+ else if (variant[i] === ':' && depth === 0) { segments.push(variant.slice(start, i)); start = i + 1; }
95
+ }
96
+ return segments;
97
+ }
98
+ export function interactionFillDrift(token) {
99
+ if (!variantSegments(variants(token)).some(segment => interactionSegment.test(segment))) return false;
100
+ const match = utility(token).match(/^bg-(muted|accent|card|background|foreground|secondary|popover|sidebar-accent|primary)\/(.+)$/);
101
+ return !!match && !(match[1] === 'muted' && match[2] === '50');
102
+ }
103
+
104
+ // Neutral fills have one strength per role (neutralFillRecipes in
105
+ // src/lib/surface-recipes.ts): a wash at muted/30, a band at muted/50, a chip at
106
+ // foreground/8, the inverse chip at background/10 and the idle marker at
107
+ // muted-foreground/40. Opaque fills are always available; interaction states belong
108
+ // to interaction-fill.
109
+ const neutralTint = /^bg-(muted|muted-foreground|foreground|background|card|popover|secondary|accent|sidebar(?:-[a-z]+)*)\/(.+)$/;
110
+ const neutralScale = new Set(['muted/30', 'muted/50', 'foreground/8', 'background/10', 'muted-foreground/40']);
111
+ export function neutralFillDrift(token) {
112
+ const match = utility(token).match(neutralTint);
113
+ if (!match || neutralScale.has(`${match[1]}/${match[2]}`)) return false;
114
+ return !variantSegments(variants(token)).some(segment => interactionSegment.test(segment));
115
+ }
116
+
117
+ // Elevation takes one theme shadow per role (elevationRecipes in
118
+ // src/lib/surface-recipes.ts): xs resting, sm card, md raised and anchored, lg lifted
119
+ // and xl modal; shadow-none clears it. A box-shadow divider line that draws
120
+ // var(--border) is divider mechanics, not elevation.
121
+ export function elevationDrift(token) {
122
+ const value = utility(token);
123
+ if (!/^shadow(?:-|$)/.test(value)) return false;
124
+ return !/^shadow-(?:none|xs|sm|md|lg|xl)$/.test(value) && !/^shadow-\[.*var\(--border\).*\]$/.test(value);
125
+ }
126
+
127
+ // Dividers have two strengths: a surface edge draws the full border role and an
128
+ // inner divider (one side, divide, separator) draws it at 60%. The control boundary
129
+ // has one strength. Only src/lib/surface-recipes.ts owns other strengths (the modal
130
+ // shell and the framed Card ring).
131
+ export function dividerStrengthDrift(token) {
132
+ const match = utility(token).match(/^(?:border(?:-[trblxyse]|-bs|-be)?|divide(?:-[xy])?|ring|inset-ring|outline|bg)-(border|sidebar-border|input)\/(.+)$/);
133
+ return !!match && !(match[1] === 'border' && match[2] === '60');
134
+ }
135
+
136
+ // Status and emphasis tints have one scale, src/lib/tone-recipes.ts: a wash, tint,
137
+ // edge, halo and line strength per tone, which the contrast contract tests. A
138
+ // translucent tone spelled anywhere else is a second scale. The invalid state's
139
+ // destructive halo belongs to the field-state and focus recipes.
140
+ const toneTint = /^(?:bg|border(?:-[trblxyse]|-bs|-be)?|ring|inset-ring|outline|divide(?:-[xy])?)-(?:info|success|warning|destructive|primary)(?:-accent)?\/.+$/;
141
+ export function statusTintDrift(token) {
142
+ return toneTint.test(utility(token)) && !/invalid|focus/.test(variants(token));
143
+ }
144
+
145
+ // State changes (colour, border and shadow) share one timing: Tailwind's default
146
+ // 150ms transition and easing. Presence and geometry motion (enter, exit, expand,
147
+ // slide) comes from src/lib/motion-recipes.ts. Returns the timing tokens that
148
+ // retime a paint-only transition.
149
+ const paintProperties = new Set(['color', 'background-color', 'background', 'border-color', 'box-shadow', 'outline-color', 'text-decoration-color', 'fill', 'stroke']);
150
+ function paintTransition(token) {
151
+ const value = utility(token);
152
+ if (value === 'transition-colors' || value === 'transition-shadow') return true;
153
+ const list = value.match(/^transition-\[(.+)\]$/)?.[1];
154
+ return !!list && list.split(',').every(property => paintProperties.has(property.trim()));
155
+ }
156
+ export function stateMotionDrift(classes) {
157
+ const resting = classes.filter(token => variants(token) === '');
158
+ if (!resting.some(paintTransition) || resting.some(token => /^transition(?:-|$)/.test(utility(token)) && !paintTransition(token))) return [];
159
+ return resting.filter(token => /^duration-(?!150$|0$)/.test(utility(token)) || /^ease-/.test(utility(token)));
160
+ }
161
+
162
+ // Corners take a role derived from --radius: rounded-radius (outer shells) and
163
+ // rounded-inner (controls, rows, nested bodies), plus rounded-full, rounded-none
164
+ // and the root-derived rounded-radius-* steps. Bare rounded is a fixed 4px that
165
+ // ignores the theme root, and the t-shirt steps are a second scale.
166
+ export function radiusRoleDrift(token) {
167
+ return /^rounded(?:-(?:[trblse]|tl|tr|br|bl|ss|se|es|ee))?(?:-(?:xs|sm|md|lg|xl|2xl|3xl|4xl))?$/.test(utility(token));
168
+ }
169
+
170
+ // One stacking scale (src/lib/layer-recipes.ts): z-10 raised, z-20 sticky, z-30
171
+ // sticky over sticky, z-40 app chrome, z-50 popups and modal layers. Local
172
+ // ordering may also use z-0, z-[1] and z-[-1].
173
+ export function layerScaleDrift(token) {
174
+ const match = utility(token).replace(/^-/, '').match(/^z-(?:(\d+)|\[(-?\d+)\])$/);
175
+ if (!match) return false;
176
+ if (match[2] !== undefined) return Math.abs(Number(match[2])) > 1;
177
+ return ![0, 10, 20, 30, 40, 50].includes(Number(match[1]));
178
+ }
179
+
180
+ // Disabled content dims once, at 50%; a child of a dimmed owner resets to 100%.
181
+ const disabledSegment = /^(?:group-|peer-)?(?:disabled|data-disabled|aria-disabled|data-\[disabled[^\]]*\]|aria-\[disabled[^\]]*\])(?:\/[\w-]+)?$/;
182
+ export function disabledDimmingDrift(token) {
183
+ if (!variantSegments(variants(token)).some(segment => disabledSegment.test(segment))) return false;
184
+ const match = utility(token).match(/^opacity-(\d+)$/);
185
+ return !!match && !['50', '100'].includes(match[1]);
186
+ }
187
+
188
+ const focusState = /focus|focused/;
189
+ const ringWidth = /^ring(?:-\d+(?:\.\d+)?|-\[(?:\d+(?:\.\d+)?)(?:px|rem|em)\])?$/;
190
+
191
+ /**
192
+ * Every focus indicator is one recipe: a 3px halo of the ring role at 50% around
193
+ * a full-strength 1px edge (the control's own `border-ring`, or `inset-ring-ring`
194
+ * on a borderless element). Returns the tokens that draw focus any other way:
195
+ * another focus ring width, an offset ring, a halo at another strength, an
196
+ * attenuated edge, or an unscoped ring colour that a focus-only width turns into
197
+ * a full-strength halo. Status tints (invalid, selected) keep their own colours.
198
+ */
199
+ export function focusRingDrift(classes) {
200
+ const focused = token => focusState.test(variants(token));
201
+ const focusWidth = classes.some(token => focused(token) && ringWidth.test(utility(token)) && utility(token) !== 'ring-0');
202
+ return classes.filter(token => {
203
+ const value = utility(token);
204
+ if (!focused(token)) return focusWidth && variants(token) === '' && /^ring-(?:ring|sidebar-ring)$/.test(value);
205
+ if (/^ring-offset-/.test(value)) return true;
206
+ if (ringWidth.test(value)) return !/^ring-[03]$/.test(value);
207
+ const halo = value.match(/^ring-(?:ring|sidebar-ring)(?:\/(.+))?$/);
208
+ if (halo) return halo[1] !== '50';
209
+ return /^(?:border|inset-ring|outline)-(?:ring|sidebar-ring)\/.+$/.test(value);
210
+ });
66
211
  }