@tmorrow/cre8-wc 2.0.7 → 2.1.0

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 (333) hide show
  1. package/a2ui/catalog +5 -5
  2. package/a2ui/catalog-kg.json +156 -20
  3. package/a2ui/catalog.compact.json +2466 -0
  4. package/a2ui/catalog.json +1636 -139
  5. package/a2ui/catalog.svg +2445 -2445
  6. package/a2ui/check-layer-parity.mjs +277 -0
  7. package/a2ui/examples/compound-families.json +298 -0
  8. package/a2ui/examples/llm-observability.json +678 -650
  9. package/a2ui/generate-catalog.mjs +256 -5
  10. package/a2ui/inert-props.json +32 -0
  11. package/a2ui/registry.js +28 -0
  12. package/a2ui/registry.ts +31 -0
  13. package/a2ui/render-audit.mjs +294 -0
  14. package/a2ui/renderer.d.ts +2 -1
  15. package/a2ui/renderer.js +1 -1
  16. package/a2ui/renderer.ts +1 -1
  17. package/a2ui/smoke-test.mjs +39 -5
  18. package/a2ui/stream/diff-test.mjs +299 -0
  19. package/a2ui/stream/diff.d.ts +28 -0
  20. package/a2ui/stream/diff.js +130 -0
  21. package/a2ui/stream/diff.ts +145 -0
  22. package/a2ui/stream/index.d.ts +11 -0
  23. package/a2ui/stream/index.js +11 -0
  24. package/a2ui/stream/index.ts +43 -0
  25. package/a2ui/stream/model.d.ts +66 -0
  26. package/a2ui/stream/model.js +429 -0
  27. package/a2ui/stream/model.ts +472 -0
  28. package/a2ui/stream/pointer.d.ts +34 -0
  29. package/a2ui/stream/pointer.js +146 -0
  30. package/a2ui/stream/pointer.ts +147 -0
  31. package/a2ui/stream/renderer.d.ts +51 -0
  32. package/a2ui/stream/renderer.js +282 -0
  33. package/a2ui/stream/renderer.ts +291 -0
  34. package/a2ui/stream/stream-test.mjs +592 -0
  35. package/a2ui/stream/types.d.ts +173 -0
  36. package/a2ui/stream/types.js +17 -0
  37. package/a2ui/stream/types.ts +127 -0
  38. package/a2ui/types.d.ts +5 -0
  39. package/a2ui/types.ts +5 -0
  40. package/cdn/cre8-wc.esm.js +3527 -3226
  41. package/cdn/cre8-wc.esm.js.map +1 -1
  42. package/cdn/cre8-wc.min.js +289 -289
  43. package/cdn/cre8-wc.min.js.map +1 -1
  44. package/dist/assets/{Changelog-Documentation-BguNswiM.js → Changelog-Documentation-CeOetLxK.js} +1 -1
  45. package/dist/assets/{Code-Guidelines-BM3dZyzL.js → Code-Guidelines-BjdezAjj.js} +1 -1
  46. package/dist/assets/{Color-6AOWCN3U-C4AEGNk3.js → Color-6AOWCN3U-DPFGZitI.js} +1 -1
  47. package/dist/assets/{Contributing-Guidelines-DZURVehh.js → Contributing-Guidelines-B1M2V1hW.js} +1 -1
  48. package/dist/assets/{DocsRenderer-JROSPFPF-DeZmCI9u.js → DocsRenderer-JROSPFPF-BBy8KWNl.js} +1 -1
  49. package/dist/assets/{Tokens-Documentation-ZecGbtQg.js → Tokens-Documentation-CdTxFDLe.js} +1 -1
  50. package/dist/assets/{WithTooltip-7X4HQR7L-2Hfrkir-.js → WithTooltip-7X4HQR7L-DZzTNMQ7.js} +1 -1
  51. package/dist/assets/{accordion-item.stories-D-MjrX5G.js → accordion-item.stories-Bl26JlHp.js} +1 -9
  52. package/dist/assets/{accordion.stories-icgNa1dl.js → accordion.stories-DjoLApQw.js} +3 -11
  53. package/dist/assets/{alert.stories-BzDaXtj-.js → alert.stories-pO1y3YCQ.js} +15 -31
  54. package/dist/assets/{badge-C5wOWgyg.js → badge-BTxW3bN2.js} +3 -11
  55. package/dist/assets/{badge.stories-5GfB4jVI.js → badge.stories-vqh63RJ2.js} +1 -1
  56. package/dist/assets/{band.stories-DhXaP_kL.js → band.stories-CjKRppSb.js} +1 -9
  57. package/dist/assets/{blocks-DhUVut8Z.js → blocks-1be_-L6v.js} +5 -5
  58. package/dist/assets/{breadcrumbs.stories-CrPUBVk1.js → breadcrumbs.stories-Doyfy3V9.js} +2 -18
  59. package/dist/assets/{button-CJL8yzAT.js → button-CgaWukz0.js} +1 -9
  60. package/dist/assets/{button-group-BgwgtSFC.js → button-group-G7qN4MwM.js} +1 -9
  61. package/dist/assets/{button-group.stories-W-07gO63.js → button-group.stories-cL3Kay6M.js} +1 -1
  62. package/dist/assets/{button.stories-BPzJ-sCv.js → button.stories-C9HSpxWb.js} +6 -6
  63. package/dist/assets/{card.stories-mlFGY2Xn.js → card.stories-BbU8YymD.js} +3 -11
  64. package/dist/assets/{chart.stories-C8yuHHeK.js → chart.stories-BL4FxIA_.js} +1 -1
  65. package/dist/assets/{checkbox-field-item-iHcdmTNw.js → checkbox-field-item-DIMHcWM0.js} +1 -9
  66. package/dist/assets/{checkbox-field-item.stories-D1aVLDXn.js → checkbox-field-item.stories-XbB4x_lO.js} +1 -1
  67. package/dist/assets/{checkbox-field.stories-BoVB2jCx.js → checkbox-field.stories-YnqFUI4K.js} +2 -10
  68. package/dist/assets/{cre8-element-DfmMtHJO.js → cre8-element-B35i4Lyg.js} +1 -1
  69. package/dist/assets/{cre8-form-element-bQpK8UYN.js → cre8-form-element-Cfc5VeYV.js} +1 -1
  70. package/dist/assets/{danger-button.stories-Cb4ljnhQ.js → danger-button.stories-xh25hmfd.js} +1 -9
  71. package/dist/assets/{date-picker.stories-Cje3qk8D.js → date-picker.stories-DD_ctzEF.js} +1 -49
  72. package/dist/assets/{divider-B_PXBGWD.js → divider-xZ2KARHf.js} +2 -10
  73. package/dist/assets/{divider.stories-CtfeBqVV.js → divider.stories-Bk9oF-OV.js} +1 -1
  74. package/dist/assets/{dropdown-Cgwne34I.js → dropdown-BEP5x3CW.js} +6 -22
  75. package/dist/assets/{dropdown-item.stories-pXkDLRuv.js → dropdown-item.stories-Iaw_UrEP.js} +1 -1
  76. package/dist/assets/{dropdown.stories-DZnmHieY.js → dropdown.stories-B0OlKD7h.js} +1 -1
  77. package/dist/assets/{example-drug-card.stories-DTzLXTFx.js → example-drug-card.stories-Bp5JIeE_.js} +1 -1
  78. package/dist/assets/{f-po-C2WpbOFJ.js → f-po-BdPzDRD-.js} +1 -1
  79. package/dist/assets/{feature.stories-DffXdJch.js → feature.stories-DYE1Js70.js} +1 -9
  80. package/dist/assets/{field-DzYRqQb2.js → field-BpUYyRW1.js} +1 -9
  81. package/dist/assets/{field-note-DKXZiXLU.js → field-note-fccBckVl.js} +3 -11
  82. package/dist/assets/{field-note.stories-DS_0bQul.js → field-note.stories-BH9AZMbF.js} +1 -1
  83. package/dist/assets/{field.stories-BvXn0oG6.js → field.stories-BQPtmziK.js} +1 -1
  84. package/dist/assets/{footer.stories-C3ZibisU.js → footer.stories-DCWEciqD.js} +1 -9
  85. package/dist/assets/{form-example.stories-C-TuOeF2.js → form-example.stories-9IDC0AgX.js} +1 -1
  86. package/dist/assets/{formatter-L2YTDE3Q-CJVnxOUW.js → formatter-L2YTDE3Q-B9u1AOWn.js} +1 -1
  87. package/dist/assets/{global-nav-item-xQL7wVjY.js → global-nav-item-T4htN-yO.js} +6 -14
  88. package/dist/assets/{global-nav-item.stories-Dp9TE3aR.js → global-nav-item.stories-2dWRfCXv.js} +1 -1
  89. package/dist/assets/{global-nav.stories-B5Nk8JZ0.js → global-nav.stories-Fh1gScqg.js} +2 -10
  90. package/dist/assets/{grid-DYgnZBsd.js → grid-C5CKMXNe.js} +3 -19
  91. package/dist/assets/{grid.stories-BFiXTq2C.js → grid.stories-BLmCNdeA.js} +1 -1
  92. package/dist/assets/{header.stories-D1f7xhjV.js → header.stories-BkDrjJtj.js} +1 -9
  93. package/dist/assets/{heading-485Jz7JZ.js → heading-Dbka33DK.js} +2 -10
  94. package/dist/assets/{heading.stories-gPF_SmTc.js → heading.stories-Be40_bmG.js} +1 -1
  95. package/dist/assets/{hero.stories-BHlFNdvF.js → hero.stories-vRu7PZG9.js} +1 -9
  96. package/dist/assets/{icon-DeTLDzTS.js → icon-ChfRWXWy.js} +2 -10
  97. package/dist/assets/{icon-description-o-YaiEjK.js → icon-description-BBSwDykJ.js} +1 -1
  98. package/dist/assets/{icon-description.stories-BdPRvEwe.js → icon-description.stories-Cg6ekOme.js} +1 -1
  99. package/dist/assets/{icon.stories-BxWpqxT5.js → icon.stories-Cj4U7L5G.js} +1 -1
  100. package/dist/assets/if-defined-Bxnzk64Q.js +1 -0
  101. package/dist/assets/{iframe-dHvya7sk.js → iframe-BNJP6ovU.js} +35 -35
  102. package/dist/assets/{inline-alert.stories-FH0bQ0jh.js → inline-alert.stories-CygBYI02.js} +1 -9
  103. package/dist/assets/{layout-container.stories-D6Z6Kx78.js → layout-container.stories-TMyIJteJ.js} +2 -10
  104. package/dist/assets/{layout.stories-CNYuwC_r.js → layout.stories-ylRM-ANL.js} +7 -23
  105. package/dist/assets/{linelength-container.stories-pCRXZvxS.js → linelength-container.stories-Br2v8jXE.js} +1 -9
  106. package/dist/assets/{link-BpCiLxNW.js → link-CRE0Eqdo.js} +1 -9
  107. package/dist/assets/{link-list.stories-12vsAa1P.js → link-list.stories--y-urrVo.js} +7 -23
  108. package/dist/assets/{link.stories-DAoQtY4_.js → link.stories-C3WQOgkY.js} +2 -2
  109. package/dist/assets/{list.stories-D0N3yBIf.js → list.stories-Bd2bxkxn.js} +7 -23
  110. package/dist/assets/{loading-spinner-g6iJajXH.js → loading-spinner-C52KNq6y.js} +4 -12
  111. package/dist/assets/{loading-spinner.stories-B6_mgPxB.js → loading-spinner.stories-DPRGEeHT.js} +1 -1
  112. package/dist/assets/{logo.stories-BvMwN2qg.js → logo.stories-2LBqqraT.js} +1 -9
  113. package/dist/assets/{main.stories-pL4zefbs.js → main.stories-BQzD7iWD.js} +2 -10
  114. package/dist/assets/{medication-card.stories-DK1XGJic.js → medication-card.stories-Wc-hA0-s.js} +5 -5
  115. package/dist/assets/{medication-form.stories-Bj5dLp5S.js → medication-form.stories-DfFOCDaU.js} +1 -1
  116. package/dist/assets/{modal-CO0M4e_8.js → modal-CCfbY4fF.js} +1 -9
  117. package/dist/assets/{modal-BNu8xy08.js → modal-GglWRNJp.js} +1 -1
  118. package/dist/assets/{modal.stories-CHYBrq_E.js → modal.stories-CpybCs79.js} +1 -1
  119. package/dist/assets/{multi-select.stories-C9XXsWio.js → multi-select.stories-BhzEKRui.js} +1 -9
  120. package/dist/assets/{nav-container.stories-DU9fhvDu.js → nav-container.stories-Be1YlegP.js} +3 -11
  121. package/dist/assets/{page-header.stories-BrstKiEY.js → page-header.stories-BOVLQ0YF.js} +1 -9
  122. package/dist/assets/{pagination.stories-Bw2M2iOn.js → pagination.stories-D62sa_1K.js} +9 -25
  123. package/dist/assets/{percent-bar.stories-UQRXYUqd.js → percent-bar.stories-CYi4El7T.js} +1 -9
  124. package/dist/assets/{popover.stories-ZkwrRFpR.js → popover.stories-B9O8F4yv.js} +1 -9
  125. package/dist/assets/{primary-nav.stories-wqOKwgQn.js → primary-nav.stories-Bt-o7h45.js} +1 -17
  126. package/dist/assets/{progress-meter-TzASasu0.js → progress-meter-Dit59091.js} +1 -9
  127. package/dist/assets/{progress-meter.stories-qfJALZf8.js → progress-meter.stories-CYnOCmjo.js} +1 -1
  128. package/dist/assets/{progress-steps-item-KvW1d_7L.js → progress-steps-item-CWJsad0s.js} +1 -9
  129. package/dist/assets/{progress-steps-item.stories-uOn6tJ1W.js → progress-steps-item.stories-ePn_6bPn.js} +1 -1
  130. package/dist/assets/{progress-steps.stories-CKFPx8D0.js → progress-steps.stories-CblrEcXF.js} +1 -9
  131. package/dist/assets/{radio-field-item-CTaR50XR.js → radio-field-item-Bm-0RWPe.js} +5 -21
  132. package/dist/assets/{radio-field-item.stories-DQSLj8W1.js → radio-field-item.stories-y_TrTRIW.js} +1 -1
  133. package/dist/assets/{radio-field.stories-Btmc_Iep.js → radio-field.stories-CSWrbUrn.js} +1 -1
  134. package/dist/assets/{remove-tag-BSEZ7VT8.js → remove-tag-lCr57c5r.js} +1 -9
  135. package/dist/assets/{remove-tag.stories-diRKi7Ua.js → remove-tag.stories-CDfwCdvZ.js} +1 -1
  136. package/dist/assets/{request-prescription.stories-DQvra7ia.js → request-prescription.stories-O4zqokfb.js} +1 -1
  137. package/dist/assets/{sample-modal.stories-deE1EBfZ.js → sample-modal.stories-BZ4N2R2Z.js} +1 -1
  138. package/dist/assets/{section.stories-DF4mcy2O.js → section.stories-D_1InThX.js} +1 -9
  139. package/dist/assets/{select-tile-D-C8oSrm.js → select-tile-BqqB3ZtE.js} +2 -10
  140. package/dist/assets/{select-tile-list.stories-vsBQUIcl.js → select-tile-list.stories-Di4ILgV8.js} +1 -9
  141. package/dist/assets/{select-tile.stories-CqHzN5fc.js → select-tile.stories-D3h_6zlV.js} +6 -6
  142. package/dist/assets/{select.stories-8aOGxTtr.js → select.stories-BB2phP9A.js} +1 -9
  143. package/dist/assets/{skeleton-loader.stories-CwR2-aC5.js → skeleton-loader.stories-y4uml_kV.js} +5 -13
  144. package/dist/assets/{split-button.stories-CyfdrK4u.js → split-button.stories-C_82I4ME.js} +2 -10
  145. package/dist/assets/{spread-BPiNgQQF.js → spread-CnPic3C2.js} +1 -1
  146. package/dist/assets/state-DkQhleoO.js +1 -0
  147. package/dist/assets/{submenu.stories-CDhNzZzh.js → submenu.stories-UDtaREr1.js} +2 -18
  148. package/dist/assets/{syntaxhighlighter-T5IQBZDB-BzI6WxUR.js → syntaxhighlighter-T5IQBZDB-D-I_s_yD.js} +1 -1
  149. package/dist/assets/{table-header-CfcchoYz.js → table-header-2837i43H.js} +3 -51
  150. package/dist/assets/{table-object.stories-Bd5qdfMU.js → table-object.stories-D4KoI-wA.js} +1 -9
  151. package/dist/assets/{table.stories-DxuBe9dJ.js → table.stories-DUJDibEp.js} +1 -1
  152. package/dist/assets/{tabs.stories-Cpc3OHJx.js → tabs.stories-C06SngOF.js} +5 -29
  153. package/dist/assets/{tag-list.stories-BmyCmrTF.js → tag-list.stories-Du-IoYzu.js} +2 -10
  154. package/dist/assets/{tag-vQFuZneb.js → tag-oHGdclJl.js} +1 -9
  155. package/dist/assets/{tag.stories-DGzrNUbb.js → tag.stories-C5D5IbuK.js} +1 -1
  156. package/dist/assets/{tertiary-nav.stories-D4q5K-am.js → tertiary-nav.stories-B1GU8Zi4.js} +3 -19
  157. package/dist/assets/{text-link-4qLRIeJB.js → text-link-B3m3KEqY.js} +1 -9
  158. package/dist/assets/{text-link.stories-D6BRm2I5.js → text-link.stories-4O6qn82H.js} +1 -1
  159. package/dist/assets/{text-passage-DGaI5i2I.js → text-passage-xQVosjOr.js} +3 -19
  160. package/dist/assets/{text-passage.stories-DkmXVUhH.js → text-passage.stories-Da1nspwG.js} +1 -1
  161. package/dist/assets/{tooltip.stories-B7ADDq7o.js → tooltip.stories-DLKyyeKn.js} +6 -14
  162. package/dist/assets/{utility-nav.stories-ffXVvyLp.js → utility-nav.stories-B6xBFe7z.js} +5 -21
  163. package/dist/design-tokens/brands/cre8/css/tokens_brand.css +1 -1
  164. package/dist/design-tokens/core/scss/theming/component.css +1 -1
  165. package/dist/design-tokens/core/scss/theming/variables.css +1 -7
  166. package/dist/design-tokens/core/scss/theming/variables.scss +0 -11
  167. package/dist/icons/cre8-icons.svg +1 -1
  168. package/dist/iframe.html +1 -24
  169. package/dist/index.html +25 -77
  170. package/dist/project.json +1 -1
  171. package/lib/a2ui/registry.d.ts.map +1 -1
  172. package/lib/a2ui/registry.js +28 -0
  173. package/lib/a2ui/registry.js.map +1 -1
  174. package/lib/a2ui/renderer.d.ts +2 -1
  175. package/lib/a2ui/renderer.d.ts.map +1 -1
  176. package/lib/a2ui/renderer.js +1 -1
  177. package/lib/a2ui/renderer.js.map +1 -1
  178. package/lib/a2ui/stream/diff.d.ts +29 -0
  179. package/lib/a2ui/stream/diff.d.ts.map +1 -0
  180. package/lib/a2ui/stream/diff.js +131 -0
  181. package/lib/a2ui/stream/diff.js.map +1 -0
  182. package/lib/a2ui/stream/index.d.ts +12 -0
  183. package/lib/a2ui/stream/index.d.ts.map +1 -0
  184. package/lib/a2ui/stream/index.js +12 -0
  185. package/lib/a2ui/stream/index.js.map +1 -0
  186. package/lib/a2ui/stream/model.d.ts +67 -0
  187. package/lib/a2ui/stream/model.d.ts.map +1 -0
  188. package/lib/a2ui/stream/model.js +423 -0
  189. package/lib/a2ui/stream/model.js.map +1 -0
  190. package/lib/a2ui/stream/pointer.d.ts +35 -0
  191. package/lib/a2ui/stream/pointer.d.ts.map +1 -0
  192. package/lib/a2ui/stream/pointer.js +147 -0
  193. package/lib/a2ui/stream/pointer.js.map +1 -0
  194. package/lib/a2ui/stream/renderer.d.ts +52 -0
  195. package/lib/a2ui/stream/renderer.d.ts.map +1 -0
  196. package/lib/a2ui/stream/renderer.js +279 -0
  197. package/lib/a2ui/stream/renderer.js.map +1 -0
  198. package/lib/a2ui/stream/types.d.ts +174 -0
  199. package/lib/a2ui/stream/types.d.ts.map +1 -0
  200. package/lib/a2ui/stream/types.js +18 -0
  201. package/lib/a2ui/stream/types.js.map +1 -0
  202. package/lib/a2ui/types.d.ts +5 -0
  203. package/lib/a2ui/types.d.ts.map +1 -1
  204. package/lib/a2ui/types.js.map +1 -1
  205. package/lib/components/accordion/accordion.d.ts +15 -0
  206. package/lib/components/accordion/accordion.d.ts.map +1 -1
  207. package/lib/components/accordion/accordion.js +23 -0
  208. package/lib/components/accordion/accordion.js.map +1 -1
  209. package/lib/components/badge/badge.d.ts +4 -17
  210. package/lib/components/badge/badge.d.ts.map +1 -1
  211. package/lib/components/badge/badge.js +0 -15
  212. package/lib/components/badge/badge.js.map +1 -1
  213. package/lib/components/breadcrumbs/breadcrumbs.d.ts +14 -0
  214. package/lib/components/breadcrumbs/breadcrumbs.d.ts.map +1 -1
  215. package/lib/components/breadcrumbs/breadcrumbs.js +21 -0
  216. package/lib/components/breadcrumbs/breadcrumbs.js.map +1 -1
  217. package/lib/components/chart/chart.d.ts +3 -3
  218. package/lib/components/chart/chart.js +6 -6
  219. package/lib/components/chart/chart.js.map +1 -1
  220. package/lib/components/checkbox-field/checkbox-field.d.ts +19 -0
  221. package/lib/components/checkbox-field/checkbox-field.d.ts.map +1 -1
  222. package/lib/components/checkbox-field/checkbox-field.js +28 -0
  223. package/lib/components/checkbox-field/checkbox-field.js.map +1 -1
  224. package/lib/components/cre8-element.d.ts +19 -0
  225. package/lib/components/cre8-element.d.ts.map +1 -1
  226. package/lib/components/cre8-element.js +51 -2
  227. package/lib/components/cre8-element.js.map +1 -1
  228. package/lib/components/divider/divider.d.ts +1 -1
  229. package/lib/components/divider/divider.d.ts.map +1 -1
  230. package/lib/components/divider/divider.js.map +1 -1
  231. package/lib/components/dropdown/dropdown.d.ts +13 -0
  232. package/lib/components/dropdown/dropdown.d.ts.map +1 -1
  233. package/lib/components/dropdown/dropdown.js +19 -0
  234. package/lib/components/dropdown/dropdown.js.map +1 -1
  235. package/lib/components/dropdown-item/dropdown-item.d.ts +1 -1
  236. package/lib/components/dropdown-item/dropdown-item.js +2 -2
  237. package/lib/components/dropdown-item/dropdown-item.js.map +1 -1
  238. package/lib/components/heading/heading.d.ts +3 -5
  239. package/lib/components/heading/heading.d.ts.map +1 -1
  240. package/lib/components/heading/heading.js +2 -4
  241. package/lib/components/heading/heading.js.map +1 -1
  242. package/lib/components/link-list/link-list.d.ts +19 -0
  243. package/lib/components/link-list/link-list.d.ts.map +1 -1
  244. package/lib/components/link-list/link-list.js +19 -0
  245. package/lib/components/link-list/link-list.js.map +1 -1
  246. package/lib/components/list/list.d.ts +13 -0
  247. package/lib/components/list/list.d.ts.map +1 -1
  248. package/lib/components/list/list.js +15 -0
  249. package/lib/components/list/list.js.map +1 -1
  250. package/lib/components/modal/modal.d.ts +2 -2
  251. package/lib/components/modal/modal.js +2 -2
  252. package/lib/components/modal/modal.js.map +1 -1
  253. package/lib/components/multi-select/multi-select.d.ts +2 -2
  254. package/lib/components/multi-select/multi-select.js +5 -5
  255. package/lib/components/multi-select/multi-select.js.map +1 -1
  256. package/lib/components/pagination/pagination.d.ts +1 -1
  257. package/lib/components/pagination/pagination.js +2 -2
  258. package/lib/components/pagination/pagination.js.map +1 -1
  259. package/lib/components/percent-bar/percent-bar.d.ts +2 -0
  260. package/lib/components/percent-bar/percent-bar.d.ts.map +1 -1
  261. package/lib/components/percent-bar/percent-bar.js +3 -1
  262. package/lib/components/percent-bar/percent-bar.js.map +1 -1
  263. package/lib/components/popover/popover.d.ts +6 -7
  264. package/lib/components/popover/popover.d.ts.map +1 -1
  265. package/lib/components/popover/popover.js +4 -4
  266. package/lib/components/popover/popover.js.map +1 -1
  267. package/lib/components/progress-meter/progress-meter.d.ts +0 -8
  268. package/lib/components/progress-meter/progress-meter.d.ts.map +1 -1
  269. package/lib/components/progress-meter/progress-meter.js +0 -7
  270. package/lib/components/progress-meter/progress-meter.js.map +1 -1
  271. package/lib/components/progress-steps/progress-steps.d.ts +16 -0
  272. package/lib/components/progress-steps/progress-steps.d.ts.map +1 -1
  273. package/lib/components/progress-steps/progress-steps.js +25 -0
  274. package/lib/components/progress-steps/progress-steps.js.map +1 -1
  275. package/lib/components/progress-steps-item/progress-steps-item.d.ts +1 -3
  276. package/lib/components/progress-steps-item/progress-steps-item.d.ts.map +1 -1
  277. package/lib/components/progress-steps-item/progress-steps-item.js +0 -1
  278. package/lib/components/progress-steps-item/progress-steps-item.js.map +1 -1
  279. package/lib/components/radio-field/radio-field.d.ts +33 -0
  280. package/lib/components/radio-field/radio-field.d.ts.map +1 -1
  281. package/lib/components/radio-field/radio-field.js +62 -0
  282. package/lib/components/radio-field/radio-field.js.map +1 -1
  283. package/lib/components/remove-tag/remove-tag.d.ts +1 -1
  284. package/lib/components/remove-tag/remove-tag.js +3 -3
  285. package/lib/components/remove-tag/remove-tag.js.map +1 -1
  286. package/lib/components/split-button/split-button.d.ts +3 -0
  287. package/lib/components/split-button/split-button.d.ts.map +1 -1
  288. package/lib/components/split-button/split-button.js +5 -2
  289. package/lib/components/split-button/split-button.js.map +1 -1
  290. package/lib/components/tab/tab.d.ts +1 -1
  291. package/lib/components/tab/tab.js +3 -3
  292. package/lib/components/tab/tab.js.map +1 -1
  293. package/lib/components/table/table.d.ts +36 -0
  294. package/lib/components/table/table.d.ts.map +1 -1
  295. package/lib/components/table/table.js +55 -0
  296. package/lib/components/table/table.js.map +1 -1
  297. package/lib/components/tabs/tabs.d.ts +20 -3
  298. package/lib/components/tabs/tabs.d.ts.map +1 -1
  299. package/lib/components/tabs/tabs.js +33 -5
  300. package/lib/components/tabs/tabs.js.map +1 -1
  301. package/lib/components/tag-list/tag-list.d.ts +17 -0
  302. package/lib/components/tag-list/tag-list.d.ts.map +1 -1
  303. package/lib/components/tag-list/tag-list.js +25 -0
  304. package/lib/components/tag-list/tag-list.js.map +1 -1
  305. package/lib/components/tooltip/tooltip.d.ts +2 -2
  306. package/lib/components/tooltip/tooltip.js +4 -4
  307. package/lib/components/tooltip/tooltip.js.map +1 -1
  308. package/lib/components/utils/light-children.d.ts +40 -0
  309. package/lib/components/utils/light-children.d.ts.map +1 -0
  310. package/lib/components/utils/light-children.js +100 -0
  311. package/lib/components/utils/light-children.js.map +1 -0
  312. package/lib/directives/if-truthy.d.ts +1 -1
  313. package/lib/light-children-TlEXev5S.js +39 -0
  314. package/lib/scripts/generate-mcp-manifest.js +38 -0
  315. package/lib/scripts/generate-mcp-manifest.js.map +1 -1
  316. package/lib/scripts/generate-react-wrappers.d.ts +8 -1
  317. package/lib/scripts/generate-react-wrappers.d.ts.map +1 -1
  318. package/lib/scripts/generate-react-wrappers.js +45 -1
  319. package/lib/scripts/generate-react-wrappers.js.map +1 -1
  320. package/mcp-manifest.json +169 -52
  321. package/package.json +14 -5
  322. package/react-manifest.json +153 -47
  323. package/dist/assets/if-defined-HKKhGupN.js +0 -1
  324. package/dist/assets/iframe-CWwoGI65.css +0 -1
  325. package/dist/assets/state-CfuknrX8.js +0 -1
  326. package/dist/fonts/PlusJakartaSans-Bold.woff2 +0 -0
  327. package/dist/fonts/PlusJakartaSans-Medium.woff2 +0 -0
  328. package/dist/fonts/PlusJakartaSans-Regular.woff2 +0 -0
  329. package/dist/fonts/PlusJakartaSans-SemiBold.woff2 +0 -0
  330. package/dist/logo.svg +0 -1
  331. package/dist/sb-addons/storybook-4/manager-bundle.js +0 -8
  332. /package/dist/icons/{express-scripts copy.svg → pharmacy copy.svg} +0 -0
  333. /package/dist/icons/{express-scripts.svg → pharmacy.svg} +0 -0
