@supersoniks/concorde 5.1.1 → 5.1.3-immutable.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (459) hide show
  1. package/.agents/skills/concorde-docs/SKILL.md +153 -0
  2. package/.agents/skills/{concorde-component-docs/template.md → concorde-docs/templates/component.md} +6 -2
  3. package/.agents/skills/concorde-docs/templates/decorator.md +43 -0
  4. package/.agents/skills/concorde-docs/templates/guide.md +25 -0
  5. package/.claude/skills +1 -0
  6. package/.github/workflows/ci.yml +21 -0
  7. package/.github-export-ignore +30 -0
  8. package/CONTRIBUTING.md +59 -0
  9. package/DEV.md +54 -0
  10. package/LICENSE +21 -0
  11. package/OPEN_SOURCE_CHECKPOINT.md +133 -0
  12. package/README.md +4 -4
  13. package/ai/README.md +29 -41
  14. package/ai/skills/concorde/SKILL.md +54 -324
  15. package/ai/skills/concorde/rules/composition.md +32 -0
  16. package/ai/skills/concorde/rules/data.md +47 -0
  17. package/ai/skills/concorde/rules/http.md +25 -0
  18. package/ai/skills/concorde/rules/lists-forms.md +35 -0
  19. package/ai/skills/concorde/rules/styling.md +46 -0
  20. package/ai/skills/concorde/rules/troubleshooting.md +45 -0
  21. package/build-infos.json +1 -1
  22. package/concorde-core.bundle.js +177 -177
  23. package/concorde-core.es.js +4993 -4833
  24. package/custom-elements-manifest.public.config.mjs +8 -0
  25. package/{.tmp-cem/custom-elements.json → custom-elements.json} +11758 -8904
  26. package/dist/concorde-core.bundle.js +177 -177
  27. package/dist/concorde-core.es.js +4993 -4833
  28. package/dist/docs-mock-api-sw.js +58 -223
  29. package/dist/docs-mock-api-sw.js.map +4 -4
  30. package/dist/img/concorde/plane_01.jpg +0 -0
  31. package/dist/img/concorde/plane_02.jpg +0 -0
  32. package/dist/img/concorde/plane_03.jpg +0 -0
  33. package/dist/img/concorde/plane_04.jpg +0 -0
  34. package/dist/img/concorde/plane_05.jpg +0 -0
  35. package/dist/img/concorde/plane_06.jpg +0 -0
  36. package/dist/img/concorde/plane_07.jpg +0 -0
  37. package/dist/img/concorde/plane_08.jpg +0 -0
  38. package/dist/img/concorde/plane_09.jpg +0 -0
  39. package/dist/img/concorde/plane_10.jpg +0 -0
  40. package/dist/img/concorde/plane_11.jpg +0 -0
  41. package/dist/img/concorde/plane_12.jpg +0 -0
  42. package/dist/img/concorde/plane_13.jpg +0 -0
  43. package/dist/img/og-concorde.jpg +0 -0
  44. package/dist/robots.txt +11 -10
  45. package/docs/assets/index-D_alEsng.js +12122 -0
  46. package/docs/crawl/core/components/functional/date/date.html +190 -0
  47. package/docs/crawl/core/components/functional/fetch/fetch.html +109 -0
  48. package/docs/crawl/core/components/functional/if/if.html +27 -0
  49. package/docs/crawl/core/components/functional/jsonata/jsonata.html +79 -0
  50. package/docs/crawl/core/components/functional/list/list.html +70 -0
  51. package/docs/crawl/core/components/functional/mix/mix.html +45 -0
  52. package/docs/crawl/core/components/functional/queue/queue.html +96 -0
  53. package/docs/crawl/core/components/functional/router/router.html +106 -0
  54. package/docs/crawl/core/components/functional/sdui/sdui-extension-points.html +126 -0
  55. package/docs/crawl/core/components/functional/sdui/sdui.html +368 -0
  56. package/docs/crawl/core/components/functional/states/states.html +66 -0
  57. package/docs/crawl/core/components/functional/submit/submit.html +160 -0
  58. package/docs/crawl/core/components/functional/subscriber/subscriber.html +67 -0
  59. package/docs/crawl/core/components/functional/value/value.html +51 -0
  60. package/docs/crawl/core/components/ui/alert/alert.html +211 -0
  61. package/docs/crawl/core/components/ui/alert-messages/alert-messages.html +131 -0
  62. package/docs/crawl/core/components/ui/badge/badge.html +197 -0
  63. package/docs/crawl/core/components/ui/button/button.html +150 -0
  64. package/docs/crawl/core/components/ui/captcha/captcha.html +112 -0
  65. package/docs/crawl/core/components/ui/card/card.html +253 -0
  66. package/docs/crawl/core/components/ui/divider/divider.html +144 -0
  67. package/docs/crawl/core/components/ui/form/checkbox/checkbox.html +73 -0
  68. package/docs/crawl/core/components/ui/form/fieldset/fieldset.html +266 -0
  69. package/docs/crawl/core/components/ui/form/form-actions/form-actions.html +122 -0
  70. package/docs/crawl/core/components/ui/form/form-layout/form-layout.html +121 -0
  71. package/docs/crawl/core/components/ui/form/input/input.html +109 -0
  72. package/docs/crawl/core/components/ui/form/input-autocomplete/input-autocomplete.html +38 -0
  73. package/docs/crawl/core/components/ui/form/radio/radio.html +56 -0
  74. package/docs/crawl/core/components/ui/form/select/select.html +73 -0
  75. package/docs/crawl/core/components/ui/form/switch/switch.html +56 -0
  76. package/docs/crawl/core/components/ui/form/textarea/textarea.html +59 -0
  77. package/docs/crawl/core/components/ui/group/group.html +104 -0
  78. package/docs/crawl/core/components/ui/icon/icon.html +222 -0
  79. package/docs/crawl/core/components/ui/image/image.html +298 -0
  80. package/docs/crawl/core/components/ui/link/link.html +100 -0
  81. package/docs/crawl/core/components/ui/loader/loader.html +124 -0
  82. package/docs/crawl/core/components/ui/menu/menu.html +394 -0
  83. package/docs/crawl/core/components/ui/modal/modal.html +342 -0
  84. package/docs/crawl/core/components/ui/pop/pop.html +296 -0
  85. package/docs/crawl/core/components/ui/progress/progress.html +131 -0
  86. package/docs/crawl/core/components/ui/table/table.html +545 -0
  87. package/docs/crawl/core/components/ui/theme/theme.html +131 -0
  88. package/docs/crawl/core/components/ui/toast/toast.html +233 -0
  89. package/docs/crawl/core/components/ui/tooltip/tooltip.html +140 -0
  90. package/docs/crawl/docs/_core-concept/dataFlow.html +177 -0
  91. package/docs/crawl/docs/_core-concept/overview.html +66 -0
  92. package/docs/crawl/docs/_core-concept/subscriber.html +75 -0
  93. package/docs/crawl/docs/_decorators/ancestor-attribute.html +117 -0
  94. package/docs/crawl/docs/_decorators/auto-subscribe.html +202 -0
  95. package/docs/crawl/docs/_decorators/bind.html +141 -0
  96. package/docs/crawl/docs/_decorators/get.html +149 -0
  97. package/docs/crawl/docs/_decorators/handle.html +165 -0
  98. package/docs/crawl/docs/_decorators/on-assign.html +355 -0
  99. package/docs/crawl/docs/_decorators/patch.html +78 -0
  100. package/docs/crawl/docs/_decorators/post.html +139 -0
  101. package/docs/crawl/docs/_decorators/publish.html +61 -0
  102. package/docs/crawl/docs/_decorators/put.html +78 -0
  103. package/docs/crawl/docs/_decorators/subscribe.html +109 -0
  104. package/docs/crawl/docs/_decorators/wait-for-ancestors.html +137 -0
  105. package/docs/crawl/docs/_directives/sub.html +93 -0
  106. package/docs/crawl/docs/_getting-started/ai-agents.html +173 -0
  107. package/docs/crawl/docs/_getting-started/concorde-manual-install.html +100 -0
  108. package/docs/crawl/docs/_getting-started/concorde-outside.html +58 -0
  109. package/docs/crawl/docs/_getting-started/create-a-component.html +111 -0
  110. package/docs/crawl/docs/_getting-started/my-first-component.html +189 -0
  111. package/docs/crawl/docs/_getting-started/my-first-subscriber.html +110 -0
  112. package/docs/crawl/docs/_getting-started/pubsub.html +62 -0
  113. package/docs/crawl/docs/_getting-started/start.html +76 -0
  114. package/docs/crawl/docs/_getting-started/theming.html +333 -0
  115. package/docs/crawl/docs/_misc/api-configuration.html +149 -0
  116. package/docs/crawl/docs/_misc/dataProviderKey.html +135 -0
  117. package/docs/crawl/docs/_misc/docs-mock-api.html +158 -0
  118. package/docs/crawl/docs/_misc/dynamic-path.html +180 -0
  119. package/docs/crawl/docs/_misc/endpoint.html +50 -0
  120. package/docs/crawl/docs/_misc/formelement-subscriber-removal.html +138 -0
  121. package/docs/crawl/docs/_misc/html-integration.html +48 -0
  122. package/docs/crawl/hubs/decorators.html +547 -0
  123. package/docs/crawl/hubs/form-components.html +381 -0
  124. package/docs/crawl/hubs/remote-data.html +452 -0
  125. package/docs/crawl/index.html +103 -0
  126. package/docs/index.html +1 -1
  127. package/docs/llms-full.txt +7174 -0
  128. package/docs/llms.txt +98 -0
  129. package/docs/sitemap.xml +243 -0
  130. package/docs/src/core/components/functional/date/date.md +290 -0
  131. package/docs/src/core/components/functional/fetch/fetch.md +125 -0
  132. package/docs/src/core/components/functional/if/if.md +9 -0
  133. package/docs/src/core/components/functional/jsonata/jsonata.md +56 -0
  134. package/docs/src/core/components/functional/list/list.md +65 -0
  135. package/docs/src/core/components/functional/mix/mix.md +41 -0
  136. package/docs/src/core/components/functional/queue/queue.md +72 -0
  137. package/docs/src/core/components/functional/router/router.md +94 -0
  138. package/docs/src/core/components/functional/sdui/component-catalog.gaps.json +511 -0
  139. package/docs/src/core/components/functional/sdui/component-catalog.json +3103 -0
  140. package/docs/src/core/components/functional/sdui/default-library.json +108 -0
  141. package/docs/src/core/components/functional/sdui/example.json +99 -0
  142. package/docs/src/core/components/functional/sdui/sdui-extension-points.md +94 -0
  143. package/docs/src/core/components/functional/sdui/sdui.md +478 -0
  144. package/docs/src/core/components/functional/states/states.md +87 -0
  145. package/docs/src/core/components/functional/submit/submit.md +114 -0
  146. package/docs/src/core/components/functional/subscriber/subscriber.md +91 -0
  147. package/docs/src/core/components/functional/value/value.md +35 -0
  148. package/docs/src/core/components/ui/alert/alert.md +196 -0
  149. package/docs/src/core/components/ui/alert-messages/alert-messages.md +85 -0
  150. package/docs/src/core/components/ui/badge/badge.md +188 -0
  151. package/docs/src/core/components/ui/button/button.md +183 -0
  152. package/docs/src/core/components/ui/captcha/captcha.md +71 -0
  153. package/docs/src/core/components/ui/card/card.md +215 -0
  154. package/docs/src/core/components/ui/divider/divider.md +129 -0
  155. package/docs/src/core/components/ui/form/checkbox/checkbox.md +77 -0
  156. package/docs/src/core/components/ui/form/fieldset/fieldset.md +205 -0
  157. package/docs/src/core/components/ui/form/form-actions/form-actions.md +100 -0
  158. package/docs/src/core/components/ui/form/form-layout/form-layout.md +119 -0
  159. package/docs/src/core/components/ui/form/input/input.md +142 -0
  160. package/docs/src/core/components/ui/form/radio/radio.md +57 -0
  161. package/docs/src/core/components/ui/form/select/select.md +71 -0
  162. package/docs/src/core/components/ui/form/switch/switch.md +57 -0
  163. package/docs/src/core/components/ui/form/textarea/textarea.md +65 -0
  164. package/docs/src/core/components/ui/group/group.md +75 -0
  165. package/docs/src/core/components/ui/icon/icon.md +214 -0
  166. package/docs/src/core/components/ui/icon/icons.json +1 -0
  167. package/docs/src/core/components/ui/image/image.md +233 -0
  168. package/docs/src/core/components/ui/link/link.md +81 -0
  169. package/docs/src/core/components/ui/loader/loader.md +112 -0
  170. package/docs/src/core/components/ui/menu/menu.md +370 -0
  171. package/docs/src/core/components/ui/modal/modal.md +235 -0
  172. package/docs/src/core/components/ui/pop/pop.md +294 -0
  173. package/docs/src/core/components/ui/progress/progress.md +109 -0
  174. package/docs/src/core/components/ui/table/table.md +431 -0
  175. package/docs/src/core/components/ui/theme/theme.md +122 -0
  176. package/docs/src/core/components/ui/toast/toast.md +216 -0
  177. package/docs/src/core/components/ui/tooltip/tooltip.md +124 -0
  178. package/{src → docs/src}/docs/_core-concept/subscriber.md +0 -0
  179. package/{src → docs/src}/docs/_getting-started/my-first-subscriber.md +0 -0
  180. package/{src → docs/src}/docs/_getting-started/pubsub.md +0 -0
  181. package/docs/src/docs/_getting-started/theming.md +253 -0
  182. package/docs/src/docs/search/docs-search.json +12242 -0
  183. package/docs/src/tag-list.json +1 -0
  184. package/docs/src/tsconfig-model.json +23 -0
  185. package/docs/src/tsconfig.declarations.json +22 -0
  186. package/docs/src/tsconfig.emit.json +23 -0
  187. package/docs/src/tsconfig.json +1332 -0
  188. package/gitlab/job_github_mirror.sh +39 -0
  189. package/index.html +157 -5
  190. package/package.json +22 -4
  191. package/public/docs-mock-api-sw.js +58 -223
  192. package/public/docs-mock-api-sw.js.map +4 -4
  193. package/public/img/concorde/plane_01.jpg +0 -0
  194. package/public/img/concorde/plane_02.jpg +0 -0
  195. package/public/img/concorde/plane_03.jpg +0 -0
  196. package/public/img/concorde/plane_04.jpg +0 -0
  197. package/public/img/concorde/plane_05.jpg +0 -0
  198. package/public/img/concorde/plane_06.jpg +0 -0
  199. package/public/img/concorde/plane_07.jpg +0 -0
  200. package/public/img/concorde/plane_08.jpg +0 -0
  201. package/public/img/concorde/plane_09.jpg +0 -0
  202. package/public/img/concorde/plane_10.jpg +0 -0
  203. package/public/img/concorde/plane_11.jpg +0 -0
  204. package/public/img/concorde/plane_12.jpg +0 -0
  205. package/public/img/concorde/plane_13.jpg +0 -0
  206. package/public/img/og-concorde.jpg +0 -0
  207. package/public/robots.txt +11 -10
  208. package/scripts/ai-init.mjs +104 -379
  209. package/scripts/ai-init.test.mjs +81 -239
  210. package/scripts/docs-markdown-vite-plugin.ts +43 -0
  211. package/scripts/docs-public-url.mjs +56 -0
  212. package/scripts/docs.htaccess +82 -0
  213. package/scripts/generate-cem.mjs +244 -0
  214. package/scripts/generate-cem.test.mjs +122 -0
  215. package/scripts/generate-crawl-docs.mjs +233 -118
  216. package/scripts/generate-crawl-docs.test.mjs +124 -0
  217. package/scripts/generate-sdui-catalog.mjs +11 -10
  218. package/scripts/github-export.mjs +150 -0
  219. package/scripts/post-build-docs.js +37 -50
  220. package/scripts/post-build.mjs +0 -0
  221. package/scripts/pre-publish.mjs +2 -1
  222. package/scripts/site-pages.mjs +212 -0
  223. package/scripts/site-pages.test.mjs +116 -0
  224. package/site-pages/about.md +22 -0
  225. package/site-pages/privacy.md +32 -0
  226. package/src/core/components/functional/date/date.md +91 -231
  227. package/src/core/components/functional/example/example.ts +3 -1
  228. package/src/core/components/functional/fetch/fetch.md +66 -83
  229. package/src/core/components/functional/if/if.md +28 -3
  230. package/src/core/components/functional/if/if.ts +0 -0
  231. package/src/core/components/functional/jsonata/jsonata.md +42 -37
  232. package/src/core/components/functional/list/list.demo.ts +0 -0
  233. package/src/core/components/functional/list/list.md +103 -43
  234. package/src/core/components/functional/list/list.ts +17 -4
  235. package/src/core/components/functional/mix/mix.md +31 -26
  236. package/src/core/components/functional/queue/queue.demo.ts +10 -7
  237. package/src/core/components/functional/queue/queue.md +40 -61
  238. package/src/core/components/functional/router/router.demo.ts +16 -16
  239. package/src/core/components/functional/router/router.md +64 -65
  240. package/src/core/components/functional/router/router.ts +0 -0
  241. package/src/core/components/functional/sdui/SDUIDescriptorTransformer.ts +0 -0
  242. package/src/core/components/functional/sdui/component-catalog.gaps.json +1 -1
  243. package/src/core/components/functional/sdui/component-catalog.json +2 -2
  244. package/src/core/components/functional/sdui/example.json +19 -86
  245. package/src/core/components/functional/sdui/sdui-extension-points.md +1 -1
  246. package/src/core/components/functional/sdui/sdui-immutable.spec.ts +74 -0
  247. package/src/core/components/functional/sdui/sdui.md +187 -358
  248. package/src/core/components/functional/sdui/sdui.ts +33 -8
  249. package/src/core/components/functional/sdui/types.ts +0 -0
  250. package/src/core/components/functional/states/states.demo.ts +21 -22
  251. package/src/core/components/functional/states/states.md +86 -61
  252. package/src/core/components/functional/states/states.ts +1 -1
  253. package/src/core/components/functional/submit/submit.md +64 -72
  254. package/src/core/components/functional/submit/submit.spec.ts +60 -0
  255. package/src/core/components/functional/submit/submit.ts +6 -3
  256. package/src/core/components/functional/subscriber/subscriber.ts +0 -0
  257. package/src/core/components/functional/translation/translation.md +38 -0
  258. package/src/core/components/functional/value/value.md +34 -22
  259. package/src/core/components/functional/value/value.ts +0 -0
  260. package/src/core/components/ui/_css/size.ts +0 -0
  261. package/src/core/components/ui/alert/alert.md +48 -58
  262. package/src/core/components/ui/badge/badge.md +27 -34
  263. package/src/core/components/ui/button/button.md +139 -106
  264. package/src/core/components/ui/captcha/altchaStyles.ts +0 -0
  265. package/src/core/components/ui/captcha/captcha.md +17 -32
  266. package/src/core/components/ui/card/card.md +6 -6
  267. package/src/core/components/ui/divider/divider.md +8 -11
  268. package/src/core/components/ui/form/checkbox/checkbox.md +90 -42
  269. package/src/core/components/ui/form/fieldset/fieldset.md +31 -75
  270. package/src/core/components/ui/form/form-actions/form-actions.md +14 -16
  271. package/src/core/components/ui/form/form-layout/form-layout.md +19 -29
  272. package/src/core/components/ui/form/input/input.md +108 -90
  273. package/src/core/components/ui/form/input/input.ts +8 -2
  274. package/src/core/components/ui/form/radio/radio.md +65 -30
  275. package/src/core/components/ui/form/select/select.md +60 -45
  276. package/src/core/components/ui/form/switch/switch.md +57 -34
  277. package/src/core/components/ui/form/textarea/textarea.md +55 -38
  278. package/src/core/components/ui/group/group.md +35 -33
  279. package/src/core/components/ui/icon/icon.md +4 -4
  280. package/src/core/components/ui/image/image.md +41 -107
  281. package/src/core/components/ui/link/link.md +6 -6
  282. package/src/core/components/ui/loader/loader.md +30 -55
  283. package/src/core/components/ui/menu/menu.md +27 -27
  284. package/src/core/components/ui/modal/modal.md +72 -96
  285. package/src/core/components/ui/pop/pop.md +80 -158
  286. package/src/core/components/ui/progress/progress.md +2 -2
  287. package/src/core/components/ui/table/table.md +91 -255
  288. package/src/core/components/ui/theme/theme.md +11 -36
  289. package/src/core/components/ui/toast/toast.md +48 -117
  290. package/src/core/components/ui/tooltip/tooltip.md +27 -62
  291. package/src/core/decorators/subscriber/bind.ts +9 -14
  292. package/src/core/decorators/subscriber/subscribe.ts +15 -9
  293. package/src/core/decorators/subscriber/subscribe.type-test.ts +14 -5
  294. package/src/core/mixins/Subscriber.ts +0 -0
  295. package/src/core/utils/DataBindObserver.ts +0 -0
  296. package/src/core/utils/LocationHandler.spec.ts +80 -0
  297. package/src/core/utils/LocationHandler.ts +5 -9
  298. package/src/core/utils/Objects.ts +0 -0
  299. package/src/core/utils/PublisherProxy.ts +166 -125
  300. package/src/core/utils/deepReadonly.spec.ts +66 -0
  301. package/src/core/utils/deepReadonly.ts +71 -0
  302. package/src/core/utils/immutableValue.spec.ts +54 -0
  303. package/src/core/utils/immutableValue.ts +102 -0
  304. package/src/core/utils/nestedDotForm.spec.ts +88 -0
  305. package/src/core/utils/publisherImmutable.spec.ts +76 -0
  306. package/src/core/utils/route.ts +0 -0
  307. package/src/core/utils/strictGet.spec.ts +61 -0
  308. package/src/core/utils/strictGet.ts +102 -0
  309. package/src/css.d.ts +19 -0
  310. package/src/docs/components/docs-demo-sources.ts +55 -140
  311. package/src/docs/components/docs-lit-demo.ts +1 -3
  312. package/src/docs/components/docs-source-link.ts +0 -82
  313. package/src/docs/decorators/ancestor-attribute.md +59 -0
  314. package/src/docs/decorators/auto-subscribe.md +40 -0
  315. package/src/docs/decorators/bind.md +76 -0
  316. package/src/docs/decorators/get.md +160 -0
  317. package/src/docs/decorators/handle.md +119 -0
  318. package/src/docs/decorators/on-assign.md +63 -0
  319. package/src/docs/decorators/patch.md +44 -0
  320. package/src/docs/decorators/post.md +134 -0
  321. package/src/docs/decorators/publish.md +56 -0
  322. package/src/docs/decorators/put.md +51 -0
  323. package/src/docs/decorators/subscribe.md +87 -0
  324. package/src/docs/decorators/wait-for-ancestors.md +76 -0
  325. package/src/docs/directives/sub.md +75 -0
  326. package/src/docs/directives/t.md +73 -0
  327. package/src/docs/docs-location.spec.ts +56 -0
  328. package/src/docs/docs-location.ts +133 -32
  329. package/src/docs/docs.ts +1 -2
  330. package/src/docs/example/decorators-demo-bind-demos.ts +83 -135
  331. package/src/docs/example/decorators-demo-geo.ts +30 -19
  332. package/src/docs/example/decorators-demo-post.ts +88 -186
  333. package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +165 -268
  334. package/src/docs/example/decorators-demo.ts +85 -98
  335. package/src/docs/example/docs-api-config-demos.ts +19 -20
  336. package/src/docs/example/docs-flight-demos.ts +147 -0
  337. package/src/docs/example/docs-jsonata-demos.ts +52 -52
  338. package/src/docs/example/docs-list-demos.ts +43 -123
  339. package/src/docs/example/docs-provider-keys.ts +21 -28
  340. package/src/docs/example/docs-queue-demos.ts +37 -77
  341. package/src/docs/example/docs-router-demos.ts +20 -25
  342. package/src/docs/example/docs-submit-demos.ts +48 -48
  343. package/src/docs/example/docs-toggle-demos.ts +4 -3
  344. package/src/docs/example/users.ts +0 -0
  345. package/src/docs/getting-started/ai-agents.md +50 -0
  346. package/src/docs/getting-started/create-a-component.md +136 -0
  347. package/src/docs/getting-started/dataFlow.md +87 -0
  348. package/src/docs/getting-started/installation.md +36 -0
  349. package/src/docs/getting-started/my-first-component.md +227 -0
  350. package/src/docs/getting-started/start.md +35 -0
  351. package/src/docs/header/header.ts +11 -6
  352. package/src/docs/home/catalog.ts +1 -1
  353. package/src/docs/home/home.ts +20 -11
  354. package/src/docs/layout.ts +12 -13
  355. package/src/docs/misc/api-configuration.md +79 -0
  356. package/src/docs/misc/dataProviderKey.md +168 -0
  357. package/src/docs/misc/docs-mock-api.md +62 -0
  358. package/src/docs/misc/dynamic-path.md +71 -0
  359. package/src/docs/misc/endpoint.md +45 -0
  360. package/src/docs/misc/html-integration.md +14 -0
  361. package/src/docs/misc/publisher-get-immutability-docs-crawl.json +902 -0
  362. package/src/docs/misc/publisher-get-immutability-docs-recheck.json +13 -0
  363. package/src/docs/misc/publisher-get-immutability-study.md +229 -0
  364. package/src/docs/mock-api/api-config-mock.ts +5 -0
  365. package/src/docs/mock-api/fixtures.ts +0 -278
  366. package/src/docs/mock-api/flights.ts +89 -0
  367. package/src/docs/mock-api/router.ts +3 -4
  368. package/src/docs/mock-api/urls.ts +1 -2
  369. package/src/docs/navigation/navigation.ts +84 -101
  370. package/src/docs/navigation/toc.ts +7 -4
  371. package/src/docs/search/docs-search.json +3188 -5153
  372. package/src/docs/search/markdown-renderer.ts +31 -8
  373. package/src/docs/search/page.ts +9 -6
  374. package/src/docs/search/search.ts +154 -122
  375. package/src/docs/tailwind/css/docs/content.css +4 -5
  376. package/src/tsconfig.declarations.json +22 -0
  377. package/src/tsconfig.emit.json +23 -0
  378. package/src/tsconfig.json +53 -5
  379. package/src/tsconfig.tsbuildinfo +1 -1
  380. package/vite.config.mts +11 -2
  381. package/.agents/skills/concorde-component-docs/SKILL.md +0 -194
  382. package/.taste-skill/after/desktop-fold.jpg +0 -0
  383. package/.taste-skill/after/desktop-page-01.jpg +0 -0
  384. package/.taste-skill/after/desktop-page-02.jpg +0 -0
  385. package/.taste-skill/after/desktop-page-03.jpg +0 -0
  386. package/.taste-skill/after/mobile-fold.jpg +0 -0
  387. package/.taste-skill/after/mobile-page-01.jpg +0 -0
  388. package/.taste-skill/after/report.json +0 -4103
  389. package/.taste-skill/after/tablet-fold.jpg +0 -0
  390. package/.taste-skill/after/tablet-page-01.jpg +0 -0
  391. package/.taste-skill/after/tablet-page-02.jpg +0 -0
  392. package/.taste-skill/before/desktop-fold.jpg +0 -0
  393. package/.taste-skill/before/desktop-page-01.jpg +0 -0
  394. package/.taste-skill/before/desktop-page-02.jpg +0 -0
  395. package/.taste-skill/before/mobile-fold.jpg +0 -0
  396. package/.taste-skill/before/mobile-page-01.jpg +0 -0
  397. package/.taste-skill/before/report.json +0 -2556
  398. package/.taste-skill/before/tablet-fold.jpg +0 -0
  399. package/.taste-skill/before/tablet-page-01.jpg +0 -0
  400. package/.taste-skill/direction.json +0 -510
  401. package/.taste-skill/notes.md +0 -84
  402. package/.taste-skill/prod/desktop-fold.jpg +0 -0
  403. package/.taste-skill/prod/desktop-page-01.jpg +0 -0
  404. package/.taste-skill/prod/desktop-page-02.jpg +0 -0
  405. package/.taste-skill/prod/desktop-page-03.jpg +0 -0
  406. package/.taste-skill/prod/mobile-fold.jpg +0 -0
  407. package/.taste-skill/prod/mobile-page-01.jpg +0 -0
  408. package/.taste-skill/prod/mobile-page-02.jpg +0 -0
  409. package/.taste-skill/prod/report.json +0 -1973
  410. package/.taste-skill/prod/tablet-fold.jpg +0 -0
  411. package/.taste-skill/prod/tablet-page-01.jpg +0 -0
  412. package/.taste-skill/prod/tablet-page-02.jpg +0 -0
  413. package/AUDIT.md +0 -228
  414. package/PLAN-AMELIORATION.md +0 -220
  415. package/ai/AGENTS.md +0 -56
  416. package/ai/cursor/rules/concorde-menu.mdc +0 -15
  417. package/ai/cursor/rules/concorde-scope.mdc +0 -14
  418. package/ai/cursor/rules/concorde-theme.mdc +0 -13
  419. package/ai/cursor/rules/concorde.mdc +0 -66
  420. package/ai/jetbrains/rules/concorde.md +0 -53
  421. package/ai/skills/concorde-get-set-dp/SKILL.md +0 -194
  422. package/ai/skills/concorde-imports/SKILL.md +0 -78
  423. package/ai/skills/concorde-menu/SKILL.md +0 -74
  424. package/ai/skills/concorde-scope/SKILL.md +0 -70
  425. package/ai/skills/concorde-theme/SKILL.md +0 -57
  426. package/docs/assets/index-Bb-_LRyY.js +0 -12280
  427. package/src/docs/example/docs-input-autocomplete-demos.ts +0 -110
  428. package/src/docs/example/docs-joke-demos.ts +0 -297
  429. /package/{src → docs/src}/core/components/ui/form/input-autocomplete/input-autocomplete.md +0 -0
  430. /package/{src → docs/src}/docs/_core-concept/dataFlow.md +0 -0
  431. /package/{src → docs/src}/docs/_core-concept/overview.md +0 -0
  432. /package/{src → docs/src}/docs/_decorators/ancestor-attribute.md +0 -0
  433. /package/{src → docs/src}/docs/_decorators/auto-subscribe.md +0 -0
  434. /package/{src → docs/src}/docs/_decorators/bind.md +0 -0
  435. /package/{src → docs/src}/docs/_decorators/get.md +0 -0
  436. /package/{src → docs/src}/docs/_decorators/handle.md +0 -0
  437. /package/{src → docs/src}/docs/_decorators/on-assign.md +0 -0
  438. /package/{src → docs/src}/docs/_decorators/patch.md +0 -0
  439. /package/{src → docs/src}/docs/_decorators/post.md +0 -0
  440. /package/{src → docs/src}/docs/_decorators/publish.md +0 -0
  441. /package/{src → docs/src}/docs/_decorators/put.md +0 -0
  442. /package/{src → docs/src}/docs/_decorators/subscribe.md +0 -0
  443. /package/{src → docs/src}/docs/_decorators/wait-for-ancestors.md +0 -0
  444. /package/{src → docs/src}/docs/_directives/sub.md +0 -0
  445. /package/{src → docs/src}/docs/_getting-started/ai-agents.md +0 -0
  446. /package/{src → docs/src}/docs/_getting-started/concorde-manual-install.md +0 -0
  447. /package/{src → docs/src}/docs/_getting-started/concorde-outside.md +0 -0
  448. /package/{src → docs/src}/docs/_getting-started/create-a-component.md +0 -0
  449. /package/{src → docs/src}/docs/_getting-started/my-first-component.md +0 -0
  450. /package/{src → docs/src}/docs/_getting-started/start.md +0 -0
  451. /package/{src → docs/src}/docs/_misc/api-configuration.md +0 -0
  452. /package/{src → docs/src}/docs/_misc/dataProviderKey.md +0 -0
  453. /package/{src → docs/src}/docs/_misc/docs-mock-api.md +0 -0
  454. /package/{src → docs/src}/docs/_misc/dynamic-path.md +0 -0
  455. /package/{src → docs/src}/docs/_misc/endpoint.md +0 -0
  456. /package/{src → docs/src}/docs/_misc/formelement-subscriber-removal.md +0 -0
  457. /package/{src → docs/src}/docs/_misc/html-integration.md +0 -0
  458. /package/src/docs/{_getting-started → getting-started}/components.md +0 -0
  459. /package/src/docs/{_getting-started → getting-started}/theming.md +0 -0
