@supersoniks/concorde 5.1.2 → 5.1.3-immutable.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (497) hide show
  1. package/.agents/skills/concorde-docs/SKILL.md +1 -1
  2. package/.claude/skills +1 -0
  3. package/.github/workflows/ci.yml +21 -0
  4. package/.github-export-ignore +30 -0
  5. package/CONTRIBUTING.md +59 -0
  6. package/DEV.md +54 -0
  7. package/LICENSE +21 -0
  8. package/OPEN_SOURCE_CHECKPOINT.md +133 -0
  9. package/README.md +1 -1
  10. package/ai/README.md +29 -41
  11. package/ai/skills/concorde/SKILL.md +54 -324
  12. package/ai/skills/concorde/rules/composition.md +32 -0
  13. package/ai/skills/concorde/rules/data.md +47 -0
  14. package/ai/skills/concorde/rules/http.md +25 -0
  15. package/ai/skills/concorde/rules/lists-forms.md +35 -0
  16. package/ai/skills/concorde/rules/styling.md +46 -0
  17. package/ai/skills/concorde/rules/troubleshooting.md +45 -0
  18. package/build-infos.json +1 -1
  19. package/concorde-core.bundle.js +177 -177
  20. package/concorde-core.es.js +5183 -5018
  21. package/custom-elements-manifest.public.config.mjs +8 -0
  22. package/{.tmp-cem/custom-elements.json → custom-elements.json} +11722 -8868
  23. package/dist/concorde-core.bundle.js +177 -177
  24. package/dist/concorde-core.es.js +5183 -5018
  25. package/dist/docs-mock-api-sw.js +58 -223
  26. package/dist/docs-mock-api-sw.js.map +4 -4
  27. package/dist/img/og-concorde.jpg +0 -0
  28. package/dist/robots.txt +11 -10
  29. package/docs/assets/index-CD4WyL6o.css +1 -0
  30. package/docs/assets/index-D_alEsng.js +12122 -0
  31. package/docs/crawl/core/components/functional/date/date.html +190 -0
  32. package/docs/crawl/core/components/functional/fetch/fetch.html +109 -0
  33. package/docs/crawl/core/components/functional/if/if.html +27 -0
  34. package/docs/crawl/core/components/functional/jsonata/jsonata.html +79 -0
  35. package/docs/crawl/core/components/functional/list/list.html +70 -0
  36. package/docs/crawl/core/components/functional/mix/mix.html +45 -0
  37. package/docs/crawl/core/components/functional/queue/queue.html +96 -0
  38. package/docs/crawl/core/components/functional/router/router.html +106 -0
  39. package/docs/{core → crawl/core}/components/functional/sdui/sdui-extension-points.html +8 -9
  40. package/docs/crawl/core/components/functional/sdui/sdui.html +368 -0
  41. package/docs/crawl/core/components/functional/states/states.html +66 -0
  42. package/docs/crawl/core/components/functional/submit/submit.html +160 -0
  43. package/docs/{core → crawl/core}/components/functional/subscriber/subscriber.html +5 -6
  44. package/docs/crawl/core/components/functional/value/value.html +51 -0
  45. package/docs/{core → crawl/core}/components/ui/alert/alert.html +63 -53
  46. package/docs/{core → crawl/core}/components/ui/alert-messages/alert-messages.html +5 -6
  47. package/docs/{core → crawl/core}/components/ui/badge/badge.html +33 -33
  48. package/docs/crawl/core/components/ui/button/button.html +150 -0
  49. package/docs/crawl/core/components/ui/captcha/captcha.html +112 -0
  50. package/docs/{core → crawl/core}/components/ui/card/card.html +11 -12
  51. package/docs/{core → crawl/core}/components/ui/divider/divider.html +14 -14
  52. package/docs/crawl/core/components/ui/form/checkbox/checkbox.html +73 -0
  53. package/docs/crawl/core/components/ui/form/fieldset/fieldset.html +266 -0
  54. package/docs/{core → crawl/core}/components/ui/form/form-actions/form-actions.html +23 -23
  55. package/docs/crawl/core/components/ui/form/form-layout/form-layout.html +121 -0
  56. package/docs/crawl/core/components/ui/form/input/input.html +109 -0
  57. package/docs/crawl/core/components/ui/form/input-autocomplete/input-autocomplete.html +38 -0
  58. package/docs/crawl/core/components/ui/form/radio/radio.html +56 -0
  59. package/docs/crawl/core/components/ui/form/select/select.html +73 -0
  60. package/docs/crawl/core/components/ui/form/switch/switch.html +56 -0
  61. package/docs/crawl/core/components/ui/form/textarea/textarea.html +59 -0
  62. package/docs/crawl/core/components/ui/group/group.html +104 -0
  63. package/docs/{core → crawl/core}/components/ui/icon/icon.html +9 -10
  64. package/docs/crawl/core/components/ui/image/image.html +298 -0
  65. package/docs/{core → crawl/core}/components/ui/link/link.html +11 -12
  66. package/docs/crawl/core/components/ui/loader/loader.html +124 -0
  67. package/docs/{core → crawl/core}/components/ui/menu/menu.html +33 -34
  68. package/docs/crawl/core/components/ui/modal/modal.html +342 -0
  69. package/docs/crawl/core/components/ui/pop/pop.html +296 -0
  70. package/docs/{core → crawl/core}/components/ui/progress/progress.html +7 -8
  71. package/docs/crawl/core/components/ui/table/table.html +545 -0
  72. package/docs/crawl/core/components/ui/theme/theme.html +131 -0
  73. package/docs/crawl/core/components/ui/toast/toast.html +233 -0
  74. package/docs/crawl/core/components/ui/tooltip/tooltip.html +140 -0
  75. package/docs/{docs/getting-started → crawl/docs/_core-concept}/dataFlow.html +29 -26
  76. package/docs/crawl/docs/_core-concept/overview.html +66 -0
  77. package/docs/crawl/docs/_core-concept/subscriber.html +75 -0
  78. package/docs/crawl/docs/_decorators/ancestor-attribute.html +117 -0
  79. package/docs/crawl/docs/_decorators/auto-subscribe.html +202 -0
  80. package/docs/crawl/docs/_decorators/bind.html +141 -0
  81. package/docs/crawl/docs/_decorators/get.html +149 -0
  82. package/docs/crawl/docs/_decorators/handle.html +165 -0
  83. package/docs/crawl/docs/_decorators/on-assign.html +355 -0
  84. package/docs/crawl/docs/_decorators/patch.html +78 -0
  85. package/docs/crawl/docs/_decorators/post.html +139 -0
  86. package/docs/crawl/docs/_decorators/publish.html +61 -0
  87. package/docs/crawl/docs/_decorators/put.html +78 -0
  88. package/docs/crawl/docs/_decorators/subscribe.html +109 -0
  89. package/docs/crawl/docs/_decorators/wait-for-ancestors.html +137 -0
  90. package/docs/crawl/docs/_directives/sub.html +93 -0
  91. package/docs/{docs/getting-started → crawl/docs/_getting-started}/ai-agents.html +11 -12
  92. package/docs/crawl/docs/_getting-started/concorde-manual-install.html +100 -0
  93. package/docs/crawl/docs/_getting-started/concorde-outside.html +58 -0
  94. package/docs/{docs/getting-started → crawl/docs/_getting-started}/create-a-component.html +14 -11
  95. package/docs/{docs/getting-started → crawl/docs/_getting-started}/my-first-component.html +22 -13
  96. package/docs/crawl/docs/_getting-started/my-first-subscriber.html +110 -0
  97. package/docs/crawl/docs/_getting-started/pubsub.html +62 -0
  98. package/docs/crawl/docs/_getting-started/start.html +76 -0
  99. package/docs/{docs/getting-started → crawl/docs/_getting-started}/theming.html +9 -10
  100. package/docs/{docs/misc → crawl/docs/_misc}/api-configuration.html +18 -18
  101. package/docs/{docs/misc → crawl/docs/_misc}/dataProviderKey.html +11 -12
  102. package/docs/{docs/misc → crawl/docs/_misc}/docs-mock-api.html +28 -25
  103. package/docs/{docs/misc → crawl/docs/_misc}/dynamic-path.html +15 -16
  104. package/docs/{docs/misc → crawl/docs/_misc}/endpoint.html +15 -16
  105. package/docs/crawl/docs/_misc/formelement-subscriber-removal.html +138 -0
  106. package/docs/{docs/misc → crawl/docs/_misc}/html-integration.html +15 -12
  107. package/docs/crawl/hubs/decorators.html +547 -0
  108. package/docs/crawl/hubs/form-components.html +381 -0
  109. package/docs/crawl/hubs/remote-data.html +452 -0
  110. package/docs/crawl/index.html +103 -0
  111. package/docs/docs-mock-api-sw.js +223 -58
  112. package/docs/docs-mock-api-sw.js.map +4 -4
  113. package/docs/index.html +68 -95
  114. package/docs/llms-full.txt +3610 -2231
  115. package/docs/llms.txt +86 -94
  116. package/docs/robots.txt +10 -11
  117. package/docs/sitemap.xml +84 -78
  118. package/docs/src/core/components/functional/date/date.md +231 -91
  119. package/docs/src/core/components/functional/fetch/fetch.md +83 -66
  120. package/docs/src/core/components/functional/if/if.md +3 -28
  121. package/docs/src/core/components/functional/jsonata/jsonata.md +37 -42
  122. package/docs/src/core/components/functional/list/list.md +43 -99
  123. package/docs/src/core/components/functional/mix/mix.md +26 -31
  124. package/docs/src/core/components/functional/queue/queue.md +61 -40
  125. package/docs/src/core/components/functional/router/router.md +65 -64
  126. package/docs/src/core/components/functional/sdui/component-catalog.gaps.json +1 -1
  127. package/docs/src/core/components/functional/sdui/component-catalog.json +1 -1
  128. package/docs/src/core/components/functional/sdui/example.json +86 -19
  129. package/docs/src/core/components/functional/sdui/sdui-extension-points.md +1 -1
  130. package/docs/src/core/components/functional/sdui/sdui.md +358 -187
  131. package/docs/src/core/components/functional/states/states.md +61 -86
  132. package/docs/src/core/components/functional/submit/submit.md +72 -64
  133. package/docs/src/core/components/functional/value/value.md +22 -34
  134. package/docs/src/core/components/ui/alert/alert.md +58 -48
  135. package/docs/src/core/components/ui/badge/badge.md +34 -27
  136. package/docs/src/core/components/ui/button/button.md +106 -139
  137. package/docs/src/core/components/ui/captcha/captcha.md +32 -17
  138. package/docs/src/core/components/ui/card/card.md +6 -6
  139. package/docs/src/core/components/ui/divider/divider.md +11 -8
  140. package/docs/src/core/components/ui/form/checkbox/checkbox.md +42 -90
  141. package/docs/src/core/components/ui/form/fieldset/fieldset.md +75 -31
  142. package/docs/src/core/components/ui/form/form-actions/form-actions.md +16 -14
  143. package/docs/src/core/components/ui/form/form-layout/form-layout.md +29 -19
  144. package/docs/src/core/components/ui/form/input/input.md +95 -95
  145. package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +29 -0
  146. package/docs/src/core/components/ui/form/radio/radio.md +34 -55
  147. package/docs/src/core/components/ui/form/select/select.md +45 -60
  148. package/docs/src/core/components/ui/form/switch/switch.md +34 -57
  149. package/docs/src/core/components/ui/form/textarea/textarea.md +38 -55
  150. package/docs/src/core/components/ui/group/group.md +33 -35
  151. package/docs/src/core/components/ui/icon/icon.md +4 -4
  152. package/docs/src/core/components/ui/image/image.md +107 -41
  153. package/docs/src/core/components/ui/link/link.md +6 -6
  154. package/docs/src/core/components/ui/loader/loader.md +55 -30
  155. package/docs/src/core/components/ui/menu/menu.md +27 -27
  156. package/docs/src/core/components/ui/modal/modal.md +96 -72
  157. package/docs/src/core/components/ui/pop/pop.md +158 -80
  158. package/docs/src/core/components/ui/progress/progress.md +2 -2
  159. package/docs/src/core/components/ui/table/table.md +255 -91
  160. package/docs/src/core/components/ui/theme/theme.md +36 -11
  161. package/docs/src/core/components/ui/toast/toast.md +117 -48
  162. package/docs/src/core/components/ui/tooltip/tooltip.md +62 -27
  163. package/docs/{docs/getting-started → src/docs/_core-concept}/dataFlow.md +18 -17
  164. package/docs/src/docs/_core-concept/overview.md +57 -0
  165. package/docs/src/docs/_core-concept/subscriber.md +75 -0
  166. package/docs/src/docs/_decorators/ancestor-attribute.md +128 -0
  167. package/docs/src/docs/_decorators/auto-subscribe.md +202 -0
  168. package/docs/src/docs/_decorators/bind.md +167 -0
  169. package/docs/src/docs/_decorators/get.md +162 -0
  170. package/docs/src/docs/_decorators/handle.md +175 -0
  171. package/docs/src/docs/_decorators/on-assign.md +390 -0
  172. package/docs/src/docs/_decorators/patch.md +70 -0
  173. package/docs/src/docs/_decorators/post.md +146 -0
  174. package/docs/src/docs/_decorators/publish.md +55 -0
  175. package/docs/src/docs/_decorators/put.md +70 -0
  176. package/docs/src/docs/_decorators/subscribe.md +100 -0
  177. package/docs/src/docs/_decorators/wait-for-ancestors.md +163 -0
  178. package/docs/src/docs/_directives/sub.md +91 -0
  179. package/docs/src/docs/{getting-started → _getting-started}/ai-agents.md +3 -3
  180. package/docs/src/docs/_getting-started/concorde-manual-install.md +133 -0
  181. package/docs/src/docs/_getting-started/concorde-outside.md +33 -0
  182. package/docs/{docs/getting-started → src/docs/_getting-started}/create-a-component.md +6 -3
  183. package/docs/src/docs/{getting-started → _getting-started}/my-first-component.md +14 -5
  184. package/docs/src/docs/_getting-started/my-first-subscriber.md +120 -0
  185. package/docs/src/docs/_getting-started/pubsub.md +37 -0
  186. package/docs/src/docs/{getting-started → _getting-started}/start.md +13 -1
  187. package/docs/src/docs/{getting-started → _getting-started}/theming.md +2 -2
  188. package/docs/src/docs/{misc → _misc}/api-configuration.md +12 -10
  189. package/docs/src/docs/{misc → _misc}/dataProviderKey.md +4 -4
  190. package/docs/{docs/misc → src/docs/_misc}/docs-mock-api.md +13 -12
  191. package/docs/{docs/misc → src/docs/_misc}/dynamic-path.md +8 -8
  192. package/docs/{docs/misc → src/docs/_misc}/endpoint.md +8 -8
  193. package/docs/src/docs/_misc/formelement-subscriber-removal.md +115 -0
  194. package/docs/{docs/misc → src/docs/_misc}/html-integration.md +5 -4
  195. package/docs/src/docs/search/docs-search.json +4375 -2420
  196. package/docs/src/tsconfig.declarations.json +22 -0
  197. package/docs/src/tsconfig.emit.json +23 -0
  198. package/docs/src/tsconfig.json +2 -23
  199. package/gitlab/job_github_mirror.sh +39 -0
  200. package/index.html +89 -0
  201. package/package.json +22 -4
  202. package/public/img/og-concorde.jpg +0 -0
  203. package/scripts/ai-init.mjs +104 -379
  204. package/scripts/ai-init.test.mjs +81 -239
  205. package/scripts/docs-markdown-vite-plugin.ts +11 -5
  206. package/scripts/docs-public-url.mjs +6 -0
  207. package/scripts/docs.htaccess +7 -0
  208. package/scripts/generate-cem.mjs +244 -0
  209. package/scripts/generate-cem.test.mjs +122 -0
  210. package/scripts/generate-crawl-docs.mjs +29 -5
  211. package/scripts/generate-sdui-catalog.mjs +11 -10
  212. package/scripts/github-export.mjs +150 -0
  213. package/scripts/post-build-docs.js +3 -0
  214. package/scripts/post-build.mjs +0 -0
  215. package/scripts/pre-publish.mjs +2 -1
  216. package/scripts/site-pages.mjs +212 -0
  217. package/scripts/site-pages.test.mjs +116 -0
  218. package/site-pages/about.md +22 -0
  219. package/site-pages/privacy.md +32 -0
  220. package/src/core/components/functional/date/date.md +1 -1
  221. package/src/core/components/functional/example/example.ts +3 -1
  222. package/src/core/components/functional/if/if.ts +0 -0
  223. package/src/core/components/functional/list/list.demo.ts +0 -0
  224. package/src/core/components/functional/list/list.md +6 -2
  225. package/src/core/components/functional/list/list.ts +17 -4
  226. package/src/core/components/functional/mix/mix.md +0 -0
  227. package/src/core/components/functional/router/router.demo.ts +0 -0
  228. package/src/core/components/functional/router/router.ts +0 -0
  229. package/src/core/components/functional/sdui/SDUIDescriptorTransformer.ts +0 -0
  230. package/src/core/components/functional/sdui/component-catalog.gaps.json +1 -1
  231. package/src/core/components/functional/sdui/component-catalog.json +2 -2
  232. package/src/core/components/functional/sdui/example.json +0 -0
  233. package/src/core/components/functional/sdui/sdui-immutable.spec.ts +74 -0
  234. package/src/core/components/functional/sdui/sdui.ts +33 -8
  235. package/src/core/components/functional/sdui/types.ts +0 -0
  236. package/src/core/components/functional/states/states.ts +0 -0
  237. package/src/core/components/functional/submit/submit.spec.ts +60 -0
  238. package/src/core/components/functional/submit/submit.ts +6 -3
  239. package/src/core/components/functional/subscriber/subscriber.ts +0 -0
  240. package/src/core/components/functional/value/value.md +0 -0
  241. package/src/core/components/functional/value/value.ts +0 -0
  242. package/src/core/components/ui/_css/size.ts +0 -0
  243. package/src/core/components/ui/captcha/altchaStyles.ts +0 -0
  244. package/src/core/components/ui/card/card.md +1 -1
  245. package/src/core/components/ui/form/input/input.md +19 -1
  246. package/src/core/components/ui/form/input/input.ts +8 -2
  247. package/src/core/components/ui/form/radio/radio.md +14 -0
  248. package/src/core/components/ui/image/image.md +17 -17
  249. package/src/core/components/ui/modal/modal.md +2 -2
  250. package/src/core/decorators/subscriber/bind.ts +9 -14
  251. package/src/core/decorators/subscriber/subscribe.ts +15 -9
  252. package/src/core/decorators/subscriber/subscribe.type-test.ts +14 -5
  253. package/src/core/mixins/Subscriber.ts +0 -0
  254. package/src/core/utils/DataBindObserver.ts +0 -0
  255. package/src/core/utils/Objects.ts +0 -0
  256. package/src/core/utils/PublisherProxy.ts +166 -125
  257. package/src/core/utils/deepReadonly.spec.ts +66 -0
  258. package/src/core/utils/deepReadonly.ts +71 -0
  259. package/src/core/utils/immutableValue.spec.ts +58 -0
  260. package/src/core/utils/immutableValue.ts +116 -0
  261. package/src/core/utils/nestedDotForm.spec.ts +88 -0
  262. package/src/core/utils/publisherImmutable.spec.ts +127 -0
  263. package/src/core/utils/route.ts +0 -0
  264. package/src/core/utils/strictGet.spec.ts +61 -0
  265. package/src/core/utils/strictGet.ts +102 -0
  266. package/src/css.d.ts +19 -0
  267. package/src/docs/components/docs-demo-sources.ts +3 -3
  268. package/src/docs/decorators/bind.md +23 -24
  269. package/src/docs/docs-location.spec.ts +10 -0
  270. package/src/docs/docs-location.ts +10 -0
  271. package/src/docs/example/decorators-demo-bind-demos.ts +11 -28
  272. package/src/docs/example/docs-toggle-demos.ts +1 -1
  273. package/src/docs/example/users.ts +0 -0
  274. package/src/docs/getting-started/ai-agents.md +51 -51
  275. package/src/docs/getting-started/dataFlow.md +2 -2
  276. package/src/docs/home/home.ts +3 -1
  277. package/src/docs/misc/publisher-get-immutability-docs-crawl.json +902 -0
  278. package/src/docs/misc/publisher-get-immutability-docs-recheck.json +13 -0
  279. package/src/docs/misc/publisher-get-immutability-study.md +229 -0
  280. package/src/docs/navigation/navigation.ts +5 -1
  281. package/src/docs/search/docs-search.json +358 -58
  282. package/src/docs/search/markdown-renderer.ts +6 -1
  283. package/src/docs/tailwind/css/docs/content.css +4 -5
  284. package/src/tsconfig.declarations.json +22 -0
  285. package/src/tsconfig.emit.json +23 -0
  286. package/src/tsconfig.json +53 -5
  287. package/src/tsconfig.tsbuildinfo +1 -1
  288. package/.taste-skill/after/desktop-fold.jpg +0 -0
  289. package/.taste-skill/after/desktop-page-01.jpg +0 -0
  290. package/.taste-skill/after/desktop-page-02.jpg +0 -0
  291. package/.taste-skill/after/desktop-page-03.jpg +0 -0
  292. package/.taste-skill/after/mobile-fold.jpg +0 -0
  293. package/.taste-skill/after/mobile-page-01.jpg +0 -0
  294. package/.taste-skill/after/report.json +0 -4103
  295. package/.taste-skill/after/tablet-fold.jpg +0 -0
  296. package/.taste-skill/after/tablet-page-01.jpg +0 -0
  297. package/.taste-skill/after/tablet-page-02.jpg +0 -0
  298. package/.taste-skill/before/desktop-fold.jpg +0 -0
  299. package/.taste-skill/before/desktop-page-01.jpg +0 -0
  300. package/.taste-skill/before/desktop-page-02.jpg +0 -0
  301. package/.taste-skill/before/mobile-fold.jpg +0 -0
  302. package/.taste-skill/before/mobile-page-01.jpg +0 -0
  303. package/.taste-skill/before/report.json +0 -2556
  304. package/.taste-skill/before/tablet-fold.jpg +0 -0
  305. package/.taste-skill/before/tablet-page-01.jpg +0 -0
  306. package/.taste-skill/direction.json +0 -510
  307. package/.taste-skill/notes.md +0 -84
  308. package/.taste-skill/prod/desktop-fold.jpg +0 -0
  309. package/.taste-skill/prod/desktop-page-01.jpg +0 -0
  310. package/.taste-skill/prod/desktop-page-02.jpg +0 -0
  311. package/.taste-skill/prod/desktop-page-03.jpg +0 -0
  312. package/.taste-skill/prod/mobile-fold.jpg +0 -0
  313. package/.taste-skill/prod/mobile-page-01.jpg +0 -0
  314. package/.taste-skill/prod/mobile-page-02.jpg +0 -0
  315. package/.taste-skill/prod/report.json +0 -1973
  316. package/.taste-skill/prod/tablet-fold.jpg +0 -0
  317. package/.taste-skill/prod/tablet-page-01.jpg +0 -0
  318. package/.taste-skill/prod/tablet-page-02.jpg +0 -0
  319. package/AUDIT.md +0 -228
  320. package/PLAN-AMELIORATION.md +0 -220
  321. package/PLAN-DOCS-AGENTS.md +0 -80
  322. package/ai/AGENTS.md +0 -56
  323. package/ai/cursor/rules/concorde-menu.mdc +0 -15
  324. package/ai/cursor/rules/concorde-scope.mdc +0 -14
  325. package/ai/cursor/rules/concorde-theme.mdc +0 -13
  326. package/ai/cursor/rules/concorde.mdc +0 -66
  327. package/ai/jetbrains/rules/concorde.md +0 -53
  328. package/ai/skills/concorde-get-set-dp/SKILL.md +0 -194
  329. package/ai/skills/concorde-imports/SKILL.md +0 -78
  330. package/ai/skills/concorde-menu/SKILL.md +0 -74
  331. package/ai/skills/concorde-scope/SKILL.md +0 -70
  332. package/ai/skills/concorde-theme/SKILL.md +0 -57
  333. package/docs/.htaccess +0 -75
  334. package/docs/404.html +0 -15
  335. package/docs/404.md +0 -5
  336. package/docs/assets/index-BgG6FFPt.js +0 -11765
  337. package/docs/assets/index-x89XINSG.css +0 -1
  338. package/docs/core/components/functional/date/date.html +0 -211
  339. package/docs/core/components/functional/date/date.md +0 -150
  340. package/docs/core/components/functional/fetch/fetch.html +0 -180
  341. package/docs/core/components/functional/fetch/fetch.md +0 -108
  342. package/docs/core/components/functional/if/if.html +0 -65
  343. package/docs/core/components/functional/if/if.md +0 -34
  344. package/docs/core/components/functional/jsonata/jsonata.html +0 -110
  345. package/docs/core/components/functional/jsonata/jsonata.md +0 -61
  346. package/docs/core/components/functional/list/list.html +0 -198
  347. package/docs/core/components/functional/list/list.md +0 -121
  348. package/docs/core/components/functional/mix/mix.html +0 -78
  349. package/docs/core/components/functional/mix/mix.md +0 -46
  350. package/docs/core/components/functional/queue/queue.html +0 -155
  351. package/docs/core/components/functional/queue/queue.md +0 -51
  352. package/docs/core/components/functional/router/router.html +0 -154
  353. package/docs/core/components/functional/router/router.md +0 -93
  354. package/docs/core/components/functional/sdui/sdui-extension-points.md +0 -94
  355. package/docs/core/components/functional/sdui/sdui.html +0 -397
  356. package/docs/core/components/functional/sdui/sdui.md +0 -307
  357. package/docs/core/components/functional/states/states.html +0 -141
  358. package/docs/core/components/functional/states/states.md +0 -112
  359. package/docs/core/components/functional/submit/submit.html +0 -178
  360. package/docs/core/components/functional/submit/submit.md +0 -106
  361. package/docs/core/components/functional/subscriber/subscriber.md +0 -91
  362. package/docs/core/components/functional/translation/translation.html +0 -60
  363. package/docs/core/components/functional/translation/translation.md +0 -38
  364. package/docs/core/components/functional/value/value.html +0 -81
  365. package/docs/core/components/functional/value/value.md +0 -47
  366. package/docs/core/components/ui/alert/alert.md +0 -186
  367. package/docs/core/components/ui/alert-messages/alert-messages.md +0 -85
  368. package/docs/core/components/ui/badge/badge.md +0 -181
  369. package/docs/core/components/ui/button/button.html +0 -309
  370. package/docs/core/components/ui/button/button.md +0 -216
  371. package/docs/core/components/ui/captcha/captcha.html +0 -80
  372. package/docs/core/components/ui/captcha/captcha.md +0 -56
  373. package/docs/core/components/ui/card/card.md +0 -215
  374. package/docs/core/components/ui/divider/divider.md +0 -126
  375. package/docs/core/components/ui/form/checkbox/checkbox.html +0 -200
  376. package/docs/core/components/ui/form/checkbox/checkbox.md +0 -125
  377. package/docs/core/components/ui/form/fieldset/fieldset.html +0 -238
  378. package/docs/core/components/ui/form/fieldset/fieldset.md +0 -161
  379. package/docs/core/components/ui/form/form-actions/form-actions.md +0 -98
  380. package/docs/core/components/ui/form/form-layout/form-layout.html +0 -115
  381. package/docs/core/components/ui/form/form-layout/form-layout.md +0 -109
  382. package/docs/core/components/ui/form/input/input.html +0 -235
  383. package/docs/core/components/ui/form/input/input.md +0 -142
  384. package/docs/core/components/ui/form/radio/radio.html +0 -144
  385. package/docs/core/components/ui/form/radio/radio.md +0 -78
  386. package/docs/core/components/ui/form/select/select.html +0 -178
  387. package/docs/core/components/ui/form/select/select.md +0 -86
  388. package/docs/core/components/ui/form/switch/switch.html +0 -146
  389. package/docs/core/components/ui/form/switch/switch.md +0 -80
  390. package/docs/core/components/ui/form/textarea/textarea.html +0 -162
  391. package/docs/core/components/ui/form/textarea/textarea.md +0 -82
  392. package/docs/core/components/ui/group/group.html +0 -113
  393. package/docs/core/components/ui/group/group.md +0 -77
  394. package/docs/core/components/ui/icon/icon.md +0 -214
  395. package/docs/core/components/ui/image/image.html +0 -194
  396. package/docs/core/components/ui/image/image.md +0 -167
  397. package/docs/core/components/ui/link/link.md +0 -81
  398. package/docs/core/components/ui/loader/loader.html +0 -114
  399. package/docs/core/components/ui/loader/loader.md +0 -87
  400. package/docs/core/components/ui/menu/menu.md +0 -370
  401. package/docs/core/components/ui/modal/modal.html +0 -324
  402. package/docs/core/components/ui/modal/modal.md +0 -211
  403. package/docs/core/components/ui/pop/pop.html +0 -250
  404. package/docs/core/components/ui/pop/pop.md +0 -216
  405. package/docs/core/components/ui/progress/progress.md +0 -109
  406. package/docs/core/components/ui/table/table.html +0 -333
  407. package/docs/core/components/ui/table/table.md +0 -267
  408. package/docs/core/components/ui/theme/theme.html +0 -116
  409. package/docs/core/components/ui/theme/theme.md +0 -97
  410. package/docs/core/components/ui/toast/toast.html +0 -185
  411. package/docs/core/components/ui/toast/toast.md +0 -147
  412. package/docs/core/components/ui/tooltip/tooltip.html +0 -112
  413. package/docs/core/components/ui/tooltip/tooltip.md +0 -89
  414. package/docs/docs/decorators/ancestor-attribute.html +0 -71
  415. package/docs/docs/decorators/ancestor-attribute.md +0 -59
  416. package/docs/docs/decorators/auto-subscribe.html +0 -61
  417. package/docs/docs/decorators/auto-subscribe.md +0 -40
  418. package/docs/docs/decorators/bind.html +0 -86
  419. package/docs/docs/decorators/bind.md +0 -77
  420. package/docs/docs/decorators/get.html +0 -166
  421. package/docs/docs/decorators/get.md +0 -160
  422. package/docs/docs/decorators/handle.html +0 -139
  423. package/docs/docs/decorators/handle.md +0 -119
  424. package/docs/docs/decorators/on-assign.html +0 -72
  425. package/docs/docs/decorators/on-assign.md +0 -63
  426. package/docs/docs/decorators/patch.html +0 -76
  427. package/docs/docs/decorators/patch.md +0 -44
  428. package/docs/docs/decorators/post.html +0 -150
  429. package/docs/docs/decorators/post.md +0 -134
  430. package/docs/docs/decorators/publish.html +0 -74
  431. package/docs/docs/decorators/publish.md +0 -56
  432. package/docs/docs/decorators/put.html +0 -83
  433. package/docs/docs/decorators/put.md +0 -51
  434. package/docs/docs/decorators/subscribe.html +0 -91
  435. package/docs/docs/decorators/subscribe.md +0 -87
  436. package/docs/docs/decorators/wait-for-ancestors.html +0 -82
  437. package/docs/docs/decorators/wait-for-ancestors.md +0 -76
  438. package/docs/docs/directives/sub.html +0 -79
  439. package/docs/docs/directives/sub.md +0 -75
  440. package/docs/docs/directives/t.html +0 -91
  441. package/docs/docs/directives/t.md +0 -73
  442. package/docs/docs/getting-started/ai-agents.md +0 -76
  443. package/docs/docs/getting-started/components.html +0 -27
  444. package/docs/docs/getting-started/components.md +0 -5
  445. package/docs/docs/getting-started/installation.html +0 -69
  446. package/docs/docs/getting-started/installation.md +0 -36
  447. package/docs/docs/getting-started/my-first-component.md +0 -227
  448. package/docs/docs/getting-started/start.html +0 -47
  449. package/docs/docs/getting-started/start.md +0 -35
  450. package/docs/docs/getting-started/theming.md +0 -253
  451. package/docs/docs/index.html +0 -99
  452. package/docs/docs/misc/api-configuration.md +0 -79
  453. package/docs/docs/misc/dataProviderKey.md +0 -168
  454. package/docs/hubs/decorators.html +0 -443
  455. package/docs/hubs/form-components.html +0 -404
  456. package/docs/hubs/remote-data.html +0 -371
  457. package/docs/img/archive/concorde-001-2cv.webp +0 -0
  458. package/docs/img/archive/concorde-red-arrows-2002-poster.jpg +0 -0
  459. package/docs/img/archive/concorde-red-arrows-2002.webm +0 -0
  460. package/docs/img/archive/credits.json +0 -28
  461. package/docs/index.md +0 -22
  462. package/docs/src/core/components/functional/translation/translation.md +0 -38
  463. package/docs/src/docs/decorators/ancestor-attribute.md +0 -59
  464. package/docs/src/docs/decorators/auto-subscribe.md +0 -40
  465. package/docs/src/docs/decorators/bind.md +0 -77
  466. package/docs/src/docs/decorators/get.md +0 -160
  467. package/docs/src/docs/decorators/handle.md +0 -119
  468. package/docs/src/docs/decorators/on-assign.md +0 -63
  469. package/docs/src/docs/decorators/patch.md +0 -44
  470. package/docs/src/docs/decorators/post.md +0 -134
  471. package/docs/src/docs/decorators/publish.md +0 -56
  472. package/docs/src/docs/decorators/put.md +0 -51
  473. package/docs/src/docs/decorators/subscribe.md +0 -87
  474. package/docs/src/docs/decorators/wait-for-ancestors.md +0 -76
  475. package/docs/src/docs/directives/sub.md +0 -75
  476. package/docs/src/docs/directives/t.md +0 -73
  477. package/docs/src/docs/getting-started/components.md +0 -5
  478. package/docs/src/docs/getting-started/create-a-component.md +0 -136
  479. package/docs/src/docs/getting-started/dataFlow.md +0 -87
  480. package/docs/src/docs/getting-started/installation.md +0 -36
  481. package/docs/src/docs/misc/docs-mock-api.md +0 -62
  482. package/docs/src/docs/misc/dynamic-path.md +0 -71
  483. package/docs/src/docs/misc/endpoint.md +0 -45
  484. package/docs/src/docs/misc/html-integration.md +0 -14
  485. /package/{docs → dist}/img/concorde/plane_01.jpg +0 -0
  486. /package/{docs → dist}/img/concorde/plane_02.jpg +0 -0
  487. /package/{docs → dist}/img/concorde/plane_03.jpg +0 -0
  488. /package/{docs → dist}/img/concorde/plane_04.jpg +0 -0
  489. /package/{docs → dist}/img/concorde/plane_05.jpg +0 -0
  490. /package/{docs → dist}/img/concorde/plane_06.jpg +0 -0
  491. /package/{docs → dist}/img/concorde/plane_07.jpg +0 -0
  492. /package/{docs → dist}/img/concorde/plane_08.jpg +0 -0
  493. /package/{docs → dist}/img/concorde/plane_09.jpg +0 -0
  494. /package/{docs → dist}/img/concorde/plane_10.jpg +0 -0
  495. /package/{docs → dist}/img/concorde/plane_11.jpg +0 -0
  496. /package/{docs → dist}/img/concorde/plane_12.jpg +0 -0
  497. /package/{docs → dist}/img/concorde/plane_13.jpg +0 -0
