@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.
- package/.agents/skills/concorde-docs/SKILL.md +153 -0
- package/.agents/skills/{concorde-component-docs/template.md → concorde-docs/templates/component.md} +6 -2
- package/.agents/skills/concorde-docs/templates/decorator.md +43 -0
- package/.agents/skills/concorde-docs/templates/guide.md +25 -0
- package/.claude/skills +1 -0
- package/.github/workflows/ci.yml +21 -0
- package/.github-export-ignore +30 -0
- package/CONTRIBUTING.md +59 -0
- package/DEV.md +54 -0
- package/LICENSE +21 -0
- package/OPEN_SOURCE_CHECKPOINT.md +133 -0
- package/README.md +4 -4
- package/ai/README.md +29 -41
- package/ai/skills/concorde/SKILL.md +54 -324
- package/ai/skills/concorde/rules/composition.md +32 -0
- package/ai/skills/concorde/rules/data.md +47 -0
- package/ai/skills/concorde/rules/http.md +25 -0
- package/ai/skills/concorde/rules/lists-forms.md +35 -0
- package/ai/skills/concorde/rules/styling.md +46 -0
- package/ai/skills/concorde/rules/troubleshooting.md +45 -0
- package/build-infos.json +1 -1
- package/concorde-core.bundle.js +177 -177
- package/concorde-core.es.js +4993 -4833
- package/custom-elements-manifest.public.config.mjs +8 -0
- package/{.tmp-cem/custom-elements.json → custom-elements.json} +11758 -8904
- package/dist/concorde-core.bundle.js +177 -177
- package/dist/concorde-core.es.js +4993 -4833
- package/dist/docs-mock-api-sw.js +58 -223
- package/dist/docs-mock-api-sw.js.map +4 -4
- package/dist/img/concorde/plane_01.jpg +0 -0
- package/dist/img/concorde/plane_02.jpg +0 -0
- package/dist/img/concorde/plane_03.jpg +0 -0
- package/dist/img/concorde/plane_04.jpg +0 -0
- package/dist/img/concorde/plane_05.jpg +0 -0
- package/dist/img/concorde/plane_06.jpg +0 -0
- package/dist/img/concorde/plane_07.jpg +0 -0
- package/dist/img/concorde/plane_08.jpg +0 -0
- package/dist/img/concorde/plane_09.jpg +0 -0
- package/dist/img/concorde/plane_10.jpg +0 -0
- package/dist/img/concorde/plane_11.jpg +0 -0
- package/dist/img/concorde/plane_12.jpg +0 -0
- package/dist/img/concorde/plane_13.jpg +0 -0
- package/dist/img/og-concorde.jpg +0 -0
- package/dist/robots.txt +11 -10
- package/docs/assets/index-D_alEsng.js +12122 -0
- package/docs/crawl/core/components/functional/date/date.html +190 -0
- package/docs/crawl/core/components/functional/fetch/fetch.html +109 -0
- package/docs/crawl/core/components/functional/if/if.html +27 -0
- package/docs/crawl/core/components/functional/jsonata/jsonata.html +79 -0
- package/docs/crawl/core/components/functional/list/list.html +70 -0
- package/docs/crawl/core/components/functional/mix/mix.html +45 -0
- package/docs/crawl/core/components/functional/queue/queue.html +96 -0
- package/docs/crawl/core/components/functional/router/router.html +106 -0
- package/docs/crawl/core/components/functional/sdui/sdui-extension-points.html +126 -0
- package/docs/crawl/core/components/functional/sdui/sdui.html +368 -0
- package/docs/crawl/core/components/functional/states/states.html +66 -0
- package/docs/crawl/core/components/functional/submit/submit.html +160 -0
- package/docs/crawl/core/components/functional/subscriber/subscriber.html +67 -0
- package/docs/crawl/core/components/functional/value/value.html +51 -0
- package/docs/crawl/core/components/ui/alert/alert.html +211 -0
- package/docs/crawl/core/components/ui/alert-messages/alert-messages.html +131 -0
- package/docs/crawl/core/components/ui/badge/badge.html +197 -0
- package/docs/crawl/core/components/ui/button/button.html +150 -0
- package/docs/crawl/core/components/ui/captcha/captcha.html +112 -0
- package/docs/crawl/core/components/ui/card/card.html +253 -0
- package/docs/crawl/core/components/ui/divider/divider.html +144 -0
- package/docs/crawl/core/components/ui/form/checkbox/checkbox.html +73 -0
- package/docs/crawl/core/components/ui/form/fieldset/fieldset.html +266 -0
- package/docs/crawl/core/components/ui/form/form-actions/form-actions.html +122 -0
- package/docs/crawl/core/components/ui/form/form-layout/form-layout.html +121 -0
- package/docs/crawl/core/components/ui/form/input/input.html +109 -0
- package/docs/crawl/core/components/ui/form/input-autocomplete/input-autocomplete.html +38 -0
- package/docs/crawl/core/components/ui/form/radio/radio.html +56 -0
- package/docs/crawl/core/components/ui/form/select/select.html +73 -0
- package/docs/crawl/core/components/ui/form/switch/switch.html +56 -0
- package/docs/crawl/core/components/ui/form/textarea/textarea.html +59 -0
- package/docs/crawl/core/components/ui/group/group.html +104 -0
- package/docs/crawl/core/components/ui/icon/icon.html +222 -0
- package/docs/crawl/core/components/ui/image/image.html +298 -0
- package/docs/crawl/core/components/ui/link/link.html +100 -0
- package/docs/crawl/core/components/ui/loader/loader.html +124 -0
- package/docs/crawl/core/components/ui/menu/menu.html +394 -0
- package/docs/crawl/core/components/ui/modal/modal.html +342 -0
- package/docs/crawl/core/components/ui/pop/pop.html +296 -0
- package/docs/crawl/core/components/ui/progress/progress.html +131 -0
- package/docs/crawl/core/components/ui/table/table.html +545 -0
- package/docs/crawl/core/components/ui/theme/theme.html +131 -0
- package/docs/crawl/core/components/ui/toast/toast.html +233 -0
- package/docs/crawl/core/components/ui/tooltip/tooltip.html +140 -0
- package/docs/crawl/docs/_core-concept/dataFlow.html +177 -0
- package/docs/crawl/docs/_core-concept/overview.html +66 -0
- package/docs/crawl/docs/_core-concept/subscriber.html +75 -0
- package/docs/crawl/docs/_decorators/ancestor-attribute.html +117 -0
- package/docs/crawl/docs/_decorators/auto-subscribe.html +202 -0
- package/docs/crawl/docs/_decorators/bind.html +141 -0
- package/docs/crawl/docs/_decorators/get.html +149 -0
- package/docs/crawl/docs/_decorators/handle.html +165 -0
- package/docs/crawl/docs/_decorators/on-assign.html +355 -0
- package/docs/crawl/docs/_decorators/patch.html +78 -0
- package/docs/crawl/docs/_decorators/post.html +139 -0
- package/docs/crawl/docs/_decorators/publish.html +61 -0
- package/docs/crawl/docs/_decorators/put.html +78 -0
- package/docs/crawl/docs/_decorators/subscribe.html +109 -0
- package/docs/crawl/docs/_decorators/wait-for-ancestors.html +137 -0
- package/docs/crawl/docs/_directives/sub.html +93 -0
- package/docs/crawl/docs/_getting-started/ai-agents.html +173 -0
- package/docs/crawl/docs/_getting-started/concorde-manual-install.html +100 -0
- package/docs/crawl/docs/_getting-started/concorde-outside.html +58 -0
- package/docs/crawl/docs/_getting-started/create-a-component.html +111 -0
- package/docs/crawl/docs/_getting-started/my-first-component.html +189 -0
- package/docs/crawl/docs/_getting-started/my-first-subscriber.html +110 -0
- package/docs/crawl/docs/_getting-started/pubsub.html +62 -0
- package/docs/crawl/docs/_getting-started/start.html +76 -0
- package/docs/crawl/docs/_getting-started/theming.html +333 -0
- package/docs/crawl/docs/_misc/api-configuration.html +149 -0
- package/docs/crawl/docs/_misc/dataProviderKey.html +135 -0
- package/docs/crawl/docs/_misc/docs-mock-api.html +158 -0
- package/docs/crawl/docs/_misc/dynamic-path.html +180 -0
- package/docs/crawl/docs/_misc/endpoint.html +50 -0
- package/docs/crawl/docs/_misc/formelement-subscriber-removal.html +138 -0
- package/docs/crawl/docs/_misc/html-integration.html +48 -0
- package/docs/crawl/hubs/decorators.html +547 -0
- package/docs/crawl/hubs/form-components.html +381 -0
- package/docs/crawl/hubs/remote-data.html +452 -0
- package/docs/crawl/index.html +103 -0
- package/docs/index.html +1 -1
- package/docs/llms-full.txt +7174 -0
- package/docs/llms.txt +98 -0
- package/docs/sitemap.xml +243 -0
- package/docs/src/core/components/functional/date/date.md +290 -0
- package/docs/src/core/components/functional/fetch/fetch.md +125 -0
- package/docs/src/core/components/functional/if/if.md +9 -0
- package/docs/src/core/components/functional/jsonata/jsonata.md +56 -0
- package/docs/src/core/components/functional/list/list.md +65 -0
- package/docs/src/core/components/functional/mix/mix.md +41 -0
- package/docs/src/core/components/functional/queue/queue.md +72 -0
- package/docs/src/core/components/functional/router/router.md +94 -0
- package/docs/src/core/components/functional/sdui/component-catalog.gaps.json +511 -0
- package/docs/src/core/components/functional/sdui/component-catalog.json +3103 -0
- package/docs/src/core/components/functional/sdui/default-library.json +108 -0
- package/docs/src/core/components/functional/sdui/example.json +99 -0
- package/docs/src/core/components/functional/sdui/sdui-extension-points.md +94 -0
- package/docs/src/core/components/functional/sdui/sdui.md +478 -0
- package/docs/src/core/components/functional/states/states.md +87 -0
- package/docs/src/core/components/functional/submit/submit.md +114 -0
- package/docs/src/core/components/functional/subscriber/subscriber.md +91 -0
- package/docs/src/core/components/functional/value/value.md +35 -0
- package/docs/src/core/components/ui/alert/alert.md +196 -0
- package/docs/src/core/components/ui/alert-messages/alert-messages.md +85 -0
- package/docs/src/core/components/ui/badge/badge.md +188 -0
- package/docs/src/core/components/ui/button/button.md +183 -0
- package/docs/src/core/components/ui/captcha/captcha.md +71 -0
- package/docs/src/core/components/ui/card/card.md +215 -0
- package/docs/src/core/components/ui/divider/divider.md +129 -0
- package/docs/src/core/components/ui/form/checkbox/checkbox.md +77 -0
- package/docs/src/core/components/ui/form/fieldset/fieldset.md +205 -0
- package/docs/src/core/components/ui/form/form-actions/form-actions.md +100 -0
- package/docs/src/core/components/ui/form/form-layout/form-layout.md +119 -0
- package/docs/src/core/components/ui/form/input/input.md +142 -0
- package/docs/src/core/components/ui/form/radio/radio.md +57 -0
- package/docs/src/core/components/ui/form/select/select.md +71 -0
- package/docs/src/core/components/ui/form/switch/switch.md +57 -0
- package/docs/src/core/components/ui/form/textarea/textarea.md +65 -0
- package/docs/src/core/components/ui/group/group.md +75 -0
- package/docs/src/core/components/ui/icon/icon.md +214 -0
- package/docs/src/core/components/ui/icon/icons.json +1 -0
- package/docs/src/core/components/ui/image/image.md +233 -0
- package/docs/src/core/components/ui/link/link.md +81 -0
- package/docs/src/core/components/ui/loader/loader.md +112 -0
- package/docs/src/core/components/ui/menu/menu.md +370 -0
- package/docs/src/core/components/ui/modal/modal.md +235 -0
- package/docs/src/core/components/ui/pop/pop.md +294 -0
- package/docs/src/core/components/ui/progress/progress.md +109 -0
- package/docs/src/core/components/ui/table/table.md +431 -0
- package/docs/src/core/components/ui/theme/theme.md +122 -0
- package/docs/src/core/components/ui/toast/toast.md +216 -0
- package/docs/src/core/components/ui/tooltip/tooltip.md +124 -0
- package/{src → docs/src}/docs/_core-concept/subscriber.md +0 -0
- package/{src → docs/src}/docs/_getting-started/my-first-subscriber.md +0 -0
- package/{src → docs/src}/docs/_getting-started/pubsub.md +0 -0
- package/docs/src/docs/_getting-started/theming.md +253 -0
- package/docs/src/docs/search/docs-search.json +12242 -0
- package/docs/src/tag-list.json +1 -0
- package/docs/src/tsconfig-model.json +23 -0
- package/docs/src/tsconfig.declarations.json +22 -0
- package/docs/src/tsconfig.emit.json +23 -0
- package/docs/src/tsconfig.json +1332 -0
- package/gitlab/job_github_mirror.sh +39 -0
- package/index.html +157 -5
- package/package.json +22 -4
- package/public/docs-mock-api-sw.js +58 -223
- package/public/docs-mock-api-sw.js.map +4 -4
- package/public/img/concorde/plane_01.jpg +0 -0
- package/public/img/concorde/plane_02.jpg +0 -0
- package/public/img/concorde/plane_03.jpg +0 -0
- package/public/img/concorde/plane_04.jpg +0 -0
- package/public/img/concorde/plane_05.jpg +0 -0
- package/public/img/concorde/plane_06.jpg +0 -0
- package/public/img/concorde/plane_07.jpg +0 -0
- package/public/img/concorde/plane_08.jpg +0 -0
- package/public/img/concorde/plane_09.jpg +0 -0
- package/public/img/concorde/plane_10.jpg +0 -0
- package/public/img/concorde/plane_11.jpg +0 -0
- package/public/img/concorde/plane_12.jpg +0 -0
- package/public/img/concorde/plane_13.jpg +0 -0
- package/public/img/og-concorde.jpg +0 -0
- package/public/robots.txt +11 -10
- package/scripts/ai-init.mjs +104 -379
- package/scripts/ai-init.test.mjs +81 -239
- package/scripts/docs-markdown-vite-plugin.ts +43 -0
- package/scripts/docs-public-url.mjs +56 -0
- package/scripts/docs.htaccess +82 -0
- package/scripts/generate-cem.mjs +244 -0
- package/scripts/generate-cem.test.mjs +122 -0
- package/scripts/generate-crawl-docs.mjs +233 -118
- package/scripts/generate-crawl-docs.test.mjs +124 -0
- package/scripts/generate-sdui-catalog.mjs +11 -10
- package/scripts/github-export.mjs +150 -0
- package/scripts/post-build-docs.js +37 -50
- package/scripts/post-build.mjs +0 -0
- package/scripts/pre-publish.mjs +2 -1
- package/scripts/site-pages.mjs +212 -0
- package/scripts/site-pages.test.mjs +116 -0
- package/site-pages/about.md +22 -0
- package/site-pages/privacy.md +32 -0
- package/src/core/components/functional/date/date.md +91 -231
- package/src/core/components/functional/example/example.ts +3 -1
- package/src/core/components/functional/fetch/fetch.md +66 -83
- package/src/core/components/functional/if/if.md +28 -3
- package/src/core/components/functional/if/if.ts +0 -0
- package/src/core/components/functional/jsonata/jsonata.md +42 -37
- package/src/core/components/functional/list/list.demo.ts +0 -0
- package/src/core/components/functional/list/list.md +103 -43
- package/src/core/components/functional/list/list.ts +17 -4
- package/src/core/components/functional/mix/mix.md +31 -26
- package/src/core/components/functional/queue/queue.demo.ts +10 -7
- package/src/core/components/functional/queue/queue.md +40 -61
- package/src/core/components/functional/router/router.demo.ts +16 -16
- package/src/core/components/functional/router/router.md +64 -65
- package/src/core/components/functional/router/router.ts +0 -0
- package/src/core/components/functional/sdui/SDUIDescriptorTransformer.ts +0 -0
- package/src/core/components/functional/sdui/component-catalog.gaps.json +1 -1
- package/src/core/components/functional/sdui/component-catalog.json +2 -2
- package/src/core/components/functional/sdui/example.json +19 -86
- package/src/core/components/functional/sdui/sdui-extension-points.md +1 -1
- package/src/core/components/functional/sdui/sdui-immutable.spec.ts +74 -0
- package/src/core/components/functional/sdui/sdui.md +187 -358
- package/src/core/components/functional/sdui/sdui.ts +33 -8
- package/src/core/components/functional/sdui/types.ts +0 -0
- package/src/core/components/functional/states/states.demo.ts +21 -22
- package/src/core/components/functional/states/states.md +86 -61
- package/src/core/components/functional/states/states.ts +1 -1
- package/src/core/components/functional/submit/submit.md +64 -72
- package/src/core/components/functional/submit/submit.spec.ts +60 -0
- package/src/core/components/functional/submit/submit.ts +6 -3
- package/src/core/components/functional/subscriber/subscriber.ts +0 -0
- package/src/core/components/functional/translation/translation.md +38 -0
- package/src/core/components/functional/value/value.md +34 -22
- package/src/core/components/functional/value/value.ts +0 -0
- package/src/core/components/ui/_css/size.ts +0 -0
- package/src/core/components/ui/alert/alert.md +48 -58
- package/src/core/components/ui/badge/badge.md +27 -34
- package/src/core/components/ui/button/button.md +139 -106
- package/src/core/components/ui/captcha/altchaStyles.ts +0 -0
- package/src/core/components/ui/captcha/captcha.md +17 -32
- package/src/core/components/ui/card/card.md +6 -6
- package/src/core/components/ui/divider/divider.md +8 -11
- package/src/core/components/ui/form/checkbox/checkbox.md +90 -42
- package/src/core/components/ui/form/fieldset/fieldset.md +31 -75
- package/src/core/components/ui/form/form-actions/form-actions.md +14 -16
- package/src/core/components/ui/form/form-layout/form-layout.md +19 -29
- package/src/core/components/ui/form/input/input.md +108 -90
- package/src/core/components/ui/form/input/input.ts +8 -2
- package/src/core/components/ui/form/radio/radio.md +65 -30
- package/src/core/components/ui/form/select/select.md +60 -45
- package/src/core/components/ui/form/switch/switch.md +57 -34
- package/src/core/components/ui/form/textarea/textarea.md +55 -38
- package/src/core/components/ui/group/group.md +35 -33
- package/src/core/components/ui/icon/icon.md +4 -4
- package/src/core/components/ui/image/image.md +41 -107
- package/src/core/components/ui/link/link.md +6 -6
- package/src/core/components/ui/loader/loader.md +30 -55
- package/src/core/components/ui/menu/menu.md +27 -27
- package/src/core/components/ui/modal/modal.md +72 -96
- package/src/core/components/ui/pop/pop.md +80 -158
- package/src/core/components/ui/progress/progress.md +2 -2
- package/src/core/components/ui/table/table.md +91 -255
- package/src/core/components/ui/theme/theme.md +11 -36
- package/src/core/components/ui/toast/toast.md +48 -117
- package/src/core/components/ui/tooltip/tooltip.md +27 -62
- package/src/core/decorators/subscriber/bind.ts +9 -14
- package/src/core/decorators/subscriber/subscribe.ts +15 -9
- package/src/core/decorators/subscriber/subscribe.type-test.ts +14 -5
- package/src/core/mixins/Subscriber.ts +0 -0
- package/src/core/utils/DataBindObserver.ts +0 -0
- package/src/core/utils/LocationHandler.spec.ts +80 -0
- package/src/core/utils/LocationHandler.ts +5 -9
- package/src/core/utils/Objects.ts +0 -0
- package/src/core/utils/PublisherProxy.ts +166 -125
- package/src/core/utils/deepReadonly.spec.ts +66 -0
- package/src/core/utils/deepReadonly.ts +71 -0
- package/src/core/utils/immutableValue.spec.ts +54 -0
- package/src/core/utils/immutableValue.ts +102 -0
- package/src/core/utils/nestedDotForm.spec.ts +88 -0
- package/src/core/utils/publisherImmutable.spec.ts +76 -0
- package/src/core/utils/route.ts +0 -0
- package/src/core/utils/strictGet.spec.ts +61 -0
- package/src/core/utils/strictGet.ts +102 -0
- package/src/css.d.ts +19 -0
- package/src/docs/components/docs-demo-sources.ts +55 -140
- package/src/docs/components/docs-lit-demo.ts +1 -3
- package/src/docs/components/docs-source-link.ts +0 -82
- package/src/docs/decorators/ancestor-attribute.md +59 -0
- package/src/docs/decorators/auto-subscribe.md +40 -0
- package/src/docs/decorators/bind.md +76 -0
- package/src/docs/decorators/get.md +160 -0
- package/src/docs/decorators/handle.md +119 -0
- package/src/docs/decorators/on-assign.md +63 -0
- package/src/docs/decorators/patch.md +44 -0
- package/src/docs/decorators/post.md +134 -0
- package/src/docs/decorators/publish.md +56 -0
- package/src/docs/decorators/put.md +51 -0
- package/src/docs/decorators/subscribe.md +87 -0
- package/src/docs/decorators/wait-for-ancestors.md +76 -0
- package/src/docs/directives/sub.md +75 -0
- package/src/docs/directives/t.md +73 -0
- package/src/docs/docs-location.spec.ts +56 -0
- package/src/docs/docs-location.ts +133 -32
- package/src/docs/docs.ts +1 -2
- package/src/docs/example/decorators-demo-bind-demos.ts +83 -135
- package/src/docs/example/decorators-demo-geo.ts +30 -19
- package/src/docs/example/decorators-demo-post.ts +88 -186
- package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +165 -268
- package/src/docs/example/decorators-demo.ts +85 -98
- package/src/docs/example/docs-api-config-demos.ts +19 -20
- package/src/docs/example/docs-flight-demos.ts +147 -0
- package/src/docs/example/docs-jsonata-demos.ts +52 -52
- package/src/docs/example/docs-list-demos.ts +43 -123
- package/src/docs/example/docs-provider-keys.ts +21 -28
- package/src/docs/example/docs-queue-demos.ts +37 -77
- package/src/docs/example/docs-router-demos.ts +20 -25
- package/src/docs/example/docs-submit-demos.ts +48 -48
- package/src/docs/example/docs-toggle-demos.ts +4 -3
- package/src/docs/example/users.ts +0 -0
- package/src/docs/getting-started/ai-agents.md +50 -0
- package/src/docs/getting-started/create-a-component.md +136 -0
- package/src/docs/getting-started/dataFlow.md +87 -0
- package/src/docs/getting-started/installation.md +36 -0
- package/src/docs/getting-started/my-first-component.md +227 -0
- package/src/docs/getting-started/start.md +35 -0
- package/src/docs/header/header.ts +11 -6
- package/src/docs/home/catalog.ts +1 -1
- package/src/docs/home/home.ts +20 -11
- package/src/docs/layout.ts +12 -13
- package/src/docs/misc/api-configuration.md +79 -0
- package/src/docs/misc/dataProviderKey.md +168 -0
- package/src/docs/misc/docs-mock-api.md +62 -0
- package/src/docs/misc/dynamic-path.md +71 -0
- package/src/docs/misc/endpoint.md +45 -0
- package/src/docs/misc/html-integration.md +14 -0
- package/src/docs/misc/publisher-get-immutability-docs-crawl.json +902 -0
- package/src/docs/misc/publisher-get-immutability-docs-recheck.json +13 -0
- package/src/docs/misc/publisher-get-immutability-study.md +229 -0
- package/src/docs/mock-api/api-config-mock.ts +5 -0
- package/src/docs/mock-api/fixtures.ts +0 -278
- package/src/docs/mock-api/flights.ts +89 -0
- package/src/docs/mock-api/router.ts +3 -4
- package/src/docs/mock-api/urls.ts +1 -2
- package/src/docs/navigation/navigation.ts +84 -101
- package/src/docs/navigation/toc.ts +7 -4
- package/src/docs/search/docs-search.json +3188 -5153
- package/src/docs/search/markdown-renderer.ts +31 -8
- package/src/docs/search/page.ts +9 -6
- package/src/docs/search/search.ts +154 -122
- package/src/docs/tailwind/css/docs/content.css +4 -5
- package/src/tsconfig.declarations.json +22 -0
- package/src/tsconfig.emit.json +23 -0
- package/src/tsconfig.json +53 -5
- package/src/tsconfig.tsbuildinfo +1 -1
- package/vite.config.mts +11 -2
- package/.agents/skills/concorde-component-docs/SKILL.md +0 -194
- package/.taste-skill/after/desktop-fold.jpg +0 -0
- package/.taste-skill/after/desktop-page-01.jpg +0 -0
- package/.taste-skill/after/desktop-page-02.jpg +0 -0
- package/.taste-skill/after/desktop-page-03.jpg +0 -0
- package/.taste-skill/after/mobile-fold.jpg +0 -0
- package/.taste-skill/after/mobile-page-01.jpg +0 -0
- package/.taste-skill/after/report.json +0 -4103
- package/.taste-skill/after/tablet-fold.jpg +0 -0
- package/.taste-skill/after/tablet-page-01.jpg +0 -0
- package/.taste-skill/after/tablet-page-02.jpg +0 -0
- package/.taste-skill/before/desktop-fold.jpg +0 -0
- package/.taste-skill/before/desktop-page-01.jpg +0 -0
- package/.taste-skill/before/desktop-page-02.jpg +0 -0
- package/.taste-skill/before/mobile-fold.jpg +0 -0
- package/.taste-skill/before/mobile-page-01.jpg +0 -0
- package/.taste-skill/before/report.json +0 -2556
- package/.taste-skill/before/tablet-fold.jpg +0 -0
- package/.taste-skill/before/tablet-page-01.jpg +0 -0
- package/.taste-skill/direction.json +0 -510
- package/.taste-skill/notes.md +0 -84
- package/.taste-skill/prod/desktop-fold.jpg +0 -0
- package/.taste-skill/prod/desktop-page-01.jpg +0 -0
- package/.taste-skill/prod/desktop-page-02.jpg +0 -0
- package/.taste-skill/prod/desktop-page-03.jpg +0 -0
- package/.taste-skill/prod/mobile-fold.jpg +0 -0
- package/.taste-skill/prod/mobile-page-01.jpg +0 -0
- package/.taste-skill/prod/mobile-page-02.jpg +0 -0
- package/.taste-skill/prod/report.json +0 -1973
- package/.taste-skill/prod/tablet-fold.jpg +0 -0
- package/.taste-skill/prod/tablet-page-01.jpg +0 -0
- package/.taste-skill/prod/tablet-page-02.jpg +0 -0
- package/AUDIT.md +0 -228
- package/PLAN-AMELIORATION.md +0 -220
- package/ai/AGENTS.md +0 -56
- package/ai/cursor/rules/concorde-menu.mdc +0 -15
- package/ai/cursor/rules/concorde-scope.mdc +0 -14
- package/ai/cursor/rules/concorde-theme.mdc +0 -13
- package/ai/cursor/rules/concorde.mdc +0 -66
- package/ai/jetbrains/rules/concorde.md +0 -53
- package/ai/skills/concorde-get-set-dp/SKILL.md +0 -194
- package/ai/skills/concorde-imports/SKILL.md +0 -78
- package/ai/skills/concorde-menu/SKILL.md +0 -74
- package/ai/skills/concorde-scope/SKILL.md +0 -70
- package/ai/skills/concorde-theme/SKILL.md +0 -57
- package/docs/assets/index-Bb-_LRyY.js +0 -12280
- package/src/docs/example/docs-input-autocomplete-demos.ts +0 -110
- package/src/docs/example/docs-joke-demos.ts +0 -297
- /package/{src → docs/src}/core/components/ui/form/input-autocomplete/input-autocomplete.md +0 -0
- /package/{src → docs/src}/docs/_core-concept/dataFlow.md +0 -0
- /package/{src → docs/src}/docs/_core-concept/overview.md +0 -0
- /package/{src → docs/src}/docs/_decorators/ancestor-attribute.md +0 -0
- /package/{src → docs/src}/docs/_decorators/auto-subscribe.md +0 -0
- /package/{src → docs/src}/docs/_decorators/bind.md +0 -0
- /package/{src → docs/src}/docs/_decorators/get.md +0 -0
- /package/{src → docs/src}/docs/_decorators/handle.md +0 -0
- /package/{src → docs/src}/docs/_decorators/on-assign.md +0 -0
- /package/{src → docs/src}/docs/_decorators/patch.md +0 -0
- /package/{src → docs/src}/docs/_decorators/post.md +0 -0
- /package/{src → docs/src}/docs/_decorators/publish.md +0 -0
- /package/{src → docs/src}/docs/_decorators/put.md +0 -0
- /package/{src → docs/src}/docs/_decorators/subscribe.md +0 -0
- /package/{src → docs/src}/docs/_decorators/wait-for-ancestors.md +0 -0
- /package/{src → docs/src}/docs/_directives/sub.md +0 -0
- /package/{src → docs/src}/docs/_getting-started/ai-agents.md +0 -0
- /package/{src → docs/src}/docs/_getting-started/concorde-manual-install.md +0 -0
- /package/{src → docs/src}/docs/_getting-started/concorde-outside.md +0 -0
- /package/{src → docs/src}/docs/_getting-started/create-a-component.md +0 -0
- /package/{src → docs/src}/docs/_getting-started/my-first-component.md +0 -0
- /package/{src → docs/src}/docs/_getting-started/start.md +0 -0
- /package/{src → docs/src}/docs/_misc/api-configuration.md +0 -0
- /package/{src → docs/src}/docs/_misc/dataProviderKey.md +0 -0
- /package/{src → docs/src}/docs/_misc/docs-mock-api.md +0 -0
- /package/{src → docs/src}/docs/_misc/dynamic-path.md +0 -0
- /package/{src → docs/src}/docs/_misc/endpoint.md +0 -0
- /package/{src → docs/src}/docs/_misc/formelement-subscriber-removal.md +0 -0
- /package/{src → docs/src}/docs/_misc/html-integration.md +0 -0
- /package/src/docs/{_getting-started → getting-started}/components.md +0 -0
- /package/src/docs/{_getting-started → getting-started}/theming.md +0 -0
|
@@ -115,15 +115,11 @@ export default class LocationHandler {
|
|
|
115
115
|
return;
|
|
116
116
|
}
|
|
117
117
|
const url = new URL(to, document.location.href);
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
prevSp = sp;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
to = "/" + newPathName.join("/") + url.search + (url.hash ? url.hash : "");
|
|
118
|
+
// Drop empty segments from pathname.split ("/a//b" → /a/b) so we never
|
|
119
|
+
// emit a protocol-relative `//path`. Public docs URLs are already pretty
|
|
120
|
+
// (no …/router/router); equal siblings are left untouched if present.
|
|
121
|
+
const parts = url.pathname.split("/").filter(Boolean);
|
|
122
|
+
to = `/${parts.join("/")}${url.search}${url.hash || ""}`;
|
|
127
123
|
if (component.hasAttribute("pushState")) {
|
|
128
124
|
history.pushState(null, "", to);
|
|
129
125
|
} else if (component.hasAttribute("replaceState")) {
|
|
File without changes
|
|
@@ -11,10 +11,39 @@ import type {
|
|
|
11
11
|
} from "../_types/types";
|
|
12
12
|
import type { DataProviderKey } from "./dataProviderKey";
|
|
13
13
|
import { resolveStaticPublisherPath } from "./dataProviderKey";
|
|
14
|
+
import type { Frozen } from "./deepReadonly";
|
|
14
15
|
import HTML from "./HTML";
|
|
16
|
+
import {
|
|
17
|
+
deepFreeze,
|
|
18
|
+
deleteAtKey,
|
|
19
|
+
setAtKey,
|
|
20
|
+
stripUndefinedKeys,
|
|
21
|
+
takeOwnership,
|
|
22
|
+
} from "./immutableValue";
|
|
15
23
|
import Objects from "./Objects";
|
|
24
|
+
import {
|
|
25
|
+
getStrictGetMode,
|
|
26
|
+
setStrictGetMode,
|
|
27
|
+
wrapStrictGet,
|
|
28
|
+
type StrictGetMode,
|
|
29
|
+
} from "./strictGet";
|
|
16
30
|
import { sonicClassPrefix } from "./Utils";
|
|
17
31
|
|
|
32
|
+
export type {
|
|
33
|
+
DeepReadonly,
|
|
34
|
+
Frozen,
|
|
35
|
+
FrozenArray,
|
|
36
|
+
FrozenObject,
|
|
37
|
+
} from "./deepReadonly";
|
|
38
|
+
/** @deprecated Prefer {@link Frozen}. */
|
|
39
|
+
export type ReadonlyDeep<T> = Frozen<T>;
|
|
40
|
+
export type { StrictGetMode } from "./strictGet";
|
|
41
|
+
export {
|
|
42
|
+
clearStrictGetWarnings,
|
|
43
|
+
getStrictGetMode,
|
|
44
|
+
setStrictGetMode,
|
|
45
|
+
} from "./strictGet";
|
|
46
|
+
|
|
18
47
|
export type Observable = string;
|
|
19
48
|
|
|
20
49
|
type DynamicFillingListener = any;
|
|
@@ -85,7 +114,7 @@ export class PublisherProxy<T = any> {
|
|
|
85
114
|
_invalidate_on_page_show_ = false;
|
|
86
115
|
_invalidateListeners_ = new Set<VoidFunction>();
|
|
87
116
|
_formInvalidateListeners_ = new Set<VoidFunction>();
|
|
88
|
-
_assignListeners_ = new Set<(value: T) => void>();
|
|
117
|
+
_assignListeners_ = new Set<(value: Frozen<T>) => void>();
|
|
89
118
|
_mutationListeners_ = new Set<VoidFunction>();
|
|
90
119
|
_fillListeners_ = new Set<Record<string, CoreJSType>>();
|
|
91
120
|
_templateFillListeners_ = new Set<TemplateFillingListener>();
|
|
@@ -100,7 +129,8 @@ export class PublisherProxy<T = any> {
|
|
|
100
129
|
parentProxPub: PublisherProxy | null,
|
|
101
130
|
parentKey?: string,
|
|
102
131
|
) {
|
|
103
|
-
|
|
132
|
+
// Child publishers often receive an already-owned (frozen) subtree from the parent.
|
|
133
|
+
this._value_ = takeOwnership(target) as T;
|
|
104
134
|
this.parent = parentProxPub || null;
|
|
105
135
|
this._parentKey_ = parentKey;
|
|
106
136
|
this.root = this;
|
|
@@ -165,7 +195,7 @@ export class PublisherProxy<T = any> {
|
|
|
165
195
|
if (currentId !== this._assignmentId_) return;
|
|
166
196
|
const newValue = this.get();
|
|
167
197
|
|
|
168
|
-
this._assignListeners_.forEach((handler
|
|
198
|
+
this._assignListeners_.forEach((handler) => {
|
|
169
199
|
handler(newValue);
|
|
170
200
|
});
|
|
171
201
|
this._publishInternalMutation_(lockInternalMutationsTransmission);
|
|
@@ -206,7 +236,10 @@ export class PublisherProxy<T = any> {
|
|
|
206
236
|
* Appel la fonction "handler" (passée en paramettre) lorsque la valeur gérée par le proxy change par assignation
|
|
207
237
|
* hanlder reçois alors la nouvelle valeur interne du proxy en paramètre
|
|
208
238
|
*/
|
|
209
|
-
onAssign(
|
|
239
|
+
onAssign(
|
|
240
|
+
handler: (value: Frozen<T>) => void,
|
|
241
|
+
directHandlerCall = true,
|
|
242
|
+
) {
|
|
210
243
|
if (typeof handler != "function") return;
|
|
211
244
|
if (this._assignListeners_.has(handler)) return;
|
|
212
245
|
this._assignListeners_.add(handler);
|
|
@@ -215,7 +248,7 @@ export class PublisherProxy<T = any> {
|
|
|
215
248
|
/**
|
|
216
249
|
* Stop les appels de la fonction "handler" (passée en paramettre) lorsque la valeur gérée par le proxy change par assignation
|
|
217
250
|
*/
|
|
218
|
-
offAssign(handler: (value: T) => void) {
|
|
251
|
+
offAssign(handler: (value: Frozen<T>) => void) {
|
|
219
252
|
this._assignListeners_.delete(handler);
|
|
220
253
|
}
|
|
221
254
|
|
|
@@ -320,84 +353,54 @@ export class PublisherProxy<T = any> {
|
|
|
320
353
|
this._fillListeners_.delete(handler);
|
|
321
354
|
}
|
|
322
355
|
/**
|
|
323
|
-
* Assigne une nouvelle valeur
|
|
356
|
+
* Assigne une nouvelle valeur : ownership (clone) + freeze, puis publication.
|
|
357
|
+
* @param alreadyOwned si true, `newValue` est déjà une valeur du store (frozen) — pas de re-clone.
|
|
324
358
|
*/
|
|
359
|
+
set(
|
|
360
|
+
newValue: T | Frozen<T>,
|
|
361
|
+
lockInternalMutationsTransmission = false,
|
|
362
|
+
alreadyOwned = false,
|
|
363
|
+
) {
|
|
364
|
+
const normalized = (
|
|
365
|
+
isComplex(newValue) ? newValue : { __value: newValue }
|
|
366
|
+
) as T;
|
|
367
|
+
const prepared = stripUndefinedKeys(normalized);
|
|
368
|
+
// alreadyOwned: freeze without re-clone (subtree from parent or fresh __value wrapper).
|
|
369
|
+
const owned = (
|
|
370
|
+
alreadyOwned ? deepFreeze(prepared) : takeOwnership(prepared)
|
|
371
|
+
) as T;
|
|
325
372
|
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* On retounre tout de suite si la valeur n'a pas changé
|
|
329
|
-
*/
|
|
330
|
-
|
|
331
|
-
if (this._value_ === newValue) return true;
|
|
373
|
+
if (this._value_ === owned) return true;
|
|
332
374
|
|
|
333
|
-
/**
|
|
334
|
-
* On retounre tout de suite si la valeur n'a pas changé
|
|
335
|
-
* et qu'elle est primitive
|
|
336
|
-
*/
|
|
337
375
|
if (
|
|
338
376
|
(isComplex(this._value_) &&
|
|
339
|
-
isComplex(
|
|
340
|
-
|
|
377
|
+
isComplex(owned) &&
|
|
378
|
+
owned &&
|
|
341
379
|
isLeaf(this._value_) &&
|
|
342
|
-
isLeaf(
|
|
343
|
-
(this._value_ as any).__value === (
|
|
380
|
+
isLeaf(owned) &&
|
|
381
|
+
(this._value_ as any).__value === (owned as any).__value) ||
|
|
344
382
|
(!isComplex(newValue) && newValue === (this._value_ as any).__value)
|
|
345
383
|
) {
|
|
346
384
|
return true;
|
|
347
385
|
}
|
|
348
386
|
|
|
349
|
-
|
|
350
|
-
* On assigne la nouvelle valeur
|
|
351
|
-
*/
|
|
352
|
-
|
|
353
|
-
/** Si la valeur est complexe on assigne newValue directe sinon on le met dans une sous valeur __value */
|
|
354
|
-
this._value_ = isComplex(newValue)
|
|
355
|
-
? newValue
|
|
356
|
-
: ({ __value: newValue } as any);
|
|
387
|
+
this._value_ = owned;
|
|
357
388
|
this._cachedGet_ = undefined;
|
|
358
389
|
|
|
359
|
-
/**
|
|
360
|
-
* Si il s'agit d'une valeur primitive (un entier, une chaine ) la valeure en renseignée par un objet contenant la vaeur {__value}
|
|
361
|
-
* On publie juste et on sen va.
|
|
362
|
-
*/
|
|
363
390
|
const isLeafNewValue = isLeaf(this._value_);
|
|
364
391
|
|
|
365
|
-
if (this._parentKey_ && this.parent) {
|
|
366
|
-
|
|
367
|
-
const valueTosetInParent = isLeaf(this._value_)
|
|
368
|
-
? (this._value_ as any).__value
|
|
369
|
-
: this._value_;
|
|
370
|
-
if (this.parent?.get() == null && this.parent?.get() == undefined) {
|
|
371
|
-
//if _parentKey_ is a number, we assume it's an array
|
|
372
|
-
if (!isNaN(Number(this._parentKey_))) {
|
|
373
|
-
const parent = [];
|
|
374
|
-
parent[Number(this._parentKey_)] = valueTosetInParent;
|
|
375
|
-
this.parent.set(parent);
|
|
376
|
-
} else {
|
|
377
|
-
this.parent.set({ [this._parentKey_]: valueTosetInParent });
|
|
378
|
-
}
|
|
379
|
-
// return;
|
|
380
|
-
} else {
|
|
381
|
-
//on mets à jour la valeur de la clef dans l'objet parnet pour refléter le changement au ca sou elle n'existait pas
|
|
382
|
-
this.parent._value_[this._parentKey_] = valueTosetInParent;
|
|
383
|
-
}
|
|
392
|
+
if (this._parentKey_ && this.parent && !lockInternalMutationsTransmission) {
|
|
393
|
+
this._syncOwnedValueIntoParent_(lockInternalMutationsTransmission);
|
|
384
394
|
}
|
|
385
395
|
|
|
386
396
|
if (isLeafNewValue) {
|
|
387
|
-
// Si la valeur précédente était composite, on reset tous les sous-éléments à null
|
|
388
397
|
this._proxies_.forEach((_subProxy, key) => {
|
|
389
|
-
/**
|
|
390
|
-
*
|
|
391
|
-
* On reùmplace les undefined par des nuls pour eviter la suppression des clefs sauf pour les clef tableaux
|
|
392
|
-
**/
|
|
393
|
-
|
|
394
398
|
if (key != "_parent_") {
|
|
395
|
-
_subProxy.set(null);
|
|
399
|
+
_subProxy.set(null, true, true);
|
|
396
400
|
this._publishDynamicFilling_(key, null);
|
|
397
401
|
}
|
|
398
402
|
});
|
|
399
403
|
|
|
400
|
-
//await //await here gives better performance but can cause issues with some listeners
|
|
401
404
|
this._publishAssignement_(lockInternalMutationsTransmission);
|
|
402
405
|
if (this.parent && this._parentKey_) {
|
|
403
406
|
this.parent._publishDynamicFilling_(
|
|
@@ -408,23 +411,8 @@ export class PublisherProxy<T = any> {
|
|
|
408
411
|
|
|
409
412
|
return true;
|
|
410
413
|
}
|
|
411
|
-
/**
|
|
412
|
-
* On fait la diff sur l'existant.
|
|
413
|
-
* On maintient les proxys à supprimer et ceux à ajouter.
|
|
414
|
-
* On met à jour leur valeur interne
|
|
415
|
-
* On publie les maj au fur et a mesure de modifications
|
|
416
|
-
*/
|
|
417
|
-
|
|
418
|
-
for (const key in this._value_) {
|
|
419
|
-
const currentValue = this._value_[key] as any;
|
|
420
|
-
if (currentValue === undefined) delete this._value_[key];
|
|
421
|
-
}
|
|
422
414
|
|
|
423
415
|
this._proxies_.forEach((_subProxy, key) => {
|
|
424
|
-
/**
|
|
425
|
-
*
|
|
426
|
-
* On reùmplace les undefined par des nuls pour eviter la suppression des clefs sauf pour les clef tableaux
|
|
427
|
-
**/
|
|
428
416
|
const currentValue: any = (this._value_ as any)[key];
|
|
429
417
|
|
|
430
418
|
if (key != "_parent_") {
|
|
@@ -433,63 +421,99 @@ export class PublisherProxy<T = any> {
|
|
|
433
421
|
currentValue !== null &&
|
|
434
422
|
isNaN(Number(key))
|
|
435
423
|
) {
|
|
436
|
-
_subProxy.set(null);
|
|
424
|
+
_subProxy.set(null, true, true);
|
|
437
425
|
this._publishDynamicFilling_(key, null);
|
|
438
426
|
}
|
|
439
427
|
}
|
|
440
428
|
});
|
|
441
429
|
|
|
442
|
-
|
|
443
|
-
* On prévient les écouteurs que la valeur a changé
|
|
444
|
-
*/
|
|
445
|
-
//await //await here gives better performance but can cause issues with some listeners
|
|
446
|
-
this._publishAssignement_();
|
|
430
|
+
this._publishAssignement_(lockInternalMutationsTransmission);
|
|
447
431
|
if (this.parent && this._parentKey_)
|
|
448
432
|
this.parent._publishDynamicFilling_(
|
|
449
433
|
this._parentKey_,
|
|
450
434
|
this._value_ as any,
|
|
451
435
|
);
|
|
452
|
-
/**
|
|
453
|
-
* Si la donnée est complexe (objet, tableau)
|
|
454
|
-
* on crée les proxys pour les sous-éléments qui n'en on pas
|
|
455
|
-
* On renseigne les nouvelles valeurs internes des proxies
|
|
456
|
-
*/
|
|
457
436
|
|
|
458
437
|
if (isComplex(this._value_)) {
|
|
459
438
|
for (const key in this._value_) {
|
|
460
|
-
const v =
|
|
439
|
+
const v = (this._value_ as any)[key];
|
|
461
440
|
const isVComplex = isComplex(v);
|
|
462
441
|
const valueV = isVComplex ? v : { __value: v };
|
|
463
442
|
if (!this._proxies_.has(key)) {
|
|
464
|
-
// A surveiller ancienne version
|
|
465
|
-
// const newPublisher = new DataProvider({}, this);
|
|
466
|
-
// this._proxies_.set(key, newPublisher);
|
|
467
|
-
// newPublisher._proxies_.set("_parent_", this);
|
|
468
|
-
|
|
469
443
|
this._publishDynamicFilling_(key, v);
|
|
470
444
|
continue;
|
|
471
445
|
}
|
|
472
|
-
//
|
|
473
|
-
this._proxies_.get(key)?.set(valueV, true);
|
|
446
|
+
// Child already holds an owned subtree — do not sync back to parent.
|
|
447
|
+
this._proxies_.get(key)?.set(valueV as any, true, true);
|
|
474
448
|
this._publishDynamicFilling_(key, v);
|
|
475
449
|
}
|
|
476
450
|
}
|
|
477
451
|
return true;
|
|
478
452
|
}
|
|
453
|
+
|
|
454
|
+
/** Rebuild parent immutably so this node's owned value is reflected at `_parentKey_`. */
|
|
455
|
+
_syncOwnedValueIntoParent_(lockInternalMutationsTransmission = false) {
|
|
456
|
+
if (!this.parent || this._parentKey_ == null) return;
|
|
457
|
+
const valueTosetInParent = isLeaf(this._value_)
|
|
458
|
+
? (this._value_ as any).__value
|
|
459
|
+
: this._value_;
|
|
460
|
+
const parentRaw = this.parent._value_;
|
|
461
|
+
const parentEmpty =
|
|
462
|
+
parentRaw == null ||
|
|
463
|
+
parentRaw === undefined ||
|
|
464
|
+
(isLeaf(parentRaw) && (parentRaw as any).__value == null);
|
|
465
|
+
|
|
466
|
+
if (parentEmpty) {
|
|
467
|
+
if (!isNaN(Number(this._parentKey_))) {
|
|
468
|
+
const parent: any[] = [];
|
|
469
|
+
parent[Number(this._parentKey_)] = valueTosetInParent;
|
|
470
|
+
this.parent.set(parent as any, lockInternalMutationsTransmission);
|
|
471
|
+
} else {
|
|
472
|
+
this.parent.set(
|
|
473
|
+
{ [this._parentKey_]: valueTosetInParent } as any,
|
|
474
|
+
lockInternalMutationsTransmission,
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Already reflected on parent (same ref) — skip rebuild/publish (avoids list render loops).
|
|
481
|
+
const currentAtKey = (parentRaw as any)[this._parentKey_];
|
|
482
|
+
if (currentAtKey === valueTosetInParent) return;
|
|
483
|
+
|
|
484
|
+
const nextParent = setAtKey(
|
|
485
|
+
parentRaw as object,
|
|
486
|
+
this._parentKey_,
|
|
487
|
+
valueTosetInParent,
|
|
488
|
+
);
|
|
489
|
+
this.parent.set(
|
|
490
|
+
nextParent as any,
|
|
491
|
+
lockInternalMutationsTransmission,
|
|
492
|
+
true,
|
|
493
|
+
);
|
|
494
|
+
}
|
|
479
495
|
/**
|
|
480
496
|
* Extraire la valeur actuelle du proxy
|
|
481
497
|
*/
|
|
482
498
|
_cachedGet_?: T;
|
|
483
|
-
|
|
499
|
+
/**
|
|
500
|
+
* Lecture typée {@link Frozen}. Runtime = valeur **owned / frozen** du store
|
|
501
|
+
* (même ref entre deux `set`). `strictGet` reste un radar optionnel sur le wrap.
|
|
502
|
+
*/
|
|
503
|
+
get(): Frozen<T> {
|
|
484
504
|
trackModifiedPublisher(this);
|
|
485
|
-
|
|
486
|
-
if (
|
|
505
|
+
let raw: T;
|
|
506
|
+
if (this._cachedGet_ !== undefined) {
|
|
507
|
+
raw = this._cachedGet_;
|
|
508
|
+
} else if (Object.prototype.hasOwnProperty.call(this._value_, "__value")) {
|
|
487
509
|
const v = (this._value_ as any).__value;
|
|
488
|
-
|
|
510
|
+
raw = this._cachedGet_ = (v != undefined ? v : null) as T;
|
|
511
|
+
} else {
|
|
512
|
+
raw = this._cachedGet_ = (
|
|
513
|
+
this._value_ != undefined ? this._value_ : null
|
|
514
|
+
) as T;
|
|
489
515
|
}
|
|
490
|
-
return (
|
|
491
|
-
this._value_ != undefined ? this._value_ : null
|
|
492
|
-
) as T);
|
|
516
|
+
return wrapStrictGet(raw) as Frozen<T>;
|
|
493
517
|
}
|
|
494
518
|
/**
|
|
495
519
|
* retourner le webcomponent auquel le proxy est associé
|
|
@@ -539,6 +563,17 @@ export class PublisherManager {
|
|
|
539
563
|
static saveId = 0;
|
|
540
564
|
static instance: PublisherManager | null = null;
|
|
541
565
|
static instances: Map<string, PublisherManager> = new Map();
|
|
566
|
+
/**
|
|
567
|
+
* Runtime guard on `get()` results: `off` | `warn` | `throw`.
|
|
568
|
+
* Default `off`. Enable in local/CI to detect in-place mutations after get().
|
|
569
|
+
* @see wrapStrictGet
|
|
570
|
+
*/
|
|
571
|
+
static get strictGet(): StrictGetMode {
|
|
572
|
+
return getStrictGetMode();
|
|
573
|
+
}
|
|
574
|
+
static set strictGet(mode: StrictGetMode) {
|
|
575
|
+
setStrictGetMode(mode);
|
|
576
|
+
}
|
|
542
577
|
enabledLocaStorageProxies: string[] = [];
|
|
543
578
|
publishers = new Map<string, PublisherInterface>();
|
|
544
579
|
localStorageData: Record<
|
|
@@ -825,6 +860,7 @@ const internalProps: Set<string> = new Set([
|
|
|
825
860
|
"_publishFormInvalidation_",
|
|
826
861
|
"_publishTemplateFilling_",
|
|
827
862
|
"_publishAssignement_",
|
|
863
|
+
"_syncOwnedValueIntoParent_",
|
|
828
864
|
"_proxies_",
|
|
829
865
|
"parent",
|
|
830
866
|
"_parentKey_",
|
|
@@ -943,19 +979,17 @@ function createPublisherHandler<T = any>(
|
|
|
943
979
|
newPublisher._proxies_.set("_parent_", getProxy());
|
|
944
980
|
publisherInstance._proxies_.set(sKey, newPublisher);
|
|
945
981
|
}
|
|
946
|
-
//mis à jour et publication de la donnée si elle a changé
|
|
947
982
|
|
|
948
|
-
const prevValue = (publisherInstance._value_ as any)[sKey];
|
|
983
|
+
const prevValue = (publisherInstance._value_ as any)?.[sKey];
|
|
949
984
|
|
|
950
985
|
if (prevValue !== vValue) {
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
986
|
+
const childStorage = isComplex(vValue)
|
|
987
|
+
? vValue
|
|
988
|
+
: ({ __value: vValue } as any);
|
|
989
|
+
// Child commits owned value and syncs parent immutably (no in-place _value_ patch).
|
|
990
|
+
publisherInstance._proxies_.get(sKey)?.set(childStorage as any);
|
|
991
|
+
publisherInstance._publishDynamicFilling_(sKey, vValue as any);
|
|
956
992
|
}
|
|
957
|
-
//on retourne le proxy pour pouvoir chainer les assignements
|
|
958
|
-
// return publisherInstance._proxies_.get(sKey);
|
|
959
993
|
return true;
|
|
960
994
|
},
|
|
961
995
|
/**
|
|
@@ -963,12 +997,17 @@ function createPublisherHandler<T = any>(
|
|
|
963
997
|
*/
|
|
964
998
|
deleteProperty: function (_publisherInstance, sKey: string) {
|
|
965
999
|
publisherInstance._publishDynamicFilling_(sKey, null);
|
|
966
|
-
//
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1000
|
+
// Clear child without syncing; parent rebuild drops the key immutably.
|
|
1001
|
+
publisherInstance._proxies_.get(sKey)?.set(null, true, true);
|
|
1002
|
+
if (
|
|
1003
|
+
publisherInstance._value_ != null &&
|
|
1004
|
+
typeof publisherInstance._value_ === "object" &&
|
|
1005
|
+
!isLeaf(publisherInstance._value_)
|
|
1006
|
+
) {
|
|
1007
|
+
const next = deleteAtKey(publisherInstance._value_ as object, sKey);
|
|
1008
|
+
publisherInstance.set(next as any, false, true);
|
|
1009
|
+
}
|
|
1010
|
+
return true;
|
|
972
1011
|
},
|
|
973
1012
|
// enumerate: function (publisherInstance, sKey): CoreJSType {
|
|
974
1013
|
// return publisherInstance._value_.keys();
|
|
@@ -981,10 +1020,9 @@ function createPublisherHandler<T = any>(
|
|
|
981
1020
|
},
|
|
982
1021
|
defineProperty: function (_publisherInstance, sKey, oDesc) {
|
|
983
1022
|
if (oDesc && "value" in oDesc) {
|
|
984
|
-
(
|
|
1023
|
+
(getProxy() as any)[sKey] = oDesc.value;
|
|
985
1024
|
}
|
|
986
1025
|
return true;
|
|
987
|
-
// return publisherInstance._value_;
|
|
988
1026
|
},
|
|
989
1027
|
getOwnPropertyDescriptor: function (_publisherInstance, sKey) {
|
|
990
1028
|
sKey;
|
|
@@ -1076,12 +1114,12 @@ export const getObservables = <T = any>(
|
|
|
1076
1114
|
return new Set<DataProvider<T>>([observable as DataProvider<T>]);
|
|
1077
1115
|
};
|
|
1078
1116
|
|
|
1079
|
-
// get value (
|
|
1080
|
-
export function get<T>(id: DataProviderKey<T>): T
|
|
1081
|
-
export function get<T = any>(id: string): T
|
|
1082
|
-
export function get<T>(id: string | DataProviderKey<T>): T {
|
|
1117
|
+
// get value (typed Frozen — owned frozen store ref; see get() JSDoc)
|
|
1118
|
+
export function get<T>(id: DataProviderKey<T>): Frozen<T>;
|
|
1119
|
+
export function get<T = any>(id: string): Frozen<T>;
|
|
1120
|
+
export function get<T>(id: string | DataProviderKey<T>): Frozen<T> {
|
|
1083
1121
|
const path = resolveStaticPublisherPath(id);
|
|
1084
|
-
return getObservables<T>(path).values().next().value?.get() as T
|
|
1122
|
+
return getObservables<T>(path).values().next().value?.get() as Frozen<T>;
|
|
1085
1123
|
}
|
|
1086
1124
|
|
|
1087
1125
|
function deepee<T>(
|
|
@@ -1177,9 +1215,12 @@ export function mirrorDp(
|
|
|
1177
1215
|
);
|
|
1178
1216
|
}
|
|
1179
1217
|
|
|
1180
|
-
export function set<T>(id: DataProviderKey<T>, value: T): void;
|
|
1181
|
-
export function set<T = any>(id: string, value: T): void;
|
|
1182
|
-
export function set<T>(
|
|
1218
|
+
export function set<T>(id: DataProviderKey<T>, value: T | Frozen<T>): void;
|
|
1219
|
+
export function set<T = any>(id: string, value: T | Frozen<T>): void;
|
|
1220
|
+
export function set<T>(
|
|
1221
|
+
id: string | DataProviderKey<T>,
|
|
1222
|
+
value: T | Frozen<T>,
|
|
1223
|
+
): void {
|
|
1183
1224
|
const path = resolveStaticPublisherPath(id);
|
|
1184
1225
|
getObservables(path).values().next().value?.set(value);
|
|
1185
1226
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { describe, it, expect, expectTypeOf } from "vitest";
|
|
2
|
+
import { DataProviderKey } from "./dataProviderKey";
|
|
3
|
+
import type { Frozen, FrozenArray } from "./deepReadonly";
|
|
4
|
+
import { dp, get, set } from "./PublisherProxy";
|
|
5
|
+
|
|
6
|
+
type Cart = { items: { id: number; qty: number }[]; total: number };
|
|
7
|
+
type City = { nom: string; code: string };
|
|
8
|
+
|
|
9
|
+
describe("Frozen get() (79567)", () => {
|
|
10
|
+
const cartKey = new DataProviderKey<Cart>("deepReadonlySpecCart");
|
|
11
|
+
|
|
12
|
+
it("runtime: get() returns the owned frozen store ref", () => {
|
|
13
|
+
const initial: Cart = { items: [{ id: 1, qty: 1 }], total: 1 };
|
|
14
|
+
set(cartKey, initial);
|
|
15
|
+
const snapshot = get(cartKey);
|
|
16
|
+
expect(snapshot).toBe(dp(cartKey).get());
|
|
17
|
+
expect(Object.isFrozen(snapshot)).toBe(true);
|
|
18
|
+
expect(() => {
|
|
19
|
+
(snapshot as Cart).total = 99;
|
|
20
|
+
}).toThrow();
|
|
21
|
+
expect(get(cartKey).total).toBe(1);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("types: array is FrozenArray and index is Frozen element", () => {
|
|
25
|
+
type Arr = Frozen<City[]>;
|
|
26
|
+
expectTypeOf<Arr>().toMatchTypeOf<FrozenArray<City>>();
|
|
27
|
+
type Elem = Arr[0];
|
|
28
|
+
expectTypeOf<Elem>().toEqualTypeOf<Frozen<City>>();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("types: get() is Frozen when the key is typed", () => {
|
|
32
|
+
set(cartKey, { items: [{ id: 1, qty: 1 }], total: 1 });
|
|
33
|
+
const cart = get(cartKey);
|
|
34
|
+
expectTypeOf(cart).toEqualTypeOf<Frozen<Cart>>();
|
|
35
|
+
expectTypeOf(cart.items).toMatchTypeOf<FrozenArray<{ id: number; qty: number }>>();
|
|
36
|
+
expect(cart.total).toBeTypeOf("number");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("types: keyof FrozenObject keeps domain keys (IDE completions)", () => {
|
|
40
|
+
type Payload = { request: Request; response?: Response; result: City[] };
|
|
41
|
+
type Keys = keyof Frozen<Payload>;
|
|
42
|
+
expectTypeOf<Keys>().toEqualTypeOf<"request" | "response" | "result">();
|
|
43
|
+
type R = Frozen<Payload>["result"];
|
|
44
|
+
expectTypeOf<R>().toEqualTypeOf<FrozenArray<City>>();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("types: nested mutation is rejected", () => {
|
|
48
|
+
set(cartKey, { items: [{ id: 1, qty: 1 }], total: 1 });
|
|
49
|
+
const cart = get(cartKey);
|
|
50
|
+
if (false as boolean) {
|
|
51
|
+
// @ts-expect-error Frozen blocks push on items
|
|
52
|
+
cart.items.push({ id: 2, qty: 1 });
|
|
53
|
+
// @ts-expect-error Frozen blocks property write
|
|
54
|
+
cart.total = 0;
|
|
55
|
+
// @ts-expect-error Frozen blocks nested write
|
|
56
|
+
cart.items[0].qty = 3;
|
|
57
|
+
}
|
|
58
|
+
expect(cart.items).toHaveLength(1);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("set accepts get() snapshot without cast", () => {
|
|
62
|
+
set(cartKey, { items: [], total: 0 });
|
|
63
|
+
set(cartKey, get(cartKey));
|
|
64
|
+
expect(get(cartKey).total).toBe(0);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Valeur du DataProvider en lecture seule (runtime = frozen).
|
|
3
|
+
*
|
|
4
|
+
* Nom public : `Frozen<T>`.
|
|
5
|
+
* - Tableaux → interface `FrozenArray<V>` (hover nommé + autocomplétion OK).
|
|
6
|
+
* - Objets → alias mappé `FrozenObject<T>` (l’interface `extends` un mapped
|
|
7
|
+
* générique est illégale / TS2312 → props perdues, `test.` vide).
|
|
8
|
+
* - Built-ins DOM/host (`Request`, `Response`, `Date`, …) : opaque, non retraversés
|
|
9
|
+
* (sinon language service noyé, ex. `ApiResult`).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** Types host / builtin : shallow (pas de deep Frozen). */
|
|
13
|
+
type FrozenLeaf =
|
|
14
|
+
| Date
|
|
15
|
+
| RegExp
|
|
16
|
+
| Error
|
|
17
|
+
| ArrayBuffer
|
|
18
|
+
| SharedArrayBuffer
|
|
19
|
+
| DataView
|
|
20
|
+
| Promise<unknown>
|
|
21
|
+
| WeakMap<object, unknown>
|
|
22
|
+
| WeakSet<object>
|
|
23
|
+
| Request
|
|
24
|
+
| Response
|
|
25
|
+
| Headers
|
|
26
|
+
| FormData
|
|
27
|
+
| Blob
|
|
28
|
+
| File
|
|
29
|
+
| URL
|
|
30
|
+
| URLSearchParams
|
|
31
|
+
| AbortSignal
|
|
32
|
+
| AbortController
|
|
33
|
+
| ReadableStream<unknown>
|
|
34
|
+
| WritableStream<unknown>
|
|
35
|
+
| TransformStream<unknown, unknown>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Objet frozen — mapped alias (seul pattern compatible autocomplétion).
|
|
39
|
+
* Hover peut déplier les champs ; le paramètre `T` reste le type maître.
|
|
40
|
+
*/
|
|
41
|
+
export type FrozenObject<T> = {
|
|
42
|
+
readonly [K in keyof T]: Frozen<T[K]>;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Tableau frozen nommé — hover = `FrozenArray<V>` ; `arr[0]` = `Frozen<V>`.
|
|
47
|
+
*/
|
|
48
|
+
export interface FrozenArray<T> extends ReadonlyArray<Frozen<T>> {}
|
|
49
|
+
|
|
50
|
+
export type Frozen<T> = 0 extends 1 & T
|
|
51
|
+
? T
|
|
52
|
+
: unknown extends T
|
|
53
|
+
? T
|
|
54
|
+
: T extends string | number | boolean | bigint | symbol | null | undefined
|
|
55
|
+
? T
|
|
56
|
+
: T extends (...args: never[]) => unknown
|
|
57
|
+
? T
|
|
58
|
+
: T extends FrozenLeaf
|
|
59
|
+
? T
|
|
60
|
+
: T extends ReadonlyMap<infer K, infer V>
|
|
61
|
+
? ReadonlyMap<Frozen<K>, Frozen<V>>
|
|
62
|
+
: T extends ReadonlySet<infer V>
|
|
63
|
+
? ReadonlySet<Frozen<V>>
|
|
64
|
+
: T extends readonly (infer V)[]
|
|
65
|
+
? FrozenArray<V>
|
|
66
|
+
: T extends object
|
|
67
|
+
? FrozenObject<T>
|
|
68
|
+
: T;
|
|
69
|
+
|
|
70
|
+
/** @deprecated Prefer {@link Frozen} — même type, nom plus long. */
|
|
71
|
+
export type DeepReadonly<T> = Frozen<T>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
deepFreeze,
|
|
4
|
+
deleteAtKey,
|
|
5
|
+
setAtKey,
|
|
6
|
+
takeOwnership,
|
|
7
|
+
} from "./immutableValue";
|
|
8
|
+
|
|
9
|
+
describe("immutableValue helpers", () => {
|
|
10
|
+
it("takeOwnership clones so external mutation does not affect owned value", () => {
|
|
11
|
+
const external = { a: 1, nested: { b: 2 } };
|
|
12
|
+
const owned = takeOwnership(external);
|
|
13
|
+
external.a = 9;
|
|
14
|
+
external.nested.b = 9;
|
|
15
|
+
expect(owned.a).toBe(1);
|
|
16
|
+
expect(owned.nested.b).toBe(2);
|
|
17
|
+
expect(Object.isFrozen(owned)).toBe(true);
|
|
18
|
+
expect(Object.isFrozen(owned.nested)).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("takeOwnership is idempotent on frozen values", () => {
|
|
22
|
+
const once = takeOwnership({ x: 1 });
|
|
23
|
+
expect(takeOwnership(once)).toBe(once);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("deepFreeze blocks assignment", () => {
|
|
27
|
+
const v = deepFreeze({ n: 1 });
|
|
28
|
+
expect(() => {
|
|
29
|
+
(v as { n: number }).n = 2;
|
|
30
|
+
}).toThrow();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("setAtKey / deleteAtKey rebuild without mutating root", () => {
|
|
34
|
+
const root = takeOwnership({ a: 1, b: 2 });
|
|
35
|
+
const next = setAtKey(root, "b", 3);
|
|
36
|
+
expect(root.b).toBe(2);
|
|
37
|
+
expect(next.b).toBe(3);
|
|
38
|
+
expect(Object.isFrozen(next)).toBe(true);
|
|
39
|
+
const dropped = deleteAtKey(next, "a");
|
|
40
|
+
expect("a" in dropped).toBe(false);
|
|
41
|
+
expect(next.a).toBe(1);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("unclonable values warn and pass through", () => {
|
|
45
|
+
const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
46
|
+
const fn = () => 1;
|
|
47
|
+
const obj = { fn };
|
|
48
|
+
// functions inside plain objects: structuredClone throws in many engines
|
|
49
|
+
const owned = takeOwnership(obj);
|
|
50
|
+
expect(owned).toBe(obj);
|
|
51
|
+
expect(warn).toHaveBeenCalled();
|
|
52
|
+
warn.mockRestore();
|
|
53
|
+
});
|
|
54
|
+
});
|