themelia-react-ui 1.0.2 → 2.0.1

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 (748) hide show
  1. package/CHANGELOG.md +632 -1
  2. package/README.md +31 -13
  3. package/dist/accordion-B6a3vVgA.js +207 -0
  4. package/dist/accordion-B6a3vVgA.js.map +1 -0
  5. package/dist/action-menu-TzCoSlwL.js +280 -0
  6. package/dist/action-menu-TzCoSlwL.js.map +1 -0
  7. package/dist/{affordance-geometry.generated-CL84ZN9A.js → affordance-geometry.generated-B5iu-Mkr.js} +9 -3
  8. package/dist/affordance-geometry.generated-B5iu-Mkr.js.map +1 -0
  9. package/dist/{ai-artifact-DLVdK0Py.js → ai-artifact-BMJdv-6q.js} +389 -391
  10. package/dist/ai-artifact-BMJdv-6q.js.map +1 -0
  11. package/dist/{app-shell-C_fKpljx.js → app-shell-ZK5RWdo6.js} +4 -4
  12. package/dist/{app-shell-C_fKpljx.js.map → app-shell-ZK5RWdo6.js.map} +1 -1
  13. package/dist/attachment-BtfhGm8i.js +245 -0
  14. package/dist/attachment-BtfhGm8i.js.map +1 -0
  15. package/dist/{auth-CAQcasMV.js → auth-CYxKfo69.js} +239 -237
  16. package/dist/auth-CYxKfo69.js.map +1 -0
  17. package/dist/{avatar-Bu2HhitA.js → avatar-BBnEJIx8.js} +71 -68
  18. package/dist/avatar-BBnEJIx8.js.map +1 -0
  19. package/dist/badge-MrKVNzW9.js +93 -0
  20. package/dist/badge-MrKVNzW9.js.map +1 -0
  21. package/dist/base/accordion.js +1 -1
  22. package/dist/base/action-menu.js +1 -1
  23. package/dist/base/attachment.js +1 -1
  24. package/dist/base/avatar.js +1 -1
  25. package/dist/base/badge.js +1 -1
  26. package/dist/base/batch-action-bar.js +3 -0
  27. package/dist/base/buttons.js +2 -3
  28. package/dist/base/cards.js +2 -2
  29. package/dist/base/carousel.js +19 -19
  30. package/dist/base/carousel.js.map +1 -1
  31. package/dist/base/cascader.js +234 -224
  32. package/dist/base/cascader.js.map +1 -1
  33. package/dist/base/chart.js +1 -1
  34. package/dist/base/choice-inputs.js +3 -3
  35. package/dist/base/code-block.js +1 -1
  36. package/dist/base/combobox.js +1 -1
  37. package/dist/base/command.js +1 -1
  38. package/dist/base/copyable.js +1 -1
  39. package/dist/base/date-pickers.js +2 -2
  40. package/dist/base/display.js +7 -7
  41. package/dist/base/feedback.js +3 -3
  42. package/dist/base/forms-numeric.js +1 -1
  43. package/dist/base/forms.js +2 -2
  44. package/dist/base/inline-edit.js +81 -76
  45. package/dist/base/inline-edit.js.map +1 -1
  46. package/dist/base/item.js +1 -1
  47. package/dist/base/media-gallery.js +1 -1
  48. package/dist/base/metadata-list.js +3 -0
  49. package/dist/base/navigation.js +7 -7
  50. package/dist/base/popover-menu.js +1 -1
  51. package/dist/base/popover.js +1 -1
  52. package/dist/base/qr-code.js +7 -4
  53. package/dist/base/qr-code.js.map +1 -1
  54. package/dist/base/repeaters.js +175 -174
  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 +148 -138
  59. package/dist/base/signature-pad.js.map +1 -1
  60. package/dist/base/skeleton.js +1 -1
  61. package/dist/base/spinner.js +1 -1
  62. package/dist/base/structure.js +1 -1
  63. package/dist/base/table.js +1 -1
  64. package/dist/base/text-inputs.js +2 -2
  65. package/dist/base/toaster.js +4 -4
  66. package/dist/base/toaster.js.map +1 -1
  67. package/dist/base/tree.js +1 -1
  68. package/dist/base/upload-queue.js +1 -1
  69. package/dist/base/upload.js +3 -3
  70. package/dist/base/value-inputs.js +2 -2
  71. package/dist/batch-action-bar-BZGDG-Si.js +104 -0
  72. package/dist/batch-action-bar-BZGDG-Si.js.map +1 -0
  73. package/dist/blocks/admin.js +264 -253
  74. package/dist/blocks/admin.js.map +1 -1
  75. package/dist/blocks/ai.js +293 -323
  76. package/dist/blocks/ai.js.map +1 -1
  77. package/dist/blocks/analytics/usage-card.js +1 -1
  78. package/dist/blocks/analytics.js +596 -587
  79. package/dist/blocks/analytics.js.map +1 -1
  80. package/dist/blocks/collaboration.js +1 -1
  81. package/dist/blocks/commerce/receipt.js +1 -1
  82. package/dist/blocks/commerce.js +2246 -1693
  83. package/dist/blocks/commerce.js.map +1 -1
  84. package/dist/blocks/data-display.js +3 -2
  85. package/dist/blocks/onboarding.js +50 -49
  86. package/dist/blocks/onboarding.js.map +1 -1
  87. package/dist/blocks/planning.js +82 -91
  88. package/dist/blocks/planning.js.map +1 -1
  89. package/dist/blocks/timelines.js +1 -1
  90. package/dist/breadcrumbs-D5t7I023.js +129 -0
  91. package/dist/breadcrumbs-D5t7I023.js.map +1 -0
  92. package/dist/{button-BZyfTvwm.js → button-QYwiyhD2.js} +15 -14
  93. package/dist/button-QYwiyhD2.js.map +1 -0
  94. package/dist/buttons-SbIcm1HJ.js +661 -0
  95. package/dist/buttons-SbIcm1HJ.js.map +1 -0
  96. package/dist/{cards-qGSErLw_.js → cards-CiiHpKYd.js} +8 -8
  97. package/dist/cards-CiiHpKYd.js.map +1 -0
  98. package/dist/{chart-Bsc5BICK.js → chart-QfrARkXl.js} +17 -15
  99. package/dist/chart-QfrARkXl.js.map +1 -0
  100. package/dist/checkbox-DhB6K0bK.js +36 -0
  101. package/dist/checkbox-DhB6K0bK.js.map +1 -0
  102. package/dist/choice-inputs-t6w3ATNz.js +766 -0
  103. package/dist/choice-inputs-t6w3ATNz.js.map +1 -0
  104. package/dist/code-block-Dgbu-CU3.js +185 -0
  105. package/dist/code-block-Dgbu-CU3.js.map +1 -0
  106. package/dist/{collapsible-ClvC7Bj3.js → collapsible-D8AEGU1-.js} +4 -4
  107. package/dist/{collapsible-ClvC7Bj3.js.map → collapsible-D8AEGU1-.js.map} +1 -1
  108. package/dist/{collection-content-D6S8cv_n.js → collection-content-uK16Grv0.js} +3 -3
  109. package/dist/{collection-content-D6S8cv_n.js.map → collection-content-uK16Grv0.js.map} +1 -1
  110. package/dist/{combobox-BFnbJJp3.js → combobox-2Ic8N9bL.js} +103 -98
  111. package/dist/combobox-2Ic8N9bL.js.map +1 -0
  112. package/dist/combobox-DLl0bfiq.js +867 -0
  113. package/dist/combobox-DLl0bfiq.js.map +1 -0
  114. package/dist/{command-BnmSchli.js → command-kNR20o7x.js} +34 -30
  115. package/dist/command-kNR20o7x.js.map +1 -0
  116. package/dist/{comments-u5L0OGip.js → comments-BpDuCUUu.js} +304 -301
  117. package/dist/comments-BpDuCUUu.js.map +1 -0
  118. package/dist/components/base/accordion/accordion-variants.d.ts +3 -3
  119. package/dist/components/base/action-menu/action-menu.d.ts +27 -5
  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/avatar/stacked-avatars.d.ts +5 -4
  123. package/dist/components/base/badge/badge.d.ts +1 -1
  124. package/dist/components/base/badge/badge.recipes.d.ts +6 -6
  125. package/dist/components/base/batch-action-bar/batch-action-bar.d.ts +50 -0
  126. package/dist/components/base/batch-action-bar/batch-action-bar.strings.d.ts +20 -0
  127. package/dist/components/base/batch-action-bar/index.d.ts +8 -0
  128. package/dist/components/base/buttons/base-button.d.ts +7 -0
  129. package/dist/components/base/buttons/button-group.recipes.d.ts +2 -2
  130. package/dist/components/base/buttons/button.recipes.d.ts +2 -2
  131. package/dist/components/base/buttons/button.variants.d.ts +1 -0
  132. package/dist/components/base/buttons/loader-button.d.ts +3 -1
  133. package/dist/components/base/buttons/text-button.d.ts +2 -2
  134. package/dist/components/base/carousel/carousel.d.ts +3 -1
  135. package/dist/components/base/chart/chart.d.ts +7 -7
  136. package/dist/components/base/choice-inputs/checkbox.d.ts +6 -7
  137. package/dist/components/base/choice-inputs/choice-types.d.ts +24 -3
  138. package/dist/components/base/choice-inputs/pill-radio-group.d.ts +9 -0
  139. package/dist/components/base/choice-inputs/select-popup.d.ts +9 -1
  140. package/dist/components/base/choice-inputs/switch-card.d.ts +1 -1
  141. package/dist/components/base/date-pickers/date-picker-field.d.ts +23 -0
  142. package/dist/components/base/date-pickers/datepicker.types.d.ts +13 -3
  143. package/dist/components/base/display/alert-dialog.d.ts +10 -3
  144. package/dist/components/base/display/content-block.d.ts +4 -2
  145. package/dist/components/base/display/date-block.d.ts +1 -1
  146. package/dist/components/base/display/dialog.d.ts +8 -5
  147. package/dist/components/base/display/icon-badge/icon-badge.d.ts +1 -1
  148. package/dist/components/base/display/surface-title.d.ts +6 -1
  149. package/dist/components/base/feedback/alert.d.ts +1 -1
  150. package/dist/components/base/feedback/state-display.d.ts +5 -4
  151. package/dist/components/base/forms/form-sizing.d.ts +43 -8
  152. package/dist/components/base/forms/workflow.d.ts +2 -0
  153. package/dist/components/base/forms-numeric/coordinates-input.d.ts +3 -0
  154. package/dist/components/base/forms-numeric/rounding-mode-select.d.ts +4 -1
  155. package/dist/components/base/metadata-list/index.d.ts +12 -0
  156. package/dist/components/{blocks/data-display/metadata → base/metadata-list}/metadata-list.d.ts +28 -25
  157. package/dist/components/{blocks/data-display/metadata → base/metadata-list}/metadata-value.d.ts +2 -2
  158. package/dist/components/base/navigation/dropdown-menu.d.ts +2 -2
  159. package/dist/components/base/navigation/index.d.ts +1 -1
  160. package/dist/components/base/navigation/language-switcher.d.ts +4 -1
  161. package/dist/components/base/navigation/overflow-tab-bar.d.ts +7 -0
  162. package/dist/components/base/navigation/page-header/index.d.ts +1 -0
  163. package/dist/components/base/navigation/page-header/page-header-commands.d.ts +73 -0
  164. package/dist/components/base/navigation/page-header/page-header.d.ts +30 -4
  165. package/dist/components/base/qr-code/qr-code.d.ts +2 -0
  166. package/dist/components/base/sheet/index.d.ts +29 -1
  167. package/dist/components/base/sheet/sheet.d.ts +10 -5
  168. package/dist/components/base/signature-pad/signature-pad.types.d.ts +5 -1
  169. package/dist/components/base/signature-pad/signature-pad.utils.d.ts +11 -3
  170. package/dist/components/base/spinner/spinner.d.ts +3 -2
  171. package/dist/components/base/structure/structure.types.d.ts +1 -1
  172. package/dist/components/base/text-inputs/field-clear-button.d.ts +6 -0
  173. package/dist/components/base/text-inputs/input-group.d.ts +2 -2
  174. package/dist/components/base/upload/upload.recipes.d.ts +33 -0
  175. package/dist/components/base/value-inputs/date-time-input.d.ts +4 -2
  176. package/dist/components/base/value-inputs/index.d.ts +5 -5
  177. package/dist/components/base/value-inputs/tags-input.d.ts +38 -12
  178. package/dist/components/blocks/admin/api-key-list/api-key-list.types.d.ts +1 -1
  179. package/dist/components/blocks/analytics/format-metric-value.d.ts +11 -1
  180. package/dist/components/blocks/analytics/index.d.ts +1 -1
  181. package/dist/components/blocks/analytics/use-metric-format-options.d.ts +3 -0
  182. package/dist/components/blocks/commerce/address-card/address-card.d.ts +1 -1
  183. package/dist/components/blocks/commerce/address-card/types.d.ts +4 -1
  184. package/dist/components/blocks/commerce/booking-calendar-event-card/booking-calendar-event-card.d.ts +4 -0
  185. package/dist/components/blocks/commerce/booking-calendar-event-card/booking-calendar-event-card.types.d.ts +2 -2
  186. package/dist/components/blocks/commerce/cart-summary/cart-summary.d.ts +3 -1
  187. package/dist/components/blocks/commerce/cart-summary/index.d.ts +2 -2
  188. package/dist/components/blocks/commerce/cart-summary/types.d.ts +6 -1
  189. package/dist/components/blocks/commerce/discount-stack/discount-stack.d.ts +3 -1
  190. package/dist/components/blocks/commerce/discount-stack/index.d.ts +2 -2
  191. package/dist/components/blocks/commerce/discount-stack/types.d.ts +16 -4
  192. package/dist/components/blocks/commerce/fulfillment-group/fulfillment-group.d.ts +5 -0
  193. package/dist/components/blocks/commerce/fulfillment-group/index.d.ts +2 -0
  194. package/dist/components/blocks/commerce/fulfillment-group/types.d.ts +43 -0
  195. package/dist/components/blocks/commerce/index.d.ts +13 -5
  196. package/dist/components/blocks/commerce/inventory-section/types.d.ts +4 -1
  197. package/dist/components/blocks/commerce/invoice-header/invoice-header.d.ts +1 -1
  198. package/dist/components/blocks/commerce/invoice-header/types.d.ts +4 -2
  199. package/dist/components/blocks/commerce/invoice-mini/invoice-mini.d.ts +1 -1
  200. package/dist/components/blocks/commerce/invoice-mini/types.d.ts +2 -1
  201. package/dist/components/blocks/commerce/loyalty-points/types.d.ts +1 -1
  202. package/dist/components/blocks/commerce/order-customer/index.d.ts +2 -0
  203. package/dist/components/blocks/commerce/order-customer/order-customer.d.ts +5 -0
  204. package/dist/components/blocks/commerce/order-customer/types.d.ts +48 -0
  205. package/dist/components/blocks/commerce/order-header/index.d.ts +2 -0
  206. package/dist/components/blocks/commerce/order-header/order-header.d.ts +5 -0
  207. package/dist/components/blocks/commerce/order-header/types.d.ts +37 -0
  208. package/dist/components/blocks/commerce/order-line-item/index.d.ts +2 -0
  209. package/dist/components/blocks/commerce/order-line-item/order-line-item.d.ts +5 -0
  210. package/dist/components/blocks/commerce/order-line-item/types.d.ts +46 -0
  211. package/dist/components/blocks/commerce/order-status/types.d.ts +4 -0
  212. package/dist/components/blocks/commerce/order-summary/index.d.ts +2 -0
  213. package/dist/components/blocks/commerce/order-summary/order-summary.d.ts +5 -0
  214. package/dist/components/blocks/commerce/order-summary/types.d.ts +42 -0
  215. package/dist/components/blocks/commerce/order-transactions/index.d.ts +2 -0
  216. package/dist/components/blocks/commerce/order-transactions/order-transactions.d.ts +5 -0
  217. package/dist/components/blocks/commerce/order-transactions/types.d.ts +46 -0
  218. package/dist/components/blocks/commerce/payment-method/index.d.ts +2 -2
  219. package/dist/components/blocks/commerce/payment-method/payment-method.d.ts +9 -1
  220. package/dist/components/blocks/commerce/payment-method/types.d.ts +14 -1
  221. package/dist/components/blocks/commerce/refund-status/index.d.ts +2 -2
  222. package/dist/components/blocks/commerce/refund-status/refund-status.d.ts +3 -1
  223. package/dist/components/blocks/commerce/refund-status/types.d.ts +6 -3
  224. package/dist/components/blocks/commerce/seo-listing/seo-listing-card.d.ts +1 -1
  225. package/dist/components/blocks/commerce/seo-listing/types.d.ts +3 -1
  226. package/dist/components/blocks/commerce/shared/address-lines.d.ts +21 -0
  227. package/dist/components/blocks/commerce/shared/line-thumbnail.d.ts +9 -0
  228. package/dist/components/blocks/commerce/shared/order-status.d.ts +51 -0
  229. package/dist/components/blocks/commerce/shipment-tracking/shipment-tracking.d.ts +1 -1
  230. package/dist/components/blocks/commerce/shipment-tracking/types.d.ts +27 -6
  231. package/dist/components/blocks/commerce/summary-panel/amount-row.d.ts +2 -0
  232. package/dist/components/blocks/commerce/summary-panel/index.d.ts +3 -0
  233. package/dist/components/blocks/commerce/summary-panel/summary-panel.d.ts +2 -0
  234. package/dist/components/blocks/commerce/summary-panel/types.d.ts +26 -0
  235. package/dist/components/blocks/commerce/tax-breakdown/tax-breakdown.d.ts +1 -1
  236. package/dist/components/blocks/commerce/tax-breakdown/types.d.ts +2 -1
  237. package/dist/components/blocks/commerce/vendor-profile/types.d.ts +4 -1
  238. package/dist/components/blocks/data-display/dense-info-card/dense-info.strings.d.ts +4 -1
  239. package/dist/components/blocks/data-display/inline-stat/inline-stat.d.ts +4 -1
  240. package/dist/components/blocks/data-display/metadata/index.d.ts +30 -4
  241. package/dist/components/features/activities/partials/activity-row.d.ts +6 -2
  242. package/dist/components/features/activities/partials/tone-tokens.d.ts +0 -6
  243. package/dist/components/features/global-search/partials/global-search-group-heading.d.ts +15 -0
  244. package/dist/components/features/global-search/partials/global-search-idle-state.d.ts +1 -1
  245. package/dist/components/features/global-search/partials/tone-palettes.d.ts +0 -5
  246. package/dist/components/features/kanban/kanban.d.ts +1 -1
  247. package/dist/components/features/kanban/kanban.strings.d.ts +1 -1
  248. package/dist/components/features/kanban/kanban.types.d.ts +2 -2
  249. package/dist/components/features/media-library/hooks/use-media-library.d.ts +1 -1
  250. package/dist/components/features/media-library/index.d.ts +1 -1
  251. package/dist/components/features/media-library/media-library.d.ts +1 -1
  252. package/dist/components/features/media-library/media-library.strings.d.ts +4 -0
  253. package/dist/components/features/media-library/media-library.types.d.ts +74 -1
  254. package/dist/components/features/media-library/partials/media-library-partials.d.ts +3 -3
  255. package/dist/components/features/mentions/partials/mention-kind-toggles.d.ts +16 -0
  256. package/dist/components/features/overlays/alert-dialog.d.ts +1 -1
  257. package/dist/components/features/overlays/dialog.d.ts +1 -1
  258. package/dist/components/features/overlays/drawer.d.ts +1 -1
  259. package/dist/components/features/overlays/hooks/use-overlay-actions.d.ts +2 -2
  260. package/dist/components/features/overlays/hooks/use-overlay-visibility.d.ts +11 -4
  261. package/dist/components/features/overlays/index.d.ts +1 -1
  262. package/dist/components/features/overlays/overlay-tone-icon.d.ts +37 -0
  263. package/dist/components/features/overlays/overlays.types.d.ts +62 -19
  264. package/dist/components/features/products/components/product-contract-overview.d.ts +5 -0
  265. package/dist/components/features/products/components/product-details-card.d.ts +5 -0
  266. package/dist/components/features/products/components/product-operations-card.d.ts +5 -0
  267. package/dist/components/features/products/components/product-option-action-menu.d.ts +5 -0
  268. package/dist/components/features/products/components/product-options-summary.d.ts +5 -0
  269. package/dist/components/features/products/components/product-policies-card.d.ts +5 -0
  270. package/dist/components/features/products/components/product-quote-preview-card.d.ts +5 -0
  271. package/dist/components/features/products/components/product-readiness-card.d.ts +5 -0
  272. package/dist/components/features/products/components/product-structure-card.d.ts +5 -0
  273. package/dist/components/features/products/components/product-variant-action-menu.d.ts +23 -1
  274. package/dist/components/features/products/components/product-variants-manager.d.ts +1 -1
  275. package/dist/components/features/products/partials/index.d.ts +1 -1
  276. package/dist/components/features/products/partials/product-metric-tile.d.ts +6 -0
  277. package/dist/components/features/products/partials/product-tone.d.ts +11 -1
  278. package/dist/components/features/products/products.types.d.ts +11 -3
  279. package/dist/components/features/resource/index.d.ts +1 -1
  280. package/dist/components/features/resource/resource.d.ts +1 -1
  281. package/dist/components/features/resource/resource.types.d.ts +34 -6
  282. package/dist/components/features/rich-text-editor/index.d.ts +2 -1
  283. package/dist/components/features/rich-text-editor/partials/image-nodes.d.ts +13 -0
  284. package/dist/components/features/rich-text-editor/partials/image-uploads.d.ts +66 -0
  285. package/dist/components/features/rich-text-editor/partials/inline-reference-node.d.ts +19 -0
  286. package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +1 -1
  287. package/dist/components/features/rich-text-editor/rich-text-editor.strings.d.ts +14 -0
  288. package/dist/components/features/rich-text-editor/rich-text-editor.types.d.ts +45 -0
  289. package/dist/components/features/rich-text-editor/use-rich-text-images.d.ts +18 -0
  290. package/dist/components/features/sync/index.d.ts +26 -3
  291. package/dist/components/features/table/data-table.d.ts +1 -1
  292. package/dist/components/features/table/partials/cell-renderers.d.ts +1 -1
  293. package/dist/components/features/table/table.types.d.ts +32 -7
  294. package/dist/components/layout/page/index.d.ts +1 -1
  295. package/dist/components/layout/page/page.types.d.ts +51 -4
  296. package/dist/components/layout/page/partials/page-actions.d.ts +1 -0
  297. package/dist/components/layout/page/partials/page-header.d.ts +1 -1
  298. package/dist/components/layout/settings/settings.d.ts +16 -2
  299. package/dist/components/layout/workspace/workspace.types.d.ts +21 -4
  300. package/dist/components/primitives/date.d.ts +16 -3
  301. package/dist/components/primitives/dimensions.d.ts +6 -0
  302. package/dist/components/primitives/duration.d.ts +6 -0
  303. package/dist/components/primitives/file-size.d.ts +6 -0
  304. package/dist/components/primitives/index.d.ts +1 -1
  305. package/dist/components/primitives/initials.d.ts +11 -2
  306. package/dist/components/primitives/link.d.ts +7 -0
  307. package/dist/components/primitives/money.d.ts +29 -7
  308. package/dist/components/primitives/number.d.ts +17 -0
  309. package/dist/components/primitives/value-typography.d.ts +54 -0
  310. package/dist/components/primitives/value.d.ts +31 -6
  311. package/dist/components/typography/heading.d.ts +9 -1
  312. package/dist/components/typography/label.d.ts +3 -0
  313. package/dist/components/typography/rich-text/index.d.ts +1 -1
  314. package/dist/components/typography/rich-text/rich-text-tree.d.ts +19 -0
  315. package/dist/components/typography/rich-text/rich-text.d.ts +16 -0
  316. package/dist/components/typography/running-text.d.ts +12 -0
  317. package/dist/components/typography/text-link.d.ts +24 -1
  318. package/dist/components/typography/text.d.ts +12 -0
  319. package/dist/components/typography/text.styles.d.ts +35 -13
  320. package/dist/components/ui/button.d.ts +1 -1
  321. package/dist/components/ui/checkbox.d.ts +6 -0
  322. package/dist/components/ui/overlay.recipes.d.ts +6 -2
  323. package/dist/components/ui/select.d.ts +3 -1
  324. package/dist/components/ui/switch.d.ts +5 -0
  325. package/dist/{containers-DqB-bSYE.js → containers-DmWiJa2I.js} +36 -35
  326. package/dist/containers-DmWiJa2I.js.map +1 -0
  327. package/dist/{copyable-BTSByfmq.js → copyable-B3Gwgdqc.js} +6 -6
  328. package/dist/{copyable-BTSByfmq.js.map → copyable-B3Gwgdqc.js.map} +1 -1
  329. package/dist/data-display-DafIvCl5.js +960 -0
  330. package/dist/data-display-DafIvCl5.js.map +1 -0
  331. package/dist/date-BgK3bTdo.js +144 -0
  332. package/dist/date-BgK3bTdo.js.map +1 -0
  333. package/dist/date-picker-CF-DtUpF.js +1529 -0
  334. package/dist/date-picker-CF-DtUpF.js.map +1 -0
  335. package/dist/date-pickers-BmzxJl5l.js +174 -0
  336. package/dist/date-pickers-BmzxJl5l.js.map +1 -0
  337. package/dist/{display-CS6Hbk18.js → display-DsQTVzMz.js} +88 -87
  338. package/dist/display-DsQTVzMz.js.map +1 -0
  339. package/dist/{dropdown-menu-D-boNgGO.js → dropdown-menu-E2qmdC7o.js} +23 -16
  340. package/dist/dropdown-menu-E2qmdC7o.js.map +1 -0
  341. package/dist/features/activities.js +437 -521
  342. package/dist/features/activities.js.map +1 -1
  343. package/dist/features/ai-chat.js +174 -172
  344. package/dist/features/ai-chat.js.map +1 -1
  345. package/dist/features/async-preview.js +8 -8
  346. package/dist/features/async-preview.js.map +1 -1
  347. package/dist/features/combobox.js +1 -1
  348. package/dist/features/comments.js +1 -1
  349. package/dist/features/data-view.js +139 -138
  350. package/dist/features/data-view.js.map +1 -1
  351. package/dist/features/email-composer/engine.js +1 -1
  352. package/dist/features/email-composer.js +353 -352
  353. package/dist/features/email-composer.js.map +1 -1
  354. package/dist/features/event-calendar.js +262 -269
  355. package/dist/features/event-calendar.js.map +1 -1
  356. package/dist/features/filters.js +1 -1
  357. package/dist/features/global-search.js +307 -310
  358. package/dist/features/global-search.js.map +1 -1
  359. package/dist/features/kanban.js +95 -97
  360. package/dist/features/kanban.js.map +1 -1
  361. package/dist/features/map.js +56 -57
  362. package/dist/features/map.js.map +1 -1
  363. package/dist/features/media-library.js +914 -824
  364. package/dist/features/media-library.js.map +1 -1
  365. package/dist/features/mentions.js +1 -1
  366. package/dist/features/overlays.js +1 -1
  367. package/dist/features/products.js +1272 -1311
  368. package/dist/features/products.js.map +1 -1
  369. package/dist/features/questionnaire.js +204 -194
  370. package/dist/features/questionnaire.js.map +1 -1
  371. package/dist/features/resource-assignment.js +103 -95
  372. package/dist/features/resource-assignment.js.map +1 -1
  373. package/dist/features/resource.js +77 -69
  374. package/dist/features/resource.js.map +1 -1
  375. package/dist/features/rich-text-editor.js +30 -11
  376. package/dist/features/rich-text-editor.js.map +1 -1
  377. package/dist/features/schema-form.js +193 -189
  378. package/dist/features/schema-form.js.map +1 -1
  379. package/dist/features/suggestions.js +3 -3
  380. package/dist/features/sync.js +7 -7
  381. package/dist/features/sync.js.map +1 -1
  382. package/dist/features/table.js +1 -1
  383. package/dist/features/theme-tweaker.js +455 -455
  384. package/dist/features/theme-tweaker.js.map +1 -1
  385. package/dist/feedback-qNuMBtRH.js +233 -0
  386. package/dist/feedback-qNuMBtRH.js.map +1 -0
  387. package/dist/field-affordance-recipes-qQeIf4lG.js +48 -0
  388. package/dist/field-affordance-recipes-qQeIf4lG.js.map +1 -0
  389. package/dist/field-state-recipes-BVA2CWHo.js +12 -0
  390. package/dist/field-state-recipes-BVA2CWHo.js.map +1 -0
  391. package/dist/{filters-D6FF8L6s.js → filters-BkHH53uv.js} +414 -412
  392. package/dist/filters-BkHH53uv.js.map +1 -0
  393. package/dist/focus-recipes-B653VaLq.js +12 -0
  394. package/dist/focus-recipes-B653VaLq.js.map +1 -0
  395. package/dist/{form-field-CZwrkP7m.js → form-field-DUt4UxSV.js} +7 -7
  396. package/dist/{form-field-CZwrkP7m.js.map → form-field-DUt4UxSV.js.map} +1 -1
  397. package/dist/form-sizing-By94KzXE.js +130 -0
  398. package/dist/form-sizing-By94KzXE.js.map +1 -0
  399. package/dist/{forms-B5NCbkSC.js → forms-Bzha-Y3B.js} +25 -25
  400. package/dist/forms-Bzha-Y3B.js.map +1 -0
  401. package/dist/forms-numeric-C0bvjRPZ.js +906 -0
  402. package/dist/forms-numeric-C0bvjRPZ.js.map +1 -0
  403. package/dist/{header-kxruN3RM.js → header-BOefOKd1.js} +38 -41
  404. package/dist/header-BOefOKd1.js.map +1 -0
  405. package/dist/{hooks-BrlnCwQd.js → hooks-9k_TtmKh.js} +2 -2
  406. package/dist/{hooks-BrlnCwQd.js.map → hooks-9k_TtmKh.js.map} +1 -1
  407. package/dist/{http-CdEIHyQf.js → http-D_6rOnzU.js} +2 -2
  408. package/dist/{http-CdEIHyQf.js.map → http-D_6rOnzU.js.map} +1 -1
  409. package/dist/icon-badge-CAuKupo9.js +55 -0
  410. package/dist/icon-badge-CAuKupo9.js.map +1 -0
  411. package/dist/index.js +7 -7
  412. package/dist/input-DWhBBBww.js +262 -0
  413. package/dist/input-DWhBBBww.js.map +1 -0
  414. package/dist/{input-vxcaNCYC.js → input-Ddi_LSYv.js} +3 -3
  415. package/dist/{input-vxcaNCYC.js.map → input-Ddi_LSYv.js.map} +1 -1
  416. package/dist/interaction-recipes-CHr0dJUs.js +24 -0
  417. package/dist/interaction-recipes-CHr0dJUs.js.map +1 -0
  418. package/dist/item-DEmDiTlD.js +265 -0
  419. package/dist/item-DEmDiTlD.js.map +1 -0
  420. package/dist/layer-recipes-CCpklYME.js +13 -0
  421. package/dist/layer-recipes-CCpklYME.js.map +1 -0
  422. package/dist/layout/app-shell.js +1 -1
  423. package/dist/layout/auth.js +1 -1
  424. package/dist/layout/containers.js +1 -1
  425. package/dist/layout/header.js +1 -1
  426. package/dist/layout/hooks.js +1 -1
  427. package/dist/layout/navigation.js +1 -1
  428. package/dist/layout/page.js +1 -1
  429. package/dist/layout/settings.js +1 -1
  430. package/dist/layout/sidebar.js +2 -2
  431. package/dist/layout/workspace.js +1 -1
  432. package/dist/layout.js +10 -10
  433. package/dist/lib/affordance-geometry.generated.d.ts +7 -1
  434. package/dist/lib/field-affordance-recipes.d.ts +41 -1
  435. package/dist/lib/field-state-recipes.d.ts +9 -6
  436. package/dist/lib/focus-recipes.d.ts +24 -0
  437. package/dist/lib/format.d.ts +9 -0
  438. package/dist/lib/interaction-recipes.d.ts +35 -0
  439. package/dist/lib/layer-recipes.d.ts +19 -0
  440. package/dist/lib/money-format.d.ts +30 -0
  441. package/dist/lib/motion-recipes.d.ts +1 -0
  442. package/dist/lib/overlay-anatomy-recipes.d.ts +2 -1
  443. package/dist/lib/safe-image-src.d.ts +10 -0
  444. package/dist/lib/sanitize-html.d.ts +15 -3
  445. package/dist/lib/surface-recipes.d.ts +48 -6
  446. package/dist/lib/token-merge.generated.d.ts +17 -14
  447. package/dist/lib/tone-recipes.d.ts +79 -0
  448. package/dist/lib/track-recipes.d.ts +1 -1
  449. package/dist/lib/ui-provider/hooks.d.ts +2 -1
  450. package/dist/lib/ui-provider/index.d.ts +2 -2
  451. package/dist/lib/ui-provider/provider.d.ts +7 -2
  452. package/dist/lib/ui-provider/store.d.ts +6 -2
  453. package/dist/lib/ui-provider/types.d.ts +14 -2
  454. package/dist/lib/utils.js +1 -1
  455. package/dist/media-gallery-DcTtAaeC.js +203 -0
  456. package/dist/media-gallery-DcTtAaeC.js.map +1 -0
  457. package/dist/mentions-D-uyCh01.js +568 -0
  458. package/dist/mentions-D-uyCh01.js.map +1 -0
  459. package/dist/{message-SZUNB1eX.js → message-CdHgIWKf.js} +5 -5
  460. package/dist/{message-SZUNB1eX.js.map → message-CdHgIWKf.js.map} +1 -1
  461. package/dist/metadata-list-X5rYAKSB.js +394 -0
  462. package/dist/metadata-list-X5rYAKSB.js.map +1 -0
  463. package/dist/{motion-recipes-B6jKXEcN.js → motion-recipes-ChBg4HBq.js} +3 -2
  464. package/dist/{motion-recipes-B6jKXEcN.js.map → motion-recipes-ChBg4HBq.js.map} +1 -1
  465. package/dist/navigation-D3KwXmaq.js +145 -0
  466. package/dist/navigation-D3KwXmaq.js.map +1 -0
  467. package/dist/navigation-HJf5zxlH.js +268 -0
  468. package/dist/navigation-HJf5zxlH.js.map +1 -0
  469. package/dist/{navigation-row-recipes-DQEXQcqY.js → navigation-row-recipes-BVowojQw.js} +2 -2
  470. package/dist/{navigation-row-recipes-DQEXQcqY.js.map → navigation-row-recipes-BVowojQw.js.map} +1 -1
  471. package/dist/number-DMhe-Vsk.js +352 -0
  472. package/dist/number-DMhe-Vsk.js.map +1 -0
  473. package/dist/overflow-tab-bar-sQHXLlwQ.js +280 -0
  474. package/dist/overflow-tab-bar-sQHXLlwQ.js.map +1 -0
  475. package/dist/overlay.recipes-8GHqmlb4.js +6 -0
  476. package/dist/overlay.recipes-8GHqmlb4.js.map +1 -0
  477. package/dist/overlays-I0axtYA6.js +999 -0
  478. package/dist/overlays-I0axtYA6.js.map +1 -0
  479. package/dist/{page-hGmT4nWK.js → page-B5dTH9gE.js} +79 -68
  480. package/dist/page-B5dTH9gE.js.map +1 -0
  481. package/dist/page-header-commands-DjzFEq3E.js +126 -0
  482. package/dist/page-header-commands-DjzFEq3E.js.map +1 -0
  483. package/dist/{pagination-NLGqRirf.js → pagination-3bPA_a6K.js} +19 -19
  484. package/dist/{pagination-NLGqRirf.js.map → pagination-3bPA_a6K.js.map} +1 -1
  485. package/dist/{popover-CghIYdQf.js → popover-Di55PyAI.js} +8 -8
  486. package/dist/popover-Di55PyAI.js.map +1 -0
  487. package/dist/{popover-menu-B4PoWhRl.js → popover-menu-B71Tn2Qz.js} +6 -6
  488. package/dist/{popover-menu-B4PoWhRl.js.map → popover-menu-B71Tn2Qz.js.map} +1 -1
  489. package/dist/{popover.recipes-QlD4JenO.js → popover.recipes-Bdyhj2db.js} +2 -2
  490. package/dist/{popover.recipes-QlD4JenO.js.map → popover.recipes-Bdyhj2db.js.map} +1 -1
  491. package/dist/primitives-B-CkiEMU.js +379 -0
  492. package/dist/primitives-B-CkiEMU.js.map +1 -0
  493. package/dist/primitives.js +5 -5
  494. package/dist/{progress-BroqrAyV.js → progress-rnS8-uAW.js} +11 -11
  495. package/dist/progress-rnS8-uAW.js.map +1 -0
  496. package/dist/{receipt-BuJynLgf.js → receipt-D0oswZ0p.js} +6 -6
  497. package/dist/{receipt-BuJynLgf.js.map → receipt-D0oswZ0p.js.map} +1 -1
  498. package/dist/rich-text-DvGulsNJ.js +78 -0
  499. package/dist/rich-text-DvGulsNJ.js.map +1 -0
  500. package/dist/rich-text-editor-sMU_Scqm.js +1204 -0
  501. package/dist/rich-text-editor-sMU_Scqm.js.map +1 -0
  502. package/dist/rich-text-editor.recipes-CadiF_Uu.js +88 -0
  503. package/dist/rich-text-editor.recipes-CadiF_Uu.js.map +1 -0
  504. package/dist/rich-text-editor.strings-CB59ekH2.js +38 -0
  505. package/dist/rich-text-editor.strings-CB59ekH2.js.map +1 -0
  506. package/dist/safe-image-src-C6kQSMBZ.js +17 -0
  507. package/dist/safe-image-src-C6kQSMBZ.js.map +1 -0
  508. package/dist/sanitize-html-DsQmI48u.js +92 -0
  509. package/dist/sanitize-html-DsQmI48u.js.map +1 -0
  510. package/dist/scroll-area-Bt_vXY2b.js +48 -0
  511. package/dist/scroll-area-Bt_vXY2b.js.map +1 -0
  512. package/dist/{separator-BNIgG3au.js → separator-C8DlRGwF.js} +4 -4
  513. package/dist/separator-C8DlRGwF.js.map +1 -0
  514. package/dist/{separator-BhtFyo4x.js → separator-CYHnjsAb.js} +2 -2
  515. package/dist/{separator-BhtFyo4x.js.map → separator-CYHnjsAb.js.map} +1 -1
  516. package/dist/services/actions/action-adapters.d.ts +22 -0
  517. package/dist/services/actions/index.d.ts +1 -1
  518. package/dist/services/actions.js +23 -6
  519. package/dist/services/actions.js.map +1 -1
  520. package/dist/settings-CQW3b-Cu.js +170 -0
  521. package/dist/settings-CQW3b-Cu.js.map +1 -0
  522. package/dist/sheet-4SEvVYzA.js +210 -0
  523. package/dist/sheet-4SEvVYzA.js.map +1 -0
  524. package/dist/{sidebar-CyR4XKwR.js → sidebar-C7WWR29L.js} +181 -180
  525. package/dist/sidebar-C7WWR29L.js.map +1 -0
  526. package/dist/sidebar-d7Dg80ln.js +511 -0
  527. package/dist/sidebar-d7Dg80ln.js.map +1 -0
  528. package/dist/{skeleton-3F0uhYn3.js → skeleton-Cz890JZF.js} +10 -10
  529. package/dist/skeleton-Cz890JZF.js.map +1 -0
  530. package/dist/smart-card-lFKxn5Hu.js +595 -0
  531. package/dist/smart-card-lFKxn5Hu.js.map +1 -0
  532. package/dist/{spinner-Cpf7oRkF.js → spinner-fa3h1Aif.js} +10 -8
  533. package/dist/spinner-fa3h1Aif.js.map +1 -0
  534. package/dist/{structure-CRdqVawd.js → structure-DC2dygdA.js} +3 -3
  535. package/dist/{structure-CRdqVawd.js.map → structure-DC2dygdA.js.map} +1 -1
  536. package/dist/{structure.recipes-Bqhf9oIh.js → structure.recipes-EPz60cU8.js} +37 -19
  537. package/dist/structure.recipes-EPz60cU8.js.map +1 -0
  538. package/dist/style.css +1 -1
  539. package/dist/surface-recipes-BKRVW8Os.js +43 -0
  540. package/dist/surface-recipes-BKRVW8Os.js.map +1 -0
  541. package/dist/table-CIKyLUsy.js +163 -0
  542. package/dist/table-CIKyLUsy.js.map +1 -0
  543. package/dist/{table-CcRDZiLP.js → table-CrcLN9Io.js} +544 -530
  544. package/dist/table-CrcLN9Io.js.map +1 -0
  545. package/dist/tabs-DwBJfjxX.js +190 -0
  546. package/dist/tabs-DwBJfjxX.js.map +1 -0
  547. package/dist/{text-inputs-DsR56TR-.js → text-inputs-aaK9wcDT.js} +151 -155
  548. package/dist/text-inputs-aaK9wcDT.js.map +1 -0
  549. package/dist/{text.styles-Q4sGAIgA.js → text.styles-g4He6UIW.js} +17 -14
  550. package/dist/text.styles-g4He6UIW.js.map +1 -0
  551. package/dist/theme.css +16 -12
  552. package/dist/themes/green.css +24 -0
  553. package/dist/{timelines-D1pkt3se.js → timelines-C_SBwHNP.js} +154 -164
  554. package/dist/timelines-C_SBwHNP.js.map +1 -0
  555. package/dist/tone-recipes-CPoExcTE.js +70 -0
  556. package/dist/tone-recipes-CPoExcTE.js.map +1 -0
  557. package/dist/tooltip-CsfgrfS7.js +111 -0
  558. package/dist/tooltip-CsfgrfS7.js.map +1 -0
  559. package/dist/track-recipes-CDcKmndW.js +10 -0
  560. package/dist/track-recipes-CDcKmndW.js.map +1 -0
  561. package/dist/{tree-BtmYyMZV.js → tree-BiKhg8AY.js} +72 -70
  562. package/dist/tree-BiKhg8AY.js.map +1 -0
  563. package/dist/typography/rich-text.js +1 -1
  564. package/dist/typography-DTRkE9zL.js +117 -0
  565. package/dist/typography-DTRkE9zL.js.map +1 -0
  566. package/dist/typography.js +2 -2
  567. package/dist/{ui-provider-DRPn3qNl.js → ui-provider-1D_NSYzO.js} +30 -23
  568. package/dist/ui-provider-1D_NSYzO.js.map +1 -0
  569. package/dist/ui-provider.js +3 -3
  570. package/dist/{upload-CDbYw1WN.js → upload-BO8-CLN6.js} +294 -293
  571. package/dist/upload-BO8-CLN6.js.map +1 -0
  572. package/dist/{upload-queue-CNd_hH_a.js → upload-queue-EOC8g1gf.js} +133 -138
  573. package/dist/upload-queue-EOC8g1gf.js.map +1 -0
  574. package/dist/upload.recipes-BbxTqrCT.js +61 -0
  575. package/dist/upload.recipes-BbxTqrCT.js.map +1 -0
  576. package/dist/{usage-card-VyJLUwRr.js → usage-card-obRaBskq.js} +42 -43
  577. package/dist/{usage-card-VyJLUwRr.js.map → usage-card-obRaBskq.js.map} +1 -1
  578. package/dist/{utils-BvH9PSmq.js → utils-l5LpDw2z.js} +264 -62
  579. package/dist/utils-l5LpDw2z.js.map +1 -0
  580. package/dist/value-inputs-TAYMX111.js +947 -0
  581. package/dist/value-inputs-TAYMX111.js.map +1 -0
  582. package/dist/value-typography-b8wpz1eX.js +116 -0
  583. package/dist/value-typography-b8wpz1eX.js.map +1 -0
  584. package/dist/workspace-DH0v0KcB.js +407 -0
  585. package/dist/workspace-DH0v0KcB.js.map +1 -0
  586. package/docs/consumer-skill/SKILL.md +62 -50
  587. package/docs/consumer-skill/examples/app-layout.tsx +3 -5
  588. package/docs/consumer-skill/examples/composition.tsx +3 -3
  589. package/docs/consumer-skill/examples/detail.tsx +59 -13
  590. package/docs/consumer-skill/examples/edit.tsx +2 -2
  591. package/docs/consumer-skill/examples/layout-blocks.tsx +20 -0
  592. package/docs/consumer-skill/examples/manifest.json +28 -6
  593. package/docs/consumer-skill/examples/receipt.tsx +2 -2
  594. package/docs/consumer-skill/examples/scoped-directory.tsx +3 -3
  595. package/docs/consumer-skill/examples/website.tsx +1 -1
  596. package/docs/consumer-skill/references/agents-md.md +33 -0
  597. package/docs/consumer-skill/references/analytics.md +1 -1
  598. package/docs/consumer-skill/references/composition.md +139 -24
  599. package/docs/consumer-skill/references/design-contract.md +12 -3
  600. package/docs/consumer-skill/references/discovery.md +4 -0
  601. package/docs/consumer-skill/references/installation.md +33 -1
  602. package/docs/consumer-skill/references/integration.md +32 -1
  603. package/docs/consumer-skill/references/public-api.json +1051 -610
  604. package/docs/consumer-skill/references/review.md +44 -8
  605. package/docs/consumer-skill/references/theming.md +14 -4
  606. package/docs/consumer-skill/references/tokens.json +5 -2
  607. package/docs/consumer-skill/references/workflows.md +30 -9
  608. package/docs/consumer-skill/scripts/composition-policy.mjs +127 -6
  609. package/docs/consumer-skill/scripts/discovery.mjs +11 -3
  610. package/docs/consumer-skill/scripts/pin-button-defaults.mjs +95 -0
  611. package/docs/consumer-skill/scripts/surface-policy.mjs +139 -5
  612. package/package.json +13 -3
  613. package/dist/accordion-BRTcsp8J.js +0 -205
  614. package/dist/accordion-BRTcsp8J.js.map +0 -1
  615. package/dist/action-menu-Drxw_vJk.js +0 -265
  616. package/dist/action-menu-Drxw_vJk.js.map +0 -1
  617. package/dist/affordance-geometry.generated-CL84ZN9A.js.map +0 -1
  618. package/dist/ai-artifact-DLVdK0Py.js.map +0 -1
  619. package/dist/attachment-DbjUWsP0.js +0 -244
  620. package/dist/attachment-DbjUWsP0.js.map +0 -1
  621. package/dist/auth-CAQcasMV.js.map +0 -1
  622. package/dist/avatar-Bu2HhitA.js.map +0 -1
  623. package/dist/badge-CzId1Wlm.js +0 -92
  624. package/dist/badge-CzId1Wlm.js.map +0 -1
  625. package/dist/breadcrumbs-BuYz5SDU.js +0 -128
  626. package/dist/breadcrumbs-BuYz5SDU.js.map +0 -1
  627. package/dist/button-BZDasD04.js +0 -651
  628. package/dist/button-BZDasD04.js.map +0 -1
  629. package/dist/button-BZyfTvwm.js.map +0 -1
  630. package/dist/buttons-D_6KJvEE.js +0 -99
  631. package/dist/buttons-D_6KJvEE.js.map +0 -1
  632. package/dist/cards-qGSErLw_.js.map +0 -1
  633. package/dist/chart-Bsc5BICK.js.map +0 -1
  634. package/dist/checkbox-BQNDjUCh.js +0 -34
  635. package/dist/checkbox-BQNDjUCh.js.map +0 -1
  636. package/dist/choice-inputs-Mk3iWbhr.js +0 -725
  637. package/dist/choice-inputs-Mk3iWbhr.js.map +0 -1
  638. package/dist/code-block-DzHKRybS.js +0 -183
  639. package/dist/code-block-DzHKRybS.js.map +0 -1
  640. package/dist/combobox-BFnbJJp3.js.map +0 -1
  641. package/dist/combobox-hozNwUcc.js +0 -847
  642. package/dist/combobox-hozNwUcc.js.map +0 -1
  643. package/dist/command-BnmSchli.js.map +0 -1
  644. package/dist/comments-u5L0OGip.js.map +0 -1
  645. package/dist/containers-DqB-bSYE.js.map +0 -1
  646. package/dist/data-display-Bihs9Ven.js +0 -1342
  647. package/dist/data-display-Bihs9Ven.js.map +0 -1
  648. package/dist/date-DOKhJPu7.js +0 -140
  649. package/dist/date-DOKhJPu7.js.map +0 -1
  650. package/dist/date-picker-DzP5HQq7.js +0 -1541
  651. package/dist/date-picker-DzP5HQq7.js.map +0 -1
  652. package/dist/date-pickers-BpgGz7S-.js +0 -196
  653. package/dist/date-pickers-BpgGz7S-.js.map +0 -1
  654. package/dist/display-CS6Hbk18.js.map +0 -1
  655. package/dist/dropdown-menu-D-boNgGO.js.map +0 -1
  656. package/dist/feedback-CJkUAapr.js +0 -233
  657. package/dist/feedback-CJkUAapr.js.map +0 -1
  658. package/dist/field-affordance-recipes-uKY4MsZ_.js +0 -25
  659. package/dist/field-affordance-recipes-uKY4MsZ_.js.map +0 -1
  660. package/dist/field-state-recipes-DQQpiLWC.js +0 -11
  661. package/dist/field-state-recipes-DQQpiLWC.js.map +0 -1
  662. package/dist/filters-D6FF8L6s.js.map +0 -1
  663. package/dist/form-sizing-QP8aIRaW.js +0 -103
  664. package/dist/form-sizing-QP8aIRaW.js.map +0 -1
  665. package/dist/format-iamDSqs2.js +0 -110
  666. package/dist/format-iamDSqs2.js.map +0 -1
  667. package/dist/forms-B5NCbkSC.js.map +0 -1
  668. package/dist/forms-numeric-Crrm80Lm.js +0 -867
  669. package/dist/forms-numeric-Crrm80Lm.js.map +0 -1
  670. package/dist/header-kxruN3RM.js.map +0 -1
  671. package/dist/icon-badge-Btc6pQrp.js +0 -53
  672. package/dist/icon-badge-Btc6pQrp.js.map +0 -1
  673. package/dist/input-SX9V0AL3.js +0 -255
  674. package/dist/input-SX9V0AL3.js.map +0 -1
  675. package/dist/item-DE4YnuJx.js +0 -258
  676. package/dist/item-DE4YnuJx.js.map +0 -1
  677. package/dist/media-gallery-DLp3HAz0.js +0 -201
  678. package/dist/media-gallery-DLp3HAz0.js.map +0 -1
  679. package/dist/mentions-Cl0Kt_Pd.js +0 -565
  680. package/dist/mentions-Cl0Kt_Pd.js.map +0 -1
  681. package/dist/navigation-DnQSNMT0.js +0 -276
  682. package/dist/navigation-DnQSNMT0.js.map +0 -1
  683. package/dist/navigation-DyytsLRB.js +0 -265
  684. package/dist/navigation-DyytsLRB.js.map +0 -1
  685. package/dist/number-DasMFWEG.js +0 -269
  686. package/dist/number-DasMFWEG.js.map +0 -1
  687. package/dist/overlay.recipes-BxW5FIfK.js +0 -6
  688. package/dist/overlay.recipes-BxW5FIfK.js.map +0 -1
  689. package/dist/overlays-DUbs1KEi.js +0 -1011
  690. package/dist/overlays-DUbs1KEi.js.map +0 -1
  691. package/dist/page-hGmT4nWK.js.map +0 -1
  692. package/dist/page-header-D8nERkn5.js +0 -112
  693. package/dist/page-header-D8nERkn5.js.map +0 -1
  694. package/dist/popover-CghIYdQf.js.map +0 -1
  695. package/dist/primitives-C7ff0QaI.js +0 -337
  696. package/dist/primitives-C7ff0QaI.js.map +0 -1
  697. package/dist/progress-BroqrAyV.js.map +0 -1
  698. package/dist/rich-text-DlxDOtf4.js +0 -32
  699. package/dist/rich-text-DlxDOtf4.js.map +0 -1
  700. package/dist/rich-text-editor-BKyG7rWz.js +0 -574
  701. package/dist/rich-text-editor-BKyG7rWz.js.map +0 -1
  702. package/dist/rich-text-editor.recipes-B72Nfuze.js +0 -81
  703. package/dist/rich-text-editor.recipes-B72Nfuze.js.map +0 -1
  704. package/dist/rich-text-editor.strings-BpnIQgMl.js +0 -25
  705. package/dist/rich-text-editor.strings-BpnIQgMl.js.map +0 -1
  706. package/dist/sanitize-html-BG9FGe-j.js +0 -64
  707. package/dist/sanitize-html-BG9FGe-j.js.map +0 -1
  708. package/dist/scroll-area-D-pIhEKl.js +0 -47
  709. package/dist/scroll-area-D-pIhEKl.js.map +0 -1
  710. package/dist/separator-BNIgG3au.js.map +0 -1
  711. package/dist/settings-DOTOzeZ2.js +0 -161
  712. package/dist/settings-DOTOzeZ2.js.map +0 -1
  713. package/dist/sheet-BFhrNehm.js +0 -205
  714. package/dist/sheet-BFhrNehm.js.map +0 -1
  715. package/dist/sidebar-CyR4XKwR.js.map +0 -1
  716. package/dist/sidebar-SvGJ0Zwi.js +0 -506
  717. package/dist/sidebar-SvGJ0Zwi.js.map +0 -1
  718. package/dist/skeleton-3F0uhYn3.js.map +0 -1
  719. package/dist/smart-card-DjGVV2xr.js +0 -584
  720. package/dist/smart-card-DjGVV2xr.js.map +0 -1
  721. package/dist/spinner-Cpf7oRkF.js.map +0 -1
  722. package/dist/structure.recipes-Bqhf9oIh.js.map +0 -1
  723. package/dist/surface-recipes-Dd__PD-w.js +0 -28
  724. package/dist/surface-recipes-Dd__PD-w.js.map +0 -1
  725. package/dist/table-CLtJTxoR.js +0 -147
  726. package/dist/table-CLtJTxoR.js.map +0 -1
  727. package/dist/table-CcRDZiLP.js.map +0 -1
  728. package/dist/tabs-BNgu7g0u.js +0 -188
  729. package/dist/tabs-BNgu7g0u.js.map +0 -1
  730. package/dist/text-inputs-DsR56TR-.js.map +0 -1
  731. package/dist/text.styles-Q4sGAIgA.js.map +0 -1
  732. package/dist/timelines-D1pkt3se.js.map +0 -1
  733. package/dist/track-recipes-LLPNVwFg.js +0 -10
  734. package/dist/track-recipes-LLPNVwFg.js.map +0 -1
  735. package/dist/tree-BtmYyMZV.js.map +0 -1
  736. package/dist/typography-BxQgiZyw.js +0 -96
  737. package/dist/typography-BxQgiZyw.js.map +0 -1
  738. package/dist/ui-provider-DRPn3qNl.js.map +0 -1
  739. package/dist/upload-CDbYw1WN.js.map +0 -1
  740. package/dist/upload-queue-CNd_hH_a.js.map +0 -1
  741. package/dist/use-file-drop-target-BX7GnhoQ.js +0 -39
  742. package/dist/use-file-drop-target-BX7GnhoQ.js.map +0 -1
  743. package/dist/utils-BvH9PSmq.js.map +0 -1
  744. package/dist/value-inputs-D0KCrfVC.js +0 -840
  745. package/dist/value-inputs-D0KCrfVC.js.map +0 -1
  746. package/dist/workspace-CcR8r-Nt.js +0 -395
  747. package/dist/workspace-CcR8r-Nt.js.map +0 -1
  748. /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
 