@@ -6,11 +6,56 @@ import { dirname, resolve } from 'node:path';
6
6
  const __dirname = dirname(fileURLToPath(import.meta.url));
7
7
  const manifestPath = resolve(__dirname, '..', 'mcp-manifest.json');
8
8
  const outPath = resolve(__dirname, 'catalog.json');
9
+ const compactOutPath = resolve(__dirname, 'catalog.compact.json');
9
10
 
10
11
  const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
11
12
 
12
13
  const QUOTED_LITERAL = /^"([^"]*)"$/;
13
14
 
15
+ /**
16
+ * Native DOM events, bindable on every component.
17
+ *
18
+ * Emitted into the catalog as `x-native-events` so the runtime validator can
19
+ * read it from there rather than keeping its own copy. Two lists that must stay
20
+ * equal is exactly the drift this pipeline is supposed to prevent, so there is
21
+ * one list and it lives here, next to the schema it produces.
22
+ *
23
+ * A component's `@fires` tags describe only what it dispatches itself, so these
24
+ * can never be discovered from source — binding `click` to a button is both the
25
+ * most common thing an agent does and undocumentable by the analyzer.
26
+ */
27
+ const NATIVE_DOM_EVENTS = [
28
+ 'click', 'dblclick', 'contextmenu',
29
+ 'mousedown', 'mouseup', 'mouseenter', 'mouseleave', 'mouseover', 'mouseout', 'mousemove',
30
+ 'pointerdown', 'pointerup', 'pointerenter', 'pointerleave',
31
+ 'touchstart', 'touchend', 'touchmove', 'touchcancel',
32
+ 'keydown', 'keyup', 'keypress',
33
+ 'focus', 'blur', 'focusin', 'focusout',
34
+ 'input', 'change', 'submit', 'reset', 'invalid', 'select',
35
+ 'scroll', 'wheel', 'resize',
36
+ 'copy', 'cut', 'paste',
37
+ 'drag', 'dragstart', 'dragend', 'dragenter', 'dragleave', 'dragover', 'drop',
38
+ 'load', 'error',
39
+ ];
40
+
41
+ /** Mirrors the `EventBinding` union in types.ts. */
42
+ const EVENT_BINDING_SCHEMA = {
43
+ description: 'A handler name, or an object naming the handler plus dispatch options.',
44
+ oneOf: [
45
+ { type: 'string', minLength: 1 },
46
+ {
47
+ type: 'object',
48
+ required: ['handler'],
49
+ additionalProperties: false,
50
+ properties: {
51
+ handler: { type: 'string', minLength: 1 },
52
+ stopPropagation: { type: 'boolean' },
53
+ preventDefault: { type: 'boolean' },
54
+ },
55
+ },
56
+ ],
57
+ };
58
+
14
59
  const SELECT_OPTION_SCHEMA = {
15
60
  type: 'object',
16
61
  required: ['label', 'value'],
@@ -31,6 +76,112 @@ const SELECT_OPTION_GROUP_SCHEMA = {
31
76
  },
32
77
  };