@@ -1,14 +1,12 @@
1
1
  # Toast
2
2
 
3
- Toasts surface **short-lived feedback** in a fixed stack (bottom-right in the main window). Queue messages with **`SonicToast.add()`** on the global **`SonicToast`** class—the host **`sonic-toast`** is created automatically. Prefer **`label`** for a heading; use **`preserve`** or interactive **`text`** when the user must read or act before dismiss.
3
+ Toasts show short-lived feedback in a fixed stack at the bottom right of the page. Call **`SonicToast.add()`** (also `window.SonicToast`); the **`sonic-toast`** host is created on first use. Use **`label`** for a heading and **`preserve`** when the user must read or act before the toast goes away.
4
4
 
5
5
  ## Basic example
6
6
 
7
- Click the button to show a toast.
8
-
9
7
  <sonic-code>
10
8
  <template>
11
- <sonic-button onclick="SonicToast.add({ text: 'Simple notification' })">
9
+ <sonic-button onclick="SonicToast.add({ text: 'Flight CN 001 is now boarding' })">
12
10
  Show toast
13
11
  </sonic-button>
14
12
  </template>
@@ -16,54 +14,37 @@ Click the button to show a toast.
16
14
 
17
15
  ## Status
18
16
 
19
- **`status`** drives color, icon, and live-region behavior. Omit **`status`** or pass an empty string for a neutral toast.
17
+ **`status`** sets the color, the icon and the live-region role. With no `status`, the toast is neutral.
20
18
 
