@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
@@ -0,0 +1,51 @@
1
+ # @put
2
+
3
+ Sends the value of a publisher as the body of a `PUT` request, to replace a resource, and stores the response in an `ApiResult<T>` property. It takes the same arguments, options and `send(component)` handle as [@post](/docs/decorators/post); only the HTTP method differs.
4
+
5
+ ## Import
6
+
7
+ <sonic-code language="typescript">
8
+ <template>
9
+ import { put, type ApiResult } from "@supersoniks/concorde/decorators";
10
+ import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
11
+ import { Endpoint } from "@supersoniks/concorde/utils/endpoint";
12
+ </template>
13
+ </sonic-code>
14
+
15
+ ## Basic usage
16
+
17
+ The full passenger record is sent on connect and after each body mutation. Placeholders such as `${passengerId}` are resolved on the host component.
18
+
19
+ <sonic-code language="typescript">
20
+ <template>
21
+ type Passenger = { name: string; flight: string; seat: string };
22
+
23
+ const passengerKey = new DataProviderKey&lt;Passenger&gt;("passengerForm");
24
+ const savePassenger = put(
25
+ new Endpoint&lt;Passenger, { passengerId: string }&gt;("passengers/${passengerId}"),
26
+ passengerKey,
27
+ { autoPostOnBodyMutation: false },
28
+ );
29
+
30
+ @property() passengerId = "ada-lindqvist";
31
+
32
+ @savePassenger
33
+ @state()
34
+ payload?: ApiResult&lt;Passenger&gt;;
35
+
36
+ async save() {
37
+ await savePassenger.send(this);
38
+ }
39
+ </template>
40
+ </sonic-code>
41
+
42
+ Triggers, the `send` method decorator and every option are described on [@post](/docs/decorators/post).
43
+
44
+ ## API reference
45
+
46
+ | Argument | Type | Description |
47
+ |----------|------|-------------|
48
+ | `endpoint` | `Endpoint<T>` | Resource path and response type |
49
+ | `bodyKey` | `DataProviderKey<B>` | Publisher read as the full replacement body |
50
+ | `configurationKey` | `DataProviderKey<APIConfiguration>` (optional) | API configuration publisher. Default: HTML scope |
51
+ | `options` | `PutOptions` | Same as [@post options](/docs/decorators/post) |
@@ -0,0 +1,87 @@
1
+ # @subscribe
2
+
3
+ `@subscribe(key)` keeps a component property in sync with one path of the store: when a publisher assigns that path, the property updates and the component re-renders. It is read-only; use [@publish](/docs/decorators/publish) to write and [sub()](/docs/directives/sub) to read inside a template. See [Data flow](/docs/getting-started/dataFlow) for the overall model.
4
+
5
+ ## Import
6
+
7
+ <sonic-code language="typescript">
8
+ <template>
9
+ import { subscribe } from "@supersoniks/concorde/decorators";
10
+ import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
11
+
12
+ type Cockpit = { altitude: number };
13
+ const cockpitKey = new DataProviderKey&lt;Cockpit&gt;("cockpit");
14
+
15
+ @subscribe(cockpitKey.altitude)
16
+ @state()
17
+ altitude = 0;
18
+ </template>
19
+ </sonic-code>
20
+
21
+ ## Static path
22
+
23
+ The key is a [DataProviderKey](/docs/misc/dataProviderKey): the property type must match `T` at that path. Add `@state()` so Lit re-renders. Until the publisher holds a value, the property keeps its initializer.
24
+
25
+ <sonic-code language="typescript">
26
+ <template>
27
+ type Flight = { code: string; gate: string; status: string };
28
+ const flightKey = new DataProviderKey&lt;Flight&gt;("flight");
29
+
30
+ @subscribe(flightKey)
31
+ @state()
32
+ flight: Flight | null = null;
33
+ </template>
34
+ </sonic-code>
35
+
36
+ ## Dynamic path
37
+
38
+ `${prop}` placeholders resolve from properties of the same component. Declare them in the key's second generic so TypeScript requires them on the host. When `seatIndex` changes, the path is resolved again and `person` refreshes; while the placeholder is `null` or `undefined`, the subscription is inactive. Resolution rules: [Dynamic paths](/docs/misc/dynamic-path).
39
+
40
+ <sonic-code language="typescript">
41
+ <template>
42
+ type OnBoard = { name: string; role: string; seat: string };
43
+ const personKey = new DataProviderKey&lt;OnBoard, { seatIndex: number }&gt;(
44
+ "demoOnBoard.${seatIndex}",
45
+ );
46
+
47
+ @property({ type: Number }) seatIndex = 0;
48
+
49
+ @subscribe(personKey)
50
+ @state()
51
+ person: OnBoard | null = null;
52
+ </template>
53
+ </sonic-code>
54
+
55
+ <sonic-code>
56
+ <template>
57
+ <docs-demo-sources for="demo-subscribe-dynamic"></docs-demo-sources>
58
+ <demo-subscribe-dynamic></demo-subscribe-dynamic>
59
+ </template>
60
+ </sonic-code>
61
+
62
+ ## Ancestor scope
63
+
64
+ Inside a list row or a `dataProvider` wrapper, read the path from the closest ancestor with [@ancestorAttribute](/docs/decorators/ancestor-attribute), then use it as the placeholder.
65
+
66
+ <sonic-code language="typescript">
67
+ <template>
68
+ const rowKey = new DataProviderKey&lt;OnBoard, { dataProvider: string | null }&gt;(
69
+ "${dataProvider}",
70
+ );
71
+
72
+ @ancestorAttribute("dataProvider")
73
+ dataProvider: string | null = null;
74
+
75
+ @subscribe(rowKey)
76
+ @state()
77
+ person: OnBoard | null = null;
78
+ </template>
79
+ </sonic-code>
80
+
81
+ ## API reference
82
+
83
+ | Argument | Type | Description |
84
+ |----------|------|-------------|
85
+ | `key` | `DataProviderKey<T, U>` | Path to read. `U` lists the host properties used by `${…}` placeholders |
86
+
87
+ The decorated property is typed `T` (optionally `| null` or `| undefined`). The subscription starts when the component connects and stops when it disconnects.
@@ -0,0 +1,76 @@
1
+ # @awaitConnectedAncestors
2
+
3
+ Delays a component's `connectedCallback` until its matching ancestors are defined and connected, so context they set up (a `dataProvider`, a publisher, a fetched payload) is ready when the child starts. Pair it with `@dispatchConnectedEvent` on the ancestors, which signals readiness.
4
+
5
+ ## Import
6
+
7
+ <sonic-code language="typescript">
8
+ <template>
9
+ import {
10
+ awaitConnectedAncestors,
11
+ dispatchConnectedEvent,
12
+ } from "@supersoniks/concorde/decorators";
13
+
14
+ @customElement("flight-scope")
15
+ @dispatchConnectedEvent()
16
+ export class FlightScope extends LitElement {}
17
+
18
+ @customElement("gate-panel")
19
+ @awaitConnectedAncestors("flight-scope")
20
+ export class GatePanel extends LitElement {}
21
+ </template>
22
+ </sonic-code>
23
+
24
+ ## Wait for an ancestor
25
+
26
+ Arguments are CSS selectors tested with `element.matches()` on each ancestor, across shadow roots. Here the parent element is not defined yet: the child stays uninitialized until you register it.
27
+
28
+ <sonic-code>
29
+ <template>
30
+ <docs-demo-sources for="demo-wait-ancestors-section"></docs-demo-sources>
31
+ <demo-wait-ancestors-section></demo-wait-ancestors-section>
32
+ </template>
33
+ </sonic-code>
34
+
35
+ ## Several ancestors
36
+
37
+ With several selectors, the child waits for every matching ancestor. Register both to initialize it, in any order.
38
+
39
+ <sonic-code>
40
+ <template>
41
+ <docs-demo-sources for="demo-wait-ancestors-multi-section"></docs-demo-sources>
42
+ <demo-wait-ancestors-multi-section></demo-wait-ancestors-multi-section>
43
+ </template>
44
+ </sonic-code>
45
+
46
+ ## Ancestor already connected
47
+
48
+ When the ancestor is already connected, or no ancestor matches, the child initializes immediately.
49
+
50
+ <sonic-code>
51
+ <template>
52
+ <docs-demo-sources for="demo-wait-ancestors-ready-section"></docs-demo-sources>
53
+ <demo-wait-ancestors-ready-section></demo-wait-ancestors-ready-section>
54
+ </template>
55
+ </sonic-code>
56
+
57
+ ## Signal readiness
58
+
59
+ `@dispatchConnectedEvent()` dispatches a bubbling `sonic-connected` event (exported as `CONNECTED`) at the end of the ancestor's `connectedCallback`. You can listen to it anywhere:
60
+
61
+ <sonic-code language="typescript">
62
+ <template>
63
+ import { CONNECTED } from "@supersoniks/concorde/decorators";
64
+
65
+ document.addEventListener(CONNECTED, (e) => console.log("ready:", e.target));
66
+ </template>
67
+ </sonic-code>
68
+
69
+ Elements without a hyphen in their tag name count as connected. A custom element ancestor that never dispatches the event releases the child after a **5 second** timeout, so decorate the ancestors you wait for.
70
+
71
+ ## API reference
72
+
73
+ | Decorator | Argument | Description |
74
+ |-----------|----------|-------------|
75
+ | `@awaitConnectedAncestors` | `...selectors: string[]` | Class decorator. CSS selectors of the ancestors to wait for; with no selector, the class is left unchanged |
76
+ | `@dispatchConnectedEvent` | none | Class decorator. Dispatches `CONNECTED` (`"sonic-connected"`, bubbles) after `connectedCallback` |
@@ -0,0 +1,75 @@
1
+ # sub()
2
+
3
+ `sub(path)` is a Lit directive that renders the current value of a store path and updates in place on every assignment. Use it inside `html` templates for read-only display; in a decorator, the same path goes to [@subscribe](/docs/decorators/subscribe). See [Data flow](/docs/getting-started/dataFlow) for the overall model.
4
+
5
+ ## Import
6
+
7
+ <sonic-code language="typescript">
8
+ <template>
9
+ import { sub } from "@supersoniks/concorde/directives";
10
+
11
+ render() {
12
+ return html`&lt;p&gt;Altitude: ${sub("cockpit.altitude")} ft&lt;/p&gt;`;
13
+ }
14
+ </template>
15
+ </sonic-code>
16
+
17
+ ## DataProviderKey
18
+
19
+ Pass a [DataProviderKey](/docs/misc/dataProviderKey) instead of a string to get a typo-safe path. Until the publisher holds a value, nothing is rendered.
20
+
21
+ <sonic-code language="typescript">
22
+ <template>
23
+ import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
24
+
25
+ const flightKey = new DataProviderKey&lt;{ code: string; gate: string }&gt;("flight");
26
+
27
+ render() {
28
+ return html`&lt;p&gt;${sub(flightKey.code)} · gate ${sub(flightKey.gate)}&lt;/p&gt;`;
29
+ }
30
+ </template>
31
+ </sonic-code>
32
+
33
+ ## Dynamic path
34
+
35
+ `${prop}` placeholders resolve from properties of the component that renders the template; the directive re-subscribes when they change. While a placeholder is `null` or `undefined`, nothing is rendered. Rules: [Dynamic paths](/docs/misc/dynamic-path). `skipEmptyPlaceholder` is not available on `sub()`.
36
+
37
+ <sonic-code language="typescript">
38
+ <template>
39
+ const personKey = new DataProviderKey&lt;OnBoard, { seatIndex: number }&gt;(
40
+ "demoOnBoard.${seatIndex}",
41
+ );
42
+
43
+ @property({ type: Number }) seatIndex = 0;
44
+
45
+ render() {
46
+ return html`&lt;strong&gt;${sub(personKey.name)}&lt;/strong&gt; · ${sub(personKey.role)}`;
47
+ }
48
+ </template>
49
+ </sonic-code>
50
+
51
+ <sonic-code>
52
+ <template>
53
+ <docs-demo-sources for="demo-sub-template"></docs-demo-sources>
54
+ <demo-sub-template></demo-sub-template>
55
+ </template>
56
+ </sonic-code>
57
+
58
+ ## sub() or get()
59
+
60
+ `get(path)` from `@supersoniks/concorde/utils` returns a one-time snapshot: in a template it never updates. Use `sub()` in templates and `get` / `set` / `dp` in imperative code.
61
+
62
+ <sonic-code language="typescript">
63
+ <template>
64
+ html`${sub(flightKey.gate)}`; // updates on gate change
65
+ html`${get(flightKey.gate)}`; // frozen at first render
66
+ </template>
67
+ </sonic-code>
68
+
69
+ ## API reference
70
+
71
+ | Argument | Type | Description |
72
+ |----------|------|-------------|
73
+ | `path` | `string` or `DataProviderKey<T, U>` | Path to read. Placeholders resolve on the template host |
74
+
75
+ The directive subscribes when its part connects and unsubscribes when it disconnects.
@@ -0,0 +1,73 @@
1
+ # t()
2
+
3
+ Lit directive that renders a translated label by key. Keys are batched into one GET to the endpoint set by the nearest `wordingProvider` ancestor attribute, and results are cached in `localStorage`.
4
+
5
+ ## Import
6
+
7
+ <sonic-code language="typescript">
8
+ <template>
9
+ import { t } from "@supersoniks/concorde/directives/Wording";
10
+ </template>
11
+ </sonic-code>
12
+
13
+ `wording` and `w` are aliases of `t`. In plain HTML, use the [`sonic-t`](/core/components/functional/translation) element.
14
+
15
+ ## Usage
16
+
17
+ Set `serviceURL` and `wordingProvider` on the host component or one of its ancestors, then call `t(key)` in a template. Attributes on elements **inside** the component's own template are not read. Click the button to bump the version and reload the labels.
18
+
19
+ <docs-lit-demo for="docs-api-config-wording-demo"></docs-lit-demo>
20
+
21
+ ## Endpoint contract
22
+
23
+ All keys requested in the same tick are sent in one request, appended to `wordingProvider` as `labels[]`:
24
+
25
+ <sonic-code language="shell">
26
+ <template>
27
+ GET {serviceURL}/wording/labels?lang=fr&labels[]=greeting&labels[]=farewell
28
+ </template>
29
+ </sonic-code>
30
+
31
+ The response is a flat map of key to label:
32
+
33
+ <sonic-code language="json">
34
+ <template>
35
+ { "greeting": "Bonjour", "farewell": "Au revoir" }
36
+ </template>
37
+ </sonic-code>
38
+
39
+ Until the label arrives, `t()` renders an empty string.
40
+
41
+ ## HTML labels
42
+
43
+ `t()` escapes the label. Use `unsafeWording(key)` for labels that contain trusted HTML.
44
+
45
+ <sonic-code language="typescript">
46
+ <template>
47
+ import { unsafeWording } from "@supersoniks/concorde/directives/Wording";
48
+
49
+ html`&lt;p&gt;${unsafeWording("terms.notice")}&lt;/p&gt;`;
50
+ </template>
51
+ </sonic-code>
52
+
53
+ ## Reloading labels
54
+
55
+ Labels are fetched again when:
56
+
57
+ - the `lang` attribute of `<html>` changes
58
+ - the number stored at `wordingVersionProvider` changes — bump it after publishing new labels to invalidate the `localStorage` cache
59
+
60
+ ## API reference
61
+
62
+ | Function | Description |
63
+ |----------|-------------|
64
+ | `t(key)` · `wording(key)` · `w(key)` | Renders the escaped label for `key` |
65
+ | `unsafeWording(key)` | Renders the label as HTML |
66
+ | `isWordingReady(key)` | `true` once the label for `key` is loaded |
67
+
68
+ | Ancestor attribute | Description |
69
+ |--------------------|-------------|
70
+ | `wordingProvider` | Endpoint path and query, relative to `serviceURL` |
71
+ | `wordingVersionProvider` | DataProvider path holding a version number |
72
+
73
+ Other ancestor attributes (`serviceURL`, `token`, …) apply as for any request: see [API configuration](/docs/misc/api-configuration).
@@ -0,0 +1,56 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { docsPageHref, docsPagePath, parseDocsLocation } from "./docs-location";
3
+
4
+ describe("docsPagePath / docsPageHref", () => {
5
+ it("builds pretty public pathnames", () => {
6
+ expect(docsPagePath("docs/getting-started/start.md")).toBe(
7
+ "/docs/getting-started/start",
8
+ );
9
+ expect(docsPageHref("core/components/ui/button/button.md")).toBe(
10
+ "/core/components/ui/button",
11
+ );
12
+ expect(docsPageHref("docs/decorators/get.md", "options")).toBe(
13
+ "/docs/decorators/get#options",
14
+ );
15
+ expect(
16
+ docsPagePath("core/components/functional/sdui/sdui-extension-points.md"),
17
+ ).toBe("/core/components/functional/sdui/sdui-extension-points");
18
+ });
19
+ });
20
+
21
+ describe("parseDocsLocation", () => {
22
+ it("maps root site pages to their markdown", () => {
23
+ const r = parseDocsLocation("/about");
24
+ expect(r.url).toBe("about.md");
25
+ expect(r.pagePath).toBe("/about");
26
+ expect(parseDocsLocation("/privacy#your-rights").anchor).toBe("your-rights");
27
+ expect(parseDocsLocation("/about/").url).toBe("about.md");
28
+ expect(parseDocsLocation("/developers").url).toBe("");
29
+ expect(parseDocsLocation("/unknown").url).toBe("");
30
+ });
31
+
32
+ it("parses pretty pathname doc URLs", () => {
33
+ const r = parseDocsLocation("/docs/getting-started/start");
34
+ expect(r.url).toBe("docs/getting-started/start.md");
35
+ expect(r.pagePath).toBe("/docs/getting-started/start");
36
+ expect(r.anchor).toBe("");
37
+ });
38
+
39
+ it("parses pretty component paths and heading fragments", () => {
40
+ const r = parseDocsLocation("/core/components/ui/button#Size");
41
+ expect(r.url).toBe("core/components/ui/button.md");
42
+ expect(r.anchor).toBe("Size");
43
+ expect(r.pagePath).toBe("/core/components/ui/button");
44
+ });
45
+
46
+ it("treats / as home", () => {
47
+ const r = parseDocsLocation("/");
48
+ expect(r.url).toBe("");
49
+ expect(r.pagePath).toBe("/");
50
+ });
51
+
52
+ it("ignores raw .md / .html file URLs (not SPA routes)", () => {
53
+ expect(parseDocsLocation("/docs/getting-started/start.md").url).toBe("");
54
+ expect(parseDocsLocation("/docs/getting-started/start.html").url).toBe("");
55
+ });
56
+ });
@@ -1,54 +1,155 @@
1
- /** Doc page hash for `router.md` (markdown anchor, before demo sub-routes). */
2
- export const DOC_ROUTER_PAGE_HASH =
3
- "#core/components/functional/router/router.md/router";
4
-
5
1
  /**
6
- * Doc site hash: `#<markdown-path>/<page-anchor>[#<in-page-demo-route>]`
7
- * e.g. `#core/.../router.md/router#home` — second `#` is for sonic-router demos only.
2
+ * Docs site URLs use the pathname (pushState):
3
+ * /docs/getting-started/start
4
+ * /core/components/ui/button
5
+ * Optional fragment for in-page headings or router demos:
6
+ * /core/components/functional/router#departures
7
+ *
8
+ * Docs markdown paths match the public URL; components keep `…/name/name.md` on disk.
8
9
  */
