themelia-react-ui 1.0.1 → 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 (488) hide show
  1. package/CHANGELOG.md +137 -0
  2. package/README.md +59 -13
  3. package/dist/{accordion-B-5Focs8.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-B5tPpXnS.js → ai-artifact-DLVdK0Py.js} +151 -155
  10. package/dist/ai-artifact-DLVdK0Py.js.map +1 -0
  11. package/dist/{app-shell-at8Kt4l_.js → app-shell-C_fKpljx.js} +11 -10
  12. package/dist/app-shell-C_fKpljx.js.map +1 -0
  13. package/dist/{attachment-BO2R47wn.js → attachment-DbjUWsP0.js} +12 -12
  14. package/dist/{attachment-BO2R47wn.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-Bpzty83c.js → avatar-Bu2HhitA.js} +6 -6
  18. package/dist/{avatar-Bpzty83c.js.map → avatar-Bu2HhitA.js.map} +1 -1
  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 +2 -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 -4
  41. package/dist/base/forms-numeric.js +1 -1
  42. package/dist/base/forms.js +2 -2
  43. package/dist/base/inline-edit.js +40 -43
  44. package/dist/base/inline-edit.js.map +1 -1
  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 +1 -1
  73. package/dist/blocks/analytics.js +510 -472
  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 +36 -36
  83. package/dist/blocks/planning.js.map +1 -1
  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-Cum56XOF.js → cards-qGSErLw_.js} +12 -12
  94. package/dist/{cards-Cum56XOF.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-BavDRjF7.js → checkbox-BQNDjUCh.js} +3 -3
  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-xHKbAJDj.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-DEbdr-3u.js → combobox-BFnbJJp3.js} +18 -18
  108. package/dist/combobox-BFnbJJp3.js.map +1 -0
  109. package/dist/{combobox-xv3yJbzl.js → combobox-hozNwUcc.js} +313 -316
  110. package/dist/combobox-hozNwUcc.js.map +1 -0
  111. package/dist/{command-C0xe7u9B.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 +1 -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/navigation/tabs.d.ts +3 -5
  126. package/dist/components/base/popover/popover.recipes.d.ts +3 -3
  127. package/dist/components/base/table/index.d.ts +1 -1
  128. package/dist/components/base/text-inputs/clear-native-field.d.ts +2 -0
  129. package/dist/components/base/text-inputs/input-trailing-action.d.ts +3 -0
  130. package/dist/components/blocks/analytics/types.d.ts +1 -1
  131. package/dist/components/blocks/collaboration/message/message.recipes.d.ts +12 -0
  132. package/dist/components/blocks/data-display/empty-state/partials/illustrations/document-stack.d.ts +1 -4
  133. package/dist/components/blocks/data-display/empty-state/partials/illustrations/inbox-clean.d.ts +1 -4
  134. package/dist/components/blocks/data-display/empty-state/partials/illustrations/index.d.ts +3 -3
  135. package/dist/components/blocks/data-display/empty-state/partials/illustrations/stacked-cards.d.ts +1 -6
  136. package/dist/components/features/combobox/components/error-message.d.ts +1 -1
  137. package/dist/components/features/comments/hooks/use-attachment-upload.d.ts +5 -0
  138. package/dist/components/features/filters/facets/search-facet.d.ts +0 -12
  139. package/dist/components/features/filters/facets/tags-facet.d.ts +1 -1
  140. package/dist/components/features/media-library/media-library.d.ts +1 -1
  141. package/dist/components/features/media-library/media-library.types.d.ts +9 -1
  142. package/dist/components/features/media-library/partials/media-library-partials.d.ts +1 -1
  143. package/dist/components/features/overlays/hooks/use-pending-overlay-focus.d.ts +2 -0
  144. package/dist/components/features/overlays/overlays.types.d.ts +5 -4
  145. package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +2 -1
  146. package/dist/components/features/table/data-table.d.ts +1 -1
  147. package/dist/components/features/table/table.types.d.ts +1 -1
  148. package/dist/components/features/theme-tweaker/theme-provider-settings.d.ts +3 -1
  149. package/dist/components/layout/auth/auth.types.d.ts +1 -0
  150. package/dist/components/layout/page/page.d.ts +0 -1
  151. package/dist/components/layout/page/page.types.d.ts +9 -3
  152. package/dist/components/layout/sidebar/sidebar.context.d.ts +1 -1
  153. package/dist/components/layout/sidebar/sidebar.types.d.ts +4 -0
  154. package/dist/components/layout/workspace/workspace.types.d.ts +3 -0
  155. package/dist/components/typography/heading.d.ts +5 -2
  156. package/dist/components/typography/index.d.ts +1 -1
  157. package/dist/components/typography/text.styles.d.ts +10 -0
  158. package/dist/components/ui/popover.d.ts +1 -1
  159. package/dist/components/ui/sidebar.d.ts +1 -1
  160. package/dist/components/ui/table.d.ts +2 -1
  161. package/dist/container.recipes-D9t8MHR3.js +27 -0
  162. package/dist/container.recipes-D9t8MHR3.js.map +1 -0
  163. package/dist/{containers-6s-ucRQQ.js → containers-DqB-bSYE.js} +33 -56
  164. package/dist/containers-DqB-bSYE.js.map +1 -0
  165. package/dist/control-group-recipes-DBXmfh2E.js +21 -0
  166. package/dist/control-group-recipes-DBXmfh2E.js.map +1 -0
  167. package/dist/{copyable-B7SBXJMr.js → copyable-BTSByfmq.js} +6 -6
  168. package/dist/{copyable-B7SBXJMr.js.map → copyable-BTSByfmq.js.map} +1 -1
  169. package/dist/{data-display-cWIRdeaf.js → data-display-Bihs9Ven.js} +545 -332
  170. package/dist/data-display-Bihs9Ven.js.map +1 -0
  171. package/dist/{date-BFNMnrS5.js → date-DOKhJPu7.js} +4 -4
  172. package/dist/{date-BFNMnrS5.js.map → date-DOKhJPu7.js.map} +1 -1
  173. package/dist/{date-picker-CA6ogMQB.js → date-picker-DzP5HQq7.js} +492 -472
  174. package/dist/date-picker-DzP5HQq7.js.map +1 -0
  175. package/dist/date-pickers-BpgGz7S-.js +196 -0
  176. package/dist/date-pickers-BpgGz7S-.js.map +1 -0
  177. package/dist/{display-CFM5myut.js → display-CS6Hbk18.js} +8 -8
  178. package/dist/{display-CFM5myut.js.map → display-CS6Hbk18.js.map} +1 -1
  179. package/dist/{dropdown-menu-BlnyHr-9.js → dropdown-menu-D-boNgGO.js} +7 -7
  180. package/dist/{dropdown-menu-BlnyHr-9.js.map → dropdown-menu-D-boNgGO.js.map} +1 -1
  181. package/dist/features/activities.js +152 -141
  182. package/dist/features/activities.js.map +1 -1
  183. package/dist/features/ai-chat.js +182 -179
  184. package/dist/features/ai-chat.js.map +1 -1
  185. package/dist/features/async-preview.js +9 -9
  186. package/dist/features/async-preview.js.map +1 -1
  187. package/dist/features/combobox.js +1 -1
  188. package/dist/features/comments.js +1 -1
  189. package/dist/features/data-view.js +25 -23
  190. package/dist/features/data-view.js.map +1 -1
  191. package/dist/features/email-composer/engine.js +1 -1
  192. package/dist/features/email-composer.js +103 -104
  193. package/dist/features/email-composer.js.map +1 -1
  194. package/dist/features/event-calendar.js +375 -373
  195. package/dist/features/event-calendar.js.map +1 -1
  196. package/dist/features/filters.js +1 -1
  197. package/dist/features/global-search.js +222 -224
  198. package/dist/features/global-search.js.map +1 -1
  199. package/dist/features/kanban.js +29 -29
  200. package/dist/features/kanban.js.map +1 -1
  201. package/dist/features/map.js +59 -58
  202. package/dist/features/map.js.map +1 -1
  203. package/dist/features/media-library.js +856 -855
  204. package/dist/features/media-library.js.map +1 -1
  205. package/dist/features/mentions.js +1 -1
  206. package/dist/features/overlays.js +1 -1
  207. package/dist/features/products.js +1209 -1209
  208. package/dist/features/products.js.map +1 -1
  209. package/dist/features/questionnaire.js +52 -52
  210. package/dist/features/questionnaire.js.map +1 -1
  211. package/dist/features/resource-assignment.js +29 -31
  212. package/dist/features/resource-assignment.js.map +1 -1
  213. package/dist/features/resource.js +13 -13
  214. package/dist/features/resource.js.map +1 -1
  215. package/dist/features/rich-text-editor.js +2 -2
  216. package/dist/features/schema-form.js +82 -82
  217. package/dist/features/schema-form.js.map +1 -1
  218. package/dist/features/suggestions.js +3 -3
  219. package/dist/features/sync.js +4 -4
  220. package/dist/features/sync.js.map +1 -1
  221. package/dist/features/table.js +1 -1
  222. package/dist/features/theme-tweaker.js +456 -450
  223. package/dist/features/theme-tweaker.js.map +1 -1
  224. package/dist/{feedback-DWUkgEjR.js → feedback-CJkUAapr.js} +29 -29
  225. package/dist/feedback-CJkUAapr.js.map +1 -0
  226. package/dist/field-affordance-recipes-uKY4MsZ_.js +25 -0
  227. package/dist/field-affordance-recipes-uKY4MsZ_.js.map +1 -0
  228. package/dist/{field-state-recipes-CBTRt9Bt.js → field-state-recipes-DQQpiLWC.js} +3 -3
  229. package/dist/field-state-recipes-DQQpiLWC.js.map +1 -0
  230. package/dist/{filters-BhsUtsxW.js → filters-D6FF8L6s.js} +715 -720
  231. package/dist/filters-D6FF8L6s.js.map +1 -0
  232. package/dist/{form-field-Bn7ZH1rA.js → form-field-CZwrkP7m.js} +17 -9
  233. package/dist/form-field-CZwrkP7m.js.map +1 -0
  234. package/dist/{form-sizing-BWs70_a2.js → form-sizing-QP8aIRaW.js} +8 -5
  235. package/dist/form-sizing-QP8aIRaW.js.map +1 -0
  236. package/dist/{forms-B7pzS25o.js → forms-B5NCbkSC.js} +35 -35
  237. package/dist/{forms-B7pzS25o.js.map → forms-B5NCbkSC.js.map} +1 -1
  238. package/dist/forms-numeric-Crrm80Lm.js +867 -0
  239. package/dist/forms-numeric-Crrm80Lm.js.map +1 -0
  240. package/dist/{header-C59QZyxV.js → header-kxruN3RM.js} +53 -49
  241. package/dist/header-kxruN3RM.js.map +1 -0
  242. package/dist/{hooks-CM1Vp9Pe.js → hooks-BrlnCwQd.js} +2 -2
  243. package/dist/{hooks-CM1Vp9Pe.js.map → hooks-BrlnCwQd.js.map} +1 -1
  244. package/dist/{http-CLTVJc5I.js → http-CdEIHyQf.js} +2 -2
  245. package/dist/http-CdEIHyQf.js.map +1 -0
  246. package/dist/{icon-badge-Dv0RYQwj.js → icon-badge-Btc6pQrp.js} +4 -4
  247. package/dist/{icon-badge-Dv0RYQwj.js.map → icon-badge-Btc6pQrp.js.map} +1 -1
  248. package/dist/index.js +2 -2
  249. package/dist/input-SX9V0AL3.js +255 -0
  250. package/dist/input-SX9V0AL3.js.map +1 -0
  251. package/dist/input-vxcaNCYC.js +20 -0
  252. package/dist/input-vxcaNCYC.js.map +1 -0
  253. package/dist/{item-pJ0GsOiJ.js → item-DE4YnuJx.js} +18 -17
  254. package/dist/item-DE4YnuJx.js.map +1 -0
  255. package/dist/layout/app-shell.js +1 -1
  256. package/dist/layout/auth.js +1 -1
  257. package/dist/layout/containers.js +1 -1
  258. package/dist/layout/header.js +1 -1
  259. package/dist/layout/hooks.js +1 -1
  260. package/dist/layout/navigation.js +1 -1
  261. package/dist/layout/page.js +1 -1
  262. package/dist/layout/settings.js +1 -1
  263. package/dist/layout/sidebar.js +2 -2
  264. package/dist/layout/workspace.js +1 -1
  265. package/dist/layout.js +10 -10
  266. package/dist/lib/affordance-geometry.generated.d.ts +40 -9
  267. package/dist/lib/control-group-recipes.d.ts +22 -0
  268. package/dist/lib/field-affordance-recipes.d.ts +35 -2
  269. package/dist/lib/field-state-recipes.d.ts +2 -2
  270. package/dist/lib/navigation-row-recipes.d.ts +3 -2
  271. package/dist/lib/overlay-anatomy-recipes.d.ts +1 -1
  272. package/dist/lib/surface-recipes.d.ts +5 -2
  273. package/dist/lib/token-merge.generated.d.ts +144 -2
  274. package/dist/lib/ui-provider/types.d.ts +4 -2
  275. package/dist/lib/use-prefers-reduced-motion.d.ts +2 -0
  276. package/dist/lib/utils.js +1 -1
  277. package/dist/{media-gallery-DhDRgnVZ.js → media-gallery-DLp3HAz0.js} +75 -74
  278. package/dist/media-gallery-DLp3HAz0.js.map +1 -0
  279. package/dist/{mentions-B8Ko-fhS.js → mentions-Cl0Kt_Pd.js} +52 -50
  280. package/dist/{mentions-B8Ko-fhS.js.map → mentions-Cl0Kt_Pd.js.map} +1 -1
  281. package/dist/message-SZUNB1eX.js +127 -0
  282. package/dist/message-SZUNB1eX.js.map +1 -0
  283. package/dist/{navigation-DBEu4POU.js → navigation-DnQSNMT0.js} +64 -55
  284. package/dist/navigation-DnQSNMT0.js.map +1 -0
  285. package/dist/{navigation-BUIn2Qxx.js → navigation-DyytsLRB.js} +37 -37
  286. package/dist/navigation-DyytsLRB.js.map +1 -0
  287. package/dist/{navigation-row-recipes-GVh11KiT.js → navigation-row-recipes-DQEXQcqY.js} +3 -3
  288. package/dist/navigation-row-recipes-DQEXQcqY.js.map +1 -0
  289. package/dist/{number-BNT_BIzJ.js → number-DasMFWEG.js} +4 -4
  290. package/dist/{number-BNT_BIzJ.js.map → number-DasMFWEG.js.map} +1 -1
  291. package/dist/overlays-DUbs1KEi.js +1011 -0
  292. package/dist/overlays-DUbs1KEi.js.map +1 -0
  293. package/dist/{page-BV6ioQg3.js → page-hGmT4nWK.js} +75 -64
  294. package/dist/page-hGmT4nWK.js.map +1 -0
  295. package/dist/{page-header-DQRa0jug.js → page-header-D8nERkn5.js} +9 -9
  296. package/dist/page-header-D8nERkn5.js.map +1 -0
  297. package/dist/{pagination-C29vvt3I.js → pagination-NLGqRirf.js} +20 -20
  298. package/dist/pagination-NLGqRirf.js.map +1 -0
  299. package/dist/{popover-CoLDEg19.js → popover-CghIYdQf.js} +23 -22
  300. package/dist/popover-CghIYdQf.js.map +1 -0
  301. package/dist/{popover-menu-GLIQTJTx.js → popover-menu-B4PoWhRl.js} +6 -6
  302. package/dist/{popover-menu-GLIQTJTx.js.map → popover-menu-B4PoWhRl.js.map} +1 -1
  303. package/dist/{popover.recipes-zgBhMlUu.js → popover.recipes-QlD4JenO.js} +5 -5
  304. package/dist/popover.recipes-QlD4JenO.js.map +1 -0
  305. package/dist/{primitives-DKPOGVpj.js → primitives-C7ff0QaI.js} +120 -113
  306. package/dist/primitives-C7ff0QaI.js.map +1 -0
  307. package/dist/primitives.js +3 -3
  308. package/dist/{progress-BOe8l_FZ.js → progress-BroqrAyV.js} +10 -9
  309. package/dist/progress-BroqrAyV.js.map +1 -0
  310. package/dist/{receipt-BM8xsGFy.js → receipt-BuJynLgf.js} +8 -8
  311. package/dist/{receipt-BM8xsGFy.js.map → receipt-BuJynLgf.js.map} +1 -1
  312. package/dist/{rich-text-B7sBAdDG.js → rich-text-DlxDOtf4.js} +4 -4
  313. package/dist/{rich-text-B7sBAdDG.js.map → rich-text-DlxDOtf4.js.map} +1 -1
  314. package/dist/rich-text-editor-BKyG7rWz.js +574 -0
  315. package/dist/rich-text-editor-BKyG7rWz.js.map +1 -0
  316. package/dist/{rich-text-editor.recipes-DxvOE0Lp.js → rich-text-editor.recipes-B72Nfuze.js} +35 -26
  317. package/dist/rich-text-editor.recipes-B72Nfuze.js.map +1 -0
  318. package/dist/{scroll-area-BheMQ270.js → scroll-area-D-pIhEKl.js} +3 -3
  319. package/dist/scroll-area-D-pIhEKl.js.map +1 -0
  320. package/dist/{separator-Gk_WXH-l.js → separator-BNIgG3au.js} +3 -3
  321. package/dist/{separator-Gk_WXH-l.js.map → separator-BNIgG3au.js.map} +1 -1
  322. package/dist/{separator-DO0EbCEm.js → separator-BhtFyo4x.js} +2 -2
  323. package/dist/{separator-DO0EbCEm.js.map → separator-BhtFyo4x.js.map} +1 -1
  324. package/dist/services/actions.js +1 -1
  325. package/dist/{settings-BnCyyPOJ.js → settings-DOTOzeZ2.js} +10 -9
  326. package/dist/{settings-BnCyyPOJ.js.map → settings-DOTOzeZ2.js.map} +1 -1
  327. package/dist/{sheet-B-q914Ad.js → sheet-BFhrNehm.js} +11 -11
  328. package/dist/sheet-BFhrNehm.js.map +1 -0
  329. package/dist/{sidebar-DPR7fmqN.js → sidebar-CyR4XKwR.js} +219 -200
  330. package/dist/sidebar-CyR4XKwR.js.map +1 -0
  331. package/dist/{sidebar-C_2p3Tfj.js → sidebar-SvGJ0Zwi.js} +63 -58
  332. package/dist/sidebar-SvGJ0Zwi.js.map +1 -0
  333. package/dist/{skeleton-CmT1ppqb.js → skeleton-3F0uhYn3.js} +4 -4
  334. package/dist/{skeleton-CmT1ppqb.js.map → skeleton-3F0uhYn3.js.map} +1 -1
  335. package/dist/{smart-card-CYLn46e6.js → smart-card-DjGVV2xr.js} +171 -165
  336. package/dist/smart-card-DjGVV2xr.js.map +1 -0
  337. package/dist/{spinner-BY9HbUEh.js → spinner-Cpf7oRkF.js} +5 -5
  338. package/dist/{spinner-BY9HbUEh.js.map → spinner-Cpf7oRkF.js.map} +1 -1
  339. package/dist/{structure-MvKVq-oL.js → structure-CRdqVawd.js} +2 -2
  340. package/dist/{structure-MvKVq-oL.js.map → structure-CRdqVawd.js.map} +1 -1
  341. package/dist/style.css +1 -1
  342. package/dist/{surface-recipes-CQfRr-VL.js → surface-recipes-Dd__PD-w.js} +4 -3
  343. package/dist/surface-recipes-Dd__PD-w.js.map +1 -0
  344. package/dist/{table-DnlAJ-xR.js → table-CLtJTxoR.js} +17 -16
  345. package/dist/table-CLtJTxoR.js.map +1 -0
  346. package/dist/table-CcRDZiLP.js +1444 -0
  347. package/dist/table-CcRDZiLP.js.map +1 -0
  348. package/dist/tabs-BNgu7g0u.js +188 -0
  349. package/dist/tabs-BNgu7g0u.js.map +1 -0
  350. package/dist/text-inputs-DsR56TR-.js +330 -0
  351. package/dist/text-inputs-DsR56TR-.js.map +1 -0
  352. package/dist/{text.styles-BwB7vAF2.js → text.styles-Q4sGAIgA.js} +18 -10
  353. package/dist/text.styles-Q4sGAIgA.js.map +1 -0
  354. package/dist/theme.css +77 -115
  355. package/dist/{timelines-B9ICkQcV.js → timelines-D1pkt3se.js} +84 -78
  356. package/dist/timelines-D1pkt3se.js.map +1 -0
  357. package/dist/{tree-BdWSaoFT.js → tree-BtmYyMZV.js} +8 -8
  358. package/dist/{tree-BdWSaoFT.js.map → tree-BtmYyMZV.js.map} +1 -1
  359. package/dist/typography/rich-text.js +1 -1
  360. package/dist/typography-BxQgiZyw.js +96 -0
  361. package/dist/typography-BxQgiZyw.js.map +1 -0
  362. package/dist/typography.js +1 -1
  363. package/dist/{ui-provider-CftIB6TY.js → ui-provider-DRPn3qNl.js} +3 -2
  364. package/dist/ui-provider-DRPn3qNl.js.map +1 -0
  365. package/dist/ui-provider.js +1 -1
  366. package/dist/{upload-D8Za5x_c.js → upload-CDbYw1WN.js} +326 -323
  367. package/dist/upload-CDbYw1WN.js.map +1 -0
  368. package/dist/{upload-queue-hIIYBLS7.js → upload-queue-CNd_hH_a.js} +25 -25
  369. package/dist/upload-queue-CNd_hH_a.js.map +1 -0
  370. package/dist/{usage-card-DnmnJ58D.js → usage-card-VyJLUwRr.js} +53 -54
  371. package/dist/usage-card-VyJLUwRr.js.map +1 -0
  372. package/dist/utils-BvH9PSmq.js +4275 -0
  373. package/dist/utils-BvH9PSmq.js.map +1 -0
  374. package/dist/value-inputs-D0KCrfVC.js +840 -0
  375. package/dist/value-inputs-D0KCrfVC.js.map +1 -0
  376. package/dist/{workspace-C1PZmk8L.js → workspace-CcR8r-Nt.js} +115 -122
  377. package/dist/workspace-CcR8r-Nt.js.map +1 -0
  378. package/docs/consumer-skill/SKILL.md +110 -119
  379. package/docs/consumer-skill/examples/analytics.tsx +34 -0
  380. package/docs/consumer-skill/examples/app-layout.tsx +42 -12
  381. package/docs/consumer-skill/examples/detail.tsx +20 -4
  382. package/docs/consumer-skill/examples/manifest.json +13 -1
  383. package/docs/consumer-skill/examples/website.tsx +56 -0
  384. package/docs/consumer-skill/references/analytics.md +70 -0
  385. package/docs/consumer-skill/references/composition.md +116 -2
  386. package/docs/consumer-skill/references/design-contract.md +33 -7
  387. package/docs/consumer-skill/references/discovery.md +76 -5
  388. package/docs/consumer-skill/references/integration.md +14 -0
  389. package/docs/consumer-skill/references/public-api.json +2023 -218
  390. package/docs/consumer-skill/references/review.md +55 -3
  391. package/docs/consumer-skill/references/theming.md +52 -7
  392. package/docs/consumer-skill/references/tokens.json +177 -9
  393. package/docs/consumer-skill/references/workflows.md +32 -0
  394. package/docs/consumer-skill/scripts/check-composition.mjs +1 -1
  395. package/docs/consumer-skill/scripts/composition-policy.mjs +179 -17
  396. package/docs/consumer-skill/scripts/discovery.mjs +61 -9
  397. package/docs/consumer-skill/scripts/surface-policy.mjs +44 -0
  398. package/package.json +7 -4
  399. package/dist/accordion-B-5Focs8.js.map +0 -1
  400. package/dist/action-menu-Cx3SdfbN.js.map +0 -1
  401. package/dist/affordance-geometry.generated-D8Jcfb0G.js +0 -32
  402. package/dist/affordance-geometry.generated-D8Jcfb0G.js.map +0 -1
  403. package/dist/ai-artifact-B5tPpXnS.js.map +0 -1
  404. package/dist/app-shell-at8Kt4l_.js.map +0 -1
  405. package/dist/auth-OFwWSAap.js +0 -704
  406. package/dist/auth-OFwWSAap.js.map +0 -1
  407. package/dist/breadcrumbs-DdQ_I5ra.js.map +0 -1
  408. package/dist/button-BS6l5JUw.js.map +0 -1
  409. package/dist/buttons-Co6GavvM.js +0 -674
  410. package/dist/buttons-Co6GavvM.js.map +0 -1
  411. package/dist/chart-DVfcwQu6.js +0 -149
  412. package/dist/chart-DVfcwQu6.js.map +0 -1
  413. package/dist/checkbox-BavDRjF7.js.map +0 -1
  414. package/dist/choice-inputs-CC7XqPQO.js +0 -619
  415. package/dist/choice-inputs-CC7XqPQO.js.map +0 -1
  416. package/dist/code-block-xHKbAJDj.js.map +0 -1
  417. package/dist/combobox-DEbdr-3u.js.map +0 -1
  418. package/dist/combobox-xv3yJbzl.js.map +0 -1
  419. package/dist/command-C0xe7u9B.js.map +0 -1
  420. package/dist/comments-DviPLnwy.js +0 -1132
  421. package/dist/comments-DviPLnwy.js.map +0 -1
  422. package/dist/containers-6s-ucRQQ.js.map +0 -1
  423. package/dist/data-display-cWIRdeaf.js.map +0 -1
  424. package/dist/date-picker-CA6ogMQB.js.map +0 -1
  425. package/dist/date-pickers-BPIKLdsD.js +0 -224
  426. package/dist/date-pickers-BPIKLdsD.js.map +0 -1
  427. package/dist/feedback-DWUkgEjR.js.map +0 -1
  428. package/dist/field-affordance-recipes-IjzPrCTw.js +0 -17
  429. package/dist/field-affordance-recipes-IjzPrCTw.js.map +0 -1
  430. package/dist/field-state-recipes-CBTRt9Bt.js.map +0 -1
  431. package/dist/filters-BhsUtsxW.js.map +0 -1
  432. package/dist/form-field-Bn7ZH1rA.js.map +0 -1
  433. package/dist/form-sizing-BWs70_a2.js.map +0 -1
  434. package/dist/forms-numeric-BUBxELBv.js +0 -867
  435. package/dist/forms-numeric-BUBxELBv.js.map +0 -1
  436. package/dist/header-C59QZyxV.js.map +0 -1
  437. package/dist/http-CLTVJc5I.js.map +0 -1
  438. package/dist/input-WwYQZJzG.js +0 -202
  439. package/dist/input-WwYQZJzG.js.map +0 -1
  440. package/dist/input-ci9fIgFH.js +0 -20
  441. package/dist/input-ci9fIgFH.js.map +0 -1
  442. package/dist/item-pJ0GsOiJ.js.map +0 -1
  443. package/dist/media-gallery-DhDRgnVZ.js.map +0 -1
  444. package/dist/message-COsdEvXT.js +0 -108
  445. package/dist/message-COsdEvXT.js.map +0 -1
  446. package/dist/navigation-BUIn2Qxx.js.map +0 -1
  447. package/dist/navigation-DBEu4POU.js.map +0 -1
  448. package/dist/navigation-row-recipes-GVh11KiT.js.map +0 -1
  449. package/dist/overlays-B11wZka6.js +0 -982
  450. package/dist/overlays-B11wZka6.js.map +0 -1
  451. package/dist/page-BV6ioQg3.js.map +0 -1
  452. package/dist/page-header-DQRa0jug.js.map +0 -1
  453. package/dist/pagination-C29vvt3I.js.map +0 -1
  454. package/dist/popover-CoLDEg19.js.map +0 -1
  455. package/dist/popover.recipes-zgBhMlUu.js.map +0 -1
  456. package/dist/primitives-DKPOGVpj.js.map +0 -1
  457. package/dist/progress-BOe8l_FZ.js.map +0 -1
  458. package/dist/rich-text-editor-CoVrTiSv.js +0 -575
  459. package/dist/rich-text-editor-CoVrTiSv.js.map +0 -1
  460. package/dist/rich-text-editor.recipes-DxvOE0Lp.js.map +0 -1
  461. package/dist/scroll-area-BheMQ270.js.map +0 -1
  462. package/dist/select-B2mb-qN2.js +0 -108
  463. package/dist/select-B2mb-qN2.js.map +0 -1
  464. package/dist/sheet-B-q914Ad.js.map +0 -1
  465. package/dist/sidebar-C_2p3Tfj.js.map +0 -1
  466. package/dist/sidebar-DPR7fmqN.js.map +0 -1
  467. package/dist/smart-card-CYLn46e6.js.map +0 -1
  468. package/dist/surface-recipes-CQfRr-VL.js.map +0 -1
  469. package/dist/table-BS39xnlq.js +0 -1424
  470. package/dist/table-BS39xnlq.js.map +0 -1
  471. package/dist/table-DnlAJ-xR.js.map +0 -1
  472. package/dist/tabs-B5cNMWiP.js +0 -187
  473. package/dist/tabs-B5cNMWiP.js.map +0 -1
  474. package/dist/text-inputs-Dh9XGyiS.js +0 -331
  475. package/dist/text-inputs-Dh9XGyiS.js.map +0 -1
  476. package/dist/text.styles-BwB7vAF2.js.map +0 -1
  477. package/dist/timelines-B9ICkQcV.js.map +0 -1
  478. package/dist/typography-Cv8MT-82.js +0 -96
  479. package/dist/typography-Cv8MT-82.js.map +0 -1
  480. package/dist/ui-provider-CftIB6TY.js.map +0 -1
  481. package/dist/upload-D8Za5x_c.js.map +0 -1
  482. package/dist/upload-queue-hIIYBLS7.js.map +0 -1
  483. package/dist/usage-card-DnmnJ58D.js.map +0 -1
  484. package/dist/utils-C2EKeIw3.js +0 -72
  485. package/dist/utils-C2EKeIw3.js.map +0 -1
  486. package/dist/value-inputs-DX2dbxjj.js +0 -824
  487. package/dist/value-inputs-DX2dbxjj.js.map +0 -1
  488. package/dist/workspace-C1PZmk8L.js.map +0 -1
@@ -1,14 +1,33 @@
1
- import { surfaceParts, surfaceForwarders, paddingClass, paddingProperty, utility } from './surface-policy.mjs';
1
+ import { surfaceParts, surfaceForwarders, paddingClass, paddingProperty, utility, attenuatedFocusRing, sharedCornerParts, displayNames, nativeDisplayNames, marginProperty, radiusProperty, replacesSharedRadius, cornerRole, addsCopyMargin } from './surface-policy.mjs';
2
2
 
3
- const controlNames = /^(?:Base)?(?:Button|ButtonLink|IconButton)$|^(Input|InputGroupInput|Textarea|SelectTrigger|ComboboxTrigger)$/;
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']);
5
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|lineHeight|letterSpacing|borderRadius)$/;
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
+ }
7
25
 