21
19
  <sonic-code>
22
20
  <template>
23
21
  <div class="flex flex-wrap gap-2">
24
- <sonic-button onclick="SonicToast.add({ text: 'Default message', status: '' })">
25
- Default
26
- </sonic-button>
27
- <sonic-button onclick="SonicToast.add({ text: 'Operation succeeded', status: 'success' })">
28
- Success
29
- </sonic-button>
30
- <sonic-button onclick="SonicToast.add({ text: 'Something went wrong', status: 'error' })">
31
- Error
32
- </sonic-button>
33
- <sonic-button onclick="SonicToast.add({ text: 'Check this detail', status: 'warning' })">
34
- Warning
35
- </sonic-button>
36
- <sonic-button onclick="SonicToast.add({ text: 'Helpful context', status: 'info' })">
37
- Info
38
- </sonic-button>
22
+ <sonic-button onclick="SonicToast.add({ text: 'Default message' })">Default</sonic-button>
23
+ <sonic-button onclick="SonicToast.add({ text: 'Operation succeeded', status: 'success' })">Success</sonic-button>
24
+ <sonic-button onclick="SonicToast.add({ text: 'Something went wrong', status: 'error' })">Error</sonic-button>
25
+ <sonic-button onclick="SonicToast.add({ text: 'Check this detail', status: 'warning' })">Warning</sonic-button>
26
+ <sonic-button onclick="SonicToast.add({ text: 'Helpful context', status: 'info' })">Info</sonic-button>
39
27
  </div>