10
+
11
+ import {
12
+ SITE_PAGE_SLUGS,
13
+ toPublicMdRel,
14
+ toPublicPath,
15
+ toSourceId,
16
+ } from "../../scripts/docs-public-url.mjs";
17
+
18
+ /** Pathname for a markdown file under `src/` (with or without `.md`). */
19
+ export function docsPagePath(mdRel: string): string {
20
+ return toPublicPath(mdRel);
21
+ }
22
+
23
+ /** Full href for a doc page, optional heading / demo fragment. */
24
+ export function docsPageHref(mdRel: string, fragment?: string): string {
25
+ const path = docsPagePath(mdRel);
26
+ if (!fragment) return path;
27
+ return `${path}#${fragment.replace(/^#/, "")}`;
28
+ }
29
+
30
+ /** Doc page path for `router.md` (pathname; demos append `#subRoute`). */
31
+ export const DOC_ROUTER_PAGE_PATH = docsPagePath(
32
+ "core/components/functional/router/router.md",
33
+ );
34
+
35
+ /** @deprecated Use DOC_ROUTER_PAGE_PATH */
36
+ export const DOC_ROUTER_PAGE_HASH = DOC_ROUTER_PAGE_PATH;
37
+
9
38
  export function parseDocsLocation(location: string): {
10
- /** Path for markdown fetch (no leading `#`). */
39
+ /** Path for markdown fetch (public `….md`, no leading `/`). */
11
40
  url: string;
12
- /** Page anchor (last segment before demo sub-hash). */
41
+ /** In-page heading id or demo sub-route (from `#…`, no leading `#`). */
13
42
  anchor: string;
14
- /** In-page route segment after a second `#` (router demos). */
43
+ /** Same as `anchor` when used for sonic-router demos. */
15
44
  demoSubHash: string;
16
- /** Full doc page hash including anchor, without demo sub-hash. */
45
+ /** Canonical page pathname (no hash), e.g. `/docs/getting-started/start`. */
46
+ pagePath: string;
47
+ /** @deprecated Prefer `pagePath`; kept for older call sites. */
17
48
  pageHash: string;
18
49
  } {
19
- const sharpIdx = location.indexOf("#");
20
- if (sharpIdx < 0) {
21
- return { url: "", anchor: "", demoSubHash: "", pageHash: "" };
50
+ const empty = {
51
+ url: "",
52
+ anchor: "",
53
+ demoSubHash: "",
54
+ pagePath: "",
55
+ pageHash: "",
56
+ };
57
+
58
+ let pathname = "";
59
+ let hash = "";
60
+
61
+ if (/^https?:\/\//i.test(location) || location.startsWith("/")) {
62
+ try {
63
+ const base =
64
+ typeof document !== "undefined" && document.location?.origin
65
+ ? document.location.origin
66
+ : "https://concorde.supersoniks.org";
67
+ const u = new URL(location, base);
68
+ pathname = u.pathname;
69
+ hash = u.hash.replace(/^#/, "");
70
+ } catch {
71
+ return empty;
72
+ }
73
+ } else if (location.startsWith("#")) {
74
+ hash = location.slice(1);
75
+ } else {
76
+ const sharp = location.indexOf("#");
77
+ if (sharp >= 0) {
78
+ pathname = location.slice(0, sharp);
79
+ hash = location.slice(sharp + 1);
80
+ } else {
81
+ pathname = location;
82
+ }
83
+ }
84
+
85
+ pathname = pathname.replace(/\/index\.html$/i, "") || "/";
86
+ if (pathname !== "/" && pathname.endsWith("/")) {
87
+ pathname = pathname.slice(0, -1);
88
+ }
89
+
90
+ if (pathname === "/" || pathname === "") {
91
+ return { ...empty, pagePath: "/", pageHash: "/" };
22
92
  }
23
93
 
24
- let hashBody = location.substring(sharpIdx + 1);
25
- let demoSubHash = "";
26
- const nested = hashBody.lastIndexOf("#");
27
- if (nested > 0) {
28
- demoSubHash = hashBody.substring(nested + 1);
29
- hashBody = hashBody.substring(0, nested);
94
+ if (
95
+ pathname.startsWith("/assets/") ||
96
+ pathname.startsWith("/crawl/") ||
97
+ pathname.startsWith("/src/") ||
98
+ pathname.startsWith("/hubs/") ||
99
+ pathname.endsWith(".md") ||
100
+ pathname.endsWith(".mdx") ||
101
+ pathname.endsWith(".html") ||
102
+ pathname === "/llms.txt" ||
103
+ pathname === "/llms-full.txt" ||
104
+ pathname === "/sitemap.xml" ||
105
+ pathname === "/robots.txt"
106
+ ) {
107
+ return empty;
30
108
  }
31
109
 
32
- const parts = hashBody.split("/").filter(Boolean);
33
- const anchor = decodeURIComponent(parts.pop() || "");
34
- const url = parts.join("/");
110
+ const rel = pathname.replace(/^\//, "");
111
+ if (SITE_PAGE_SLUGS.includes(rel)) {
112
+ return {
113
+ url: `${rel}.md`,
114
+ anchor: hash,
115
+ demoSubHash: hash,
116
+ pagePath: pathname,
117
+ pageHash: pathname,
118
+ };
119
+ }
120
+ if (!rel || !isDocsContentPath(rel)) {
121
+ return empty;
122
+ }
123
+
124
+ const sourceId = toSourceId(rel);
125
+ const pagePath = toPublicPath(sourceId);
126
+ const url = toPublicMdRel(sourceId);
35
127
 
36
128
  return {
37
129
  url,
38
- anchor,
39
- demoSubHash,
40
- pageHash: hashBody ? `#${hashBody}` : "",
130
+ anchor: hash,
131
+ demoSubHash: hash,
132
+ pagePath,
133
+ pageHash: pagePath,
41
134
  };
42
135
  }
43
136
 
44
- /** Navigate inside the current doc page without reloading markdown. */
45
- export function setDocsDemoSubHash(subRoute: string, pageHash?: string): void {
137
+ function isDocsContentPath(rel: string): boolean {
138
+ return (
139
+ rel.startsWith("docs/") ||
140
+ rel.startsWith("core/components/") ||
141
+ rel.startsWith("core/")
142
+ );
143
+ }
144
+
145
+ /** Navigate inside the current doc page without reloading markdown (router demos). */
146
+ export function setDocsDemoSubHash(subRoute: string, pagePath?: string): void {
46
147
  const loc = document.location;
47
148
  const base =
48
- pageHash ||
49
- parseDocsLocation(loc.pathname + loc.search + loc.hash).pageHash ||
50
- loc.hash;
149
+ pagePath ||
150
+ parseDocsLocation(loc.pathname + loc.search + loc.hash).pagePath ||
151
+ loc.pathname;
51
152
  const sub = subRoute.replace(/^#/, "");
52
- const nextHash = sub ? `${base}#${sub}` : base;
53
- history.replaceState(history.state, "", `${loc.pathname}${loc.search}${nextHash}`);
153
+ const next = sub ? `${base}#${sub}` : base;
154
+ history.replaceState(history.state, "", `${next}`);
54
155
  }
package/src/docs/docs.ts CHANGED
@@ -15,9 +15,8 @@ import "./home/home";
15
15
  import "./example/users";
16
16
  import "./example/docs-users-list";
17
17
  import "./example/docs-user-two-scopes";
18
- import "./example/docs-joke-demos";
18
+ import "./example/docs-flight-demos";
19
19
  import "./example/docs-queue-demos";
20
- import "./example/docs-input-autocomplete-demos";
21
20
  import "./example/docs-toggle-demos";
22
21
  import "./example/docs-boarding-pass-demo";
23
22
  import "./example/docs-list-demos";