8
26
  /** Small static review: TypeScript is supplied by the app, never a runtime peer. */
9
27
  export function analyzeComposition(text, { filename, index, ts }) {
10
28
  const kind = /\.jsx?$/.test(filename) ? ts.ScriptKind.JSX : filename.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
11
29
  const source = ts.createSourceFile(filename, text, ts.ScriptTarget.Latest, true, kind);
30
+ const symbolFor = sourceBindings(source, ts);
12
31
  const families = new Map(index.families.map(owner => [owner.import, owner]));
13
32
  const bindings = new Map();
14
33
  const namespaces = new Map();
@@ -33,7 +52,7 @@ export function analyzeComposition(text, { filename, index, ts }) {
33
52
  const resolve = (node, visiting = new Set()) => {
34
53
  if (!node || visiting.has(node)) return undefined;
35
54
  visiting.add(node);
36
- if (ts.isIdentifier(node)) return resolve(declarations.get(node.text), visiting);
55
+ if (ts.isIdentifier(node)) return resolve(declarations.get(symbolFor(node)), visiting);
37
56
  if (ts.isParenthesizedExpression(node) || ts.isAsExpression(node) || ts.isSatisfiesExpression(node)) return resolve(node.expression, visiting);
38
57
  return node;
39
58
  };
@@ -60,6 +79,20 @@ export function analyzeComposition(text, { filename, index, ts }) {
60
79
  if (!node || visited.has(node)) { if (expression) unknown(expression); return []; }
61
80
  visited.add(node);
62
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
+ }
63
96
  if (ts.isConditionalExpression(node)) return [...classStrings(node.whenTrue, visited), ...classStrings(node.whenFalse, visited)];
64
97
  if (ts.isBinaryExpression(node) && [ts.SyntaxKind.AmpersandAmpersandToken, ts.SyntaxKind.BarBarToken, ts.SyntaxKind.QuestionQuestionToken].includes(node.operatorToken.kind)) return classStrings(node.right, visited);
65
98
  if (ts.isArrayLiteralExpression(node)) return node.elements.flatMap(item => classStrings(item, visited));
@@ -83,12 +116,12 @@ export function analyzeComposition(text, { filename, index, ts }) {
83
116
  for (const item of elements) {
84
117
  const symbol = (item.propertyName ?? item.name).text;
85
118
  if (!family.symbols.includes(symbol)) add(item, 'public-symbol', 'error', `${specifier} does not export ${symbol}; inspect its declaration.`);
86
- if (ts.isImportDeclaration(node)) bindings.set(item.name.text, { symbol, import: specifier });
119
+ if (ts.isImportDeclaration(node)) bindings.set(symbolFor(item.name), { symbol, import: specifier });
87
120
  }
88
- if (names && ts.isNamespaceImport(names)) namespaces.set(names.name.text, specifier);
121
+ if (names && ts.isNamespaceImport(names)) namespaces.set(symbolFor(names.name), specifier);
89
122
  }
90
123
  function gather(node) {
91
- if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) declarations.set(node.name.text, node.initializer);
124
+ if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) declarations.set(symbolFor(node.name), node.initializer);
92
125
  if ((ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) && node.moduleSpecifier && ts.isStringLiteralLike(node.moduleSpecifier)) importOwner(node, node.moduleSpecifier.text);
93
126
  if (ts.isImportTypeNode(node) && ts.isLiteralTypeNode(node.argument) && ts.isStringLiteralLike(node.argument.literal)) importOwner(node, node.argument.literal.text);
94
127
  if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword && ts.isStringLiteralLike(node.arguments[0])) importOwner(node, node.arguments[0].text);