33
78
 
79
+
80
+ /**
81
+ * Schemas for the flattened compound APIs.
82
+ *
83
+ * These are keyed by TypeScript type expression rather than by component, so a
84
+ * type used twice is described once — the same reason the select-option entry
85
+ * below is shaped this way. Without them the analyzer reports a bare interface
86
+ * name, `mapAttrPlain` falls back to `type: "string"`, and the catalog then
87
+ * *rejects* the very array the component is built to take.
88
+ */
89
+ const TABLE_COLUMN_SCHEMA = {
90
+ type: 'object',
91
+ properties: {
92
+ label: { type: 'string' },
93
+ key: { type: 'string' },
94
+ width: { type: 'string' },
95
+ },
96
+ required: ['label'],
97
+ additionalProperties: false,
98
+ };
99
+
100
+ const TABLE_ROW_SCHEMA = {
101
+ oneOf: [
102
+ { type: 'object', additionalProperties: { type: ['string', 'number'] } },
103
+ { type: 'array', items: { type: ['string', 'number'] } },
104
+ ],
105
+ };
106
+
107
+ /** `{ text }` and friends: one string field plus optional flags. */
108
+ const textItem = (extra = {}, required = ['text'], key = 'text') => ({
109
+ type: 'object',
110
+ properties: { [key]: { type: 'string' }, ...extra },
111
+ required,
112
+ additionalProperties: false,
113
+ });
114
+
115
+ const FLATTENED_ITEM_SCHEMAS = {
116
+ 'Cre8TableColumn[]': { type: 'array', items: TABLE_COLUMN_SCHEMA },
117
+ 'Cre8TableRowData[]': { type: 'array', items: TABLE_ROW_SCHEMA },
118
+ 'Cre8ListItemData[]': { type: 'array', items: textItem() },
119
+ 'Cre8DropdownItemData[]': { type: 'array', items: textItem({ ariaLabel: { type: 'string' } }) },
120
+ 'Cre8BreadcrumbData[]': { type: 'array', items: textItem({ href: { type: 'string' } }) },
121
+ 'Cre8LinkData[]': {
122
+ type: 'array',
123
+ items: textItem({ href: { type: 'string' }, isActive: { type: 'boolean' } }, ['text', 'href']),
124
+ },
125
+ 'Cre8TagData[]': {
126
+ type: 'array',
127
+ items: textItem({
128
+ variant: { type: 'string', enum: ['neutral', 'branded', 'neutral-hybrid'] },
129
+ shape: { type: 'string', enum: ['square', 'round'] },
130
+ type: { type: 'string', enum: ['checkbox', 'radio'] },
131
+ disabled: { type: 'boolean' },
132
+ }),
133
+ },
134
+ 'Cre8TabItemData[]': {
135
+ type: 'array',
136
+ items: textItem({ content: { type: 'string' } }, ['label'], 'label'),
137
+ },
138
+ 'Cre8AccordionItemData[]': {
139
+ type: 'array',
140
+ items: {
141
+ type: 'object',
142
+ properties: {
143
+ heading: { type: 'string' },
144
+ content: { type: 'string' },
145
+ isActive: { type: 'boolean' },
146
+ headingTagVariant: { type: 'string', enum: ['h1', 'h2', 'h3', 'h4'] },
147
+ },
148
+ required: ['heading', 'content'],
149
+ additionalProperties: false,
150
+ },
151
+ },
152
+ 'Cre8ProgressStepData[]': {
153
+ type: 'array',
154
+ items: {
155
+ type: 'object',
156
+ properties: {
157
+ name: { type: 'string' },
158
+ message: { type: 'string' },
159
+ state: { type: 'string', enum: ['error', 'warning', 'complete', 'current'] },
160
+ },
161
+ required: ['name'],
162
+ additionalProperties: false,
163
+ },
164
+ },
165
+ };
166
+
167
+ const choiceItem = {
168
+ type: 'array',
169
+ items: {
170
+ type: 'object',
171
+ properties: {
172
+ label: { type: 'string' },
173
+ value: { type: 'string' },
174
+ checked: { type: 'boolean' },
175
+ disabled: { type: 'boolean' },
176
+ required: { type: 'boolean' },
177
+ },
178
+ required: ['label'],
179
+ additionalProperties: false,
180
+ },
181
+ };
182
+ FLATTENED_ITEM_SCHEMAS['Cre8CheckboxItemData[]'] = choiceItem;
183
+ FLATTENED_ITEM_SCHEMAS['Cre8RadioItemData[]'] = choiceItem;
184
+
34
185
  const TS_TYPE_RESOLVERS = {
35
186
  Cre8ChartType: {
36
187
  type: 'string',
@@ -38,17 +189,24 @@ const TS_TYPE_RESOLVERS = {
38
189
  },
39
190
  Color: { type: 'string', enum: ['neutral', 'branded', 'neutral-hybrid'] },
40
191
  Shape: { type: 'string', enum: ['round', 'square'] },
41
- status: { type: 'string', enum: ['error', 'warning', 'success'] },
192
+ // No entry for the bare type name `status`: it existed only because
193
+ // `cre8-progress-meter` carried an `@attr {status}` JSDoc tag that overrode
194
+ // its literal union back to an unresolvable alias. The tag is gone and the
195
+ // union now flows through on its own.
42
196
  '(Cre8SelectOption | Cre8SelectOptionGroup)[]': {
43
197
  type: 'array',
44
198
  items: { oneOf: [SELECT_OPTION_SCHEMA, SELECT_OPTION_GROUP_SCHEMA] },
45
199
  },
200
+ ...FLATTENED_ITEM_SCHEMAS,
46
201
  };
47
202
 
48
203
  const PROP_OVERRIDES = {
49
204
  'cre8-chart.data': { type: 'object', description: 'Chart.js data object with labels and datasets arrays.' },
50
205
  'cre8-chart.options': { type: 'object', description: 'Chart.js options object.' },
51
- 'cre8-chart.colors': { type: 'array', items: { type: 'string' }, description: 'Dataset colors.' },
206
+ // No entry for `cre8-chart.colors`: the manifest type is plain `string[]`,
207
+ // which mapAttrPlain already resolves to the identical schema. Only add an
208
+ // override when the manifest type is unresolvable (an interface name, an
209
+ // imported alias, or a union TypeScript truncated with "... N more ...").
52
210
  'cre8-heading.type': {
53
211
  type: 'string',
54
212
  enum: [
@@ -62,7 +220,7 @@ const PROP_OVERRIDES = {
62
220
  'title-default',
63
221
  'title-small',
64
222
  'label-large',
65
- 'label',
223
+ 'label-default',
66
224
  'label-small',
67
225
  'meta-large',
68
226
  'meta-default',
@@ -178,7 +336,7 @@ function buildComponent(c) {
178
336
  def.properties.children = {
179
337
  type: 'array',
180
338
  description: (rawSlots.default?.description || '').trim() || 'Child instances rendered into the default slot.',
181
- items: { $ref: '#/$defs/Component' },
339
+ items: { $ref: '#/$defs/Child' },
182
340
  };
183
341
  } else if (hasSlots) {
184
342
  const slotProps = {};
@@ -188,7 +346,7 @@ function buildComponent(c) {
188
346
  slotProps[name] = {
189
347
  type: 'array',
190
348
  description: (slot.description || '').trim(),
191
- items: { $ref: '#/$defs/Component' },
349
+ items: { $ref: '#/$defs/Child' },
192
350
  };
193
351
  slotDescriptions[name] = (slot.description || '').trim();
194
352
  }
@@ -203,6 +361,24 @@ function buildComponent(c) {
203
361
 
204
362
  if (Object.keys(events).length) def['x-events'] = events;
205
363
 
364
+ // Events are declared under `properties`, alongside props and slots, rather
365
+ // than living only in `x-events` metadata. Previously the component defs were
366
+ // `additionalProperties: false` with no `events` key at all, so events were
367
+ // documented but second-class — and an invented event name validated cleanly.
368
+ // Native events are always permitted; declared custom events are added on top.
369
+ def.properties.events = {
370
+ type: 'object',
371
+ description:
372
+ 'Event bindings. Each key is an event name; the value names the handler to emit.',
373
+ // Native names are `$ref`'d rather than inlined. Repeating all 46 on each of
374
+ // 85 components cost ~57 KB and made the catalog a third larger for no
375
+ // information gain.
376
+ propertyNames: Object.keys(events).length
377
+ ? { anyOf: [{ $ref: '#/$defs/NativeEventName' }, { enum: Object.keys(events).sort() }] }
378
+ : { $ref: '#/$defs/NativeEventName' },
379
+ additionalProperties: { $ref: '#/$defs/EventBinding' },
380
+ };
381
+
206
382
  return def;
207
383
  }
208
384
 
@@ -219,6 +395,9 @@ const catalog = {
219
395
  $id: `https://cre8.dev/a2ui/catalogs/cre8-wc/${manifest.version}`,
220
396
  title: 'cre8-wc A2UI Catalog',
221
397
  description: manifest.description,
398
+ // Single source of truth for the native-event allowlist. The runtime validator
399
+ // reads it from here instead of keeping a second copy that could drift.
400
+ 'x-native-events': NATIVE_DOM_EVENTS,
222
401
  'x-a2ui': {
223
402
  catalogId: 'cre8-wc',
224
403
  library: manifest.library,
@@ -236,6 +415,24 @@ const catalog = {
236
415
  description: 'A component instance in the cre8-wc catalog.',
237
416
  oneOf: componentRefs,
238
417
  },
418
+ // Slot content is a component *or* literal text. `renderer.ts` has always
419
+ // turned a bare string into a text node, but the schema never said so, and
420
+ // that gap is load-bearing rather than cosmetic: 56 of 85 components carry
421
+ // no text-bearing prop, so their entire visible content arrives this way. A
422
+ // schema-constrained generator — guided decoding, or any JSON-Schema-
423
+ // constrained model — could not give those components any content at all.
424
+ //
425
+ // `root` stays a Component deliberately: a document cannot be bare text.
426
+ Child: {
427
+ description:
428
+ 'Slot content: either a nested component instance or literal text, which renders as a text node.',
429
+ oneOf: [{ $ref: '#/$defs/Component' }, { type: 'string' }],
430
+ },
431
+ EventBinding: EVENT_BINDING_SCHEMA,
432
+ NativeEventName: {
433
+ description: 'A native DOM event, bindable on any component.',
434
+ enum: [...NATIVE_DOM_EVENTS].sort(),
435
+ },
239
436
  components,
240
437
  },
241
438
  };
@@ -244,3 +441,57 @@ writeFileSync(outPath, JSON.stringify(catalog, null, 2) + '\n');
244
441
  console.log(
245
442
  `Wrote ${outPath} (${manifest.components.length} components, ${(JSON.stringify(catalog).length / 1024).toFixed(1)} KB)`
246
443
  );
444
+
445
+ // The compact projection: the minimum a model needs to emit valid A2UI. Prose is
446
+ // ~90% of the catalog's bytes and none of its decoding constraint, so dropping it
447
+ // is what lets a small-context model see the design system at all.
448
+ //
449
+ // Emitted here rather than in a separate script so it cannot drift from the
450
+ // catalog it projects.
451
+ function compactProps(propsNode) {
452
+ const out = {};
453
+ for (const [name, spec] of Object.entries(propsNode?.properties ?? {})) {
454
+ out[name] = spec.enum ? { enum: spec.enum } : { type: spec.type ?? 'string' };
455
+ }
456
+ return out;
457
+ }
458
+
459
+ const compactComponents = Object.entries(components)
460
+ .map(([name, def]) => {
461
+ const props = def.properties ?? {};
462
+ const entry = { name, category: def['x-category'] ?? 'Uncategorized' };
463
+
464
+ if (props.props) {
465
+ entry.props = compactProps(props.props);
466
+ if (props.props.required?.length) entry.required = props.props.required;
467
+ }
468
+ // Containment is expressed two ways and consumers need both: `children` for
469
+ // plain containers, `slots` for named regions. Dropping either makes a
470
+ // container look like a leaf.
471
+ if (props.children) entry.acceptsChildren = true;
472
+ if (props.slots) entry.slots = Object.keys(props.slots.properties ?? {});
473
+ // Events live under `x-events`, not under `properties`, which makes them easy
474
+ // to miss — the studio's hand-rolled summary looked for them in the wrong
475
+ // place and so showed the model none of the 22 events the library emits.
476
+ const events = Object.keys(def['x-events'] ?? {});
477
+ if (events.length) entry.events = events;
478
+ return entry;
479
+ })
480
+ .sort((a, b) => a.name.localeCompare(b.name));
481
+
482
+ const compact = {
483
+ contractVersion: 1,
484
+ sourceCatalog: catalog.$id,
485
+ libraryVersion: manifest.version,
486
+ componentCount: compactComponents.length,
487
+ components: compactComponents,
488
+ };
489
+
490
+ writeFileSync(compactOutPath, JSON.stringify(compact, null, 2) + '\n');
491
+
492
+ const fullBytes = JSON.stringify(components).length;
493
+ const compactBytes = JSON.stringify(compact).length;
494
+ console.log(
495
+ `Wrote ${compactOutPath} (${compactComponents.length} components, ` +
496
+ `${(compactBytes / 1024).toFixed(1)} KB, ${(fullBytes / compactBytes).toFixed(1)}x smaller)`
497
+ );
@@ -0,0 +1,32 @@
1
+ {
2
+ "$comment": "Generated by a2ui/render-audit.mjs. Props that are declared in the catalog but never reach the DOM — confirmed twice, by rendering under jsdom and by reading the component source. Setting one validates cleanly and does nothing.",
3
+ "libraryVersion": "2.0.7",
4
+ "components": {
5
+ "cre8-link-list-item": {
6
+ "text": {
7
+ "reason": "Documented as \"The link text\"; render() never reads it. The label comes from the default slot."
8
+ }
9
+ },
10
+ "cre8-field": {
11
+ "errorText": {
12
+ "reason": "Declared with a default of \"Error\" and never read. The message that renders is `fieldNote`, shown in the error style by `isError`."
13
+ },
14
+ "successText": {
15
+ "reason": "Declared with a default of \"Success\" and never read. Use `fieldNote` with `isSuccess`."
16
+ }
17
+ },
18
+ "cre8-date-picker": {
19
+ "errorText": {
20
+ "reason": "Declared and never read. Use `fieldNote` with `isError`."
21
+ },
22
+ "successText": {
23
+ "reason": "Declared and never read. Use `fieldNote` with `isSuccess`."
24
+ }
25
+ },
26
+ "cre8-modal": {
27
+ "closeButtonText": {
28
+ "reason": "Declared and never read; the close control takes its label from elsewhere."
29
+ }
30
+ }
31
+ }
32
+ }
package/a2ui/registry.js CHANGED
@@ -87,6 +87,17 @@ function describeType(v) {
87
87
  return 'array';
88
88
  return typeof v;
89
89
  }
90
+ /**
91
+ * Native DOM events, bindable on any component.
92
+ *
93
+ * Read from the catalog's `x-native-events` rather than kept here, so there is
94
+ * one list rather than two that must be held equal. A component's `@fires` tags
95
+ * describe only what it dispatches itself, so these can never be derived from
96
+ * source — `click` on a button is legitimate and undocumentable.
97
+ */
98
+ function nativeEvents(catalog) {
99
+ return new Set(catalog.schema['x-native-events'] ?? []);
100
+ }
90
101
  export function validateSpec(spec, catalog, path = '$') {
91
102
  if (!spec || typeof spec !== 'object') {
92
103
  throw new Error(`${path}: spec must be an object`);
@@ -131,7 +142,24 @@ export function validateSpec(spec, catalog, path = '$') {
131
142
  if (!s.events || typeof s.events !== 'object' || Array.isArray(s.events)) {
132
143
  throw new Error(`${path}.events: must be an object`);
133
144
  }
145
+ // Custom event *names* are checked against the catalog, the same way props
146
+ // and slots are. Previously only the binding shape was validated, so an
147
+ // invented event bound cleanly and then silently never fired — the worst
148
+ // failure mode available, since the UI renders and simply does nothing.
149
+ //
150
+ // Native DOM events are always allowed: `addEventListener` handles them on
151
+ // any element, and `@fires` documents only what a component dispatches
152
+ // itself. `click` on a button is legitimate and undocumented by design.
153
+ const declaredEvents = new Set(Object.keys(def['x-events'] ?? {}));
154
+ const native = nativeEvents(catalog);
134
155
  for (const [evtName, binding] of Object.entries(s.events)) {
156
+ if (!native.has(evtName) && !declaredEvents.has(evtName)) {
157
+ const available = [...declaredEvents].sort().join(', ');
158
+ throw new Error(`${path}.events.${evtName}: not a declared event on ${s.component}. ` +
159
+ (available
160
+ ? `Custom events available: ${available}`
161
+ : `${s.component} declares no custom events`));
162
+ }
135
163
  if (typeof binding === 'string')
136
164
  continue;
137
165
  if (!binding || typeof binding !== 'object') {
package/a2ui/registry.ts CHANGED
@@ -100,6 +100,18 @@ function describeType(v: unknown): string {
100
100
  return typeof v;
101
101
  }
102
102
 
103
+ /**
104
+ * Native DOM events, bindable on any component.
105
+ *
106
+ * Read from the catalog's `x-native-events` rather than kept here, so there is
107
+ * one list rather than two that must be held equal. A component's `@fires` tags
108
+ * describe only what it dispatches itself, so these can never be derived from
109
+ * source — `click` on a button is legitimate and undocumentable.
110
+ */
111
+ function nativeEvents(catalog: RegisteredCatalog): Set<string> {
112
+ return new Set(catalog.schema['x-native-events'] ?? []);
113
+ }
114
+
103
115
  export function validateSpec(spec: unknown, catalog: RegisteredCatalog, path = '$'): asserts spec is ComponentSpec {
104
116
  if (!spec || typeof spec !== 'object') {
105
117
  throw new Error(`${path}: spec must be an object`);
@@ -147,7 +159,26 @@ export function validateSpec(spec: unknown, catalog: RegisteredCatalog, path = '
147
159
  if (!s.events || typeof s.events !== 'object' || Array.isArray(s.events)) {
148
160
  throw new Error(`${path}.events: must be an object`);
149
161
  }
162
+ // Custom event *names* are checked against the catalog, the same way props
163
+ // and slots are. Previously only the binding shape was validated, so an
164
+ // invented event bound cleanly and then silently never fired — the worst
165
+ // failure mode available, since the UI renders and simply does nothing.
166
+ //
167
+ // Native DOM events are always allowed: `addEventListener` handles them on
168
+ // any element, and `@fires` documents only what a component dispatches
169
+ // itself. `click` on a button is legitimate and undocumented by design.
170
+ const declaredEvents = new Set(Object.keys(def['x-events'] ?? {}));
171
+ const native = nativeEvents(catalog);
150
172
  for (const [evtName, binding] of Object.entries(s.events as Record<string, unknown>)) {
173
+ if (!native.has(evtName) && !declaredEvents.has(evtName)) {
174
+ const available = [...declaredEvents].sort().join(', ');
175
+ throw new Error(
176
+ `${path}.events.${evtName}: not a declared event on ${s.component}. ` +
177
+ (available
178
+ ? `Custom events available: ${available}`
179
+ : `${s.component} declares no custom events`)
180
+ );
181
+ }
151
182
  if (typeof binding === 'string') continue;
152
183
  if (!binding || typeof binding !== 'object') {
153
184
  throw new Error(`${path}.events.${evtName}: must be a string or { handler } object`);