40
28
  </template>
41
29
  </sonic-code>
42
30
 
43
31
  ## Label
44
32
 
45
- Set **`label`** for a bold title above **`text`**. **`title`** still works but is deprecated—use **`label`** in new code.
33
+ **`label`** adds a bold heading above **`text`**. `title` is a deprecated alias.
46
34
 
47
35
  <sonic-code>
48
36
  <template>
49
- <div class="flex flex-wrap gap-2">
50
- <sonic-button
51
- onclick="SonicToast.add({ label: 'Success', text: 'Your request was processed.', status: 'success' })"
52
- >
53
- Toast with label
54
- </sonic-button>
55
- <sonic-button
56
- onclick="SonicToast.add({ label: 'Error', text: 'Processing failed. Try again.', status: 'error' })"
57
- >
58
- Error with label
59
- </sonic-button>
60
- </div>
37
+ <sonic-button
38
+ onclick="SonicToast.add({ label: 'Gate change', text: 'Flight CN 001 now departs from gate B12.', status: 'warning' })"
39
+ >
40
+ Toast with label
41
+ </sonic-button>
61
42
  </template>
62
43
  </sonic-code>
63
44
 
64
45
  ## HTML in text
65
46
 
66
- **`text`** (and **`label`**) can include HTML strings. Links and controls in **`text`** automatically enable **`preserve`** so the toast does not auto-hide while the user interacts.
47
+ **`text`** and **`label`** accept HTML strings. A link or form control in **`text`** turns on **`preserve`** automatically.
67
48
 