@@ -19,9 +19,28 @@ workflow/declarations; this is a review aid, not a new design system.
19
19
  empty/missing values and narrow parent width? Zero and unavailable differ.
20
20
 
21
21
  These criteria allow different product layouts. Do not impose a universal card
22
- count, row-line limit, primary button count or one-column form rule.
22
+ count, row-line limit or one-column form rule. Emphasis is the exception: keep
23
+ one solid primary command per page or surface, so the next action stays obvious.
23
24
 
24
- ## 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
25
44
 
26
45
  The package ships a read-only script, not an npm bin/global CLI. It needs the
27
46
  consumer's TypeScript development dependency and Node matching the package engine:
@@ -40,12 +59,29 @@ Errors cover unknown package entrypoints/symbols and statically detected overrid
40
59
  of protected Card/popup insets, Card badges in headerAction/headerStart rather
41
60
  than titleSuffix, control geometry/typography, fixed DisplayLabel/Badge
42
61
  roles, cross-role shell/inner radius replacements, display-copy margins, or
43
- 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,
44
63
  circular owners and joined-edge corner resets retain their roles. Import ownership
45
- follows lexical bindings, preserving locally shadowed application components. Deprecated migration
46
- owners, nested framed subjects and repeated literal headings produce review
47
- warnings; warnings alone do not fail CI. Messages identify the owner and remedy.
64
+ follows lexical bindings, preserving locally shadowed application components. Imports of
65
+ symbols the public index marks deprecated, nested framed subjects and repeated
66
+ literal headings produce review warnings; warnings alone do not fail CI. Messages
67
+ identify the owner and remedy. Dialog-like UI outside the overlay owners warns
68
+ too: native elements with `role="dialog"`/`"alertdialog"` or `aria-modal`, a
69
+ `fixed inset-0` layer, and imports of another modal library.
48
70
  Standalone compact Cards and Page gutter removal also produce review warnings.