@@ -0,0 +1,355 @@
1
+ <!DOCTYPE html>
2
+ <html lang="fr" data-crawl-url="https://concorde.supersoniks.org/crawl/docs/_decorators/on-assign.html" data-doc-id="docs/_decorators/on-assign">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>@onAssign — Concorde</title>
7
+ <meta name="description" content="&gt; New apps: use @handle with DataProviderKey (Data flow). @onAssign uses untyped string paths; it remains documented for existing codebases — see Migrating to @handle below.">
8
+ <meta name="keywords" content="Concorde, supersoniks, docs/_decorators/on-assign, on-assign, @onAssign, decorator, onAssign, DataProviderKey, set, get, User n°${userNumber}, user-${userNumber}@example.com">
9
+ <meta name="concorde-doc-id" content="docs/_decorators/on-assign">
10
+ <link rel="canonical" href="https://concorde.supersoniks.org/crawl/docs/_decorators/on-assign.html">
11
+ </head>
12
+ <body>
13
+ <header>
14
+ <p><a href="../../index.html">Concorde documentation (crawl)</a> · <a href="https://concorde.supersoniks.org/#docs/_decorators/on-assign.md/on-assign" rel="nofollow">interactive version</a></p>
15
+ </header>
16
+ <main>
17
+ <article>
18
+ <p class="doc-lead" id="doc-summary"><strong>Concorde decorator — @onAssign</strong>. &gt; New apps: use @handle with DataProviderKey (Data flow). @onAssign uses untyped string paths; it remains documented for existing codebases — see Migrating to @handle below. <span>Doc ID: <code>docs/_decorators/on-assign</code>. Keywords: Concorde, supersoniks, docs/_decorators/on-assign, on-assign, @onAssign, decorator, onAssign, DataProviderKey, set, get, User n°${userNumber}, user-${userNumber}@example.com. URL: <a href="https://concorde.supersoniks.org/crawl/docs/_decorators/on-assign.html">https://concorde.supersoniks.org/crawl/docs/_decorators/on-assign.html</a>.</span></p>
19
+ <h1 id="onassign">@onAssign</h1>
20
+ <blockquote>
21
+ <p><strong>New apps:</strong> use <a href="./handle.html#handle">@handle</a> with <code>DataProviderKey</code> (<a href="../_core-concept/dataFlow.html#dataFlow">Data flow</a>). <code>@onAssign</code> uses untyped string paths; it remains documented for existing codebases — see <strong>Migrating to @handle</strong> below.</p>
22
+ </blockquote>
23
+ <p>The <code>@onAssign</code> decorator allows you to execute a method when one or more publishers are updated. The method is called only when all specified publishers have been assigned values.</p>
24
+ <p>For a <strong>typed</strong> equivalent (recommended), use <a href="./handle.html#handle">@handle</a>.</p>
25
+ <h2 id="principle">Principle</h2>
26
+ <p>This decorator subscribes to one or more publishers by <strong>string path</strong> (legacy). When all specified publishers have been assigned values (via <code>set</code>), the decorated method is called with all the values as arguments. Prefer <a href="./handle.html#handle">@handle</a> + <code>DataProviderKey</code> and <code>get</code> / <code>set</code> from <a href="../_core-concept/dataFlow.html#dataFlow">Data flow</a>.</p>
27
+ <p>This is particularly useful when you need to wait for multiple data sources to be ready before executing logic.</p>
28
+ <h2 id="usage">Usage</h2>
29
+ <h3 id="import">Import</h3>
30
+ <pre><code class="language-typescript">import { onAssign } from &quot;@supersoniks/concorde/decorators&quot;;
31
+ </code></pre>
32
+ <h3 id="basic-example">Basic example</h3>
33
+ <pre><code class="language-typescript">//...
34
+ @customElement(&quot;demo-on-assign&quot;)
35
+ export class DemoOnAssign extends LitElement {
36
+ static styles = [tailwind];
37
+
38
+ @state() userWithSettings: any = null;
39
+ @state() isReady: boolean = false;
40
+ @state() lastUpdate: string = &quot;&quot;;
41
+
42
+ @onAssign(&quot;demoUser&quot;, &quot;demoUserSettings&quot;)
43
+ handleDataReady(user: any, settings: any) {
44
+ this.isReady = Object.keys(user).length &gt; 0 &amp;&amp; Object.keys(settings).length &gt; 0;
45
+ this.userWithSettings = { ...user, ...settings };
46
+ this.lastUpdate = new Date().toLocaleTimeString();
47
+ this.requestUpdate();
48
+ }
49
+
50
+ render() {
51
+ const { name, email, theme, language } = this.userWithSettings;
52
+ return //...
53
+ }
54
+
55
+ updateData() {
56
+ const user = PublisherManager.get(&quot;demoUser&quot;);
57
+ const userSettings = PublisherManager.get(&quot;demoUserSettings&quot;);
58
+ const userNumber = Math.floor(Math.random() * 100);
59
+ user.set({
60
+ name: `User n°${userNumber}`,
61
+ email: `user-${userNumber}@example.com`,
62
+ });
63
+
64
+ userSettings.set({
65
+ theme: [&quot;light&quot;, &quot;dark&quot;, &quot;auto&quot;][Math.floor(Math.random() * 3)],
66
+ language: [&quot;en&quot;, &quot;fr&quot;, &quot;es&quot;][Math.floor(Math.random() * 3)],
67
+ });
68
+ }
69
+ }
70
+ </code></pre>
71
+ <pre><code>&lt;docs-demo-sources for=&quot;demo-on-assign&quot;&gt;&lt;/docs-demo-sources&gt;
72
+ &lt;demo-on-assign&gt;&lt;/demo-on-assign&gt;
73
+ </code></pre>
74
+ <h3 id="example-with-nested-paths">Example with nested paths</h3>
75
+ <pre><code class="language-typescript">@customElement(&quot;product-view&quot;)
76
+ export class ProductView extends LitElement {
77
+ product: any = null;
78
+ inventory: any = null;
79
+
80
+ @onAssign(&quot;store.product&quot;, &quot;store.inventory&quot;)
81
+ handleProductData(product: any, inventory: any) {
82
+ this.product = product;
83
+ this.inventory = inventory;
84
+ this.requestUpdate();
85
+ }
86
+
87
+ render() {
88
+ if (!this.product) return html`&lt;div&gt;Loading...&lt;/div&gt;`;
89
+
90
+ const stock = this.inventory[this.product.id] || 0;
91
+ return html`
92
+ &lt;div&gt;
93
+ &lt;h2&gt;${this.product.name}&lt;/h2&gt;
94
+ &lt;p&gt;Price: ${this.product.price}€&lt;/p&gt;
95
+ &lt;p&gt;Stock: ${stock}&lt;/p&gt;
96
+ &lt;/div&gt;
97
+ `;
98
+ }
99
+ }
100
+ </code></pre>
101
+ <h2 id="path-syntax">Path syntax</h2>
102
+ <p>The path uses dot notation to navigate through the publisher structure:</p>
103
+ <ul>
104
+ <li><strong>First segment</strong>: dataProvider identifier (e.g., <code>&quot;userData&quot;</code>)</li>
105
+ <li><strong>Following segments</strong>: nested properties (e.g., <code>&quot;store.product&quot;</code>)</li>
106
+ <li><strong>Array access</strong>: use numeric index (e.g., <code>&quot;data.items.0&quot;</code>)</li>
107
+ </ul>
108
+ <h3 id="dynamic-path-driven-by-class-properties">Dynamic path driven by class properties</h3>
109
+ <p>You can now build the paths dynamically by referencing the host class properties inside the strings passed to <code>@onAssign</code>. Two placeholder syntaxes are supported:</p>
110
+ <ul>
111
+ <li><code>${myProperty}</code> or <code>${this.myProperty}</code></li>
112
+ <li><code>{$myProperty}</code></li>
113
+ </ul>
114
+ <p>Each placeholder is replaced at runtime with the current value of the corresponding property. <code>@onAssign</code> automatically watches those properties and:</p>
115
+ <ul>
116
+ <li>re-evaluates the final paths when one of them changes,</li>
117
+ <li>removes the previous subscriptions before attaching the new ones,</li>
118
+ <li>observe the changes inside <code>willUpdate(changedProperties)</code> so nothing touches the getters/setters.</li>
119
+ </ul>
120
+ <p>While a placeholder is <code>null</code>/<code>undefined</code>, subscriptions are detached. Optional <code>skipEmptyPlaceholder</code> on <a href="./handle.html#handle">@handle</a> (typed replacement). Details: <a href="../_misc/dynamic-path.html#dynamic-path">Dynamic path placeholders</a>.</p>
121
+ <pre><code class="language-typescript">@customElement(&quot;demo-on-assign-dynamic&quot;)
122
+ export class DemoOnAssignDynamic extends LitElement {
123
+ static styles = [tailwind];
124
+
125
+ @property({ type: String })
126
+ dataProvider: &quot;demoUsers&quot; | &quot;demoUsersAlt&quot; = &quot;demoUsers&quot;;
127
+
128
+ @property({ type: Number })
129
+ userIndex: number = 0;
130
+
131
+ @state() user: any = null;
132
+ @state() userSettings: any = null;
133
+
134
+ @onAssign(&quot;${dataProvider}.${userIndex}&quot;, &quot;${dataProvider}Settings.${userIndex}&quot;)
135
+ handleUserDataReady(user: any, settings: any) {
136
+ this.user = user;
137
+ this.userSettings = settings;
138
+ }
139
+
140
+ updateUserIndex(e: Event) {
141
+ this.userIndex = parseInt((e.target as HTMLInputElement).value);
142
+ }
143
+
144
+ updateDataProvider(e: Event) {
145
+ this.dataProvider = (e.target as HTMLSelectElement).value as
146
+ | &quot;demoUsers&quot;
147
+ | &quot;demoUsersAlt&quot;;
148
+ }
149
+
150
+ updateCurrentUserData() {
151
+ const usersPublisher = PublisherManager.get(this.dataProvider);
152
+ const settingsPublisher = PublisherManager.get(
153
+ `${this.dataProvider}Settings`
154
+ );
155
+ const userPublisher = Objects.traverse(
156
+ usersPublisher,
157
+ [String(this.userIndex)]
158
+ ) as PublisherProxy;
159
+ const settingPublisher = Objects.traverse(
160
+ settingsPublisher,
161
+ [String(this.userIndex)]
162
+ ) as PublisherProxy;
163
+
164
+ if (userPublisher &amp;&amp; settingPublisher) {
165
+ // Générer de nouvelles données aléatoires
166
+ const randomNames = [
167
+ { firstName: &quot;Alice&quot;, lastName: &quot;Wonder&quot; },
168
+ { firstName: &quot;Bob&quot;, lastName: &quot;Builder&quot; },
169
+ { firstName: &quot;Charlie&quot;, lastName: &quot;Chaplin&quot; },
170
+ ];
171
+ const randomThemes = [&quot;light&quot;, &quot;dark&quot;, &quot;auto&quot;];
172
+ const randomLanguages = [&quot;en&quot;, &quot;fr&quot;, &quot;es&quot;];
173
+
174
+ const randomName =
175
+ randomNames[Math.floor(Math.random() * randomNames.length)];
176
+ const randomEmail = `${randomName.firstName.toLowerCase()}.${randomName.lastName.toLowerCase()}@example.com`;
177
+ const randomTheme =
178
+ randomThemes[Math.floor(Math.random() * randomThemes.length)];
179
+ const randomLanguage =
180
+ randomLanguages[Math.floor(Math.random() * randomLanguages.length)];
181
+
182
+ // Mettre à jour l&#39;utilisateur directement
183
+ const currentUser = userPublisher.get() || {};
184
+ userPublisher.set({
185
+ ...currentUser,
186
+ firstName: randomName.firstName,
187
+ lastName: randomName.lastName,
188
+ email: randomEmail,
189
+ });
190
+
191
+ // Mettre à jour les settings directement
192
+ settingPublisher.set({
193
+ theme: randomTheme,
194
+ language: randomLanguage,
195
+ });
196
+ }
197
+ }
198
+
199
+ render() {
200
+ return html`
201
+ &amp;lt;div class=&quot;flex flex-col gap-2&quot;&amp;gt;
202
+ &amp;lt;sonic-select label=&quot;Users set&quot; @change=${this.updateDataProvider}&amp;gt;
203
+ &amp;lt;option value=&quot;demoUsers&quot;&amp;gt;First set of users&amp;lt;/option&amp;gt;
204
+ &amp;lt;option value=&quot;demoUsersAlt&quot;&amp;gt;Second set of users&amp;lt;/option&amp;gt;
205
+ &amp;lt;/sonic-select&amp;gt;
206
+ &amp;lt;sonic-input
207
+ type=&quot;number&quot;
208
+ .value=${this.userIndex}
209
+ @input=${this.updateUserIndex}
210
+ min=&quot;0&quot;
211
+ max=&quot;9&quot;
212
+ label=&quot;Index&quot;
213
+ class=&quot;block&quot;
214
+ &amp;gt;&amp;lt;/sonic-input&amp;gt;
215
+ &amp;lt;sonic-button @click=${this.updateCurrentUserData}&amp;gt;
216
+ Update current user data
217
+ &amp;lt;/sonic-button&amp;gt;
218
+ &amp;lt;div class=&quot;flex flex-col gap-2 border p-2&quot;&amp;gt;
219
+ &amp;lt;div&amp;gt;
220
+ &amp;lt;sonic-icon name=&quot;user&quot; library=&quot;heroicons&quot;&amp;gt;&amp;lt;/sonic-icon&amp;gt;
221
+ ${this.user?.firstName} ${this.user?.lastName}
222
+ &amp;lt;/div&amp;gt;
223
+ &amp;lt;div&amp;gt;
224
+ &amp;lt;sonic-icon name=&quot;envelope&quot; library=&quot;heroicons&quot;&amp;gt;&amp;lt;/sonic-icon&amp;gt;
225
+ ${this.user?.email}
226
+ &amp;lt;/div&amp;gt;
227
+ &amp;lt;div&amp;gt;
228
+ Theme: ${this.userSettings?.theme} | Language:
229
+ ${this.userSettings?.language}
230
+ &amp;lt;/div&amp;gt;
231
+ &amp;lt;/div&amp;gt;
232
+ &amp;lt;/div&amp;gt;
233
+ `;
234
+ }
235
+ }
236
+ </code></pre>
237
+ <pre><code>&lt;docs-demo-sources for=&quot;demo-on-assign-dynamic&quot;&gt;&lt;/docs-demo-sources&gt;
238
+ &lt;demo-on-assign-dynamic&gt;&lt;/demo-on-assign-dynamic&gt;
239
+ </code></pre>
240
+ <blockquote>
241
+ <p>⚠️ Use classic string literals: <code>@onAssign(&quot;${dataProvider}.${profileId}&quot;, &quot;settings.${profileId}&quot;)</code>. Do <strong>not</strong> use template literals (backticks), otherwise JavaScript would try to interpolate the value immediately.</p>
242
+ </blockquote>
243
+ <p>Additional constraints:</p>
244
+ <ul>
245
+ <li>The hosting class must expose a <code>willUpdate(changedProperties?: Map&lt;PropertyKey, unknown&gt;)</code> method (LitElement already provides it) so that <code>@onAssign</code> can listen to dependency changes.</li>
246
+ <li>Dependencies need to be reactive (e.g. <code>@property()</code> on LitElement) or you must call <code>this.requestUpdate(&quot;myProp&quot;)</code> manually after changing them, otherwise <code>willUpdate</code> will never be notified.</li>
247
+ <li>If you use nested expressions like <code>${user.id}</code>, the first segment (<code>user</code>) is the one being observed: you need to reassign <code>this.user</code> (e.g. with a new object) so that the binding can detect the change.</li>
248
+ </ul>
249
+ <h2 id="behavior">Behavior</h2>
250
+ <ul>
251
+ <li>The method is called only when <strong>all</strong> specified publishers have been assigned values</li>
252
+ <li>The method receives the values of all publishers as arguments, in the same order as specified</li>
253
+ <li>Subscription happens at the time of <code>connectedCallback</code></li>
254
+ <li>Unsubscription happens automatically at the time of <code>disconnectedCallback</code></li>
255
+ <li>If a publisher doesn&#39;t exist yet, it will be created with the value <code>null</code></li>
256
+ <li>The method is called with <code>this</code> bound to the component instance</li>
257
+ </ul>
258
+ <h2 id="use-cases">Use cases</h2>
259
+ <p>This decorator is particularly useful for:</p>
260
+ <ul>
261
+ <li><strong>Waiting for multiple data sources</strong> before rendering or executing logic</li>
262
+ <li><strong>Synchronizing data</strong> from different publishers</li>
263
+ <li><strong>Initializing components</strong> that depend on multiple data providers</li>
264
+ <li><strong>Handling complex data dependencies</strong> where you need all data to be ready</li>
265
+ </ul>
266
+ <h2 id="complete-example">Complete example</h2>
267
+ <pre><code class="language-typescript">import { html, LitElement } from &quot;lit&quot;;
268
+ import { customElement } from &quot;lit/decorators.js&quot;;
269
+ import { onAssign } from &quot;@supersoniks/concorde/decorators&quot;;
270
+ import { PublisherManager } from &quot;@supersoniks/concorde/core/utils/PublisherProxy&quot;;
271
+
272
+ @customElement(&quot;order-summary&quot;)
273
+ export class OrderSummary extends LitElement {
274
+ order: any = null;
275
+ customer: any = null;
276
+ shipping: any = null;
277
+
278
+ @onAssign(&quot;orderData&quot;, &quot;customerData&quot;, &quot;shippingData&quot;)
279
+ handleOrderReady(order: any, customer: any, shipping: any) {
280
+ this.order = order;
281
+ this.customer = customer;
282
+ this.shipping = shipping;
283
+ this.requestUpdate();
284
+ }
285
+
286
+ render() {
287
+ if (!this.order || !this.customer || !this.shipping) {
288
+ return html`&lt;div&gt;Loading order details...&lt;/div&gt;`;
289
+ }
290
+
291
+ return html`
292
+ &lt;div class=&quot;order-summary&quot;&gt;
293
+ &lt;h2&gt;Order #${this.order.id}&lt;/h2&gt;
294
+ &lt;p&gt;Customer: ${this.customer.name}&lt;/p&gt;
295
+ &lt;p&gt;Shipping to: ${this.shipping.address}&lt;/p&gt;
296
+ &lt;p&gt;Total: ${this.order.total}€&lt;/p&gt;
297
+ &lt;/div&gt;
298
+ `;
299
+ }
300
+ }
301
+ // Somewhere in your code, update the publishers:
302
+ const orderPub = PublisherManager.get(&quot;orderData&quot;);
303
+ const customerPub = PublisherManager.get(&quot;customerData&quot;);
304
+ const shippingPub = PublisherManager.get(&quot;shippingData&quot;);
305
+ // The method will be called only when all three are set:
306
+ orderPub.set({ id: &quot;123&quot;, total: 99.99 });
307
+ customerPub.set({ name: &quot;John Doe&quot;, email: &quot;john@example.com&quot; });
308
+ shippingPub.set({ address: &quot;123 Main St&quot; });
309
+ // handleOrderReady will be called with all three values
310
+ </code></pre>
311
+ <h2 id="migrating-to-handle">Migrating to @handle</h2>
312
+ <p><code>@handle</code> is the typed successor of <code>@onAssign</code>. The key behavioral difference: <code>@onAssign</code> waits for <strong>all</strong> values to be defined before calling the method, whereas <code>@handle</code> calls it on <strong>every</strong> assignment by default. Use the <code>waitForAllDefined</code> option to keep the old semantics.</p>
313
+ <h3 id="why-migrate">Why migrate</h3>
314
+ <ul>
315
+ <li><strong>Typed paths</strong>: keys are <code>DataProviderKey&lt;T&gt;</code>, so the method arguments are strongly typed (no more <code>any</code>).</li>
316
+ <li><strong>Explicit intent</strong>: <code>waitForAllDefined</code> and <code>skip</code> replace implicit behavior.</li>
317
+ <li><strong>Single API</strong>: <code>@handle</code> covers the mono- and multi-path cases (up to 3 keys).</li>
318
+ </ul>
319
+ <h3 id="equivalent-semantics-waitforalldefined">Equivalent semantics (<code>waitForAllDefined</code>)</h3>
320
+ <pre><code class="language-typescript">// Before
321
+ @onAssign(&quot;demoUser&quot;, &quot;demoUserSettings&quot;)
322
+ handleDataReady(user: any, settings: any) { /* ... */ }
323
+
324
+ // After — same &quot;wait for everything&quot; behavior, but typed
325
+ const user = new DataProviderKey&amp;lt;User&amp;gt;(&quot;demoUser&quot;);
326
+ const settings = new DataProviderKey&amp;lt;Settings&amp;gt;(&quot;demoUserSettings&quot;);
327
+
328
+ @handle(user, settings, { waitForAllDefined: true })
329
+ handleDataReady(user: User, settings: Settings) { /* ... */ }
330
+ </code></pre>
331
+ <h3 id="single-path">Single path</h3>
332
+ <pre><code class="language-typescript">// Before
333
+ @onAssign(&quot;settings.modules.logs_route.enabled&quot;)
334
+ onLogRoute(value: boolean) { /* ... */ }
335
+
336
+ // After
337
+ const settings = new DataProviderKey&amp;lt;AppSettings&amp;gt;(&quot;settings&quot;);
338
+
339
+ @handle(settings.modules.logs_route.enabled)
340
+ onLogRoute(value: boolean) { /* ... */ }
341
+ </code></pre>
342
+ <h3 id="4-paths">4+ paths</h3>
343
+ <p><code>@handle</code> is capped at 3 keys. For the rare case of 4 or more publishers, keep <code>@onAssign</code> for now, or split the logic into several <code>@handle</code> methods that each store their value and call a shared method (guarding against partial values).</p>
344
+ <h2 id="notes">Notes</h2>
345
+ <ul>
346
+ <li>This decorator works with any component that has <code>connectedCallback</code> and <code>disconnectedCallback</code> methods (such as <code>LitElement</code> or components extending <code>Subscriber</code>)</li>
347
+ <li>The method is called synchronously when all publishers are ready</li>
348
+ <li>If you need to update the UI, remember to call <code>this.requestUpdate()</code> inside the method</li>
349
+ <li>For more information about publishers, see the documentation on <a href="../_getting-started/pubsub.html#pubsub">Sharing data</a></li>
350
+ </ul>
351
+
352
+ </article>
353
+ </main>
354
+ </body>
355
+ </html>
@@ -0,0 +1,78 @@
1
+ <!DOCTYPE html>
2
+ <html lang="fr" data-crawl-url="https://concorde.supersoniks.org/crawl/docs/_decorators/patch.html" data-doc-id="docs/_decorators/patch">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>@patch — Concorde</title>
7
+ <meta name="description" content="@patch applies a partial update with the body from a publisher. It uses the">
8
+ <meta name="keywords" content="Concorde, supersoniks, docs/_decorators/patch, patch, @patch, decorator, Endpoint, DataProviderKey, ApiResult, send(component),
9
+
10
+ , when: &quot;before&quot;, autoPostOnBodyMutation: false, autoPostOnBodyMutation, skipIfBodyMissing">
11
+ <meta name="concorde-doc-id" content="docs/_decorators/patch">
12
+ <link rel="canonical" href="https://concorde.supersoniks.org/crawl/docs/_decorators/patch.html">
13
+ </head>
14
+ <body>
15
+ <header>
16
+ <p><a href="../../index.html">Concorde documentation (crawl)</a> · <a href="https://concorde.supersoniks.org/#docs/_decorators/patch.md/patch" rel="nofollow">interactive version</a></p>
17
+ </header>
18
+ <main>
19
+ <article>
20
+ <p class="doc-lead" id="doc-summary"><strong>Concorde decorator — @patch</strong>. @patch applies a partial update with the body from a publisher. It uses the <span>Doc ID: <code>docs/_decorators/patch</code>. Keywords: Concorde, supersoniks, docs/_decorators/patch, patch, @patch, decorator, Endpoint, DataProviderKey, ApiResult, send(component),
21
+
22
+ , when: &quot;before&quot;, autoPostOnBodyMutation: false, autoPostOnBodyMutation, skipIfBodyMissing. URL: <a href="https://concorde.supersoniks.org/crawl/docs/_decorators/patch.html">https://concorde.supersoniks.org/crawl/docs/_decorators/patch.html</a>.</span></p>
23
+ <h1 id="patch">@patch</h1>
24
+ <p><code>@patch</code> applies a partial update with the body from a publisher. It uses the
25
+ same model as <a href="./post.html#post">@post</a>:
26
+ <code>Endpoint&lt;T&gt;</code>, <code>DataProviderKey&lt;B&gt;</code>, <code>ApiResult&lt;T&gt;</code>, options, and the
27
+ <code>send(component)</code> handle.</p>
28
+ <h2 id="minimal-usage">Minimal usage</h2>
29
+ <pre><code class="language-typescript">const bodyKey = new DataProviderKey&lt;Partial&lt;User&gt;&gt;(&quot;users.patch&quot;);
30
+ const patchUser = patch(new Endpoint&lt;User&gt;(&quot;users/42&quot;), bodyKey);
31
+
32
+ @patchUser
33
+ @state()
34
+ payload?: ApiResult&lt;User&gt;;
35
+ </code></pre>
36
+ <p>The same decorator adapts to a method:</p>
37
+ <pre><code class="language-typescript">@patch(new Endpoint&lt;User&gt;(&quot;users/42&quot;), bodyKey)
38
+ handlePatch(payload?: ApiResult&lt;User&gt;) {
39
+ if (payload?.response?.ok) console.log(payload.result);
40
+ }
41
+ </code></pre>
42
+ <p>To run the operation again from the component:</p>
43
+ <pre><code class="language-typescript">async savePatch() {
44
+ await patchUser.send(this);
45
+ }
46
+ </code></pre>
47
+ <p><code>send(component)</code> returns a Promise resolved after the PATCH completes. See
48
+ <a href="./post.html#post">@post</a> for the method-decorator form and the
49
+ <code>when: &quot;before&quot;</code> option.</p>
50
+ <p>The PATCH is also sent automatically when the body mutates, unless
51
+ <code>autoPostOnBodyMutation: false</code> is set. The available options are described in
52
+ <a href="./post.html#post">@post</a>:</p>
53
+ <ul>
54
+ <li><code>autoPostOnBodyMutation</code></li>
55
+ <li><code>skipIfBodyMissing</code></li>
56
+ <li><code>refetchEveryMs</code></li>
57
+ <li><code>skipEmptyPlaceholder</code></li>
58
+ <li><code>triggerKey</code></li>
59
+ </ul>
60
+ <p>Pass explicit API configuration as the third argument:</p>
61
+ <pre><code class="language-typescript">@patch(endpoint, bodyKey, apiConfigurationKey)
62
+ </code></pre>
63
+ <h2 id="import">Import</h2>
64
+ <pre><code class="language-typescript">import { patch, type ApiResult } from &quot;@supersoniks/concorde/decorators&quot;;
65
+ import { DataProviderKey } from &quot;@supersoniks/concorde/dataProviderKey&quot;;
66
+ import { Endpoint } from &quot;@supersoniks/concorde/utils/endpoint&quot;;
67
+ </code></pre>
68
+ <h2 id="see-also">See also</h2>
69
+ <ul>
70
+ <li><a href="./post.html#post">@post</a> — options and triggers</li>
71
+ <li><a href="./put.html#put">@put</a> — full replacement</li>
72
+ <li><a href="../_misc/dynamic-path.html#dynamic-path">Dynamic path placeholders</a></li>
73
+ </ul>
74
+
75
+ </article>
76
+ </main>
77
+ </body>
78
+ </html>
@@ -0,0 +1,139 @@
1
+ <!DOCTYPE html>
2
+ <html lang="fr" data-crawl-url="https://concorde.supersoniks.org/crawl/docs/_decorators/post.html" data-doc-id="docs/_decorators/post">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>@post — Concorde</title>
7
+ <meta name="description" content="@post sends the contents of a publisher and stores the response in an">
8
+ <meta name="keywords" content="Concorde, supersoniks, docs/_decorators/post, post, @post, decorator, ApiResult, undefined, Endpoint, DataProviderKey,
9
+
10
+ The current body is read from , send(component),
11
+
12
+ , returns a ,
13
+
14
+ Use ">
15
+ <meta name="concorde-doc-id" content="docs/_decorators/post">
16
+ <link rel="canonical" href="https://concorde.supersoniks.org/crawl/docs/_decorators/post.html">
17
+ </head>
18
+ <body>
19
+ <header>
20
+ <p><a href="../../index.html">Concorde documentation (crawl)</a> · <a href="https://concorde.supersoniks.org/#docs/_decorators/post.md/post" rel="nofollow">interactive version</a></p>
21
+ </header>
22
+ <main>
23
+ <article>
24
+ <p class="doc-lead" id="doc-summary"><strong>Concorde decorator — @post</strong>. @post sends the contents of a publisher and stores the response in an <span>Doc ID: <code>docs/_decorators/post</code>. Keywords: Concorde, supersoniks, docs/_decorators/post, post, @post, decorator, ApiResult, undefined, Endpoint, DataProviderKey,
25
+
26
+ The current body is read from , send(component),
27
+
28
+ , returns a ,
29
+
30
+ Use . URL: <a href="https://concorde.supersoniks.org/crawl/docs/_decorators/post.html">https://concorde.supersoniks.org/crawl/docs/_decorators/post.html</a>.</span></p>
31
+ <h1 id="post">@post</h1>
32
+ <p><code>@post</code> sends the contents of a publisher and stores the response in an
33
+ optional <code>ApiResult&lt;T&gt;</code> property. The property is <code>undefined</code> until a result
34
+ is available.</p>
35
+ <h2 id="minimal-usage">Minimal usage</h2>
36
+ <p>Pass an <code>Endpoint&lt;T&gt;</code> and a <code>DataProviderKey&lt;B&gt;</code> for the request body.</p>
37
+ <pre><code class="language-typescript">const userBodyKey = new DataProviderKey&lt;CreateUser&gt;(&quot;users.form&quot;);
38
+ const createUser = post(new Endpoint&lt;User&gt;(&quot;users&quot;), userBodyKey);
39
+
40
+ @createUser
41
+ @state()
42
+ payload?: ApiResult&lt;User&gt;;
43
+ </code></pre>
44
+ <p>The same decorator adapts to a method and receives the complete payload:</p>
45
+ <pre><code class="language-typescript">@post(new Endpoint&lt;User&gt;(&quot;users&quot;), userBodyKey)
46
+ handleCreate(payload?: ApiResult&lt;User&gt;) {
47
+ if (payload?.response?.ok) console.log(payload.result);
48
+ }
49
+ </code></pre>
50
+ <p>The current body is read from <code>userBodyKey</code>. By default, the POST is sent when
51
+ the component connects and after each body mutation. Mutations in the same
52
+ frame are coalesced into one request.</p>
53
+ <p>API configuration is read from the HTML scope, as with
54
+ <a href="./get.html#get">@get</a>.</p>
55
+ <h2 id="sending-the-post-again">Sending the POST again</h2>
56
+ <h3 id="from-the-component">From the component</h3>
57
+ <p>Keep the decorator to access <code>send(component)</code>. The body is read again when the
58
+ operation runs.</p>
59
+ <pre><code class="language-typescript">async saveAgain() {
60
+ const payload = await createUser.send(this);
61
+ console.log(payload?.result);
62
+ }
63
+ </code></pre>
64
+ <p><code>send()</code> returns a <code>Promise&lt;ApiResult&lt;T&gt; | undefined&gt;</code> that resolves after the
65
+ operation completes. It is useful for “Save” or “Retry” buttons and can repeat
66
+ an operation with side effects.</p>
67
+ <h3 id="from-a-method-decorator">From a method decorator</h3>
68
+ <p>The send action can decorate a local method. It runs after the method by
69
+ default, waits for an eventual Promise to resolve, and the decorated method
70
+ call waits for the send to complete:</p>
71
+ <pre><code class="language-typescript">import { send } from &quot;@supersoniks/concorde/decorators&quot;;
72
+
73
+ @send(createUser)
74
+ async save() {
75
+ // Prepare local state or validate the form.
76
+ }
77
+ </code></pre>
78
+ <p>Use <code>{ when: &quot;before&quot; }</code> when the send must complete before the method runs:</p>
79
+ <pre><code class="language-typescript">@send(createUser, { when: &quot;before&quot; })
80
+ saveBefore() {
81
+ // The POST has completed before this method runs.
82
+ }
83
+ </code></pre>
84
+ <p>The method decorator adds an explicit send. If the method also mutates the body
85
+ publisher, set <code>autoPostOnBodyMutation: false</code> when the decorated method must
86
+ be the only trigger.</p>
87
+ <h2 id="options-postoptions">Options (<code>PostOptions</code>)</h2>
88
+ <p>Options are the third argument, or the fourth argument when a configuration key
89
+ is provided.</p>
90
+ <ul>
91
+ <li><code>autoPostOnBodyMutation</code>: send after a body mutation (default: <code>true</code>). Set
92
+ it to <code>false</code> to use <code>send()</code>.</li>
93
+ <li><code>skipIfBodyMissing</code>: skip when the body is <code>null</code> or <code>undefined</code> (default:
94
+ <code>true</code>).</li>
95
+ <li><code>refetchEveryMs</code>: repeat the POST at this interval. Use it only when
96
+ repeating the operation is intended.</li>
97
+ <li><code>skipEmptyPlaceholder</code>: block the request when a <code>${...}</code> placeholder is
98
+ <code>&quot;&quot;</code>.</li>
99
+ <li><code>triggerKey</code>: a publisher whose <code>invalidate()</code> sends the POST again.</li>
100
+ </ul>
101
+ <p>With a configuration key:</p>
102
+ <pre><code class="language-typescript">@post(endpoint, userBodyKey, apiConfigurationKey)
103
+ </code></pre>
104
+ <p>See <a href="../_misc/dynamic-path.html#dynamic-path">Dynamic path placeholders</a> for
105
+ dynamic path details.</p>
106
+ <h2 id="when-the-post-is-sent">When the POST is sent</h2>
107
+ <ul>
108
+ <li>when the component connects and the body and configuration are available;</li>
109
+ <li>after a body mutation, unless <code>autoPostOnBodyMutation: false</code>;</li>
110
+ <li>when a property used in <code>${...}</code> changes;</li>
111
+ <li>when a configuration publisher changes;</li>
112
+ <li>when the <code>triggerKey</code> publisher is invalidated;</li>
113
+ <li>when <code>send()</code> is called;</li>
114
+ <li>after each response when <code>refetchEveryMs</code> is set.</li>
115
+ </ul>
116
+ <h2 id="import">Import</h2>
117
+ <pre><code class="language-typescript">import { post, type ApiResult } from &quot;@supersoniks/concorde/decorators&quot;;
118
+ import { DataProviderKey } from &quot;@supersoniks/concorde/dataProviderKey&quot;;
119
+ import { Endpoint } from &quot;@supersoniks/concorde/utils/endpoint&quot;;
120
+ </code></pre>
121
+ <h2 id="demos">Demos</h2>
122
+ <pre><code>&lt;docs-demo-sources for=&quot;demo-api-post&quot;&gt;&lt;/docs-demo-sources&gt;
123
+ &lt;demo-api-post&gt;&lt;/demo-api-post&gt;
124
+ &lt;docs-demo-sources for=&quot;demo-api-post-method&quot;&gt;&lt;/docs-demo-sources&gt;
125
+ &lt;demo-api-post-method&gt;&lt;/demo-api-post-method&gt;
126
+ &lt;docs-demo-sources for=&quot;demo-api-post-dynamic&quot;&gt;&lt;/docs-demo-sources&gt;
127
+ &lt;demo-api-post-dynamic&gt;&lt;/demo-api-post-dynamic&gt;
128
+ </code></pre>
129
+ <p>See <a href="./put.html#put">@put</a> and
130
+ <a href="./patch.html#patch">@patch</a>: they use the same model with a
131
+ different HTTP method.</p>
132
+ <h2 id="advanced">Advanced</h2>
133
+ <p>External invalidation is currently available through <code>triggerKey</code>; it is kept
134
+ out of the main usage examples.</p>
135
+
136
+ </article>
137
+ </main>
138
+ </body>
139
+ </html>
@@ -0,0 +1,61 @@
1
+ <!DOCTYPE html>
2
+ <html lang="fr" data-crawl-url="https://concorde.supersoniks.org/crawl/docs/_decorators/publish.html" data-doc-id="docs/_decorators/publish">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>@publish — Concorde</title>
7
+ <meta name="description" content="Write-only binding: assigning to the property publishes to the DataProviderKey path. No read subscription (inverse of @subscribe).">
8
+ <meta name="keywords" content="Concorde, supersoniks, docs/_decorators/publish, publish, @publish, decorator, DataProviderKey, @bind, @subscribe, skipEmptyPlaceholder">
9
+ <meta name="concorde-doc-id" content="docs/_decorators/publish">
10
+ <link rel="canonical" href="https://concorde.supersoniks.org/crawl/docs/_decorators/publish.html">
11
+ </head>
12
+ <body>
13
+ <header>
14
+ <p><a href="../../index.html">Concorde documentation (crawl)</a> · <a href="https://concorde.supersoniks.org/#docs/_decorators/publish.md/publish" rel="nofollow">interactive version</a></p>
15
+ </header>
16
+ <main>
17
+ <article>
18
+ <p class="doc-lead" id="doc-summary"><strong>Concorde decorator — @publish</strong>. Write-only binding: assigning to the property publishes to the DataProviderKey path. No read subscription (inverse of @subscribe). <span>Doc ID: <code>docs/_decorators/publish</code>. Keywords: Concorde, supersoniks, docs/_decorators/publish, publish, @publish, decorator, DataProviderKey, @bind, @subscribe, skipEmptyPlaceholder. URL: <a href="https://concorde.supersoniks.org/crawl/docs/_decorators/publish.html">https://concorde.supersoniks.org/crawl/docs/_decorators/publish.html</a>.</span></p>
19
+ <h1 id="publish">@publish</h1>
20
+ <p>Write-only binding: assigning to the property publishes to the <code>DataProviderKey</code> path. No read subscription (inverse of <a href="./subscribe.html#subscribe">@subscribe</a>).</p>
21
+ <p>Similar to the “reflect” half of <a href="./bind.html#bind">@bind</a> without listening to the publisher.</p>
22
+ <h2 id="import">Import</h2>
23
+ <pre><code class="language-typescript">import { publish } from &quot;@supersoniks/concorde/decorators&quot;;
24
+ import { sub } from &quot;@supersoniks/concorde/directives&quot;;
25
+ import { DataProviderKey } from &quot;@supersoniks/concorde/dataProviderKey&quot;;
26
+ </code></pre>
27
+ <h2 id="example">Example</h2>
28
+ <pre><code class="language-typescript">type PublishDemoData = { email: string; message: string };
29
+ const publishDemoKey = new DataProviderKey&lt;PublishDemoData&gt;(&quot;publishDemo&quot;);
30
+ //
31
+ @customElement(&quot;demo-publish&quot;)
32
+ export class DemoPublish extends LitElement {
33
+ @publish(publishDemoKey.email)
34
+ @state()
35
+ email = &quot;&quot;;
36
+ //
37
+ @publish(publishDemoKey.message)
38
+ @state()
39
+ message = &quot;&quot;;
40
+ //
41
+ render() {
42
+ return html`
43
+ &lt;sonic-input
44
+ .value=${this.email}
45
+ @input=${(e) =&gt; (this.email = (e.target as HTMLInputElement).value)}
46
+ label=&quot;Email&quot;
47
+ &gt;&lt;/sonic-input&gt;
48
+ &lt;p&gt;${sub(publishDemoKey.email)}&lt;/p&gt;
49
+ `;
50
+ }
51
+ }
52
+ </code></pre>
53
+ <pre><code>&lt;docs-demo-sources for=&quot;demo-publish&quot;&gt;&lt;/docs-demo-sources&gt;
54
+ &lt;demo-publish&gt;&lt;/demo-publish&gt;
55
+ </code></pre>
56
+ <p>Dynamic paths use the same placeholder rules as <code>@bind</code> / <code>@subscribe</code>. Resolution and <code>skipEmptyPlaceholder</code>: <a href="../_misc/dynamic-path.html#dynamic-path">Dynamic path placeholders</a>.</p>
57
+
58
+ </article>
59
+ </main>
60
+ </body>
61
+ </html>