68
49
  <sonic-code>
69
50
  <template>
@@ -77,12 +58,12 @@ Set **`label`** for a bold title above **`text`**. **`title`** still works but i
77
58
 
78
59
  ## Preserve
79
60
 
80
- Without **`preserve`**, toasts auto-hide after about six seconds (timer pauses on hover or focus). Set **`preserve`** to keep the toast until the user closes it.
61
+ Toasts hide after 6 seconds; the timer pauses on hover and focus. **`preserve`** keeps the toast until the user closes it.
81
62
 
82
63
  <sonic-code>
83
64
  <template>
84
65
  <sonic-button
85
- onclick="SonicToast.add({ text: 'This toast stays until you dismiss it', status: 'info', preserve: true })"
66
+ onclick="SonicToast.add({ text: 'Turbulence ahead: please fasten your seat belt', status: 'info', preserve: true })"
86
67
  >
87
68
  Persistent toast
88
69
  </sonic-button>
@@ -91,12 +72,12 @@ Without **`preserve`**, toasts auto-hide after about six seconds (timer pauses o
91
72
 
92
73
  ## Dismiss forever
93
74
 
94
- With **`dismissForever`** and a stable **`id`**, closing the toast stores dismissal in **`localStorage`**—**`SonicToast.add`** skips it on later visits. Duplicate payloads (same fields, ignoring **`id`**) are not queued twice.
75
+ With **`dismissForever`** and a stable **`id`**, closing the toast is stored in `localStorage` and later `add()` calls with that `id` are ignored. A toast identical to one already shown (ignoring `id`) is never added twice.
95
76
 
96
77
  <sonic-code>
97
78
  <template>
98
79
  <sonic-button
99
- onclick="SonicToast.add({ id: 'unique-toast-id', text: 'Dismiss forever hides this across reloads', status: 'info', dismissForever: true })"
80
+ onclick="SonicToast.add({ id: 'welcome-toast', label: 'Welcome', text: 'Close me and I will not come back after a reload.', status: 'info', dismissForever: true })"
100
81
  >
101
82
  Dismiss forever
102
83
  </sonic-button>
@@ -105,112 +86,62 @@ With **`dismissForever`** and a stable **`id`**, closing the toast stores dismis
105
86
 
106
87
  ## Ghost
107
88
 
108
- **`ghost`** renders a semi-transparent, non-interactive toast—useful for loading or background states. **`SonicToast.removeAll`** leaves ghost toasts in place.
89
+ **`ghost`** renders a semi-transparent, non-interactive toast, for example for a background task.
109
90
 
110
91
  <sonic-code>
111
92
  <template>
112
93
  <sonic-button
113
- onclick="SonicToast.add({ text: 'Ghost toast (non-interactive)', status: 'info', ghost: true })"
94
+ onclick="SonicToast.add({ text: 'Syncing in the background', status: 'info', ghost: true })"
114
95
  >
115
96
  Ghost toast
116
97
  </sonic-button>
117
98
  </template>
118
99
  </sonic-code>
119
100
 
120
- ## Dismissal
121
-
122
- Use static helpers to clear the stack from app logic (for example after navigation).
101
+ ## Removing toasts
123
102
 
124
- ### Remove all
125
-
126
- Removes every toast except **`ghost`** items.
103
+ Static helpers clear the stack from script, for example after navigation. **`removeAll()`** keeps ghost toasts; **`removeTemporaryItems()`** keeps preserved ones.
127
104
 
128
105
  <sonic-code>
129
106
  <template>
130
107
  <div class="flex flex-wrap gap-2">
131
- <sonic-button onclick="SonicToast.add({ text: 'Toast 1', status: 'info' })">Add toast 1</sonic-button>
132
- <sonic-button onclick="SonicToast.add({ text: 'Toast 2', status: 'success' })">Add toast 2</sonic-button>
133
- <sonic-button onclick="SonicToast.add({ text: 'Toast 3', status: 'warning' })">Add toast 3</sonic-button>
134
- <sonic-button onclick="SonicToast.removeAll()">Remove all</sonic-button>
108
+ <sonic-button onclick="SonicToast.add({ text: 'Temporary success', status: 'success' })">Add success</sonic-button>
109
+ <sonic-button onclick="SonicToast.add({ text: 'Temporary error', status: 'error' })">Add error</sonic-button>
110
+ <sonic-button onclick="SonicToast.add({ text: 'Persistent info', status: 'info', preserve: true })">Add persistent</sonic-button>
135
111
  </div>
136
- </template>
137
- </sonic-code>
138
-
139
- ### Remove by status
140
-
141
- <sonic-code>
142
- <template>
143
- <div class="flex flex-wrap gap-2">
144
- <sonic-button onclick="SonicToast.add({ text: 'Success toast', status: 'success' })">Success</sonic-button>
145
- <sonic-button onclick="SonicToast.add({ text: 'Error toast', status: 'error' })">Error</sonic-button>
146
- <sonic-button onclick="SonicToast.add({ text: 'Warning toast', status: 'warning' })">Warning</sonic-button>
147
- <sonic-button onclick="SonicToast.removeItemsByStatus('success')">Remove success</sonic-button>
148
- <sonic-button onclick="SonicToast.removeItemsByStatus('error')">Remove error</sonic-button>
149
- </div>
150
- </template>
151
- </sonic-code>
152
-
153
- ### Remove temporary items
154
-
155
- Removes toasts that are not **`preserve`**.
156
-
157
- <sonic-code>
158
- <template>
159
- <div class="flex flex-wrap gap-2">
160
- <sonic-button onclick="SonicToast.add({ text: 'Temporary toast', status: 'info' })">Temporary</sonic-button>
161
- <sonic-button onclick="SonicToast.add({ text: 'Persistent toast', status: 'success', preserve: true })">
162
- Persistent
163
- </sonic-button>
164
- <sonic-button onclick="SonicToast.removeTemporaryItems()">Remove temporary</sonic-button>
112
+ <div class="flex flex-wrap gap-2 mt-3">
113
+ <sonic-button variant="outline" onclick="SonicToast.removeItemsByStatus('success')">Remove success</sonic-button>
114
+ <sonic-button variant="outline" onclick="SonicToast.removeTemporaryItems()">Remove temporary</sonic-button>
115
+ <sonic-button variant="outline" onclick="SonicToast.removeAll()">Remove all</sonic-button>
165
116
  </div>
166
117
  </template>
167
118
  </sonic-code>
168
119
 
169
- ## Combined options
170
-
171
- <sonic-code>
172
- <template>
173
- <sonic-button
174
- onclick="SonicToast.add({
175
- id: 'welcome-toast',
176
- label: 'Welcome',
177
- text: 'Welcome to the platform. Explore the docs to get started.',
178
- status: 'success',
179
- dismissForever: true
180
- })"
181
- >
182
- Full example
183
- </sonic-button>
184
- </template>
185
- </sonic-code>
186
-
187
- ## Accessibility
188
-
189
- Each toast uses **`role="alert"`** for **`error`** and **`role="status"`** otherwise (with **`aria-live="polite"`** when applicable). Status icons are decorative (**`aria-hidden`**). The close control has an i18n **`aria-label`**. When there is no **`label`**, a truncated string **`aria-label`** may be derived from plain **`text`**.
120
+ Inside an iframe, toasts are forwarded to the parent window's stack when the parent also loads Concorde.
190
121
 