71
+ Buttons placed in a Page or PageHeader `actions` region warn as well: pass
72
+ commands as `primaryAction` and ordered `secondaryActions` so the header owns
73
+ their emphasis, size and overflow. Non-command controls stay valid there.
74
+ A Page with more than one solid primary command, counting `header.primaryAction`
75
+ and every Button with `tone="primary"` and no other style, warns as well. Overlays own
76
+ their own primary command and are not counted. Raw palette classes such as
77
+ `bg-blue-500`, `text-gray-600` or `border-white` warn on any element; use a
78
+ semantic surface/foreground pair or a status tone. A Card title icon and an icon on
79
+ more than one MetadataList fact warn as decoration; keep a glyph only when it
80
+ encodes state or a brand. Native `<button>` and
81
+ `<h1>`–`<h6>` elements warn in favour of Button/TextButton and Heading, which
82
+ own focus, loading and disabled states or margins and the heading scale. A
83
+ native button passed as a package owner's `render`, such as an Item row
84
+ rendered as a button, is that owner's root and does not warn.
49
85
  Verified Card-owning Metric/card-grid, UsageCard and TaskCard compositions also
50
86
  participate in nested-surface and peer-gap review. Metric without its card variant,
51
87
  compact MetricGrid, flat TaskCard, ChartCard and Receipt do not establish a frame.
