themelia-react-ui 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (507) hide show
  1. package/CHANGELOG.md +190 -1
  2. package/README.md +92 -13
  3. package/dist/{accordion-BRWh3BM1.js → accordion-BRTcsp8J.js} +8 -8
  4. package/dist/accordion-BRTcsp8J.js.map +1 -0
  5. package/dist/{action-menu-Cx3SdfbN.js → action-menu-Drxw_vJk.js} +36 -36
  6. package/dist/action-menu-Drxw_vJk.js.map +1 -0
  7. package/dist/affordance-geometry.generated-CL84ZN9A.js +63 -0
  8. package/dist/affordance-geometry.generated-CL84ZN9A.js.map +1 -0
  9. package/dist/{ai-artifact-DkOArd3-.js → ai-artifact-DLVdK0Py.js} +151 -155
  10. package/dist/ai-artifact-DLVdK0Py.js.map +1 -0
  11. package/dist/{app-shell-BH_bGcE2.js → app-shell-C_fKpljx.js} +11 -10
  12. package/dist/app-shell-C_fKpljx.js.map +1 -0
  13. package/dist/{attachment-DsLgNHXt.js → attachment-DbjUWsP0.js} +12 -12
  14. package/dist/{attachment-DsLgNHXt.js.map → attachment-DbjUWsP0.js.map} +1 -1
  15. package/dist/auth-CAQcasMV.js +723 -0
  16. package/dist/auth-CAQcasMV.js.map +1 -0
  17. package/dist/{avatar-CsnWaYmt.js → avatar-Bu2HhitA.js} +76 -71
  18. package/dist/avatar-Bu2HhitA.js.map +1 -0
  19. package/dist/{badge-BZXZT9wd.js → badge-CzId1Wlm.js} +4 -4
  20. package/dist/{badge-BZXZT9wd.js.map → badge-CzId1Wlm.js.map} +1 -1
  21. package/dist/base/accordion.js +1 -1
  22. package/dist/base/action-menu.js +1 -1
  23. package/dist/base/attachment.js +1 -1
  24. package/dist/base/avatar.js +1 -1
  25. package/dist/base/badge.js +1 -1
  26. package/dist/base/buttons.js +3 -2
  27. package/dist/base/cards.js +3 -3
  28. package/dist/base/carousel.js +25 -27
  29. package/dist/base/carousel.js.map +1 -1
  30. package/dist/base/cascader.js +150 -148
  31. package/dist/base/cascader.js.map +1 -1
  32. package/dist/base/chart.js +1 -1
  33. package/dist/base/choice-inputs.js +3 -2
  34. package/dist/base/code-block.js +1 -1
  35. package/dist/base/combobox.js +1 -1
  36. package/dist/base/command.js +1 -1
  37. package/dist/base/copyable.js +1 -1
  38. package/dist/base/date-pickers.js +3 -3
  39. package/dist/base/display.js +7 -7
  40. package/dist/base/feedback.js +4 -3
  41. package/dist/base/forms-numeric.js +1 -1
  42. package/dist/base/forms.js +2 -2
  43. package/dist/base/inline-edit.js +233 -0
  44. package/dist/base/inline-edit.js.map +1 -0
  45. package/dist/base/item.js +1 -1
  46. package/dist/base/media-gallery.js +1 -1
  47. package/dist/base/navigation.js +6 -6
  48. package/dist/base/popover-menu.js +1 -1
  49. package/dist/base/popover.js +1 -1
  50. package/dist/base/qr-code.js +1 -1
  51. package/dist/base/repeaters.js +33 -33
  52. package/dist/base/repeaters.js.map +1 -1
  53. package/dist/base/sheet.js +1 -1
  54. package/dist/base/sidebar.js +1 -1
  55. package/dist/base/signature-pad.js +83 -81
  56. package/dist/base/signature-pad.js.map +1 -1
  57. package/dist/base/skeleton.js +1 -1
  58. package/dist/base/spinner.js +1 -1
  59. package/dist/base/structure.js +1 -1
  60. package/dist/base/table.js +1 -1
  61. package/dist/base/text-inputs.js +2 -2
  62. package/dist/base/toaster.js +6 -6
  63. package/dist/base/toaster.js.map +1 -1
  64. package/dist/base/tree.js +1 -1
  65. package/dist/base/upload-queue.js +1 -1
  66. package/dist/base/upload.js +3 -3
  67. package/dist/base/value-inputs.js +1 -1
  68. package/dist/blocks/admin.js +134 -134
  69. package/dist/blocks/admin.js.map +1 -1
  70. package/dist/blocks/ai.js +120 -117
  71. package/dist/blocks/ai.js.map +1 -1
  72. package/dist/blocks/analytics/usage-card.js +3 -0
  73. package/dist/blocks/analytics.js +530 -491
  74. package/dist/blocks/analytics.js.map +1 -1
  75. package/dist/blocks/collaboration.js +2 -2
  76. package/dist/blocks/commerce/receipt.js +1 -1
  77. package/dist/blocks/commerce.js +395 -383
  78. package/dist/blocks/commerce.js.map +1 -1
  79. package/dist/blocks/data-display.js +1 -1
  80. package/dist/blocks/onboarding.js +6 -6
  81. package/dist/blocks/onboarding.js.map +1 -1
  82. package/dist/blocks/planning.js +311 -0
  83. package/dist/blocks/planning.js.map +1 -0
  84. package/dist/blocks/timelines.js +1 -1
  85. package/dist/{breadcrumbs-DdQ_I5ra.js → breadcrumbs-BuYz5SDU.js} +9 -8
  86. package/dist/breadcrumbs-BuYz5SDU.js.map +1 -0
  87. package/dist/button-BZDasD04.js +651 -0
  88. package/dist/button-BZDasD04.js.map +1 -0
  89. package/dist/{button-BS6l5JUw.js → button-BZyfTvwm.js} +3 -3
  90. package/dist/button-BZyfTvwm.js.map +1 -0
  91. package/dist/buttons-D_6KJvEE.js +99 -0
  92. package/dist/buttons-D_6KJvEE.js.map +1 -0
  93. package/dist/{cards-BMB0laLG.js → cards-qGSErLw_.js} +12 -12
  94. package/dist/{cards-BMB0laLG.js.map → cards-qGSErLw_.js.map} +1 -1
  95. package/dist/chart-Bsc5BICK.js +150 -0
  96. package/dist/chart-Bsc5BICK.js.map +1 -0
  97. package/dist/checkbox-BQNDjUCh.js +34 -0
  98. package/dist/checkbox-BQNDjUCh.js.map +1 -0
  99. package/dist/choice-inputs-Mk3iWbhr.js +725 -0
  100. package/dist/choice-inputs-Mk3iWbhr.js.map +1 -0
  101. package/dist/{code-block-DIlqzoiD.js → code-block-DzHKRybS.js} +23 -23
  102. package/dist/code-block-DzHKRybS.js.map +1 -0
  103. package/dist/{collapsible-DsnktFNv.js → collapsible-ClvC7Bj3.js} +3 -3
  104. package/dist/{collapsible-DsnktFNv.js.map → collapsible-ClvC7Bj3.js.map} +1 -1
  105. package/dist/{collection-content-C4fthJV_.js → collection-content-D6S8cv_n.js} +3 -3
  106. package/dist/{collection-content-C4fthJV_.js.map → collection-content-D6S8cv_n.js.map} +1 -1
  107. package/dist/{combobox-HDftpzxt.js → combobox-BFnbJJp3.js} +18 -18
  108. package/dist/combobox-BFnbJJp3.js.map +1 -0
  109. package/dist/{combobox-CHD750do.js → combobox-hozNwUcc.js} +313 -316
  110. package/dist/combobox-hozNwUcc.js.map +1 -0
  111. package/dist/{command-D0kWBZfd.js → command-BnmSchli.js} +9 -9
  112. package/dist/command-BnmSchli.js.map +1 -0
  113. package/dist/comments-u5L0OGip.js +1156 -0
  114. package/dist/comments-u5L0OGip.js.map +1 -0
  115. package/dist/components/base/buttons/button-group.recipes.d.ts +1 -1
  116. package/dist/components/base/buttons/button.recipes.d.ts +10 -19
  117. package/dist/components/base/buttons/use-pending-button-focus.d.ts +3 -0
  118. package/dist/components/base/cards/card.recipes.d.ts +13 -5
  119. package/dist/components/base/cards/partials/card-primitives.d.ts +9 -4
  120. package/dist/components/base/cards/smart-card.types.d.ts +3 -1
  121. package/dist/components/base/date-pickers/date-picker.recipes.d.ts +5 -18
  122. package/dist/components/base/date-pickers/datepicker.types.d.ts +3 -0
  123. package/dist/components/base/forms/form-field.d.ts +1 -0
  124. package/dist/components/base/forms/form-sizing.d.ts +3 -3
  125. package/dist/components/base/inline-edit/index.d.ts +2 -0
  126. package/dist/components/base/inline-edit/inline-edit.d.ts +81 -0
  127. package/dist/components/base/inline-edit/inline-edit.recipes.d.ts +6 -0
  128. package/dist/components/base/navigation/tabs.d.ts +3 -5
  129. package/dist/components/base/popover/popover.recipes.d.ts +3 -3
  130. package/dist/components/base/structure/structure.recipes.d.ts +6 -0
  131. package/dist/components/base/table/index.d.ts +1 -1
  132. package/dist/components/base/text-inputs/clear-native-field.d.ts +2 -0
  133. package/dist/components/base/text-inputs/input-trailing-action.d.ts +3 -0
  134. package/dist/components/blocks/analytics/index.d.ts +1 -0
  135. package/dist/components/blocks/analytics/types.d.ts +1 -1
  136. package/dist/components/blocks/analytics/usage-card/index.d.ts +3 -0
  137. package/dist/components/blocks/analytics/usage-card/types.d.ts +52 -0
  138. package/dist/components/blocks/analytics/usage-card/usage-card.d.ts +6 -0
  139. package/dist/components/blocks/analytics/usage-card/usage-card.data.d.ts +19 -0
  140. package/dist/components/blocks/analytics/usage-card/usage-card.strings.d.ts +22 -0
  141. package/dist/components/blocks/collaboration/message/message.recipes.d.ts +12 -0
  142. package/dist/components/blocks/data-display/empty-state/partials/illustrations/document-stack.d.ts +1 -4
  143. package/dist/components/blocks/data-display/empty-state/partials/illustrations/inbox-clean.d.ts +1 -4
  144. package/dist/components/blocks/data-display/empty-state/partials/illustrations/index.d.ts +3 -3
  145. package/dist/components/blocks/data-display/empty-state/partials/illustrations/stacked-cards.d.ts +1 -6
  146. package/dist/components/blocks/planning/index.d.ts +3 -0
  147. package/dist/components/blocks/planning/task-card.d.ts +3 -0
  148. package/dist/components/blocks/planning/task-card.strings.d.ts +15 -0
  149. package/dist/components/blocks/planning/task-card.types.d.ts +66 -0
  150. package/dist/components/features/combobox/components/error-message.d.ts +1 -1
  151. package/dist/components/features/comments/hooks/use-attachment-upload.d.ts +5 -0
  152. package/dist/components/features/filters/facets/search-facet.d.ts +0 -12
  153. package/dist/components/features/filters/facets/tags-facet.d.ts +1 -1
  154. package/dist/components/features/media-library/media-library.d.ts +1 -1
  155. package/dist/components/features/media-library/media-library.types.d.ts +9 -1
  156. package/dist/components/features/media-library/partials/media-library-partials.d.ts +1 -1
  157. package/dist/components/features/overlays/hooks/use-pending-overlay-focus.d.ts +2 -0
  158. package/dist/components/features/overlays/overlays.types.d.ts +5 -4
  159. package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +2 -1
  160. package/dist/components/features/table/data-table.d.ts +1 -1
  161. package/dist/components/features/table/table.types.d.ts +1 -1
  162. package/dist/components/features/theme-tweaker/theme-provider-settings.d.ts +3 -1
  163. package/dist/components/layout/auth/auth.types.d.ts +1 -0
  164. package/dist/components/layout/page/page.d.ts +0 -1
  165. package/dist/components/layout/page/page.types.d.ts +9 -3
  166. package/dist/components/layout/sidebar/sidebar.context.d.ts +1 -1
  167. package/dist/components/layout/sidebar/sidebar.types.d.ts +4 -0
  168. package/dist/components/layout/workspace/workspace.types.d.ts +3 -0
  169. package/dist/components/typography/heading.d.ts +5 -2
  170. package/dist/components/typography/index.d.ts +1 -1
  171. package/dist/components/typography/text.styles.d.ts +10 -0
  172. package/dist/components/ui/popover.d.ts +1 -1
  173. package/dist/components/ui/sidebar.d.ts +1 -1
  174. package/dist/components/ui/table.d.ts +2 -1
  175. package/dist/container.recipes-D9t8MHR3.js +27 -0
  176. package/dist/container.recipes-D9t8MHR3.js.map +1 -0
  177. package/dist/{containers-CPNyNo1_.js → containers-DqB-bSYE.js} +34 -56
  178. package/dist/containers-DqB-bSYE.js.map +1 -0
  179. package/dist/control-group-recipes-DBXmfh2E.js +21 -0
  180. package/dist/control-group-recipes-DBXmfh2E.js.map +1 -0
  181. package/dist/{copyable-B7SBXJMr.js → copyable-BTSByfmq.js} +6 -6
  182. package/dist/{copyable-B7SBXJMr.js.map → copyable-BTSByfmq.js.map} +1 -1
  183. package/dist/{data-display-b3d1TfL4.js → data-display-Bihs9Ven.js} +542 -329
  184. package/dist/data-display-Bihs9Ven.js.map +1 -0
  185. package/dist/{date-BFNMnrS5.js → date-DOKhJPu7.js} +4 -4
  186. package/dist/{date-BFNMnrS5.js.map → date-DOKhJPu7.js.map} +1 -1
  187. package/dist/{date-picker-DI6kPNof.js → date-picker-DzP5HQq7.js} +492 -472
  188. package/dist/date-picker-DzP5HQq7.js.map +1 -0
  189. package/dist/date-pickers-BpgGz7S-.js +196 -0
  190. package/dist/date-pickers-BpgGz7S-.js.map +1 -0
  191. package/dist/{display-ByI5tkqy.js → display-CS6Hbk18.js} +8 -8
  192. package/dist/{display-ByI5tkqy.js.map → display-CS6Hbk18.js.map} +1 -1
  193. package/dist/{dropdown-menu-BlnyHr-9.js → dropdown-menu-D-boNgGO.js} +7 -7
  194. package/dist/{dropdown-menu-BlnyHr-9.js.map → dropdown-menu-D-boNgGO.js.map} +1 -1
  195. package/dist/features/activities.js +152 -141
  196. package/dist/features/activities.js.map +1 -1
  197. package/dist/features/ai-chat.js +182 -179
  198. package/dist/features/ai-chat.js.map +1 -1
  199. package/dist/features/async-preview.js +9 -9
  200. package/dist/features/async-preview.js.map +1 -1
  201. package/dist/features/combobox.js +1 -1
  202. package/dist/features/comments.js +1 -1
  203. package/dist/features/data-view.js +25 -23
  204. package/dist/features/data-view.js.map +1 -1
  205. package/dist/features/email-composer/engine.js +1 -1
  206. package/dist/features/email-composer.js +103 -104
  207. package/dist/features/email-composer.js.map +1 -1
  208. package/dist/features/event-calendar.js +375 -373
  209. package/dist/features/event-calendar.js.map +1 -1
  210. package/dist/features/filters.js +1 -1
  211. package/dist/features/global-search.js +222 -224
  212. package/dist/features/global-search.js.map +1 -1
  213. package/dist/features/kanban.js +29 -29
  214. package/dist/features/kanban.js.map +1 -1
  215. package/dist/features/map.js +59 -58
  216. package/dist/features/map.js.map +1 -1
  217. package/dist/features/media-library.js +856 -855
  218. package/dist/features/media-library.js.map +1 -1
  219. package/dist/features/mentions.js +1 -1
  220. package/dist/features/overlays.js +1 -1
  221. package/dist/features/products.js +1210 -1209
  222. package/dist/features/products.js.map +1 -1
  223. package/dist/features/questionnaire.js +133 -132
  224. package/dist/features/questionnaire.js.map +1 -1
  225. package/dist/features/resource-assignment.js +29 -31
  226. package/dist/features/resource-assignment.js.map +1 -1
  227. package/dist/features/resource.js +13 -13
  228. package/dist/features/resource.js.map +1 -1
  229. package/dist/features/rich-text-editor.js +2 -2
  230. package/dist/features/schema-form.js +82 -82
  231. package/dist/features/schema-form.js.map +1 -1
  232. package/dist/features/suggestions.js +3 -3
  233. package/dist/features/sync.js +4 -4
  234. package/dist/features/sync.js.map +1 -1
  235. package/dist/features/table.js +1 -1
  236. package/dist/features/theme-tweaker.js +456 -450
  237. package/dist/features/theme-tweaker.js.map +1 -1
  238. package/dist/feedback-CJkUAapr.js +233 -0
  239. package/dist/feedback-CJkUAapr.js.map +1 -0
  240. package/dist/field-affordance-recipes-uKY4MsZ_.js +25 -0
  241. package/dist/field-affordance-recipes-uKY4MsZ_.js.map +1 -0
  242. package/dist/{field-state-recipes-CBTRt9Bt.js → field-state-recipes-DQQpiLWC.js} +3 -3
  243. package/dist/field-state-recipes-DQQpiLWC.js.map +1 -0
  244. package/dist/{filters-qtrcv1hf.js → filters-D6FF8L6s.js} +715 -720
  245. package/dist/filters-D6FF8L6s.js.map +1 -0
  246. package/dist/{form-field-C6W-y2hR.js → form-field-CZwrkP7m.js} +17 -9
  247. package/dist/form-field-CZwrkP7m.js.map +1 -0
  248. package/dist/{form-sizing-39NohSqn.js → form-sizing-QP8aIRaW.js} +10 -6
  249. package/dist/form-sizing-QP8aIRaW.js.map +1 -0
  250. package/dist/{forms-BF-HSbff.js → forms-B5NCbkSC.js} +35 -35
  251. package/dist/{forms-BF-HSbff.js.map → forms-B5NCbkSC.js.map} +1 -1
  252. package/dist/forms-numeric-Crrm80Lm.js +867 -0
  253. package/dist/forms-numeric-Crrm80Lm.js.map +1 -0
  254. package/dist/{header-B8ex54cY.js → header-kxruN3RM.js} +53 -49
  255. package/dist/header-kxruN3RM.js.map +1 -0
  256. package/dist/{hooks-D6UBVzf2.js → hooks-BrlnCwQd.js} +2 -2
  257. package/dist/{hooks-D6UBVzf2.js.map → hooks-BrlnCwQd.js.map} +1 -1
  258. package/dist/{http-CLTVJc5I.js → http-CdEIHyQf.js} +2 -2
  259. package/dist/http-CdEIHyQf.js.map +1 -0
  260. package/dist/{icon-badge-Dv0RYQwj.js → icon-badge-Btc6pQrp.js} +4 -4
  261. package/dist/{icon-badge-Dv0RYQwj.js.map → icon-badge-Btc6pQrp.js.map} +1 -1
  262. package/dist/index.js +2 -2
  263. package/dist/input-SX9V0AL3.js +255 -0
  264. package/dist/input-SX9V0AL3.js.map +1 -0
  265. package/dist/input-vxcaNCYC.js +20 -0
  266. package/dist/input-vxcaNCYC.js.map +1 -0
  267. package/dist/{item-pJ0GsOiJ.js → item-DE4YnuJx.js} +18 -17
  268. package/dist/item-DE4YnuJx.js.map +1 -0
  269. package/dist/layout/app-shell.js +1 -1
  270. package/dist/layout/auth.js +1 -1
  271. package/dist/layout/containers.js +1 -1
  272. package/dist/layout/header.js +1 -1
  273. package/dist/layout/hooks.js +1 -1
  274. package/dist/layout/navigation.js +1 -1
  275. package/dist/layout/page.js +1 -1
  276. package/dist/layout/settings.js +1 -1
  277. package/dist/layout/sidebar.js +2 -2
  278. package/dist/layout/workspace.js +1 -1
  279. package/dist/layout.js +10 -10
  280. package/dist/lib/affordance-geometry.generated.d.ts +44 -4
  281. package/dist/lib/control-group-recipes.d.ts +22 -0
  282. package/dist/lib/field-affordance-recipes.d.ts +35 -2
  283. package/dist/lib/field-state-recipes.d.ts +2 -2
  284. package/dist/lib/navigation-row-recipes.d.ts +3 -2
  285. package/dist/lib/overlay-anatomy-recipes.d.ts +1 -1
  286. package/dist/lib/surface-recipes.d.ts +5 -2
  287. package/dist/lib/token-merge.generated.d.ts +144 -2
  288. package/dist/lib/ui-provider/types.d.ts +4 -2
  289. package/dist/lib/use-prefers-reduced-motion.d.ts +2 -0
  290. package/dist/lib/utils.js +1 -1
  291. package/dist/{media-gallery-Ca4YmvBi.js → media-gallery-DLp3HAz0.js} +75 -74
  292. package/dist/media-gallery-DLp3HAz0.js.map +1 -0
  293. package/dist/{mentions-CRio8mTm.js → mentions-Cl0Kt_Pd.js} +52 -50
  294. package/dist/{mentions-CRio8mTm.js.map → mentions-Cl0Kt_Pd.js.map} +1 -1
  295. package/dist/message-SZUNB1eX.js +127 -0
  296. package/dist/message-SZUNB1eX.js.map +1 -0
  297. package/dist/{navigation-BTrEb5u4.js → navigation-DnQSNMT0.js} +64 -55
  298. package/dist/navigation-DnQSNMT0.js.map +1 -0
  299. package/dist/{navigation-DqEITuD2.js → navigation-DyytsLRB.js} +37 -37
  300. package/dist/navigation-DyytsLRB.js.map +1 -0
  301. package/dist/{navigation-row-recipes-BFpvGPGE.js → navigation-row-recipes-DQEXQcqY.js} +3 -3
  302. package/dist/navigation-row-recipes-DQEXQcqY.js.map +1 -0
  303. package/dist/{number-BNT_BIzJ.js → number-DasMFWEG.js} +4 -4
  304. package/dist/{number-BNT_BIzJ.js.map → number-DasMFWEG.js.map} +1 -1
  305. package/dist/overlays-DUbs1KEi.js +1011 -0
  306. package/dist/overlays-DUbs1KEi.js.map +1 -0
  307. package/dist/{page-BMBGjJY8.js → page-hGmT4nWK.js} +75 -64
  308. package/dist/page-hGmT4nWK.js.map +1 -0
  309. package/dist/{page-header-BH41wCyY.js → page-header-D8nERkn5.js} +9 -9
  310. package/dist/page-header-D8nERkn5.js.map +1 -0
  311. package/dist/{pagination-C29vvt3I.js → pagination-NLGqRirf.js} +20 -20
  312. package/dist/pagination-NLGqRirf.js.map +1 -0
  313. package/dist/{popover-TInGXsjg.js → popover-CghIYdQf.js} +23 -22
  314. package/dist/popover-CghIYdQf.js.map +1 -0
  315. package/dist/{popover-menu-BzqXqE72.js → popover-menu-B4PoWhRl.js} +6 -6
  316. package/dist/{popover-menu-BzqXqE72.js.map → popover-menu-B4PoWhRl.js.map} +1 -1
  317. package/dist/{popover.recipes-zgBhMlUu.js → popover.recipes-QlD4JenO.js} +5 -5
  318. package/dist/popover.recipes-QlD4JenO.js.map +1 -0
  319. package/dist/{primitives-DKPOGVpj.js → primitives-C7ff0QaI.js} +120 -113
  320. package/dist/primitives-C7ff0QaI.js.map +1 -0
  321. package/dist/primitives.js +3 -3
  322. package/dist/progress-BroqrAyV.js +169 -0
  323. package/dist/progress-BroqrAyV.js.map +1 -0
  324. package/dist/{receipt-DYWTQGEc.js → receipt-BuJynLgf.js} +8 -8
  325. package/dist/{receipt-DYWTQGEc.js.map → receipt-BuJynLgf.js.map} +1 -1
  326. package/dist/{rich-text-B7sBAdDG.js → rich-text-DlxDOtf4.js} +4 -4
  327. package/dist/{rich-text-B7sBAdDG.js.map → rich-text-DlxDOtf4.js.map} +1 -1
  328. package/dist/rich-text-editor-BKyG7rWz.js +574 -0
  329. package/dist/rich-text-editor-BKyG7rWz.js.map +1 -0
  330. package/dist/{rich-text-editor.recipes-DxvOE0Lp.js → rich-text-editor.recipes-B72Nfuze.js} +35 -26
  331. package/dist/rich-text-editor.recipes-B72Nfuze.js.map +1 -0
  332. package/dist/{scroll-area-BheMQ270.js → scroll-area-D-pIhEKl.js} +3 -3
  333. package/dist/scroll-area-D-pIhEKl.js.map +1 -0
  334. package/dist/{separator-Gk_WXH-l.js → separator-BNIgG3au.js} +3 -3
  335. package/dist/{separator-Gk_WXH-l.js.map → separator-BNIgG3au.js.map} +1 -1
  336. package/dist/{separator-DO0EbCEm.js → separator-BhtFyo4x.js} +2 -2
  337. package/dist/{separator-DO0EbCEm.js.map → separator-BhtFyo4x.js.map} +1 -1
  338. package/dist/services/actions.js +1 -1
  339. package/dist/{settings-D9f_wdIC.js → settings-DOTOzeZ2.js} +10 -9
  340. package/dist/{settings-D9f_wdIC.js.map → settings-DOTOzeZ2.js.map} +1 -1
  341. package/dist/{sheet-vOUloJ4O.js → sheet-BFhrNehm.js} +11 -11
  342. package/dist/sheet-BFhrNehm.js.map +1 -0
  343. package/dist/{sidebar-CNBKFDRW.js → sidebar-CyR4XKwR.js} +219 -200
  344. package/dist/sidebar-CyR4XKwR.js.map +1 -0
  345. package/dist/{sidebar-C3UKkbC5.js → sidebar-SvGJ0Zwi.js} +63 -58
  346. package/dist/sidebar-SvGJ0Zwi.js.map +1 -0
  347. package/dist/{skeleton-BvRhK8y-.js → skeleton-3F0uhYn3.js} +4 -4
  348. package/dist/{skeleton-BvRhK8y-.js.map → skeleton-3F0uhYn3.js.map} +1 -1
  349. package/dist/{smart-card-B5FcKODh.js → smart-card-DjGVV2xr.js} +206 -199
  350. package/dist/smart-card-DjGVV2xr.js.map +1 -0
  351. package/dist/{spinner-JtlFJ7Nc.js → spinner-Cpf7oRkF.js} +5 -5
  352. package/dist/{spinner-JtlFJ7Nc.js.map → spinner-Cpf7oRkF.js.map} +1 -1
  353. package/dist/{structure-BvW4vG4H.js → structure-CRdqVawd.js} +14 -14
  354. package/dist/{structure-BvW4vG4H.js.map → structure-CRdqVawd.js.map} +1 -1
  355. package/dist/{structure.recipes-DjqnBpwz.js → structure.recipes-Bqhf9oIh.js} +2 -2
  356. package/dist/structure.recipes-Bqhf9oIh.js.map +1 -0
  357. package/dist/style.css +1 -1
  358. package/dist/{surface-recipes-CQfRr-VL.js → surface-recipes-Dd__PD-w.js} +4 -3
  359. package/dist/surface-recipes-Dd__PD-w.js.map +1 -0
  360. package/dist/{table-DnlAJ-xR.js → table-CLtJTxoR.js} +17 -16
  361. package/dist/table-CLtJTxoR.js.map +1 -0
  362. package/dist/table-CcRDZiLP.js +1444 -0
  363. package/dist/table-CcRDZiLP.js.map +1 -0
  364. package/dist/tabs-BNgu7g0u.js +188 -0
  365. package/dist/tabs-BNgu7g0u.js.map +1 -0
  366. package/dist/text-inputs-DsR56TR-.js +330 -0
  367. package/dist/text-inputs-DsR56TR-.js.map +1 -0
  368. package/dist/{text.styles-BwB7vAF2.js → text.styles-Q4sGAIgA.js} +18 -10
  369. package/dist/text.styles-Q4sGAIgA.js.map +1 -0
  370. package/dist/theme.css +77 -115
  371. package/dist/{timelines-CnZ2S_Gr.js → timelines-D1pkt3se.js} +84 -78
  372. package/dist/timelines-D1pkt3se.js.map +1 -0
  373. package/dist/{tree-COD9BGdU.js → tree-BtmYyMZV.js} +8 -8
  374. package/dist/{tree-COD9BGdU.js.map → tree-BtmYyMZV.js.map} +1 -1
  375. package/dist/typography/rich-text.js +1 -1
  376. package/dist/typography-BxQgiZyw.js +96 -0
  377. package/dist/typography-BxQgiZyw.js.map +1 -0
  378. package/dist/typography.js +1 -1
  379. package/dist/{ui-provider-CftIB6TY.js → ui-provider-DRPn3qNl.js} +3 -2
  380. package/dist/ui-provider-DRPn3qNl.js.map +1 -0
  381. package/dist/ui-provider.js +1 -1
  382. package/dist/{upload-DIzw1dx1.js → upload-CDbYw1WN.js} +326 -323
  383. package/dist/upload-CDbYw1WN.js.map +1 -0
  384. package/dist/{upload-queue-xRJ3qDmd.js → upload-queue-CNd_hH_a.js} +25 -25
  385. package/dist/upload-queue-CNd_hH_a.js.map +1 -0
  386. package/dist/usage-card-VyJLUwRr.js +457 -0
  387. package/dist/usage-card-VyJLUwRr.js.map +1 -0
  388. package/dist/utils-BvH9PSmq.js +4275 -0
  389. package/dist/utils-BvH9PSmq.js.map +1 -0
  390. package/dist/value-inputs-D0KCrfVC.js +840 -0
  391. package/dist/value-inputs-D0KCrfVC.js.map +1 -0
  392. package/dist/{workspace-Cbqz4FzN.js → workspace-CcR8r-Nt.js} +115 -122
  393. package/dist/workspace-CcR8r-Nt.js.map +1 -0
  394. package/docs/consumer-skill/SKILL.md +112 -18
  395. package/docs/consumer-skill/examples/analytics.tsx +34 -0
  396. package/docs/consumer-skill/examples/app-layout.tsx +42 -12
  397. package/docs/consumer-skill/examples/detail.tsx +24 -9
  398. package/docs/consumer-skill/examples/manifest.json +27 -1
  399. package/docs/consumer-skill/examples/planning-usage-edit.tsx +29 -0
  400. package/docs/consumer-skill/examples/scoped-directory.tsx +77 -0
  401. package/docs/consumer-skill/examples/website.tsx +56 -0
  402. package/docs/consumer-skill/references/analytics.md +70 -0
  403. package/docs/consumer-skill/references/composition.md +219 -2
  404. package/docs/consumer-skill/references/design-contract.md +37 -10
  405. package/docs/consumer-skill/references/discovery.md +93 -5
  406. package/docs/consumer-skill/references/installation.md +20 -3
  407. package/docs/consumer-skill/references/integration.md +26 -0
  408. package/docs/consumer-skill/references/public-api.json +2416 -388
  409. package/docs/consumer-skill/references/review.md +126 -0
  410. package/docs/consumer-skill/references/theming.md +52 -7
  411. package/docs/consumer-skill/references/tokens.json +177 -9
  412. package/docs/consumer-skill/references/workflows.md +129 -1
  413. package/docs/consumer-skill/scripts/check-composition.mjs +31 -0
  414. package/docs/consumer-skill/scripts/composition-policy.mjs +317 -0
  415. package/docs/consumer-skill/scripts/discovery.mjs +65 -8
  416. package/docs/consumer-skill/scripts/surface-policy.mjs +66 -0
  417. package/package.json +30 -6
  418. package/dist/accordion-BRWh3BM1.js.map +0 -1
  419. package/dist/action-menu-Cx3SdfbN.js.map +0 -1
  420. package/dist/affordance-geometry.generated-DXl-Zb3Z.js +0 -23
  421. package/dist/affordance-geometry.generated-DXl-Zb3Z.js.map +0 -1
  422. package/dist/ai-artifact-DkOArd3-.js.map +0 -1
  423. package/dist/app-shell-BH_bGcE2.js.map +0 -1
  424. package/dist/auth-BDB1V_2q.js +0 -704
  425. package/dist/auth-BDB1V_2q.js.map +0 -1
  426. package/dist/avatar-CsnWaYmt.js.map +0 -1
  427. package/dist/breadcrumbs-DdQ_I5ra.js.map +0 -1
  428. package/dist/button-BS6l5JUw.js.map +0 -1
  429. package/dist/buttons-Co6GavvM.js +0 -674
  430. package/dist/buttons-Co6GavvM.js.map +0 -1
  431. package/dist/chart-DVfcwQu6.js +0 -149
  432. package/dist/chart-DVfcwQu6.js.map +0 -1
  433. package/dist/choice-inputs-CavA-SGV.js +0 -644
  434. package/dist/choice-inputs-CavA-SGV.js.map +0 -1
  435. package/dist/code-block-DIlqzoiD.js.map +0 -1
  436. package/dist/combobox-CHD750do.js.map +0 -1
  437. package/dist/combobox-HDftpzxt.js.map +0 -1
  438. package/dist/command-D0kWBZfd.js.map +0 -1
  439. package/dist/comments-CvYeglMS.js +0 -1132
  440. package/dist/comments-CvYeglMS.js.map +0 -1
  441. package/dist/containers-CPNyNo1_.js.map +0 -1
  442. package/dist/data-display-b3d1TfL4.js.map +0 -1
  443. package/dist/date-picker-DI6kPNof.js.map +0 -1
  444. package/dist/date-pickers-ByP6Cv2z.js +0 -224
  445. package/dist/date-pickers-ByP6Cv2z.js.map +0 -1
  446. package/dist/feedback-a9j9J-9A.js +0 -391
  447. package/dist/feedback-a9j9J-9A.js.map +0 -1
  448. package/dist/field-affordance-recipes-CHdUtn2Z.js +0 -17
  449. package/dist/field-affordance-recipes-CHdUtn2Z.js.map +0 -1
  450. package/dist/field-state-recipes-CBTRt9Bt.js.map +0 -1
  451. package/dist/filters-qtrcv1hf.js.map +0 -1
  452. package/dist/form-field-C6W-y2hR.js.map +0 -1
  453. package/dist/form-sizing-39NohSqn.js.map +0 -1
  454. package/dist/forms-numeric-Y15Bg5Nr.js +0 -867
  455. package/dist/forms-numeric-Y15Bg5Nr.js.map +0 -1
  456. package/dist/header-B8ex54cY.js.map +0 -1
  457. package/dist/http-CLTVJc5I.js.map +0 -1
  458. package/dist/input-DMorJiTI.js +0 -202
  459. package/dist/input-DMorJiTI.js.map +0 -1
  460. package/dist/input-ci9fIgFH.js +0 -20
  461. package/dist/input-ci9fIgFH.js.map +0 -1
  462. package/dist/item-pJ0GsOiJ.js.map +0 -1
  463. package/dist/media-gallery-Ca4YmvBi.js.map +0 -1
  464. package/dist/message-B5-6LeYl.js +0 -108
  465. package/dist/message-B5-6LeYl.js.map +0 -1
  466. package/dist/navigation-BTrEb5u4.js.map +0 -1
  467. package/dist/navigation-DqEITuD2.js.map +0 -1
  468. package/dist/navigation-row-recipes-BFpvGPGE.js.map +0 -1
  469. package/dist/overlays-DBqV0J_V.js +0 -982
  470. package/dist/overlays-DBqV0J_V.js.map +0 -1
  471. package/dist/page-BMBGjJY8.js.map +0 -1
  472. package/dist/page-header-BH41wCyY.js.map +0 -1
  473. package/dist/pagination-C29vvt3I.js.map +0 -1
  474. package/dist/popover-TInGXsjg.js.map +0 -1
  475. package/dist/popover.recipes-zgBhMlUu.js.map +0 -1
  476. package/dist/primitives-DKPOGVpj.js.map +0 -1
  477. package/dist/rich-text-editor-BZSJchAF.js +0 -575
  478. package/dist/rich-text-editor-BZSJchAF.js.map +0 -1
  479. package/dist/rich-text-editor.recipes-DxvOE0Lp.js.map +0 -1
  480. package/dist/scroll-area-BheMQ270.js.map +0 -1
  481. package/dist/select-B2mb-qN2.js +0 -108
  482. package/dist/select-B2mb-qN2.js.map +0 -1
  483. package/dist/sheet-vOUloJ4O.js.map +0 -1
  484. package/dist/sidebar-C3UKkbC5.js.map +0 -1
  485. package/dist/sidebar-CNBKFDRW.js.map +0 -1
  486. package/dist/smart-card-B5FcKODh.js.map +0 -1
  487. package/dist/structure.recipes-DjqnBpwz.js.map +0 -1
  488. package/dist/surface-recipes-CQfRr-VL.js.map +0 -1
  489. package/dist/table-DnlAJ-xR.js.map +0 -1
  490. package/dist/table-ghtAQ-JJ.js +0 -1424
  491. package/dist/table-ghtAQ-JJ.js.map +0 -1
  492. package/dist/tabs-DY09eoZg.js +0 -187
  493. package/dist/tabs-DY09eoZg.js.map +0 -1
  494. package/dist/text-inputs-BhOcedTo.js +0 -331
  495. package/dist/text-inputs-BhOcedTo.js.map +0 -1
  496. package/dist/text.styles-BwB7vAF2.js.map +0 -1
  497. package/dist/timelines-CnZ2S_Gr.js.map +0 -1
  498. package/dist/typography-Cv8MT-82.js +0 -96
  499. package/dist/typography-Cv8MT-82.js.map +0 -1
  500. package/dist/ui-provider-CftIB6TY.js.map +0 -1
  501. package/dist/upload-DIzw1dx1.js.map +0 -1
  502. package/dist/upload-queue-xRJ3qDmd.js.map +0 -1
  503. package/dist/utils-C2EKeIw3.js +0 -72
  504. package/dist/utils-C2EKeIw3.js.map +0 -1
  505. package/dist/value-inputs-Co1fu-xv.js +0 -824
  506. package/dist/value-inputs-Co1fu-xv.js.map +0 -1
  507. package/dist/workspace-Cbqz4FzN.js.map +0 -1