@@ -97,10 +130,11 @@ export function analyzeComposition(text, { filename, index, ts }) {
97
130
  gather(source);
98
131
  for (const diagnostic of source.parseDiagnostics) add(source, 'syntax', 'error', ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'));
99
132
  const ownerFor = tag => {
100
- if (bindings.has(tag)) return bindings.get(tag);
101
- const [namespace, symbol] = tag.split('.');
102
- const specifier = namespaces.get(namespace);
103
- return specifier && symbol ? { symbol, import: specifier } : undefined;
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
+ }
104
138
  };
105
139
  const attributes = node => node.attributes.properties.flatMap(attribute => {
106
140
  if (ts.isJsxSpreadAttribute(attribute)) return properties(attribute.expression);
@@ -108,6 +142,91 @@ export function analyzeComposition(text, { filename, index, ts }) {
108
142
  const expression = ts.isJsxExpression(attribute.initializer) ? attribute.initializer.expression : attribute.initializer;
109
143
  return [[attribute.name.getText(source), expression]];
110
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
+ };
111
230
  function visit(node, parents = []) {
112
231
  if (ts.isJsxElement(node)) {
113
232
  const element = node.openingElement;
@@ -121,34 +240,77 @@ export function analyzeComposition(text, { filename, index, ts }) {
121
240
  ts.forEachChild(node, child => visit(child, parents));
122
241
  }
123
242
  function inspect(node, parents) {
124
- const owner = ownerFor(node.tagName.getText(source));
125
- if (!owner) return;
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
+ }
126
258
  if (!families.get(owner.import)?.symbols.includes(owner.symbol)) {
127
259
  add(node, 'public-symbol', 'error', `${owner.import} does not export ${owner.symbol}.`);
128
260
  return;
129
261
  }
262
+ const unresolvedBeforeProps = unresolved.length;
130
263
  const props = new Map(attributes(node));
264
+ const unknownProps = unresolved.length !== unresolvedBeforeProps;
131
265
  const family = owner.import.split('/base/')[1];
132
266
  const anatomy = surfaceParts[family]?.test(owner.symbol);
133
267
  const forwarder = surfaceForwarders[family] === owner.symbol;
134
268
  const control = controlFamilies.has(family) && controlNames.test(owner.symbol);
135
- for (const name of ['className', 'contentClassName']) {
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']) {
136
274
  if (!props.has(name)) continue;
137
275
  const classes = classStrings(props.get(name)).flatMap(value => value.split(/\s+/)).map(utility);
138
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.`);
139
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.`);
140
282
  }
141
- if (props.has('style')) for (const [name] of properties(props.get('style'))) {
283
+ if (props.has('style')) for (const [name,value] of properties(props.get('style'))) {
142
284
  if (anatomy && paddingProperty.test(name)) add(node, 'surface-padding', 'error', `${owner.symbol}: ${name} replaces the region inset; use its public surface props.`);
143
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.`);
144
289
  }
145
290
  if (['SmartCard', 'ContentBlock'].includes(owner.symbol)) add(node, 'deprecated-owner', 'warning', `${owner.symbol} is a migration owner; prefer Card for new compositions.`);
146
- const framed = ['Card', 'SmartCard', 'ContentBlock', 'DataTable', 'DataView'].includes(owner.symbol) && literal(props.get('surface')) !== 'flat';
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.');
147
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.`);
148
309
  const header = properties(props.get('header'), false);
149
310
  const title = literal(props.get('title')) ?? literal(new Map(header).get('title'));
150
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.`);
151
- return { framed, title };
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 };
152
314
  }
153
315
  visit(source);
154
316
  return { findings, unresolved };
@@ -3,6 +3,10 @@ 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) {
@@ -17,7 +21,17 @@ export function validateIndex(index) {
17
21
  requireFormat(text(family.declaration) && /^dist\/[\w./-]+\.d\.ts$/.test(family.declaration) && !family.declaration.split('/').includes('..'), `invalid declaration ${family.declaration}`);
18
22
  requireFormat(layers.includes(family.layer) && text(family.responsibility), `missing layer/responsibility for ${family.import}`);
19
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}`);
20
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
+ }
21
35
  requireFormat(Array.isArray(family.guidance), `invalid guidance for ${family.import}`);
22
36
  for (const guide of family.guidance) {
23
37
  requireFormat(text(guide?.title) && typeof guide.description === 'string' && typeof guide.section === 'string', 'invalid guidance title/description/section');
@@ -56,28 +70,66 @@ export function parseArguments(args) {
56
70
  return { query, ...options };
57
71
  }
58
72
 
59
- 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
+ }
60
91
 
61
92
  export function findComponents(index, { query, layer = null, limit = 5 }) {
62
93
  validateIndex(index);
63
94
  const needle = normalized(query);
64
- 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())));
65
100
  const ranked = [];
66
101
  for (const family of index.families) {
67
102
  if (layer && layer !== family.layer) continue;
103
+ if (exactOwners.length && !exactOwners.includes(family)) continue;
68
104
  const exactImport = normalized(family.import) === needle;
69
- const matchedSymbols = family.symbols.filter(symbol => normalized(symbol) === needle);
70
- 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(' '));
71
109
  // AND matching prevents a familiar term from inventing results for an
72
110
  // otherwise unknown query. Avoidance/alternatives do not recommend owners.
73
- if (!exactImport && !matchedSymbols.length && !terms.every(term => haystack.includes(term))) continue;
111
+ if (!exactImport && !matchedSymbols.length && !containsTerms(haystack, terms)) continue;
74
112
  // A dedicated, documented owner precedes an aggregate re-export of the
75
113
  // same symbol. Explicit import queries still select the requested family.
76
- const documentedSymbol = family.guidance.some(guide => guide.sections.some(section => section.symbols.some(symbol => normalized(symbol) === needle)));
114
+ const documentedSymbol = matchedSymbols.some(symbol => documented.has(symbol));
115
+ const exactFamily = searchable(family.import.split('/').at(-1)) === terms.join(' ');
77
116
  const exactIntent = family.aliases.some(alias => normalized(alias) === needle);
78
- const score = exactImport ? 10000 : matchedSymbols.length ? 9000 + Number(documentedSymbol) : exactIntent ? 8000 : 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);
79
- 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);
80
- 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 });
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 });
81
133
  }