@@ -4,7 +4,7 @@ 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.
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 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 is deliberately soft and translucent, reading the same on every surface; focus and invalid edges carry the 3:1 contrast. `--border` is for dividers and surface edges. Keep that split when rebranding.
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
 
@@ -63,6 +63,12 @@ control heights and copy gaps keep their independent roots.
63
63
 
64
64
  Use discrete inset, density and size props for the component responsibility described in [composition](composition.md). CSS scales are independent continuous theme settings. Primary row text does not shrink to xs merely because a density is compact. Public Input and Command search retain normal desktop editable text; coarse-pointer devices use text-base at mobile and tablet widths. Typography components remain margin-free.
65
65
 
66
+ The default primary is near-black so success and other status colors never compete
67
+ 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.
71
+
66
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.
67
73
 
68
74
  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.
@@ -71,9 +77,13 @@ Apps using semantic utilities in their own JSX process themelia-react-ui/theme.c
71
77
 
72
78
  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.
73
79
 
74
- `ring` and `sidebar-ring` are focus roles tested at full strength. Preserve that
75
- strength and verify at least 3:1 against adjacent surfaces when overriding the
76
- theme; adding opacity can invalidate contrast even when the root color passes.
80
+ `ring` and `sidebar-ring` are the focus roles. Every focused element draws one
81
+ indicator: a 1px edge in the role at full strength (the control's own border, an
82
+ inset edge on borderless rows, or an outline just outside link text) inside a
83
+ soft 3px halo of the role at 50%. The edge carries the tested 3:1 contrast
84
+ against adjacent surfaces, so keep the root color at that strength when
85
+ overriding the theme; the halo makes focus stand out without reading as a
86
+ heavier border.
77
87
 