191
122
  ## API reference
192
123
 
193
- Options passed to **`SonicToast.add(conf)`**:
124
+ Options of **`SonicToast.add(options)`**:
194
125
 
195
126
  | Option | Values | Description |
196
127
  |----------|---------|-------------|
197
- | `text` | string · Lit template | Main body; HTML strings are supported |
198
- | `label` | string · Lit template | Optional heading above **`text`** |
199
- | `title` | string · Lit template | Deprecated alias for **`label`** |
200
- | `status` | `success` · `error` · `warning` · `info` · `` (empty) | Semantic styling and live region behavior |
201
- | `id` | string · number | Stable id for deduplication and **`dismissForever`** (defaults to timestamp) |
202
- | `preserve` | boolean | Skip auto-hide; forced when **`text`** contains interactive markup |
203
- | `ghost` | boolean | Semi-transparent and non-interactive; kept by **`removeAll`** |
204
- | `dismissForever` | boolean | Persist dismissal in **`localStorage`** when closed (requires stable **`id`**) |
205
- | `styleSheet` | modal style input | Extra adopted styles on the toast item shadow root |
206
- | `useSlot` | boolean | Legacy: project **`text`** into the light DOM slot |
128
+ | `text` | string · Lit template | Body, required; HTML strings allowed |
129
+ | `label` | string · Lit template | Heading above `text` |
130
+ | `title` | string · Lit template | Deprecated alias of `label` |
131
+ | `status` | `success` · `error` · `warning` · `info` (default neutral) | Color and icon; `error` gets `role="alert"`, others `role="status"` |
132
+ | `id` | string · number (default timestamp) | Identifier for `removeItemById` and `dismissForever` |
133
+ | `preserve` | boolean | No auto-hide; forced when `text` contains a link or control |
134
+ | `ghost` | boolean | Semi-transparent and non-interactive; kept by `removeAll` |
135
+ | `dismissForever` | boolean | Remember the dismissal in `localStorage`; needs a stable `id` |
136
+ | `styleSheet` | `CSSResult` · `CSSStyleSheet` · array | Extra styles adopted by the toast |
137
+ | `useSlot` | boolean | Legacy: render `text` in the light DOM |
207
138
 
208
139
  | Method | Description |
209
140
  |--------|-------------|
210
- | `SonicToast.add(conf)` | Append a toast; returns the config or **`null`** if skipped (dismissed forever or duplicate) |
211
- | `SonicToast.removeAll()` | Remove all non-**`ghost`** toasts |
212
- | `SonicToast.removeItemsByStatus(status)` | Remove toasts matching **`status`** |
213
- | `SonicToast.removeItemById(id)` | Remove a single toast by **`id`** |
214
- | `SonicToast.removeTemporaryItems()` | Remove toasts without **`preserve`** |
141
+ | `SonicToast.add(options)` | Show a toast; returns the stored config, or `null` when skipped |
142
+ | `SonicToast.removeAll()` | Remove every toast except ghosts |
143
+ | `SonicToast.removeItemsByStatus(status)` | Remove toasts with this `status` |
144
+ | `SonicToast.removeItemById(id)` | Remove one toast |
145
+ | `SonicToast.removeTemporaryItems()` | Remove toasts without `preserve` |
215
146
 
216
- **`sonic-toast`** is mounted automatically; **`sonic-toast-item`** is internal. In iframes, toasts can delegate to the parent window via **`postMessage`**.
147
+ `sonic-toast` and `sonic-toast-item` are created by `add()`; do not write them in markup. `sonic-toast-message-subscriber` shows a toast for each `{ type: "public", content, status }` entry of its `messages` property.
@@ -1,12 +1,12 @@
1
1
  # Tooltip
2
2
 
3
- Tooltip shows a short **`label`** on hover (and on focus when the trigger can receive focus). Wrap the trigger in the default slot—buttons, icons, or plain text. Default **`placement`** is **`top`** (center-aligned). An empty **`label`** hides the bubble the same way as **`disabled`**.
3
+ **`sonic-tooltip`** shows a short `label` in a bubble when the trigger in the default slot is hovered or receives focus. With no `placement`, the bubble sits on `top`, centered. An empty `label` hides the bubble, like `disabled`.
4
4
 
5
5
  ## Basic example
6
6
 
7
7
  <sonic-code>
8
8
  <template>
9
- <sonic-tooltip label="Additional context on hover">
9
+ <sonic-tooltip label="Cruising at Mach 2.04">
10
10
  <sonic-button variant="outline">Hover me</sonic-button>
11
11
  </sonic-tooltip>
12
12
  </template>