82
134
  ranked.sort((a, b) => b.score - a.score || compare(a.import, b.import));
83
135
  return { package: index.package, version: index.version, query, layer, limit, total: ranked.length, results: ranked.slice(0, limit) };
@@ -1,5 +1,6 @@
1
1
  // One public anatomy vocabulary, shared by repository and opt-in consumer checks.
2
2
  export const surfaceParts = {
3
+ cards: /^Card(?:Header|Content|Footer)?$/,
3
4
  popover: /^(PopoverContent|PopoverHeader|PopoverFooter)$/,
4
5
  command: /^Command(Input|List|Group|Item|Empty|Separator)?$/,
5
6
  navigation: /^DropdownMenu(Content|SubContent|Label|Item|LinkItem|SubTrigger|CheckboxItem|RadioItem|Separator)$/,
@@ -10,6 +11,41 @@ export const surfaceForwarders = { 'choice-inputs': 'Select', 'popover-menu': 'P
10
11
  export const paddingClass = /^(?:p[xytrblse]?|p(?:bs|be)|padding)-|^\[padding/;
11
12
  export const paddingProperty = /^padding(?:Inline|Block)?(?:Start|End)?$|^padding(?:Top|Right|Bottom|Left)$|^padding-(?:(?:inline|block)(?:-(?:start|end))?|top|right|bottom|left)$/;
12
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
+
13
49
  export function utility(token) {
14
50
  let depth = 0;
15
51
  let start = 0;
@@ -20,3 +56,11 @@ export function utility(token) {
20
56
  }
21
57
  return token.slice(start).replace(/^!|!$/g, '');
22
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,6 +1,6 @@
1
1
  {
2
2
  "name": "themelia-react-ui",
3
- "version": "1.0.1",
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",
@@ -447,7 +447,7 @@
447
447
  "test:browser": "npm run build:preview && node scripts/run-browser.mjs",
448
448
  "check:package": "node scripts/check-package.mjs",
449
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",
450
- "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",
451
451
  "lint": "node scripts/generate-utilities.mjs && oxlint src/components src/lib src/preview docs/consumer-skill/examples --deny-warnings",
452
452
  "check:design-lint": "node scripts/generate-utilities.mjs && node scripts/check-design-lint.mjs",
453
453
  "check:preview": "node scripts/check-preview.mjs",
@@ -516,6 +516,8 @@
516
516
  "@mdx-js/rollup": "^3.1.1",
517
517
  "@playwright/test": "^1.63.0",
518
518
  "@shadcn/lint": "0.2.0",
519
+ "@tailwindcss/node": "^4.3.3",
520
+ "@tailwindcss/oxide": "^4.3.3",
519
521
  "@tailwindcss/vite": "^4.3.3",
520
522
  "@tanstack/react-table": "^8.21.3",
521
523
  "@testing-library/jest-dom": "^6.0.0",
@@ -540,7 +542,9 @@
540
542
  "leaflet-draw": "^1.0.4",
541
543
  "leaflet.fullscreen": "^5.3.1",
542
544
  "leaflet.markercluster": "^1.5.3",
545
+ "lightningcss": "^1.33.0",
543
546
  "lucide-react": "^1.14.0",
547
+ "magic-string": "^0.30.21",
544
548
  "oxlint": "1.87.0",
545
549
  "qrcode": "^1.5.4",
546
550
  "react": "^19.2.5",
@@ -556,8 +560,7 @@
556
560
  "tw-animate-css": "^1.4.0",
557
561
  "typescript": "^5.9.3",
558
562
  "vite": "^8.0.0",
559
- "vitest": "^5.0.3",
560
- "magic-string": "^0.30.21"
563
+ "vitest": "^5.0.3"
561
564
  },
562
565
  "engines": {
563
566
  "node": ">=22.12.0"
@@ -1 +0,0 @@
1
- {"version":3,"file":"accordion-B-5Focs8.js","names":["Accordion","AccordionPrimitive","AccordionItem","AccordionTrigger","AccordionContent","Accordion","React","PrimitiveAccordion","PrimitiveAccordionItem","PrimitiveAccordionTrigger","PrimitiveAccordionContent","Accordion","Text","motionRecipes","Stack","DisclosurePanelElement","IconBadge","React$1","Accordion$2","props","Accordion","cn","className","AccordionItem$1","AccordionTrigger$1","children","ChevronDownIcon","AccordionContent$1","panelProps","Accordion$1","AccordionItem","AccordionTrigger","isSimpleText","AccordionContent","ACCORDION_ROOT_VARIANT_CLASS","ACCORDION_ITEM_VARIANT_CLASS","ACCORDION_TRIGGER_BASE","ACCORDION_CONTENT_PADDING","defaultSmartAccordionStrings","SmartAccordion","forwardRef","stringsProp","strings","useStrings","hasIconColumn","iconStyle","items","item","contentPadding","triggerGridClass","onValueChange","next","variant","itemClassName","triggerClassName","SmartAccordionIcon","isSimpleContent","contentClassName","content","reserveSpace","icon"],"sources":["../src/components/ui/accordion.tsx","../src/components/base/accordion/accordion.tsx","../src/components/base/accordion/accordion-variants.ts","../src/components/base/accordion/accordion.strings.ts","../src/components/base/accordion/smart-accordion.tsx"],"sourcesContent":["import { DisclosurePanelElement } from './disclosure-panel';\nimport { motionRecipes } from '../../lib/motion-recipes';\nimport { Accordion as AccordionPrimitive } from \"@base-ui/react/accordion\"\n\nimport { cn } from \"../../lib/utils\"\nimport { ChevronDownIcon } from \"lucide-react\"\n\nfunction Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n className={cn(\"border-border accordion--component flex w-full flex-col border box-border overflow-hidden\", className)}\n {...props}\n />\n )\n}\n\nfunction AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\"border-border accordion-item--component border-b last:border-b-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: AccordionPrimitive.Trigger.Props) {\n return (\n <AccordionPrimitive.Header className=\"accordion-header m-0\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\"accordion-trigger--component flex w-full items-center justify-between border-0 bg-transparent outline-none cursor-pointer box-border\", className)}\n {...props}\n >\n {children}\n <ChevronDownIcon data-slot=\"accordion-trigger-icon\" className={cn(\"accordion-trigger--icon size-icon text-muted-foreground shrink-0 [[aria-expanded=true]_&]:rotate-180\", motionRecipes.chevron)} />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\nfunction AccordionContent({\n className,\n children,\n render,\n ...props\n}: AccordionPrimitive.Panel.Props) {\n return (\n <AccordionPrimitive.Panel\n data-slot=\"accordion-content\"\n className={cn(\"accordion-content--component box-border text-foreground h-(--accordion-panel-height)\", motionRecipes.disclosure, className)}\n {...props}\n render={(panelProps, state) => <DisclosurePanelElement props={panelProps} state={state} render={render} heightVariable=\"--accordion-panel-height\" />}\n >\n {children}\n </AccordionPrimitive.Panel>\n )\n}\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\n\n","/**\n * Accordion — tokenized base wrapper around the shadcn/Base UI primitive.\n *\n * The internal primitive intentionally keeps shadcn's roomy defaults. This\n * public layer calibrates them for admin surfaces: radius tokens, 12px row\n * insets, density-aware vertical rhythm, quiet hover/focus treatments, and\n * matching trigger/content columns. Consumers retain the complete compound\n * API and can override any treatment with `className`.\n */\nimport * as React from 'react';\n\nimport {\n\tAccordion as PrimitiveAccordion,\n\tAccordionContent as PrimitiveAccordionContent,\n\tAccordionItem as PrimitiveAccordionItem,\n\tAccordionTrigger as PrimitiveAccordionTrigger,\n} from '../../ui/accordion';\nimport { Text } from '../../typography';\nimport { cn } from '../../../lib/utils';\n\nexport type AccordionProps = React.ComponentPropsWithoutRef<typeof PrimitiveAccordion>;\nexport type AccordionItemProps = React.ComponentPropsWithoutRef<typeof PrimitiveAccordionItem>;\nexport type AccordionTriggerProps = React.ComponentPropsWithoutRef<typeof PrimitiveAccordionTrigger>;\nexport type AccordionContentProps = React.ComponentPropsWithoutRef<typeof PrimitiveAccordionContent>;\n\nconst Accordion = React.forwardRef<React.ElementRef<typeof PrimitiveAccordion>, AccordionProps>(\n\tfunction Accordion({ className, ...props }, ref) {\n\t\treturn (\n\t\t\t<PrimitiveAccordion\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'accordion--component rounded-radius-lg border-border bg-card',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nAccordion.displayName = 'Accordion';\n\nconst AccordionItem = React.forwardRef<React.ElementRef<typeof PrimitiveAccordionItem>, AccordionItemProps>(\n\tfunction AccordionItem({ className, ...props }, ref) {\n\t\treturn (\n\t\t\t<PrimitiveAccordionItem\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'accordion-item--component border-border data-open:bg-muted/30',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nAccordionItem.displayName = 'AccordionItem';\n\nconst AccordionTrigger = React.forwardRef<React.ElementRef<typeof PrimitiveAccordionTrigger>, AccordionTriggerProps>(\n\tfunction AccordionTrigger({ className, children, ...props }, ref) {\n\t\tconst isSimpleText = typeof children === 'string' || typeof children === 'number' || typeof children === 'bigint';\n\t\treturn (\n\t\t\t<PrimitiveAccordionTrigger\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'accordion-trigger--component min-h-action items-center gap-space-lg px-row-x py-row-y',\n\t\t\t\t\t'text-left text-sm font-medium transition-colors hover:bg-muted/40 hover:no-underline',\n\t\t\t\t\t'focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-ring/50',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{isSimpleText ? (\n\t\t\t\t\t<Text tag=\"span\" size=\"inherit\" weight=\"medium\" lineHeight=\"tight\" className=\"text-inherit\">\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</Text>\n\t\t\t\t) : children}\n\t\t\t</PrimitiveAccordionTrigger>\n\t\t);\n\t},\n);\nAccordionTrigger.displayName = 'AccordionTrigger';\n\nconst AccordionContent = React.forwardRef<React.ElementRef<typeof PrimitiveAccordionContent>, AccordionContentProps>(\n\tfunction AccordionContent({ className, children, ...props }, ref) {\n\t\tconst isSimpleText = typeof children === 'string' || typeof children === 'number' || typeof children === 'bigint';\n\t\treturn (\n\t\t\t<PrimitiveAccordionContent\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'accordion-content--component px-row-x pb-space-lg text-sm',\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{isSimpleText ? (\n\t\t\t\t\t<Text tag=\"div\" size=\"inherit\" lineHeight=\"relaxed\" className=\"text-inherit\">\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</Text>\n\t\t\t\t) : children}\n\t\t\t</PrimitiveAccordionContent>\n\t\t);\n\t},\n);\nAccordionContent.displayName = 'AccordionContent';\n\nexport {\n\tAccordion,\n\tAccordionItem,\n\tAccordionTrigger,\n\tAccordionContent,\n};\n","/**\n * Shared accordion-shell variant classes — used by both `SmartAccordion`\n * and any blocks surface that builds on `base/accordion` directly\n * (e.g. `blocks/onboarding/checklist`).\n *\n * Exported because two consumers already keep it in lockstep; a third\n * one will copy this exact map. Centralising means a future tweak\n * (e.g. tighten `card` items to `border-border/70`) propagates.\n *\n * Padding tokens for trigger / content live alongside so the rhythm\n * is shared too:\n *\n * - Trigger: `gap-space-lg px-row-x py-row-y` — density-driven,\n * `<UIProvider>`\n * override flows through.\n * - Content padding accounts for the base panel's `px-row-x`.\n * Medallion and inline rows use shared media/spacing tokens, and\n * no-icon rows add no extra left padding so body copy tracks the\n * trigger text column instead of drifting.\n */\nimport type { DisclosureSurface } from '../../../lib/component-vocabulary';\n\nexport type AccordionShellVariant = DisclosureSurface;\n\nexport const ACCORDION_ROOT_VARIANT_CLASS: Record<AccordionShellVariant, string> = {\n\tcard: 'gap-space-md border-0 rounded-none bg-transparent overflow-visible',\n\tbordered: 'rounded-radius-lg border border-border bg-card overflow-hidden',\n\tflat: 'border-0 rounded-none bg-transparent overflow-visible',\n};\n\nexport const ACCORDION_ITEM_VARIANT_CLASS: Record<AccordionShellVariant, string> = {\n\tcard: 'border border-border bg-card rounded-radius data-open:bg-muted/25',\n\tbordered: 'bg-transparent not-last:border-b border-border data-open:bg-muted/30',\n\tflat: 'border-0 not-last:border-b-0 bg-transparent data-open:bg-muted/30 rounded-radius',\n};\n\nexport const ACCORDION_TRIGGER_BASE =\n\t'items-center gap-space-lg px-row-x py-row-y text-left hover:no-underline';\n\n/**\n * Content-padding presets keyed off the leading-icon width. Use\n * `withMedallion` when the trigger renders a default `IconBadge`\n * plus the shared row gap so body text aligns under the title at every\n * consumer density.\n */\nexport const ACCORDION_CONTENT_PADDING = {\n\twithMedallion: 'pl-[calc(var(--spacing-row-x)+var(--spacing-avatar)+var(--spacing-space-lg))] pr-row-x pt-0',\n\twithInline: 'pl-[calc(var(--spacing-row-x)+var(--spacing-icon-lg)+var(--spacing-space-lg))] pr-row-x pt-0',\n\twithoutIcon: 'px-row-x pt-0',\n} as const;\n","/**\n * Strings for `SmartAccordion`. There aren't many — Radix handles the\n * trigger ARIA states automatically, so the only library-owned copy is\n * the optional landmark label on the wrapping nav region. Consumers\n * override per-item `title` / `badge` / `content` directly via\n * `SmartAccordionItem` props (the strings live in the data, not here).\n */\nexport interface SmartAccordionStrings {\n\t/**\n\t * Sets `aria-label` on the wrapping element so screen readers can name\n\t * the accordion region. Optional — when absent, no aria-label is set.\n\t */\n\tregionAriaLabel?: string;\n}\n\nexport const defaultSmartAccordionStrings: SmartAccordionStrings = {\n\tregionAriaLabel: undefined,\n};\n","/**\n * SmartAccordion — the canonical \"icon + title + optional badge + body\"\n * accordion pattern, with three visual variants for the surface chrome\n * (`card` | `bordered` | `flat`) and three icon framings (`medallion` |\n * `inline` | `none`).\n *\n * Composes the wrapped `base/accordion` parts (rule 2 — blocks-style\n * convenience built from re-exports, not the raw shadcn primitive).\n *\n * For richer rows (multi-line metadata, custom layouts), drop down to\n * the compound API:\n *\n * import { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\n * from '.';\n */\nimport { forwardRef, type ReactNode } from 'react';\n\nimport { IconBadge } from '../display/icon-badge';\nimport { Stack } from '../structure';\nimport { Text } from '../../typography';\nimport { useStrings } from '../../../lib/strings';\nimport { cn } from '../../../lib/utils';\n\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './accordion';\nimport {\n\tACCORDION_CONTENT_PADDING,\n\tACCORDION_ITEM_VARIANT_CLASS,\n\tACCORDION_ROOT_VARIANT_CLASS,\n\tACCORDION_TRIGGER_BASE,\n} from './accordion-variants';\nimport { defaultSmartAccordionStrings } from './accordion.strings';\nimport type {\n\tSmartAccordionIconStyle,\n\tSmartAccordionProps,\n} from './accordion.types';\n\n/**\n * Bounded accordion composition for repeated icon, title, description, badge,\n * and body sections. Use the compound Accordion parts when row structure or\n * per-item presentation differs.\n */\nexport const SmartAccordion = forwardRef<HTMLDivElement, SmartAccordionProps>(function SmartAccordion({\n\titems,\n\tmultiple = false,\n\tdefaultValue,\n\tvalue,\n\tonValueChange,\n\tvariant = 'bordered',\n\ticonStyle = 'inline',\n\tclassName,\n\titemClassName,\n\ttriggerClassName,\n\tcontentClassName,\n\tstrings: stringsProp,\n}, ref) {\n\tconst strings = useStrings(defaultSmartAccordionStrings, stringsProp);\n\tconst hasIconColumn = iconStyle !== 'none' && items.some((item) => item.icon != null);\n\tconst contentPadding =\n\t\t!hasIconColumn\n\t\t\t? ACCORDION_CONTENT_PADDING.withoutIcon\n\t\t\t: iconStyle === 'medallion'\n\t\t\t? ACCORDION_CONTENT_PADDING.withMedallion\n\t\t\t: ACCORDION_CONTENT_PADDING.withInline;\n\tconst triggerGridClass = !hasIconColumn\n\t\t? 'grid-cols-[minmax(0,1fr)]'\n\t\t: 'grid-cols-[auto_minmax(0,1fr)]';\n\treturn (\n\t\t<Accordion\n\t\t\tref={ref}\n\t\t\tmultiple={multiple}\n\t\t\tdefaultValue={defaultValue}\n\t\t\tvalue={value}\n\t\t\tonValueChange={\n\t\t\t\tonValueChange\n\t\t\t\t\t? (next) => onValueChange(next as string[])\n\t\t\t\t\t: undefined\n\t\t\t}\n\t\t\taria-label={strings.regionAriaLabel}\n\t\t\tdata-variant={variant}\n\t\t\tdata-icon-style={iconStyle}\n\t\t\tclassName={cn('smart-accordion--component', ACCORDION_ROOT_VARIANT_CLASS[variant], className)}\n\t\t>\n\t\t\t{items.map((item) => (\n\t\t\t\t<AccordionItem\n\t\t\t\t\tkey={item.value}\n\t\t\t\t\tvalue={item.value}\n\t\t\t\t\tclassName={cn('smart-accordion--item', ACCORDION_ITEM_VARIANT_CLASS[variant], itemClassName)}\n\t\t\t\t>\n\t\t\t\t\t<AccordionTrigger\n\t\t\t\t\t\tclassName={cn('smart-accordion--trigger', ACCORDION_TRIGGER_BASE, triggerClassName)}\n\t\t\t\t\t\tdisabled={item.disabled}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div className={cn('grid min-w-0 flex-1 items-center gap-x-space-lg', triggerGridClass)}>\n\t\t\t\t\t\t\t<SmartAccordionIcon\n\t\t\t\t\t\t\t\ticonStyle={iconStyle}\n\t\t\t\t\t\t\t\ticon={item.icon}\n\t\t\t\t\t\t\t\treserveSpace={hasIconColumn}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<Stack render={<span />} gap=\"dense\" className=\"smart-accordion--heading flex-1\">\n\t\t\t\t\t\t\t\t<span className=\"flex min-w-0 flex-wrap items-center gap-x-space-md gap-y-space-xs\">\n\t\t\t\t\t\t\t\t\t{isSimpleContent(item.title) ? (\n\t\t\t\t\t\t\t\t\t\t<Text tag=\"span\" weight=\"semibold\" className=\"smart-accordion--title min-w-0\">\n\t\t\t\t\t\t\t\t\t\t\t{item.title}\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t) : item.title}\n\t\t\t\t\t\t\t\t\t{item.badge != null && (\n\t\t\t\t\t\t\t\t\t\t<span className=\"smart-accordion--badge inline-flex shrink-0\">{item.badge}</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t{!!item.description && (\n\t\t\t\t\t\t\t\t\tisSimpleContent(item.description) ? (\n\t\t\t\t\t\t\t\t\t\t<Text tag=\"span\" type=\"secondary\" className=\"smart-accordion--description min-w-0\">\n\t\t\t\t\t\t\t\t\t\t\t{item.description}\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t) : item.description\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</AccordionTrigger>\n\t\t\t\t\t<AccordionContent\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'smart-accordion--content',\n\t\t\t\t\t\t\tcontentPadding,\n\t\t\t\t\t\t\tcontentClassName,\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isSimpleContent(item.content) ? (\n\t\t\t\t\t\t\t<Text tag=\"div\" type=\"secondary\" lineHeight=\"relaxed\">\n\t\t\t\t\t\t\t\t{item.content}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t) : item.content}\n\t\t\t\t\t</AccordionContent>\n\t\t\t\t</AccordionItem>\n\t\t\t))}\n\t\t</Accordion>\n\t);\n});\n\nSmartAccordion.displayName = 'SmartAccordion';\n\nfunction isSimpleContent(content: ReactNode): content is string | number | bigint {\n\treturn typeof content === 'string' || typeof content === 'number' || typeof content === 'bigint';\n}\n\nfunction SmartAccordionIcon({\n\ticonStyle,\n\ticon,\n\treserveSpace,\n}: {\n\ticonStyle: SmartAccordionIconStyle;\n\ticon?: ReactNode;\n\treserveSpace: boolean;\n}) {\n\tif (iconStyle === 'none' || !reserveSpace) return null;\n\tif (!icon) {\n\t\treturn (\n\t\t\t<span\n\t\t\t\taria-hidden=\"true\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'smart-accordion--icon inline-flex shrink-0',\n\t\t\t\t\ticonStyle === 'inline' ? 'size-icon-lg' : 'size-avatar',\n\t\t\t\t)}\n\t\t\t/>\n\t\t);\n\t}\n\tif (iconStyle === 'inline') {\n\t\treturn (\n\t\t\t<span\n\t\t\t\taria-hidden=\"true\"\n\t\t\t\tclassName=\"smart-accordion--icon inline-flex size-icon-lg shrink-0 self-center text-muted-foreground [&>svg]:size-icon\"\n\t\t\t>\n\t\t\t\t{icon}\n\t\t\t</span>\n\t\t);\n\t}\n\treturn (\n\t\t<IconBadge size=\"md\" tone=\"neutral\" shape=\"circle\" aria-hidden=\"true\" className=\"smart-accordion--icon self-center\">\n\t\t\t{icon}\n\t\t</IconBadge>\n\t);\n}\n"],"mappings":"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"}