78
88
  ## Extend without drift
79
89
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "themelia-react-ui",
3
- "version": "1.0.2",
3
+ "version": "2.0.1",
4
4
  "structural": [
5
5
  {
6
6
  "name": "--space-scale",
@@ -121,7 +121,7 @@
121
121
  "radius": {
122
122
  "name": "--radius",
123
123
  "default": "0.75rem",
124
- "purpose": "Shared 8px corners keep short controls rectangular; nested corners derive from this root.",
124
+ "purpose": "Shared 12px outer corners; inner control/row corners derive from this root and stay rectangular.",
125
125
  "defaultUtility": "rounded-radius",
126
126
  "innerUtility": "rounded-inner",
127
127
  "innerFormula": "min(calc(var(--radius) * 0.75), calc(min(var(--height-action), var(--height-control)) * var(--density-scale) / 4))"
@@ -209,6 +209,7 @@
209
209
  "gap-space-lg",
210
210
  "gap-space-xl",
211
211
  "gap-space-2xl",
212
+ "gap-space-3xl",
212
213
  "gap-x-space-2xs",
213
214
  "gap-x-space-xs",
214
215
  "gap-x-space-sm",
@@ -216,6 +217,7 @@
216
217
  "gap-x-space-lg",
217
218
  "gap-x-space-xl",
218
219
  "gap-x-space-2xl",
220
+ "gap-x-space-3xl",
219
221
  "gap-y-space-2xs",
220
222
  "gap-y-space-xs",
221
223
  "gap-y-space-sm",
@@ -223,6 +225,7 @@
223
225
  "gap-y-space-lg",
224
226
  "gap-y-space-xl",
225
227
  "gap-y-space-2xl",
228
+ "gap-y-space-3xl",
226
229
  "p-space-2xs",
227
230
  "p-space-xs",
228
231
  "p-space-sm",
@@ -28,9 +28,23 @@ Reset/removal aborts pending uploads; the app owns transport and persistence.
28
28
 
29
29
  ## Detail and framing
30
30
 
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.
31
+ [The detail recipe](../examples/detail.tsx) exports two owners.
32
+ `AccountDetailPage` is the record route: Page owns the title, one status badge,
33
+ the commands and the section tabs. `primaryAction` is Edit account,
34
+ `secondaryActions` holds Send statement and a `destructive` Delete account that
35
+ opens ConfirmDialog, and `header.tabs` carries Overview, Invoices with its count
36
+ badge, and Activity. The header renders `[secondary…] [primary] [⋯]`; destructive
37
+ and overflow commands live in the More actions menu. `AccountDetail` is the same
38
+ facts as one framed subject for a drawer or dashboard, with Edit as its one quick
39
+ `headerAction`. Name, Email, Date, Money and Value own formatting and
40
+ missing-value fallbacks; `balanceMinor` uses `Money unit="minor"`.
41
+
42
+ No optional peers are needed. The app supplies the loaded record, the section
43
+ content and the delete transport, and owns navigation, locale/provider defaults
44
+ and permissions (`visible: false` hides a command). Verify missing
45
+ email/date/balance, a rejected delete that keeps the confirmation open, tab
46
+ selection with keyboard arrows, the narrow layout where secondary commands
47
+ collapse into the menu, and light/dark themes.
34
48
 
35
49
  ## Scoped directory
36
50
 
@@ -79,12 +93,16 @@ definitions; the app then chooses appropriate destination focus.
79
93
 
80
94
  ## Single resource page
81
95
 
82
- Use `Page`, `PageHeader` and `PageActions` from `themelia-react-ui/layout/page`
83
- for the record route's identity, back navigation, content bounds and commands.
84
- The [layout recipe](../examples/app-layout.tsx) demonstrates that route boundary;
85
- the [detail recipe](../examples/detail.tsx) demonstrates an independently framed
86
- record subject with MetadataList and value primitives. Decide whether the record
87
- needs that independent Card before nesting it under Page. Avoid repeating the
96
+ Use `Page` from `themelia-react-ui/layout/page` for the record route's identity,
97
+ back navigation, content bounds, commands and section tabs. Pass the record's
98
+ main command as `header.primaryAction`, supporting commands as
99
+ `header.secondaryActions` and sections as `header.tabs`; one status badge goes in
100
+ `header.titleBadges`. `PageHeader` serves a custom shell; `PageActions` is
101
+ deprecated. The [layout recipe](../examples/app-layout.tsx) demonstrates that
102
+ route boundary; the [detail recipe](../examples/detail.tsx) demonstrates the
103
+ record route and an independently framed subject with MetadataList and value
104
+ primitives. Decide whether the record needs that independent Card before nesting
105
+ it under Page. Avoid repeating the
88
106
  route heading just to frame the same facts. Page owns gutters; PageViewport owns
89
107
  scrolling only. App navigation, record loading/missing/error/retry, permissions,
90
108
  edit and delete callbacks remain application responsibilities.
@@ -92,6 +110,9 @@ edit and delete callbacks remain application responsibilities.
92
110
  Use `WorkspaceLayout` from `themelia-react-ui/layout/workspace` when independently composed record header,
93
111
  sidebar/main/rail regions are needed; inspect `features/resource` for complete
94
112
  resource coordination. A single record does not automatically need either.
113
+ Their headers (`WorkspaceRecordHeader`, `ResourceHeader` and the resource shells)
114
+ take the same `primaryAction` and `secondaryActions` as Page; keep their
115
+ `actions` for non-command controls.
95
116
  Read [layout composition](composition.md#application-layouts) for boundary and
96
117
  parent-width behavior, then the exact selected declaration for its current props.
97
118
 
@@ -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, 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']);
@@ -9,6 +9,9 @@ const textStyle = /^(fontSize|fontWeight|fontFamily|lineHeight|letterSpacing)$/;
9
9
  const smallPeerGaps = new Set(['none', 'normal', 'dense', '2xs', 'xs', 'sm', 'md']);
10
10
  const structureDefaults = { Stack: 'md', Grid: 'xl', AdaptiveGrid: 'xl' };
11
11
  const breakpoints = ['base', 'sm', 'md', 'lg', 'xl', '2xl'];
12
+ const paletteHues = 'slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|mauve|olive|mist|taupe';
13
+ const rawPaletteClass = new RegExp(`^!?(?:bg|text|border(?:-[xytrblse])?|ring|ring-offset|outline|fill|stroke|from|via|to|divide|decoration|caret|accent|placeholder)-(?:(?:${paletteHues})-(?:50|[1-9]00|950)|black|white)(?:/\\d{1,3})?$`);
14
+ const overlayOwners = ['ActionDialog', 'ConfirmDialog', 'ActionDrawer'];
12
15
 
13
16
  /** Bind this source only; never resolve imports, read libraries or run app code. */
14
17
  export function sourceBindings(source, ts) {
@@ -24,6 +27,16 @@ export function sourceBindings(source, ts) {
24
27
  }
25
28
 
26
29
  /** Small static review: TypeScript is supplied by the app, never a runtime peer. */
30
+ const overlayRemedy = 'Use ActionDialog, ConfirmDialog or ActionDrawer with useOverlayVisibility from themelia-react-ui/features/overlays; they own focus, dismissal, pending state and portal theming.';
31
+ const modalLibrary = /^(?:@radix-ui\/react-(?:alert-)?dialog|react-modal|vaul|@base-ui(?:-components)?\/react\/(?:alert-)?dialog)$/;
32
+ const modalExports = { '@headlessui/react': /^(?:Dialog|DialogPanel)$/, 'react-aria-components': /^(?:Dialog|Modal|ModalOverlay)$/ };
33
+ const importsModal = (node, ts) => {
34
+ const specifier = node.moduleSpecifier.text;
35
+ if (modalLibrary.test(specifier)) return true;
36
+ const names = node.importClause?.namedBindings;
37
+ return !!modalExports[specifier] && !!names && ts.isNamedImports(names) && names.elements.some(item => modalExports[specifier].test((item.propertyName ?? item.name).text));
38
+ };
39
+
27
40
  export function analyzeComposition(text, { filename, index, ts }) {
28
41
  const kind = /\.jsx?$/.test(filename) ? ts.ScriptKind.JSX : filename.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
29
42
  const source = ts.createSourceFile(filename, text, ts.ScriptTarget.Latest, true, kind);
@@ -116,11 +129,13 @@ export function analyzeComposition(text, { filename, index, ts }) {
116
129
  for (const item of elements) {
117
130
  const symbol = (item.propertyName ?? item.name).text;
118
131
  if (!family.symbols.includes(symbol)) add(item, 'public-symbol', 'error', `${specifier} does not export ${symbol}; inspect its declaration.`);
132
+ else if (family.deprecated?.[symbol]) add(item, 'deprecated-owner', 'warning', `${symbol} is deprecated: ${family.deprecated[symbol]}`);
119
133
  if (ts.isImportDeclaration(node)) bindings.set(symbolFor(item.name), { symbol, import: specifier });
120
134
  }
121
135
  if (names && ts.isNamespaceImport(names)) namespaces.set(symbolFor(names.name), specifier);
122
136
  }
123
137
  function gather(node) {
138
+ if (ts.isImportDeclaration(node) && ts.isStringLiteralLike(node.moduleSpecifier) && importsModal(node, ts)) add(node, 'raw-overlay-primitive', 'warning', `${node.moduleSpecifier.text} builds a second dialog system. ${overlayRemedy}`);
124
139
  if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) declarations.set(symbolFor(node.name), node.initializer);
125
140
  if ((ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) && node.moduleSpecifier && ts.isStringLiteralLike(node.moduleSpecifier)) importOwner(node, node.moduleSpecifier.text);
126
141
  if (ts.isImportTypeNode(node) && ts.isLiteralTypeNode(node.argument) && ts.isStringLiteralLike(node.argument.literal)) importOwner(node, node.argument.literal.text);
@@ -185,6 +200,67 @@ export function analyzeComposition(text, { filename, index, ts }) {
185
200
  if (ts.isJsxExpression(node)) return slotBadge(node.expression);
186
201
  return false;
187
202
  };
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.
206
+ const commandButtons = expression => {
207
+ const node = resolve(expression);
208
+ if (!node) return false;
209
+ if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node)) {
210
+ const opening = ts.isJsxElement(node) ? node.openingElement : node;
211
+ const owner = ownerFor(opening.tagName);
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;
213
+ if (!/^(div|span)$/.test(opening.tagName.getText(source)) && !isOwner(owner, 'base/structure', ['Stack', 'Grid'])) return false;
214
+ return ts.isJsxElement(node) && node.children.some(commandButtons);
215
+ }
216
+ if (ts.isJsxFragment(node)) return node.children.some(commandButtons);
217
+ if (ts.isJsxExpression(node)) return commandButtons(node.expression);
218
+ if (ts.isConditionalExpression(node)) return commandButtons(node.whenTrue) || commandButtons(node.whenFalse);
219
+ if (ts.isBinaryExpression(node) && [ts.SyntaxKind.AmpersandAmpersandToken, ts.SyntaxKind.BarBarToken, ts.SyntaxKind.QuestionQuestionToken].includes(node.operatorToken.kind)) return commandButtons(node.right);
220
+ return false;
221
+ };
222
+ // Static class tokens only; dynamic parts are skipped rather than reported.
223
+ const staticClasses = (expression, visited = new Set()) => {
224
+ const node = resolve(expression);
225
+ if (!node || visited.has(node)) return [];
226
+ visited.add(node);
227
+ if (ts.isStringLiteralLike(node)) return [node.text];
228
+ if (ts.isTemplateExpression(node)) return [node.head.text, ...node.templateSpans.map(span => span.literal.text)];
229
+ if (ts.isConditionalExpression(node)) return [...staticClasses(node.whenTrue, visited), ...staticClasses(node.whenFalse, visited)];
230
+ if (ts.isBinaryExpression(node) && [ts.SyntaxKind.AmpersandAmpersandToken, ts.SyntaxKind.BarBarToken, ts.SyntaxKind.QuestionQuestionToken].includes(node.operatorToken.kind)) return staticClasses(node.right, visited);
231
+ if (ts.isArrayLiteralExpression(node)) return node.elements.flatMap(item => staticClasses(item, visited));
232
+ if (ts.isCallExpression(node) && /^(cn|clsx|classNames|twMerge)$/.test(node.expression.getText(source))) return node.arguments.flatMap(item => staticClasses(item, visited));
233
+ return [];
234
+ };
235
+ const classTokens = opening => {
236
+ const attribute = opening.attributes.properties.find(property => ts.isJsxAttribute(property) && property.name.getText(source) === 'className');
237
+ if (!attribute?.initializer) return [];
238
+ const expression = ts.isJsxExpression(attribute.initializer) ? attribute.initializer.expression : attribute.initializer;
239
+ // Template chunks may split a token; keep only complete-looking words.
240
+ return staticClasses(expression).flatMap(value => value.split(/\s+/)).filter(token => token && !token.startsWith('-') && !token.endsWith('-')).map(utility);
241
+ };
242
+ // tone="primary" is solid unless a buttonStyle says otherwise; untoned Buttons are neutral.
243
+ const solidPrimary = (opening, owner) => {
244
+ if (!isOwner(owner, 'base/buttons', ['Button'])) return false;
245
+ const props = new Map(attributes(opening));
246
+ const style = props.has('buttonStyle') ? literal(props.get('buttonStyle')) : 'solid';
247
+ return literal(props.get('tone')) === 'primary' && style === 'solid';
248
+ };
249
+ // Overlays are separate surfaces with their own primary command.
250
+ const solidPrimaryCount = root => {
251
+ let count = 0;
252
+ const walk = child => {
253
+ if (ts.isJsxElement(child) || ts.isJsxSelfClosingElement(child)) {
254
+ const opening = ts.isJsxElement(child) ? child.openingElement : child;
255
+ const owner = ownerFor(opening.tagName);
256
+ if (isOwner(owner, 'features/overlays', overlayOwners)) return;
257
+ if (solidPrimary(opening, owner)) count++;
258
+ }
259
+ ts.forEachChild(child, walk);
260
+ };
261
+ ts.forEachChild(root, walk);
262
+ return count;
263
+ };
188
264
  const peerCards = element => {
189
265
  if (!ts.isJsxElement(element.parent)) return new Set();
190
266
  const cards = [];
@@ -239,10 +315,31 @@ export function analyzeComposition(text, { filename, index, ts }) {
239
315
  if (ts.isJsxSelfClosingElement(node)) inspect(node, parents);
240
316
  ts.forEachChild(node, child => visit(child, parents));
241
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
+ };
242
330
  function inspect(node, parents) {
243
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);
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).');
244
335
  if (!owner) {
245
- if (node.tagName.getText(source) === 'div' && literal(new Map(attributes(node)).get('role')) === 'dialog') add(node, 'raw-overlay-primitive', 'warning', 'A custom dialog needs focus, dismissal and pending-state ownership. Compare ActionDialog/ConfirmDialog/ActionDrawer from features/overlays before maintaining that lifecycle.');
336
+ const tag = node.tagName.getText(source);
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.');
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.');
339
+ const nativeProps = new Map(attributes(node));
340
+ const modalRole = /^(?:dialog|alertdialog)$/.test(literal(nativeProps.get('role')) ?? '') || nativeProps.has('aria-modal');
341
+ const scrim = classTokens(node).includes('fixed') && classTokens(node).includes('inset-0');
342
+ if (modalRole || scrim) add(node, 'raw-overlay-primitive', 'warning', `A hand-rolled ${modalRole ? 'dialog' : 'full-screen layer'} must own focus, dismissal, pending state and theming itself. ${overlayRemedy}`);
246
343
  if (/^(?:input|textarea)$/.test(node.tagName.getText(source))) {
247
344
  const props = new Map(attributes(node));
248
345
  if (props.has('className') && classStrings(props.get('className')).flatMap(value=>value.split(/\s+/)).some(value=>replacesSharedRadius(value,'inner'))) add(node,'shared-radius','error','Native editable controls follow bounded rounded-inner; change the global theme root, not per-field corners.');
@@ -272,12 +369,15 @@ export function analyzeComposition(text, { filename, index, ts }) {
272
369
  const badge = family === 'badge' && owner.symbol === 'Badge';
273
370
  for (const name of ['className', 'headerClassName', 'contentClassName', 'footerClassName', 'subHeadingClassName']) {
274
371
  if (!props.has(name)) continue;
275
- const classes = classStrings(props.get(name)).flatMap(value => value.split(/\s+/)).map(utility);
372
+ const tokens = classStrings(props.get(name)).flatMap(value => value.split(/\s+/)).filter(Boolean);
373
+ const classes = tokens.map(utility);
374
+ const focusDrift = focusRingDrift(tokens);
276
375
  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.`);
277
376
  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.`);
278
377
  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.`);
279
378
  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.`);
280
- 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.`);
379
+ if (display && name === 'className' && tokens.some(fadedText)) add(node,'faded-text','error',`${owner.symbol}: use its type prop (main, secondary) instead of ${[...new Set(tokens.filter(fadedText))].join(', ')}; an opacity-faded text role falls under 4.5:1.`);
380
+ 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.`);
281
381
  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.`);
282
382
  }
283
383
  if (props.has('style')) for (const [name,value] of properties(props.get('style'))) {
@@ -287,7 +387,9 @@ export function analyzeComposition(text, { filename, index, ts }) {
287
387
  if (display && marginProperty.test(name) && !/^['"]?0(?:px|rem|em|%)?['"]?$/.test(resolve(value)?.getText(source)??'')) add(node,'copy-margin','error',`${owner.symbol}: typography is margin-free; the surrounding structure owns its copy gap.`);
288
388
  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.`);
289
389
  }
290
- if (['SmartCard', 'ContentBlock'].includes(owner.symbol)) add(node, 'deprecated-owner', 'warning', `${owner.symbol} is a migration owner; prefer Card for new compositions.`);
390
+ 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.`);
391
+ const facts = isOwner(owner, 'base/metadata-list', ['MetadataList']) || isOwner(owner, 'blocks/data-display', ['MetadataList']) ? resolve(props.get('items')) : undefined;
392
+ 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.');
291
393
  const framed = framedOwner(owner, props);
292
394
  if (isOwner(owner, 'base/cards', ['Card', 'SmartCard'])) {
293
395
  for (const slot of ['headerAction', 'headerStart']) if (slotBadge(props.get(slot))) add(node, 'card-badge-placement', 'error', `${owner.symbol}: put status/count/version badges in titleSuffix; ${slot} owns ${slot === 'headerAction' ? 'commands' : 'pre-title context'}.`);
@@ -296,7 +398,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
296
398
  const valueHeading = contents.some(item => role(item, ['Heading']) && /[$€£¥]|\d/.test(renderedText(item.element)));
297
399
  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.');
298
400
  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);
299
- 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.');
401
+ 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.');
300
402
  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.');
301
403
  }
302
404
  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.');
@@ -307,6 +409,25 @@ export function analyzeComposition(text, { filename, index, ts }) {
307
409
  if (framed && (!props.has('surface') || literal(props.get('surface')) === 'framed') && peers?.cards.size > 1 && peers.cards.has(node) && peers.smallGap) add(node, 'card-peer-gap', 'warning', 'Small peer gaps can be consumed by framed Card rings. Use lg/xl for independent surfaces and inspect visible edge clearance; tighter grouping needs an intentional surface policy.');
308
410
  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.`);
309
411
  const header = properties(props.get('header'), false);
412
+ const pageOwner = owner.import === `${index.package}/layout/page` || owner.import === `${index.package}/layout`;
413
+ // Every header owner takes role-based commands; its free-form regions hold
414
+ // non-command controls only.
415
+ 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']);
416
+ const headerActions = pageOwner && owner.symbol === 'Page' ? new Map(header).get('actions') : commandHeader ? props.get('actions') : undefined;
417
+ const elementSecondary = isOwner(owner, 'layout/workspace', ['WorkspaceRecordHeader']) ? props.get('secondaryActions') : undefined;
418
+ if (pageOwner && owner.symbol === 'Page') {
419
+ const primaries = solidPrimaryCount(ts.isJsxSelfClosingElement(node) ? node : node.parent) + (new Map(header).has('primaryAction') ? 1 : 0);
420
+ 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.`);
421
+ }
422
+ 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.`);
423
+ const headerProps = pageOwner && owner.symbol === 'Page' ? new Map(header) : pageOwner && owner.symbol === 'PageHeader' ? props : undefined;
424
+ if (headerProps) {
425
+ 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.`);
426
+ const hasIcon = action => properties(action, false).some(([name]) => name === 'icon');
427
+ const secondary = resolve(headerProps.get('secondaryActions'));
428
+ const iconCommands = (headerProps.has('primaryAction') && hasIcon(headerProps.get('primaryAction')) ? 1 : 0) + (secondary && ts.isArrayLiteralExpression(secondary) ? secondary.elements.filter(hasIcon).length : 0);
429
+ 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.`);
430
+ }
310
431
  const title = literal(props.get('title')) ?? literal(new Map(header).get('title'));
311
432
  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.`);
312
433
  const structure = owner.import === `${index.package}/base/structure` && Object.hasOwn(structureDefaults, owner.symbol);
@@ -21,6 +21,7 @@ export function validateIndex(index) {
21
21
  requireFormat(text(family.declaration) && /^dist\/[\w./-]+\.d\.ts$/.test(family.declaration) && !family.declaration.split('/').includes('..'), `invalid declaration ${family.declaration}`);
22
22
  requireFormat(layers.includes(family.layer) && text(family.responsibility), `missing layer/responsibility for ${family.import}`);
23
23
  for (const field of ['symbols', 'jobs', 'tags', 'aliases', 'sections', 'optionalPeers']) requireFormat(stringList(family[field]), `invalid ${field} for ${family.import}`);
24
+ if (family.deprecated !== undefined) requireFormat(family.deprecated !== null && typeof family.deprecated === 'object' && !Array.isArray(family.deprecated) && Object.entries(family.deprecated).every(([symbol, note]) => family.symbols.includes(symbol) && text(note)), `invalid deprecated symbols for ${family.import}`);
24
25
  if (family.references !== undefined) requireFormat(stringList(family.references) && family.references.every(file => /^references\/[\w/-]+\.md(?:#[\w-]+)?$/.test(file) && !file.split('/').includes('..')), `invalid focused references for ${family.import}`);
25
26
  requireFormat(family.optionalPeers.every(peer => index.peers?.some(owner => owner.name === peer && owner.optional)), `unknown optional peer for ${family.import}`);
26
27
  if (family.recipes !== undefined) {
@@ -117,11 +118,18 @@ export function findComponents(index, { query, layer = null, limit = 5 }) {
117
118
  const score = exactImport ? 10000 : matchedSymbols.length ? 9000 + Number(documentedSymbol) : exactFamily ? 8500 : exactIntent ? 8000 : focusedSymbols.length ? 7100 + 1 / Math.min(...focusedSymbols.map(symbol => words(symbol).length)) : terms.reduce((sum, term) => sum + (family.guidance.some(guide => containsTerms(guide.title, [term])) ? 20 : family.tags.some(tag => containsTerms(tag, [term])) ? 10 : 1), 0);
118
119
  const selectedSymbols = matchedSymbols.length ? matchedSymbols : focusedSymbols;
119
120
  const guidance = relevantGuidance(family, needle, terms, exactOwners.length ? selectedSymbols : [], exactImport);
120
- const relevantSymbols = exactImport ? family.symbols : exactOwners.length || matchedSymbols.length ? selectedSymbols : [...new Set([...selectedSymbols, ...guidance.flatMap(guide => guideSymbols(guide, family))])];
121
+ const candidateSymbols = exactImport ? family.symbols : exactOwners.length || matchedSymbols.length ? selectedSymbols : [...new Set([...selectedSymbols, ...guidance.flatMap(guide => guideSymbols(guide, family))])];
122
+ // Intent searches recommend current names only. Exact queries keep the
123
+ // requested symbol; either way the result reports deprecated candidates.
124
+ const lifecycle = family.deprecated ?? {};
125
+ const relevantSymbols = exactImport || matchedSymbols.length ? candidateSymbols : candidateSymbols.filter(symbol => !Object.hasOwn(lifecycle, symbol));
126
+ const deprecated = Object.fromEntries(candidateSymbols.filter(symbol => Object.hasOwn(lifecycle, symbol)).map(symbol => [symbol, lifecycle[symbol]]));
121
127
  const candidates = (family.recipes ?? []).filter(recipe => recipe.symbols.some(symbol => relevantSymbols.includes(symbol)));
122
128
  const recipeText = recipe => normalized([recipe.file, ...recipe.exports, ...recipe.references].join(' ')).replace(/[-/#]/g, ' ');
123
129
  const taskRecipes = matchedSymbols.length || exactImport ? [] : candidates.filter(recipe => terms.every(term => recipeText(recipe).includes(term)));
124
- const aliases = guidance.flatMap(guide => guide.aliases.map(alias => normalized(alias).split(/\s+/)));
130
+ // Retain related task synonyms without routing through an unrelated alias
131
+ // on the same broad family (for example, website versus main/aside layout).
132
+ const aliases = guidance.flatMap(guide => guide.aliases.filter(alias => terms.some(term => containsTerms(alias, [term]))).map(alias => normalized(alias).split(/\s+/)));
125
133
  const aliasRecipes = matchedSymbols.length || exactImport ? [] : candidates.filter(recipe => aliases.some(intent => intent.every(term => recipeText(recipe).includes(term))));
126
134
  const recipes = taskRecipes.length ? taskRecipes : aliasRecipes.length ? aliasRecipes : candidates;
127
135
  const nextReads = {
@@ -129,7 +137,7 @@ export function findComponents(index, { query, layer = null, limit = 5 }) {
129
137
  references: [...new Set([...(family.references ?? []), ...recipes.flatMap(recipe => recipe.references)])].sort(compare),
130
138
  examples: recipes.map(({ file, exports, symbols, optionalPeers = [] }) => ({ file, exports, symbols: symbols.filter(symbol => relevantSymbols.includes(symbol)), optionalPeers })),
131
139
  };
132
- ranked.push({ score, import: family.import, declaration: family.declaration, layer: family.layer, responsibility: family.responsibility, optionalPeers: family.optionalPeers, match: exactImport ? 'import' : matchedSymbols.length ? 'symbol' : 'intent', matchedSymbols, relevantSymbols, nextReads, guidance });
140
+ ranked.push({ score, import: family.import, declaration: family.declaration, layer: family.layer, responsibility: family.responsibility, optionalPeers: family.optionalPeers, match: exactImport ? 'import' : matchedSymbols.length ? 'symbol' : 'intent', matchedSymbols, relevantSymbols, ...(Object.keys(deprecated).length ? { deprecated } : {}), nextReads, guidance });
133
141
  }
134
142
  ranked.sort((a, b) => b.score - a.score || compare(a.import, b.import));
135
143
  return { package: index.package, version: index.version, query, layer, limit, total: ranked.length, results: ranked.slice(0, limit) };
@@ -0,0 +1,95 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createRequire } from 'node:module';
4
+ import { pathToFileURL } from 'node:url';
5
+ import { sourceBindings } from './composition-policy.mjs';
6
+
7
+ // An untoned Button now renders as the secondary outline, and a Button with a
8
+ // tone but no buttonStyle keeps that tone's solid treatment. Writing the old
9
+ // default tone onto untoned Buttons therefore keeps an existing screen's look.
10
+ // It edits only with --write; otherwise it reports what it would change.
11
+ // --solid-only pins only Buttons that also set no buttonStyle, so untoned
12
+ // outline and ghost Buttons (often brand-coloured by accident) turn neutral.
13
+ const usage = 'Usage: pin-button-defaults.mjs [--write] [--solid-only] [--tone=primary] [--source-root=<dir>] <files or directories>';
14
+ const owners = new Set(['Button', 'BaseButton', 'BaseButtonLink']);
15
+ const packageImports = new Set(['themelia-react-ui', 'themelia-react-ui/base/buttons']);
16
+
17
+ export function pinButtonDefaults(text, { filename, ts, tone = 'primary', solidOnly = false, sourceRoot }) {
18
+ const kind = /\.jsx?$/.test(filename) ? ts.ScriptKind.JSX : filename.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
19
+ const source = ts.createSourceFile(filename, text, ts.ScriptTarget.Latest, true, kind);
20
+ const symbolFor = sourceBindings(source, ts);
21
+ // Library maintainers pass --source-root so relative imports of the buttons family count too.
22
+ const buttonsDir = sourceRoot && path.resolve(sourceRoot, 'components/base/buttons');
23
+ const isButtonsImport = specifier => packageImports.has(specifier)
24
+ || (!!buttonsDir && specifier.startsWith('.') && `${path.resolve(path.dirname(filename), specifier)}/`.startsWith(`${buttonsDir}/`));
25
+ const named = new Set();
26
+ const namespaces = new Set();
27
+ for (const statement of source.statements) {
28
+ if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier) || !isButtonsImport(statement.moduleSpecifier.text)) continue;
29
+ const bindings = statement.importClause?.namedBindings;
30
+ if (bindings && ts.isNamespaceImport(bindings)) namespaces.add(symbolFor(bindings.name));
31
+ if (bindings && ts.isNamedImports(bindings)) for (const item of bindings.elements) {
32
+ if (!item.isTypeOnly && owners.has((item.propertyName ?? item.name).text)) named.add(symbolFor(item.name));
33
+ }
34
+ }
35
+ const isOwner = tag => (ts.isIdentifier(tag) && named.has(symbolFor(tag)))
36
+ || (ts.isPropertyAccessExpression(tag) && ts.isIdentifier(tag.expression) && namespaces.has(symbolFor(tag.expression)) && owners.has(tag.name.text));
37
+ const edits = [];
38
+ const pinned = [];
39
+ const unresolved = [];
40
+ const line = node => source.getLineAndCharacterOfPosition(node.getStart(source)).line + 1;
41
+ const visit = node => {
42
+ if ((ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) && isOwner(node.tagName)) {
43
+ const props = node.attributes.properties;
44
+ const has = name => props.some(attribute => ts.isJsxAttribute(attribute) && attribute.name.getText(source) === name);
45
+ const toned = has('tone') || (solidOnly && has('buttonStyle'));
46
+ if (!toned && props.some(ts.isJsxSpreadAttribute)) {
47
+ // A spread may already carry tone; leave it to review.
48
+ unresolved.push({ file: filename, line: line(node) });
49
+ } else if (!toned) {
50
+ edits.push({ at: (node.typeArguments ?? node.tagName).end, text: ` tone="${tone}"` });
51
+ pinned.push({ file: filename, line: line(node), tone });
52
+ }
53
+ }
54
+ ts.forEachChild(node, visit);
55
+ };
56
+ visit(source);
57
+ let output = text;
58
+ for (const edit of edits.sort((a, b) => b.at - a.at)) output = output.slice(0, edit.at) + edit.text + output.slice(edit.at);
59
+ return { output, pinned, unresolved };
60
+ }
61
+
62
+ function collect(target, files) {
63
+ const info = fs.lstatSync(target);
64
+ if (info.isSymbolicLink()) throw new Error(`Use a real source path instead of a symlink: ${target}`);
65
+ if (info.isDirectory()) {
66
+ for (const entry of fs.readdirSync(target).sort()) if (!['node_modules', '.git', 'dist', 'build'].includes(entry)) collect(path.join(target, entry), files);
67
+ } else if (/\.[jt]sx?$/.test(target) && !/\.d\.ts$/.test(target)) files.add(path.resolve(target));
68
+ }
69
+
70
+ if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) {
71
+ try {
72
+ const args = process.argv.slice(2);
73
+ const option = name => args.find(arg => arg.startsWith(`--${name}=`))?.slice(name.length + 3);
74
+ const targets = args.filter(arg => !arg.startsWith('--'));
75
+ const unknown = args.filter(arg => arg.startsWith('--') && !/^--(?:write|solid-only|tone=.+|source-root=.+)$/.test(arg));
76
+ if (!targets.length || unknown.length) throw new Error(unknown.length ? `Unknown option: ${unknown.join(', ')}\n${usage}` : usage);
77
+ const ts = createRequire(path.join(process.cwd(), 'package.json'))('typescript');
78
+ const files = new Set();
79
+ targets.forEach(target => collect(target, files));
80
+ if (!files.size) throw new Error('No supported source files found in the supplied paths.');
81
+ const write = args.includes('--write');
82
+ const sourceRoot = option('source-root') && path.resolve(option('source-root'));
83
+ const results = [...files].sort().map(filename => {
84
+ const text = fs.readFileSync(filename, 'utf8');
85
+ const result = pinButtonDefaults(text, { filename, ts, tone: option('tone'), solidOnly: args.includes('--solid-only'), sourceRoot });
86
+ if (write && result.output !== text) fs.writeFileSync(filename, result.output);
87
+ return result;
88
+ });
89
+ const pinned = results.flatMap(result => result.pinned);
90
+ process.stdout.write(JSON.stringify({ mode: write ? 'write' : 'dry-run', files: files.size, pinned: pinned.length, changedFiles: new Set(pinned.map(item => item.file)).size, unresolved: results.flatMap(result => result.unresolved), details: pinned }, null, 2) + '\n');
91
+ } catch (error) {
92
+ process.stderr.write(`pin-button-defaults: ${error.message}\nRun from the consumer app with its TypeScript development dependency installed.\n`);
93
+ process.exitCode = 1;
94
+ }
95
+ }