@@ -14,67 +14,34 @@ Tooltip shows a short **`label`** on hover (and on focus when the trigger can re
14
14
 
15
15
  ## Placement
16
16
 
17
- Use **`top`** · **`bottom`** · **`left`** · **`right`** for the main axis. Add **`-start`** or **`-end`** to align the bubble along the anchor edge.
17
+ `top` · `bottom` · `left` · `right` set the side. Add `-start` or `-end` to align the bubble with an edge of the trigger instead of its center. The bubble is repositioned while open to stay in the viewport.
18
18
 
19
19
  <sonic-code>
20
20
  <template>
21
- <div class="flex flex-wrap gap-2">
22
- <sonic-tooltip placement="top" label="Top">
23
- <sonic-button>Top</sonic-button>
24
- </sonic-tooltip>
25
- <sonic-tooltip placement="bottom" label="Bottom">
26
- <sonic-button>Bottom</sonic-button>
27
- </sonic-tooltip>
28
- <sonic-tooltip placement="right" label="Right">
29
- <sonic-button>Right</sonic-button>
30
- </sonic-tooltip>
31
- <sonic-tooltip placement="left" label="Left">
32
- <sonic-button>Left</sonic-button>
33
- </sonic-tooltip>
21
+ <div class="flex flex-wrap gap-3">
22
+ <sonic-tooltip placement="top" label="top"><sonic-button minWidth="9rem">top</sonic-button></sonic-tooltip>
23
+ <sonic-tooltip placement="top-start" label="top-start"><sonic-button minWidth="9rem">top-start</sonic-button></sonic-tooltip>
24
+ <sonic-tooltip placement="top-end" label="top-end"><sonic-button minWidth="9rem">top-end</sonic-button></sonic-tooltip>
25
+ <sonic-tooltip placement="bottom" label="bottom"><sonic-button minWidth="9rem">bottom</sonic-button></sonic-tooltip>
26
+ <sonic-tooltip placement="bottom-start" label="bottom-start"><sonic-button minWidth="9rem">bottom-start</sonic-button></sonic-tooltip>
27
+ <sonic-tooltip placement="bottom-end" label="bottom-end"><sonic-button minWidth="9rem">bottom-end</sonic-button></sonic-tooltip>
28
+ <sonic-tooltip placement="left" label="left"><sonic-button minWidth="9rem">left</sonic-button></sonic-tooltip>
29
+ <sonic-tooltip placement="left-start" label="left-start"><sonic-button minWidth="9rem">left-start</sonic-button></sonic-tooltip>
30
+ <sonic-tooltip placement="left-end" label="left-end"><sonic-button minWidth="9rem">left-end</sonic-button></sonic-tooltip>
31
+ <sonic-tooltip placement="right" label="right"><sonic-button minWidth="9rem">right</sonic-button></sonic-tooltip>
32
+ <sonic-tooltip placement="right-start" label="right-start"><sonic-button minWidth="9rem">right-start</sonic-button></sonic-tooltip>
33
+ <sonic-tooltip placement="right-end" label="right-end"><sonic-button minWidth="9rem">right-end</sonic-button></sonic-tooltip>
34
34
  </div>
35
35
  </template>
36
36
  </sonic-code>
37
37
 
38
- ### Aligned placements
38
+ ## Multiline label
39
39
 
40
- <sonic-code>
41
- <template>
42
- <div class="flex gap-3 flex-wrap">
43
- <sonic-tooltip placement="top-start" label="Top start">
44
- <sonic-button class="size-40 bg-neutral-200 rounded-lg">Top start</sonic-button>
45
- </sonic-tooltip>
46
- <sonic-tooltip placement="top-end" label="Top end">
47
- <sonic-button class="size-40 bg-neutral-200 rounded-lg">Top end</sonic-button>
48
- </sonic-tooltip>
49
- <sonic-tooltip placement="bottom-start" label="Bottom start">
50
- <sonic-button class="size-40 bg-neutral-200 rounded-lg">Bottom start</sonic-button>
51
- </sonic-tooltip>
52
- <sonic-tooltip placement="bottom-end" label="Bottom end">
53
- <sonic-button class="size-40 bg-neutral-200 rounded-lg">Bottom end</sonic-button>
54
- </sonic-tooltip>
55
- <sonic-tooltip placement="right-start" label="Right start">
56
- <sonic-button class="size-40 bg-neutral-200 rounded-lg">Right start</sonic-button>
57
- </sonic-tooltip>
58
- <sonic-tooltip placement="right-end" label="Right end">
59
- <sonic-button class="size-40 bg-neutral-200 rounded-lg">Right end</sonic-button>
60
- </sonic-tooltip>
61
- <sonic-tooltip placement="left-start" label="Left start">
62
- <sonic-button class="size-40 bg-neutral-200 rounded-lg">Left start</sonic-button>
63
- </sonic-tooltip>
64
- <sonic-tooltip placement="left-end" label="Left end">
65
- <sonic-button class="size-40 bg-neutral-200 rounded-lg">Left end</sonic-button>
66
- </sonic-tooltip>
67
- </div>
68
- </template>
69
- </sonic-code>
70
-
71
- ## Label formatting
72
-
73
- **`label`** supports line breaks (`\n` in markup or multiline text). Lines are trimmed; **`&nbsp;`** is normalized to spaces. **`white-space: pre-line`** preserves breaks in the bubble (max width **18rem**).
40
+ Line breaks in `label` (a real newline or `&#10;`) are kept. Each line is trimmed and the bubble wraps at `18rem`.
74
41
 
75
42
  <sonic-code>
76
43
  <template>
77
- <sonic-tooltip label="First line&#10;Second line">
44
+ <sonic-tooltip label="Gate B12&#10;Boarding at 08:15">
78
45
  <sonic-button variant="outline">Multiline label</sonic-button>
79
46
  </sonic-tooltip>
80
47
  </template>
@@ -82,7 +49,7 @@ Use **`top`** · **`bottom`** · **`left`** · **`right`** for the main axis. Ad
82
49
 
83
50
  ## Focusable
84
51
 
85
- On non-interactive triggers, set **`focusable`** so the host gets **`tabindex="0"`** and the tooltip opens on keyboard focus as well as hover.
52
+ Set `focusable` when the trigger is not focusable itself (text, icon): the host gets `tabindex="0"` so keyboard users can open the tooltip. The bubble uses `popover="hint"`; without Popover API support, the label falls back to a native `title` on one line.
86
53
 
87
54
  <sonic-code>
88
55
  <template>
@@ -98,6 +65,8 @@ On non-interactive triggers, set **`focusable`** so the host gets **`tabindex="0
98
65
 
99
66
  ## Disabled
100
67
 
68
+ `disabled` never shows the bubble and sets `tabindex="-1"` on the host.
69
+
101
70
  <sonic-code>
102
71
  <template>
103
72
  <sonic-tooltip disabled label="Not shown">
@@ -106,19 +75,15 @@ On non-interactive triggers, set **`focusable`** so the host gets **`tabindex="0
106
75
  </template>
107
76
  </sonic-code>
108
77
 
109
- ## Accessibility
110
-
111
- The bubble uses **`popover="hint"`** (non-modal, no pointer capture). Prefer **`focusable`** when the slotted content is not already focusable. When the Popover API is unavailable, the host falls back to the native **`title`** attribute with a single-line label. Opacity transitions respect **`prefers-reduced-motion`**.
112
-
113
78
  ## API reference
114
79
 
115
80
  | Attribute | Values | Description |
116
81
  |----------|---------|-------------|
117
- | `label` | string | Tooltip copy; whitespace-only values suppress the bubble |
118
- | `placement` | `top` (default) · `bottom` · `left` · `right` · `top-start` · `top-end` · `bottom-start` · `bottom-end` · `left-start` · `left-end` · `right-start` · `right-end` | Position relative to the trigger; repositions while open |
119
- | `disabled` | boolean | Suppress show/hide; sets **`tabindex="-1"`** on the host |
120
- | `focusable` | boolean | Add **`tabindex="0"`** on the host for keyboard access |
82
+ | `label` | string | Tooltip text; empty or whitespace-only hides the bubble |
83
+ | `placement` | `top` (default) · `bottom` · `left` · `right`, each with optional `-start` · `-end` | Side and alignment relative to the trigger |
84
+ | `disabled` | boolean | Never show the bubble; sets `tabindex="-1"` on the host |
85
+ | `focusable` | boolean | Sets `tabindex="0"` on the host so the tooltip opens on keyboard focus |
121
86
 
122
87
  | Slot | Description |
123
88
  |------|-------------|
124
- | *(default)* | Trigger content (hover target) |
89
+ | *(default)* | Trigger content |
@@ -189,28 +189,23 @@ function bindImpl(
189
189
  };
190
190
  }
191
191
 