@@ -0,0 +1,317 @@
1
+ import { surfaceParts, surfaceForwarders, paddingClass, paddingProperty, utility, attenuatedFocusRing, sharedCornerParts, displayNames, nativeDisplayNames, marginProperty, radiusProperty, replacesSharedRadius, cornerRole, addsCopyMargin } from './surface-policy.mjs';
2
+
3
+ const controlNames = /^(?:Base)?(?:Button|ButtonLink|IconButton)$|^(Input|InputGroup|InputGroupInput|InputGroupTextarea|Textarea|PasswordInput|Select|SelectTrigger|ComboboxInput|ComboboxInputTrigger|ComboboxTrigger)$/;
4
+ const controlFamilies = new Set(['buttons', 'text-inputs', 'choice-inputs', 'combobox']);
5
+ const fixedControlClass = /^(?:h|min-h|size|p[xytrblse]?)-|^rounded-(?:xs|sm|md|lg|xl|[2-9]xl|\[)|^text-(?:xs|sm|base|lg|xl|[2-9]xl|\[(?:length:|[\d.]+(?:px|rem|em)))|^(?:font|leading|tracking)-/;
6
+ const controlStyle = /^(height|minHeight|fontSize|fontWeight|fontFamily|lineHeight|letterSpacing|borderRadius)$/;
7
+ const fixedTextClass = /^text-(?:xs|sm|base|lg|xl|[2-9]xl|\[(?:length:|[\d.]+(?:px|rem|em)))|^(?:font|leading|tracking)-/;
8
+ const textStyle = /^(fontSize|fontWeight|fontFamily|lineHeight|letterSpacing)$/;
9
+ const smallPeerGaps = new Set(['none', 'normal', 'dense', '2xs', 'xs', 'sm', 'md']);
10
+ const structureDefaults = { Stack: 'md', Grid: 'xl', AdaptiveGrid: 'xl' };
11
+ const breakpoints = ['base', 'sm', 'md', 'lg', 'xl', '2xl'];
12
+
13
+ /** Bind this source only; never resolve imports, read libraries or run app code. */
14
+ export function sourceBindings(source, ts) {
15
+ const options = { noResolve: true, noLib: true, allowJs: true, jsx: ts.JsxEmit.Preserve };
16
+ const host = ts.createCompilerHost(options);
17
+ host.getSourceFile = filename => filename === source.fileName ? source : undefined;
18
+ const checker = ts.createProgram([source.fileName], options, host).getTypeChecker();
19
+ return node => {
20
+ if (!node) return undefined;
21
+ if (ts.isIdentifier(node) && ts.isShorthandPropertyAssignment(node.parent) && node.parent.name === node) return checker.getShorthandAssignmentValueSymbol(node.parent);
22
+ return checker.getSymbolAtLocation(node);
23
+ };
24
+ }
25
+
26
+ /** Small static review: TypeScript is supplied by the app, never a runtime peer. */
27
+ export function analyzeComposition(text, { filename, index, ts }) {
28
+ const kind = /\.jsx?$/.test(filename) ? ts.ScriptKind.JSX : filename.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
29
+ const source = ts.createSourceFile(filename, text, ts.ScriptTarget.Latest, true, kind);
30
+ const symbolFor = sourceBindings(source, ts);
31
+ const families = new Map(index.families.map(owner => [owner.import, owner]));
32
+ const bindings = new Map();
33
+ const namespaces = new Map();
34
+ const declarations = new Map();
35
+ const findings = [];
36
+ const unresolved = [];
37
+ const seen = new Set();
38
+ const add = (node, rule, severity, message) => {
39
+ const position = source.getLineAndCharacterOfPosition(node.getStart(source));
40
+ const key = `${node.pos}:${rule}`;
41
+ if (seen.has(key)) return;
42
+ seen.add(key);
43
+ findings.push({ file: filename, line: position.line + 1, column: position.character + 1, rule, severity, message });
44
+ };
45
+ const unknown = node => {
46
+ const key = `${node.pos}:unresolved`;
47
+ if (seen.has(key)) return;
48
+ seen.add(key);
49
+ const position = source.getLineAndCharacterOfPosition(node.getStart(source));
50
+ unresolved.push({ file: filename, line: position.line + 1, expression: node.getText(source).slice(0, 120) });
51
+ };
52
+ const resolve = (node, visiting = new Set()) => {
53
+ if (!node || visiting.has(node)) return undefined;
54
+ visiting.add(node);
55
+ if (ts.isIdentifier(node)) return resolve(declarations.get(symbolFor(node)), visiting);
56
+ if (ts.isParenthesizedExpression(node) || ts.isAsExpression(node) || ts.isSatisfiesExpression(node)) return resolve(node.expression, visiting);
57
+ return node;
58
+ };
59
+ const properties = (expression, mark = true, visited = new Set()) => {
60
+ const node = resolve(expression);
61
+ if (!node || !ts.isObjectLiteralExpression(node) || visited.has(node)) {
62
+ if (mark && expression) unknown(expression);
63
+ return [];
64
+ }
65
+ visited.add(node);
66
+ return node.properties.flatMap(property => {
67
+ if (ts.isSpreadAssignment(property)) return properties(property.expression, mark, visited);
68
+ const name = property.name;
69
+ const key = ts.isComputedPropertyName(name) ? resolve(name.expression) : name;
70
+ if (!key || !(ts.isIdentifier(key) || ts.isStringLiteralLike(key))) {
71
+ if (mark) unknown(property);
72
+ return [];
73
+ }
74
+ return [[key.text, ts.isShorthandPropertyAssignment(property) ? property.name : property.initializer]];
75
+ });
76
+ };
77
+ const classStrings = (expression, visited = new Set()) => {
78
+ const node = resolve(expression);
79
+ if (!node || visited.has(node)) { if (expression) unknown(expression); return []; }
80
+ visited.add(node);
81
+ if (ts.isStringLiteralLike(node)) return [node.text];
82
+ if (ts.isTemplateExpression(node)) {
83
+ // Keep complete static class tokens. A token split by a dynamic span is
84
+ // unresolved rather than an invented class from one of its fragments.
85
+ const chunks = [node.head.text];
86
+ for (const span of node.templateSpans) {
87
+ const resolved = resolve(span.expression);
88
+ if (resolved && (ts.isStringLiteralLike(resolved) || ts.isNumericLiteral(resolved))) chunks[chunks.length - 1] += resolved.text + span.literal.text;
89
+ else { unknown(span.expression); chunks.push(span.literal.text); }
90
+ }
91
+ return chunks.map((chunk, index) => {
92
+ const value = index > 0 ? chunk.replace(/^\S*/, '') : chunk;
93
+ return index < chunks.length - 1 ? value.replace(/\S*$/, '') : value;
94
+ });
95
+ }
96
+ if (ts.isConditionalExpression(node)) return [...classStrings(node.whenTrue, visited), ...classStrings(node.whenFalse, visited)];
97
+ if (ts.isBinaryExpression(node) && [ts.SyntaxKind.AmpersandAmpersandToken, ts.SyntaxKind.BarBarToken, ts.SyntaxKind.QuestionQuestionToken].includes(node.operatorToken.kind)) return classStrings(node.right, visited);
98
+ if (ts.isArrayLiteralExpression(node)) return node.elements.flatMap(item => classStrings(item, visited));
99
+ if (ts.isCallExpression(node) && /^(cn|clsx|classNames|twMerge)$/.test(node.expression.getText(source))) return node.arguments.flatMap(item => classStrings(item, visited));
100
+ if ([ts.SyntaxKind.FalseKeyword, ts.SyntaxKind.TrueKeyword, ts.SyntaxKind.NullKeyword].includes(node.kind)) return [];
101
+ unknown(expression);
102
+ return [];
103
+ };
104
+ const literal = expression => {
105
+ const node = resolve(expression);
106
+ return node && ts.isStringLiteralLike(node) ? node.text : undefined;
107
+ };
108
+ function importOwner(node, specifier) {
109
+ if (specifier !== index.package && !specifier.startsWith(index.package + '/')) return;
110
+ if (index.stylesheets?.includes(specifier)) return;
111
+ const family = families.get(specifier);
112
+ if (!family) { add(node, 'public-import', 'error', `No published owner for ${specifier}; discover the version-matched public entrypoint.`); return; }
113
+ const names = ts.isImportDeclaration(node) ? node.importClause?.namedBindings : node.exportClause;
114
+ if (ts.isImportDeclaration(node) && node.importClause?.name && !family.symbols.includes('default')) add(node.importClause.name, 'public-symbol', 'error', `${specifier} has no default export; use its named public symbols.`);
115
+ const elements = names && (ts.isNamedImports(names) || ts.isNamedExports(names)) ? names.elements : [];
116
+ for (const item of elements) {
117
+ const symbol = (item.propertyName ?? item.name).text;
118
+ if (!family.symbols.includes(symbol)) add(item, 'public-symbol', 'error', `${specifier} does not export ${symbol}; inspect its declaration.`);
119
+ if (ts.isImportDeclaration(node)) bindings.set(symbolFor(item.name), { symbol, import: specifier });
120
+ }
121
+ if (names && ts.isNamespaceImport(names)) namespaces.set(symbolFor(names.name), specifier);
122
+ }
123
+ function gather(node) {
124
+ if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) declarations.set(symbolFor(node.name), node.initializer);
125
+ if ((ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) && node.moduleSpecifier && ts.isStringLiteralLike(node.moduleSpecifier)) importOwner(node, node.moduleSpecifier.text);
126
+ if (ts.isImportTypeNode(node) && ts.isLiteralTypeNode(node.argument) && ts.isStringLiteralLike(node.argument.literal)) importOwner(node, node.argument.literal.text);
127
+ if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword && ts.isStringLiteralLike(node.arguments[0])) importOwner(node, node.arguments[0].text);
128
+ ts.forEachChild(node, gather);
129
+ }
130
+ gather(source);
131
+ for (const diagnostic of source.parseDiagnostics) add(source, 'syntax', 'error', ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'));
132
+ const ownerFor = tag => {
133
+ if (ts.isIdentifier(tag)) return bindings.get(symbolFor(tag));
134
+ if (ts.isPropertyAccessExpression(tag) && ts.isIdentifier(tag.expression)) {
135
+ const specifier = namespaces.get(symbolFor(tag.expression));
136
+ return specifier ? { symbol: tag.name.text, import: specifier } : undefined;
137
+ }
138
+ };
139
+ const attributes = node => node.attributes.properties.flatMap(attribute => {
140
+ if (ts.isJsxSpreadAttribute(attribute)) return properties(attribute.expression);
141
+ if (!attribute.initializer) return [[attribute.name.getText(source), undefined]];
142
+ const expression = ts.isJsxExpression(attribute.initializer) ? attribute.initializer.expression : attribute.initializer;
143
+ return [[attribute.name.getText(source), expression]];
144
+ });
145
+ const isOwner = (owner, suffix, names) => owner?.import === `${index.package}/${suffix}` && names.includes(owner.symbol);
146
+ const framedOwner = (owner, props) => {
147
+ if (literal(props.get('surface')) === 'flat') return false;
148
+ if (isOwner(owner, 'base/cards', ['Card', 'SmartCard']) || isOwner(owner, 'features/table', ['DataTable']) || isOwner(owner, 'features/data-view', ['DataView'])) return true;
149
+ if (isOwner(owner, 'blocks/analytics', ['Metric'])) return literal(props.get('variant')) === 'card';
150
+ if (isOwner(owner, 'blocks/analytics', ['MetricGrid'])) return !props.has('variant') || literal(props.get('variant')) === 'card';
151
+ return isOwner(owner, 'blocks/analytics/usage-card', ['UsageCard']) || isOwner(owner, 'blocks/analytics', ['UsageCard']) || isOwner(owner, 'blocks/planning', ['TaskCard']);
152
+ };
153
+ // Examine lexical JSX only. Names ending in Card are not evidence of framing;
154
+ // ChartCard is card-free; Receipt's flat paper has no ordinary Card frame.
155
+ const contentElements = element => {
156
+ const found = [];
157
+ function collect(child) {
158
+ if (ts.isJsxElement(child) || ts.isJsxSelfClosingElement(child)) {
159
+ const opening = ts.isJsxElement(child) ? child.openingElement : child;
160
+ const owner = ownerFor(opening.tagName);
161
+ found.push({ opening, owner, props: new Map(attributes(opening)), element: child });
162
+ if (isOwner(owner, 'base/cards', ['Card', 'SmartCard'])) return;
163
+ if (ts.isJsxElement(child)) child.children.forEach(collect);
164
+ return;
165
+ }
166
+ if (ts.isJsxFragment(child)) child.children.forEach(collect);
167
+ else if (ts.isJsxExpression(child) && child.expression) { const resolved = resolve(child.expression); if (resolved) collect(resolved); }
168
+ }
169
+ if (ts.isJsxElement(element.parent)) element.parent.children.forEach(collect);
170
+ return found;
171
+ };
172
+ const renderedText = element => ts.isJsxElement(element) ? element.children.map(child => ts.isJsxText(child) ? child.text : ts.isJsxExpression(child) ? literal(child.expression) ?? '' : '').join(' ').trim() : '';
173
+ const slotBadge = expression => {
174
+ const node = resolve(expression);
175
+ if (!node) return false;
176
+ if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node)) {
177
+ const opening = ts.isJsxElement(node) ? node.openingElement : node;
178
+ const owner = ownerFor(opening.tagName);
179
+ if (isOwner(owner, 'base/badge', ['Badge'])) return true;
180
+ if (owner?.import === `${index.package}/base/buttons` || /^(button|a)$/.test(opening.tagName.getText(source))) return false;
181
+ if (!/^(div|span)$/.test(opening.tagName.getText(source)) && !isOwner(owner, 'base/structure', ['Stack', 'Grid'])) return false;
182
+ return ts.isJsxElement(node) && node.children.some(slotBadge);
183
+ }
184
+ if (ts.isJsxFragment(node)) return node.children.some(slotBadge);
185
+ if (ts.isJsxExpression(node)) return slotBadge(node.expression);
186
+ return false;
187
+ };
188
+ const peerCards = element => {
189
+ if (!ts.isJsxElement(element.parent)) return new Set();
190
+ const cards = [];
191
+ function collect(child) {
192
+ if (ts.isJsxFragment(child)) { child.children.forEach(collect); return; }
193
+ const opening = ts.isJsxElement(child) ? child.openingElement : ts.isJsxSelfClosingElement(child) ? child : undefined;
194
+ if (!opening) return;
195
+ const owner = ownerFor(opening.tagName);
196
+ if (framedOwner(owner, new Map(attributes(opening)))) cards.push(opening);
197
+ else if (owner?.symbol === 'GridCell' && owner.import === `${index.package}/base/structure` && ts.isJsxElement(child)) child.children.forEach(collect);
198
+ }
199
+ element.parent.children.forEach(collect);
200
+ return new Set(cards);
201
+ };
202
+ const gapEntries = (expression, fallback) => {
203
+ if (!expression) return { base: fallback };
204
+ const node = resolve(expression);
205
+ if (node && ts.isStringLiteralLike(node)) return { base: node.text };
206
+ if (node && ts.isObjectLiteralExpression(node)) return { base: fallback, ...Object.fromEntries(properties(node).filter(([key]) => breakpoints.includes(key)).map(([key, value]) => {
207
+ const gap = literal(value);
208
+ if (gap === undefined && value) unknown(value);
209
+ return [key, gap];
210
+ })) };
211
+ if (node && node.kind === ts.SyntaxKind.NullKeyword || ts.isIdentifier(expression) && expression.text === 'undefined' && !symbolFor(expression)) return { base: fallback };
212
+ unknown(expression);
213
+ return { base: undefined };
214
+ };
215
+ const smallGap = (props, symbol, unknownProps) => {
216
+ // Unknown spread props may replace a missing gap. Report them as unresolved
217
+ // instead of treating the live default as a proven effective value.
218
+ if (!props.has('gap') && unknownProps) return false;
219
+ const gaps = gapEntries(props.get('gap'), structureDefaults[symbol]);
220
+ const rows = symbol === 'Stack' ? {} : gapEntries(props.get('rowGap'));
221
+ const columns = symbol === 'Stack' ? {} : gapEntries(props.get('columnGap'));
222
+ let gap; let row; let column;
223
+ return breakpoints.some(breakpoint => {
224
+ if (Object.hasOwn(gaps, breakpoint)) gap = gaps[breakpoint];
225
+ if (Object.hasOwn(rows, breakpoint)) row = rows[breakpoint];
226
+ if (Object.hasOwn(columns, breakpoint)) column = columns[breakpoint];
227
+ return smallPeerGaps.has(row ?? gap) || smallPeerGaps.has(column ?? gap);
228
+ });
229
+ };
230
+ function visit(node, parents = []) {
231
+ if (ts.isJsxElement(node)) {
232
+ const element = node.openingElement;
233
+ const context = inspect(element, parents);
234
+ for (const child of node.children) visit(child, context ? [...parents, context] : parents);
235
+ // JSX in props is a separate region, not a child frame.
236
+ for (const attribute of element.attributes.properties) ts.forEachChild(attribute, child => visit(child, parents));
237
+ return;
238
+ }
239
+ if (ts.isJsxSelfClosingElement(node)) inspect(node, parents);
240
+ ts.forEachChild(node, child => visit(child, parents));
241
+ }
242
+ function inspect(node, parents) {
243
+ const owner = ownerFor(node.tagName);
244
+ 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.');
246
+ if (/^(?:input|textarea)$/.test(node.tagName.getText(source))) {
247
+ const props = new Map(attributes(node));
248
+ 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.');
249
+ if (props.has('style') && properties(props.get('style')).some(([name])=>radiusProperty.test(name))) add(node,'shared-radius','error','Native editable corners belong to the global radius root, not inline styles.');
250
+ }
251
+ if (nativeDisplayNames.test(node.tagName.getText(source))) {
252
+ const props = new Map(attributes(node));
253
+ if (props.has('className') && classStrings(props.get('className')).flatMap(value=>value.split(/\s+/)).some(addsCopyMargin)) add(node,'copy-margin','error','Display copy is margin-free; use the surrounding structure for copy gaps.');
254
+ if (props.has('style') && properties(props.get('style')).some(([name,value])=>marginProperty.test(name)&&!/^['"]?0(?:px|rem|em|%)?['"]?$/.test(resolve(value)?.getText(source)??''))) add(node,'copy-margin','error','Display copy is margin-free; use the surrounding structure for copy gaps.');
255
+ }
256
+ return;
257
+ }
258
+ if (!families.get(owner.import)?.symbols.includes(owner.symbol)) {
259
+ add(node, 'public-symbol', 'error', `${owner.import} does not export ${owner.symbol}.`);
260
+ return;
261
+ }
262
+ const unresolvedBeforeProps = unresolved.length;
263
+ const props = new Map(attributes(node));
264
+ const unknownProps = unresolved.length !== unresolvedBeforeProps;
265
+ const family = owner.import.split('/base/')[1];
266
+ const anatomy = surfaceParts[family]?.test(owner.symbol);
267
+ const forwarder = surfaceForwarders[family] === owner.symbol;
268
+ const control = controlFamilies.has(family) && controlNames.test(owner.symbol);
269
+ const sharedCorners = sharedCornerParts[family]?.test(owner.symbol);
270
+ const display = owner.import === `${index.package}/typography` && displayNames.test(owner.symbol);
271
+ const fixedText = owner.import === `${index.package}/typography` && owner.symbol === 'DisplayLabel' || family === 'badge' && owner.symbol === 'Badge';
272
+ const badge = family === 'badge' && owner.symbol === 'Badge';
273
+ for (const name of ['className', 'headerClassName', 'contentClassName', 'footerClassName', 'subHeadingClassName']) {
274
+ if (!props.has(name)) continue;
275
+ const classes = classStrings(props.get(name)).flatMap(value => value.split(/\s+/)).map(utility);
276
+ 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
+ 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
+ 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
+ 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.`);
281
+ 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
+ }
283
+ if (props.has('style')) for (const [name,value] of properties(props.get('style'))) {
284
+ if (anatomy && paddingProperty.test(name)) add(node, 'surface-padding', 'error', `${owner.symbol}: ${name} replaces the region inset; use its public surface props.`);
285
+ if (control && (paddingProperty.test(name) || controlStyle.test(name))) add(node, 'control-anatomy', 'error', `${owner.symbol}: ${name} belongs to shared control geometry/typography.`);
286
+ if ((control || sharedCorners) && radiusProperty.test(name)) add(node,'shared-radius','error',`${owner.symbol}: corners follow the global radius theme root, not inline styles.`);
287
+ 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
+ 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
+ }
290
+ if (['SmartCard', 'ContentBlock'].includes(owner.symbol)) add(node, 'deprecated-owner', 'warning', `${owner.symbol} is a migration owner; prefer Card for new compositions.`);
291
+ const framed = framedOwner(owner, props);
292
+ if (isOwner(owner, 'base/cards', ['Card', 'SmartCard'])) {
293
+ 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'}.`);
294
+ const contents = contentElements(node);
295
+ const role = (item, names) => isOwner(item.owner, 'typography', names);
296
+ const valueHeading = contents.some(item => role(item, ['Heading']) && /[$€£¥]|\d/.test(renderedText(item.element)));
297
+ 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
+ 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.');
300
+ 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
+ }
302
+ 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.');
303
+ if (isOwner(owner, 'base/sheet', ['Sheet', 'SheetContent']) || isOwner(owner, 'base/display', ['Dialog', 'DialogContent', 'AlertDialog', 'AlertDialogContent'])) add(node, 'raw-overlay-primitive', 'warning', 'This lower-level modal needs application lifecycle coordination. Prefer ActionDialog, ConfirmDialog or ActionDrawer from features/overlays when their workflow fits.');
304
+ if (owner.symbol === 'Page' && literal(props.get('gutter')) === 'none' && !parents.some(parent => parent.framed)) add(node, 'page-gutter', 'warning', 'Page gutter="none" delegates inline padding to a real parent. PageViewport owns scrolling, not padding; verify the parent inset.');
305
+ if (owner.symbol === 'Card' && framed && literal(props.get('padding')) === 'sm' && !parents.some(parent => parent.framed)) add(node, 'compact-card', 'warning', 'Standalone Card padding="sm" halves the normal inset. Omit padding for ordinary subjects; retain sm only for an intentional compact composition.');
306
+ const peers = parents.findLast(parent => parent.structure);
307
+ 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
+ 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
+ const header = properties(props.get('header'), false);
310
+ const title = literal(props.get('title')) ?? literal(new Map(header).get('title'));
311
+ 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
+ const structure = owner.import === `${index.package}/base/structure` && Object.hasOwn(structureDefaults, owner.symbol);
313
+ return { framed, title, structure, cards: structure ? peerCards(node) : new Set(), smallGap: structure ? smallGap(props, owner.symbol, unknownProps) : false };
314
+ }
315
+ visit(source);
316
+ return { findings, unresolved };
317
+ }
@@ -3,11 +3,16 @@ const requireFormat = (condition, message) => { if (!condition) throw new Error(
3
3
  const stringList = value => Array.isArray(value) && value.every(item => typeof item === 'string');
4
4
  const text = value => typeof value === 'string' && value.trim().length > 0;
5
5
  const normalized = value => value.toLowerCase();
6
+ const words = value => value.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/([A-Z])([A-Z][a-z])/g, '$1 $2').toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);
7
+ const symbolKey = value => words(value).join('');
8
+ const searchable = value => words(value).join(' ');
9
+ const containsTerms = (value, terms) => { const tokens = new Set(words(value)); return terms.every(term => tokens.has(term)); };
6
10
  const compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;
7
11
 
8
12
  export function validateIndex(index) {
9
13
  requireFormat(index?.schemaVersion === 1 && index?.discoveryVersion === 1, 'unsupported schema/format; expected schemaVersion 1 and discoveryVersion 1');
10
14
  requireFormat(text(index.package) && text(index.version) && Array.isArray(index.families), 'package, version and families are required');
15
+ if (index.stylesheets !== undefined) requireFormat(stringList(index.stylesheets) && index.stylesheets.every(file => file.startsWith(index.package + '/') && file.endsWith('.css') && !file.includes('..')), 'invalid public stylesheets');
11
16
  const seen = new Set();
12
17
  for (const family of index.families) {
13
18
  requireFormat(text(family?.import) && (family.import === index.package || family.import.startsWith(`${index.package}/`)) && !/[\\\s]|(?:^|\/)\.\.(?:\/|$)/.test(family.import), 'invalid public import');
@@ -16,7 +21,17 @@ export function validateIndex(index) {
16
21
  requireFormat(text(family.declaration) && /^dist\/[\w./-]+\.d\.ts$/.test(family.declaration) && !family.declaration.split('/').includes('..'), `invalid declaration ${family.declaration}`);
17
22
  requireFormat(layers.includes(family.layer) && text(family.responsibility), `missing layer/responsibility for ${family.import}`);
18
23
  for (const field of ['symbols', 'jobs', 'tags', 'aliases', 'sections', 'optionalPeers']) requireFormat(stringList(family[field]), `invalid ${field} for ${family.import}`);
24
+ 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}`);
19
25
  requireFormat(family.optionalPeers.every(peer => index.peers?.some(owner => owner.name === peer && owner.optional)), `unknown optional peer for ${family.import}`);
26
+ if (family.recipes !== undefined) {
27
+ requireFormat(Array.isArray(family.recipes), `invalid recipes for ${family.import}`);
28
+ for (const recipe of family.recipes) {
29
+ requireFormat(text(recipe?.file) && /^examples\/[\w/-]+\.tsx$/.test(recipe.file) && !recipe.file.split('/').includes('..'), 'invalid recipe file');
30
+ requireFormat(stringList(recipe.exports) && recipe.exports.length > 0 && stringList(recipe.symbols) && recipe.symbols.every(symbol => family.symbols.includes(symbol)), `unknown recipe symbol for ${family.import}`);
31
+ requireFormat(stringList(recipe.references) && recipe.references.every(file => /^references\/[\w/-]+\.md(?:#[\w-]+)?$/.test(file) && !file.split('/').includes('..')), 'invalid recipe references');
32
+ if (recipe.optionalPeers !== undefined) requireFormat(stringList(recipe.optionalPeers) && recipe.optionalPeers.every(peer => index.peers?.some(owner => owner.name === peer && owner.optional)), 'invalid recipe optional peers');
33
+ }
34
+ }
20
35
  requireFormat(Array.isArray(family.guidance), `invalid guidance for ${family.import}`);
21
36
  for (const guide of family.guidance) {
22
37
  requireFormat(text(guide?.title) && typeof guide.description === 'string' && typeof guide.section === 'string', 'invalid guidance title/description/section');
@@ -55,24 +70,66 @@ export function parseArguments(args) {
55
70
  return { query, ...options };
56
71
  }
57
72
 
58
- const guideText = guide => normalized([guide.title, guide.description, ...Object.values(guide.browse), ...guide.jobs, ...guide.tags, ...guide.aliases, ...guide.chooseWhen, ...guide.appOwned, ...guide.sections.flatMap(section => [section.title, ...section.symbols])].join(' '));
73
+ const guideText = guide => searchable([guide.title, guide.description, ...Object.values(guide.browse), ...guide.jobs, ...guide.tags, ...guide.aliases, ...guide.chooseWhen, ...guide.appOwned, ...guide.sections.flatMap(section => [section.title, ...section.symbols])].join(' '));
74
+ const guideSymbols = (guide, family) => [...new Set(guide.sections.flatMap(section => section.symbols))].filter(symbol => family.symbols.includes(symbol));
75
+
76
+ function relevantGuidance(family, needle, terms, matchedSymbols, exactImport) {
77
+ const ranked = family.guidance.map(guide => {
78
+ const haystack = guideText(guide);
79
+ const count = terms.filter(term => containsTerms(haystack, [term])).length;
80
+ const symbol = matchedSymbols.some(value => guideSymbols(guide, family).includes(value));
81
+ const alias = guide.aliases.some(value => normalized(value) === needle);
82
+ const complete = count === terms.length;
83
+ const score = Number(alias) * 10000 + Number(symbol) * 1000 + Number(complete) * 100 + count;
84
+ return { guide, score, symbol, alias, complete };
85
+ }).sort((a, b) => b.score - a.score || Number(guideSymbols(b.guide, family).length > 0) - Number(guideSymbols(a.guide, family).length > 0) || compare(a.guide.title, b.guide.title));
86
+ // Exact owner and curated task matches supply their own narrow reading path.
87
+ // Generic intent can still combine terms across fields/family guidance.
88
+ const selected = ranked.filter(item => ranked.some(item => item.alias) ? item.alias : matchedSymbols.length ? item.symbol : ranked.some(item => item.complete) ? item.complete : item.score > 0);
89
+ return (selected.length || !exactImport ? selected : ranked).slice(0, 3).map(item => item.guide);
90
+ }
59
91
 
60
92
  export function findComponents(index, { query, layer = null, limit = 5 }) {
61
93
  validateIndex(index);
62
94
  const needle = normalized(query);
63
- const terms = [...new Set(needle.split(/\s+/).filter(Boolean))];
95
+ const terms = [...new Set(words(query))];
96
+ const key = symbolKey(query);
97
+ // Cased API names and explicit imports request a precise contract. Ordinary
98
+ // nouns such as table/empty remain task searches with richer alternatives.
99
+ const exactOwners = index.families.filter(family => (!layer || layer === family.layer) && (normalized(family.import) === needle || family.symbols.includes(query.trim())));
64
100
  const ranked = [];
65
101
  for (const family of index.families) {
66
102
  if (layer && layer !== family.layer) continue;
103
+ if (exactOwners.length && !exactOwners.includes(family)) continue;
67
104
  const exactImport = normalized(family.import) === needle;
68
- const matchedSymbols = family.symbols.filter(symbol => normalized(symbol) === needle);
69
- const haystack = normalized([family.import, family.responsibility, ...family.symbols, ...family.jobs, ...family.tags, ...family.aliases, ...family.sections, ...family.guidance.map(guideText)].join(' '));
105
+ const matchedSymbols = family.symbols.filter(symbol => symbolKey(symbol) === key);
106
+ const documented = new Set(family.guidance.flatMap(guide => guideSymbols(guide, family)));
107
+ const focusedSymbols = [...documented].filter(symbol => containsTerms(symbol, terms));
108
+ const haystack = searchable([family.import, family.responsibility, ...documented, ...family.jobs, ...family.tags, ...family.aliases, ...family.sections, ...family.guidance.map(guideText)].join(' '));
70
109
  // AND matching prevents a familiar term from inventing results for an
71
110
  // otherwise unknown query. Avoidance/alternatives do not recommend owners.
72
- if (!exactImport && !matchedSymbols.length && !terms.every(term => haystack.includes(term))) continue;
73
- const score = exactImport ? 10000 : matchedSymbols.length ? 9000 : terms.reduce((sum, term) => sum + (family.guidance.some(guide => normalized(guide.title).includes(term)) ? 20 : family.tags.some(tag => normalized(tag).includes(term)) ? 10 : 1), 0);
74
- const guidance = family.guidance.map(guide => ({ guide, score: terms.filter(term => guideText(guide).includes(term)).length })).sort((a, b) => b.score - a.score || compare(a.guide.title, b.guide.title)).slice(0, 3).map(({ guide }) => guide);
75
- 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, guidance });
111
+ if (!exactImport && !matchedSymbols.length && !containsTerms(haystack, terms)) continue;
112
+ // A dedicated, documented owner precedes an aggregate re-export of the
113
+ // same symbol. Explicit import queries still select the requested family.
114
+ const documentedSymbol = matchedSymbols.some(symbol => documented.has(symbol));
115
+ const exactFamily = searchable(family.import.split('/').at(-1)) === terms.join(' ');
116
+ const exactIntent = family.aliases.some(alias => normalized(alias) === needle);
117
+ 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
+ const selectedSymbols = matchedSymbols.length ? matchedSymbols : focusedSymbols;
119
+ 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 candidates = (family.recipes ?? []).filter(recipe => recipe.symbols.some(symbol => relevantSymbols.includes(symbol)));
122
+ const recipeText = recipe => normalized([recipe.file, ...recipe.exports, ...recipe.references].join(' ')).replace(/[-/#]/g, ' ');
123
+ 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+/)));
125
+ const aliasRecipes = matchedSymbols.length || exactImport ? [] : candidates.filter(recipe => aliases.some(intent => intent.every(term => recipeText(recipe).includes(term))));
126
+ const recipes = taskRecipes.length ? taskRecipes : aliasRecipes.length ? aliasRecipes : candidates;
127
+ const nextReads = {
128
+ declaration: family.declaration,
129
+ references: [...new Set([...(family.references ?? []), ...recipes.flatMap(recipe => recipe.references)])].sort(compare),
130
+ examples: recipes.map(({ file, exports, symbols, optionalPeers = [] }) => ({ file, exports, symbols: symbols.filter(symbol => relevantSymbols.includes(symbol)), optionalPeers })),
131
+ };
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 });
76
133
  }
77
134
  ranked.sort((a, b) => b.score - a.score || compare(a.import, b.import));
78
135
  return { package: index.package, version: index.version, query, layer, limit, total: ranked.length, results: ranked.slice(0, limit) };
@@ -0,0 +1,66 @@
1
+ // One public anatomy vocabulary, shared by repository and opt-in consumer checks.
2
+ export const surfaceParts = {
3
+ cards: /^Card(?:Header|Content|Footer)?$/,
4
+ popover: /^(PopoverContent|PopoverHeader|PopoverFooter)$/,
5
+ command: /^Command(Input|List|Group|Item|Empty|Separator)?$/,
6
+ navigation: /^DropdownMenu(Content|SubContent|Label|Item|LinkItem|SubTrigger|CheckboxItem|RadioItem|Separator)$/,
7
+ 'choice-inputs': /^SelectPopup(Content|Group|Item|Label|Separator)?$/,
8
+ combobox: /^Combobox(Popup|Content|List|Item|GroupLabel|Separator)$/,
9
+ };
10
+ export const surfaceForwarders = { 'choice-inputs': 'Select', 'popover-menu': 'PopoverMenu', 'action-menu': 'ActionMenu' };
11
+ export const paddingClass = /^(?:p[xytrblse]?|p(?:bs|be)|padding)-|^\[padding/;
12
+ export const paddingProperty = /^padding(?:Inline|Block)?(?:Start|End)?$|^padding(?:Top|Right|Bottom|Left)$|^padding-(?:(?:inline|block)(?:-(?:start|end))?|top|right|bottom|left)$/;
13
+
14
+ // One root, two owned roles: outer shells and inner controls/collection rows.
15
+ // Circular shapes and joined-edge resets retain their explicit mechanics.
16
+ export const sharedCornerParts = {
17
+ cards: /^Card$/,
18
+ popover: /^PopoverContent$/,
19
+ command: /^Command(?:Item)?$/,
20
+ navigation: /^(?:DropdownMenu(?:Content|SubContent|Item|LinkItem|SubTrigger|CheckboxItem|RadioItem)|TabsList|TabsTrigger)$/,
21
+ 'choice-inputs': /^SelectPopup(?:Content|Item)$/,
22
+ item: /^Item$/,
23
+ combobox: /^Combobox(?:Popup|Content|Item)$/,
24
+ display: /^(?:DialogContent|AlertDialogContent)$/,
25
+ sheet: /^SheetContent$/,
26
+ };
27
+ export const displayNames = /^(?:Text|Heading|DisplayLabel|Label|TextLink)$/;
28
+ export const nativeDisplayNames = /^(?:p|h[1-6])$/;
29
+ export const marginProperty = /^margin(?:Inline|Block)?(?:Start|End)?$|^margin(?:Top|Right|Bottom|Left)$|^margin-(?:(?:inline|block)(?:-(?:start|end))?|top|right|bottom|left)$/;
30
+ export const radiusProperty = /^border(?:(?:Top|Bottom)(?:Left|Right)|(?:Start|End)(?:Start|End))?Radius$|^border-(?:(?:top|bottom)-(?:left|right)-|(?:start|end)-(?:start|end)-)?radius$/;
31
+
32
+ export function cornerRole(family, symbol) {
33
+ if (family === 'item' && symbol === 'Item' || family === 'navigation' && /^(?:TabsList|TabsTrigger)$/.test(symbol)) return 'inner';
34
+ return sharedCornerParts[family]?.test(symbol) && /(?:Item|SubTrigger)$/.test(symbol) ? 'inner' : 'radius';
35
+ }
36
+
37
+ export function replacesSharedRadius(token, role = 'radius') {
38
+ const value = utility(token);
39
+ if (new RegExp(`^rounded(?:-[trblse]{1,2})?-(?:${role}|none)$`).test(value)) return false;
40
+ return /^rounded(?:-|$)/.test(value) || /^\[border-(?:(?:top|bottom)-(?:left|right)-|(?:start|end)-(?:start|end)-)?radius:/.test(value);
41
+ }
42
+
43
+ export function addsCopyMargin(token) {
44
+ const value = utility(token);
45
+ const match = value.match(/^-?m(?:[xytrblse]|bs|be)?-(.+)$|^\[margin[^:]*:(.+)\]$/);
46
+ return !!match && !/^(?:0(?:px|rem|em|%)?|\[0(?:px|rem|em|%)?\])$/.test(match[1] ?? match[2]);
47
+ }
48
+
49
+ export function utility(token) {
50
+ let depth = 0;
51
+ let start = 0;
52
+ for (let i = 0; i < token.length; i++) {
53
+ if (token[i] === '[' || token[i] === '(') depth++;
54
+ if (token[i] === ']' || token[i] === ')') depth--;
55
+ if (token[i] === ':' && depth === 0) start = i + 1;
56
+ }
57
+ return token.slice(start).replace(/^!|!$/g, '');
58
+ }
59
+
60
+ /** Shared focus roles are contrast-tested at full strength, unlike status tints. */
61
+ export function attenuatedFocusRing(token) {
62
+ const match = utility(token).match(/^ring-(?:ring|sidebar-ring)\/(?:(\d+(?:\.\d+)?|\.\d+)|\[(\d+(?:\.\d+)?|\.\d+)(%)?\])$/);
63
+ if (!match) return false;
64
+ const opacity = Number(match[1] ?? match[2]);
65
+ return opacity < (match[1] !== undefined || match[3] ? 100 : 1);
66
+ }
package/package.json CHANGED
@@ -1,12 +1,21 @@
1
1
  {
2
2
  "name": "themelia-react-ui",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "A composable React UI library for modern admin applications, built on Base UI and Tailwind with shadcn-compatible themes, shared design tokens, reusable layouts, blocks and workflows.",
5
5
  "publishConfig": {
6
6
  "access": "public",
7
7
  "registry": "https://registry.npmjs.org/"
8
8
  },
9
- "keywords": ["react", "ui", "admin", "dashboard", "base-ui", "tailwindcss", "shadcn", "design-system"],
9
+ "keywords": [
10
+ "react",
11
+ "ui",
12
+ "admin",
13
+ "dashboard",
14
+ "base-ui",
15
+ "tailwindcss",
16
+ "shadcn",
17
+ "design-system"
18
+ ],
10
19
  "repository": {
11
20
  "type": "git",
12
21
  "url": "git+https://github.com/nicolasvlachos/themelia-react-ui.git"
@@ -413,6 +422,18 @@
413
422
  "./features/questionnaire": {
414
423
  "types": "./dist/components/features/questionnaire/index.d.ts",
415
424
  "import": "./dist/features/questionnaire.js"
425
+ },
426
+ "./base/inline-edit": {
427
+ "types": "./dist/components/base/inline-edit/index.d.ts",
428
+ "import": "./dist/base/inline-edit.js"
429
+ },
430
+ "./blocks/planning": {
431
+ "types": "./dist/components/blocks/planning/index.d.ts",
432
+ "import": "./dist/blocks/planning.js"
433
+ },
434
+ "./blocks/analytics/usage-card": {
435
+ "types": "./dist/components/blocks/analytics/usage-card/index.d.ts",
436
+ "import": "./dist/blocks/analytics/usage-card.js"
416
437
  }
417
438
  },
418
439
  "scripts": {
@@ -426,7 +447,7 @@
426
447
  "test:browser": "npm run build:preview && node scripts/run-browser.mjs",
427
448
  "check:package": "node scripts/check-package.mjs",
428
449
  "check": "npm run check:contract && npm run check:preview && npm run check:docs && npm run lint && npm run check:design-lint && npm run typecheck && npm test && npm run build && npm run check:skill && npm run check:maps && npm run check:package && npm run build:preview",
429
- "check:contract": "node --test scripts/test-runtime-ownership.mjs scripts/test-primitive-geometry.mjs scripts/test-source-entrypoints.mjs && node scripts/check-contract.mjs",
450
+ "check:contract": "node --test scripts/test-runtime-ownership.mjs scripts/test-primitive-geometry.mjs scripts/test-source-entrypoints.mjs scripts/test-utility-vocabulary.mjs scripts/test-theme-contrast.mjs && node scripts/check-contract.mjs",
430
451
  "lint": "node scripts/generate-utilities.mjs && oxlint src/components src/lib src/preview docs/consumer-skill/examples --deny-warnings",
431
452
  "check:design-lint": "node scripts/generate-utilities.mjs && node scripts/check-design-lint.mjs",
432
453
  "check:preview": "node scripts/check-preview.mjs",
@@ -442,7 +463,7 @@
442
463
  "check:maps": "node scripts/test-client-boundaries.mjs --built",
443
464
  "build:docs": "node scripts/build-static-docs.mjs",
444
465
  "check:static-docs": "node scripts/check-static-docs.mjs",
445
- "check:agent": "node --test scripts/test-consumer-discovery.mjs scripts/test-consumer-skill-assets.mjs scripts/test-static-docs.mjs scripts/test-fixture-install.mjs && npm run check:skill",
466
+ "check:agent": "node --test scripts/test-consumer-discovery.mjs scripts/test-consumer-composition.mjs scripts/test-consumer-skill-assets.mjs scripts/test-static-docs.mjs scripts/test-fixture-install.mjs && npm run check:skill",
446
467
  "check:release": "npm run check:all && npm run check:agent && npm run build:docs && npm run check:static-docs"
447
468
  },
448
469
  "peerDependencies": {
@@ -495,6 +516,8 @@
495
516
  "@mdx-js/rollup": "^3.1.1",
496
517
  "@playwright/test": "^1.63.0",
497
518
  "@shadcn/lint": "0.2.0",
519
+ "@tailwindcss/node": "^4.3.3",
520
+ "@tailwindcss/oxide": "^4.3.3",
498
521
  "@tailwindcss/vite": "^4.3.3",
499
522
  "@tanstack/react-table": "^8.21.3",
500
523
  "@testing-library/jest-dom": "^6.0.0",
@@ -519,7 +542,9 @@
519
542
  "leaflet-draw": "^1.0.4",
520
543
  "leaflet.fullscreen": "^5.3.1",
521
544
  "leaflet.markercluster": "^1.5.3",
545
+ "lightningcss": "^1.33.0",
522
546
  "lucide-react": "^1.14.0",
547
+ "magic-string": "^0.30.21",
523
548
  "oxlint": "1.87.0",
524
549
  "qrcode": "^1.5.4",
525
550
  "react": "^19.2.5",
@@ -535,8 +560,7 @@
535
560
  "tw-animate-css": "^1.4.0",
536
561
  "typescript": "^5.9.3",
537
562
  "vite": "^8.0.0",
538
- "vitest": "^5.0.3",
539
- "magic-string": "^0.30.21"
563
+ "vitest": "^5.0.3"
540
564
  },
541
565
  "engines": {
542
566
  "node": ">=22.12.0"