192
+ /** @deprecated Pass a `DataProviderKey<T>` instead of a string path (typed, refactor-safe). */
193
+ export function bind(
194
+ path: string,
195
+ options?: BindOptions,
196
+ ): (target: unknown, propertyKey: string) => void;
192
197
  /**
193
- * Bidirectional binding to a publisher path. Subscribes to changes and optionally reflects writes back.
194
- * Accepts either a string path (legacy) or DataProviderKey&lt;T&gt; for type-safe binding.
195
- * Supports dynamic paths: use placeholders like "users.${userIndex}" in the path or DataProviderKey.
198
+ * Bidirectional binding to a publisher path: subscribes to changes and, with
199
+ * `reflect: true`, writes local assignments back. For one direction only, use
200
+ * `@subscribe` (read) or `@publish` (write).
201
+ * Supports dynamic paths: use placeholders like "users.${userIndex}" in the DataProviderKey.
196
202
  *
197
203
  * @example
198
- * // String path (legacy):
199
- * @bind("demoData.firstName")
200
- * @state()
201
- * firstName = "";
202
- *
203
- * @example
204
- * // DataProviderKey with type validation:
205
204
  * const dataKey = new DataProviderKey<Data>("data");
206
205
  * @bind(dataKey.count, { reflect: true })
207
206
  * @state()
208
207
  * count: number = 0;
209
208
  */
210
- export function bind(
211
- path: string,
212
- options?: BindOptions,
213
- ): (target: unknown, propertyKey: string) => void;
214
209
  export function bind<T, U = any>(
215
210
  key: DataProviderKey<T, U>,
216
211
  options?: BindOptions,
@@ -2,31 +2,37 @@ import type {
2
2
  DataProviderKey,
3
3
  DataProviderKeyHost,
4
4
  } from "../../utils/dataProviderKey";
5
+ import type { Frozen } from "../../utils/deepReadonly";
5
6
  import { bind } from "./bind";
6
7
 
7
8
  /**
8
- * Read-only subscription to a publisher path via DataProviderKey&lt;T&gt;. No reflect.
9
- * The decorated property is typed as `T` (or optional / `| null` / `| undefined` for Lit / TS 5).
10
- * Supports dynamic paths: use placeholders like "users.${userIndex}" in the DataProviderKey.
9
+ * Read-only subscription to a publisher path via `DataProviderKey<T>`. No reflect.
10
+ * The decorated property **must** be typed {@link Frozen}`<T>` (runtime = owned
11
+ * frozen store ref). Primitives: `Frozen<number>` ≡ `number`.
12
+ * Use `@publish` / `@bind({ reflect: true })` to write.
11
13
  *
12
14
  * @example
13
- * const dataKey = new DataProviderKey<Data>("data");
14
15
  * @subscribe(dataKey.count)
15
- * @state()
16
16
  * count: number;
17
17
  *
18
- * // Dynamic path:
18
+ * @subscribe(dataKey.cities)
19
+ * cities?: Frozen<City[]>;
20
+ *
19
21
  * @subscribe(new DataProviderKey<User>("users.${userIndex}"))
20
- * user: User | null;
22
+ * user: Frozen<User> | null;
21
23
  */
22
24
  export function subscribe<T, U = any>(
23
25
  key: DataProviderKey<T, U>,
24
26
  ): <K extends string>(
25
- target: DataProviderKeyHost<U> & { [P in K]?: T | null | undefined },
27
+ target: DataProviderKeyHost<U> & {
28
+ [P in K]?: Frozen<T> | null | undefined;
29
+ },
26
30
  propertyKey: K,
27
31
  ) => void {
28
32
  return bind(key) as <K extends string>(
29
- target: DataProviderKeyHost<U> & { [P in K]?: T | null | undefined },
33
+ target: DataProviderKeyHost<U> & {
34
+ [P in K]?: Frozen<T> | null | undefined;
35
+ },
30
36
  propertyKey: K,
31
37
  ) => void;
32
38
  }
@@ -1,32 +1,41 @@
1
1
  /**
2
- * Type tests for subscribe — ensures property type must match DataProviderKey<T>.
2
+ * Type tests for subscribe — property must be Frozen<T>.
3
3
  * Excluded from build. To verify: temporarily remove from exclude and run build.
4
- * Expected: InvalidUsage and InvalidUsage2 should produce type errors.
4
+ * Expected: InvalidUsage* should produce type errors.
5
5
  */
6
6
  import { DataProviderKey } from "../../utils/dataProviderKey";
7
+ import type { Frozen } from "../../utils/deepReadonly";
7
8
  import { subscribe } from "./subscribe";
8
9
 
9
10
  type ControlStats = {
10
11
  gauge: number;
11
12
  label: string;
13
+ cities: { nom: string }[];
12
14
  };
13
15
 
14
16
  const statsKey = new DataProviderKey<ControlStats>("stats");
15
17
 
16
- // OK: gauge is number, matches DataProviderKey<number>
17
18
  class ValidUsage {
18
19
  @subscribe(statsKey.gauge)
19
20
  gauge = 0;
20
21
  }
21
22
 
22
- // Should error: gauge should be number, not string
23
+ class ValidFrozenArray {
24
+ @subscribe(statsKey.cities)
25
+ cities?: Frozen<{ nom: string }[]>;
26
+ }
27
+
23
28
  class InvalidUsage {
24
29
  @subscribe(statsKey.gauge)
25
30
  gauge: string = "";
26
31
  }
27
32
 
28
- // Should error: label should be string, not number
29
33
  class InvalidUsage2 {
30
34
  @subscribe(statsKey.label)
31
35
  label: number = 0;
32
36
  }
37
+
38
+ class InvalidMutableArray {
39
+ @subscribe(statsKey.cities)
40
+ cities?: { nom: string }[];
41
+ }
File without changes
File without changes
@@ -0,0 +1,80 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import LocationHandler from "./LocationHandler";
3
+
4
+ describe("LocationHandler.changeFromComponent pushState", () => {
5
+ const pushState = vi.fn();
6
+
7
+ beforeEach(() => {
8
+ pushState.mockClear();
9
+ vi.stubGlobal("history", {
10
+ pushState,
11
+ replaceState: vi.fn(),
12
+ state: null,
13
+ length: 1,
14
+ });
15
+ vi.stubGlobal("document", {
16
+ location: {
17
+ href: "https://concorde.supersoniks.org/",
18
+ origin: "https://concorde.supersoniks.org",
19
+ pathname: "/",
20
+ search: "",
21
+ hash: "",
22
+ },
23
+ title: "Concorde",
24
+ });
25
+ });
26
+
27
+ function el(attrs: Record<string, string>) {
28
+ return {
29
+ getAttribute: (k: string) => (k in attrs ? attrs[k] : null),
30
+ hasAttribute: (k: string) => k in attrs,
31
+ href: attrs.href || "",
32
+ goBack: null,
33
+ autoActive: "disabled",
34
+ } as never;
35
+ }
36
+
37
+ it("pushState keeps a single leading slash (no protocol-relative //path)", () => {
38
+ LocationHandler.changeFromComponent(
39
+ el({ href: "/docs/getting-started/start", pushState: "" }),
40
+ );
41
+ expect(pushState).toHaveBeenCalledTimes(1);
42
+ expect(pushState.mock.calls[0][2]).toBe("/docs/getting-started/start");
43
+ });
44
+
45
+ it("preserves hash fragments on pathname routes", () => {
46
+ LocationHandler.changeFromComponent(
47
+ el({
48
+ href: "/core/components/functional/router#departures",
49
+ pushState: "",
50
+ }),
51
+ );
52
+ expect(pushState.mock.calls[0][2]).toBe(
53
+ "/core/components/functional/router#departures",
54
+ );
55
+ });
56
+
57
+ it("keeps pretty component paths without inventing a trailing duplicate", () => {
58
+ LocationHandler.changeFromComponent(
59
+ el({
60
+ href: "/core/components/functional/router",
61
+ pushState: "",
62
+ }),
63
+ );
64
+ expect(pushState.mock.calls[0][2]).toBe(
65
+ "/core/components/functional/router",
66
+ );
67
+ });
68
+
69
+ it("collapses empty segments from double slashes", () => {
70
+ LocationHandler.changeFromComponent(
71
+ el({ href: "/docs//getting-started//start", pushState: "" }),
72
+ );
73
+ expect(pushState.mock.calls[0][2]).toBe("/docs/getting-started/start");
74
+ });
75
+
76
+ it("navigates to / for the homepage", () => {
77
+ LocationHandler.changeFromComponent(el({ href: "/", pushState: "" }));
78
+ expect(pushState.mock.calls[0][2]).toBe("/");
79
+ });
80
+ });