@supersoniks/concorde 5.1.2 → 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 +1 -1
- 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 +1 -1
- 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} +11722 -8868
- 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/og-concorde.jpg +0 -0
- package/dist/robots.txt +11 -10
- package/docs/assets/index-CD4WyL6o.css +1 -0
- 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/{core → crawl/core}/components/functional/sdui/sdui-extension-points.html +8 -9
- 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/{core → crawl/core}/components/functional/subscriber/subscriber.html +5 -6
- package/docs/crawl/core/components/functional/value/value.html +51 -0
- package/docs/{core → crawl/core}/components/ui/alert/alert.html +63 -53
- package/docs/{core → crawl/core}/components/ui/alert-messages/alert-messages.html +5 -6
- package/docs/{core → crawl/core}/components/ui/badge/badge.html +33 -33
- package/docs/crawl/core/components/ui/button/button.html +150 -0
- package/docs/crawl/core/components/ui/captcha/captcha.html +112 -0
- package/docs/{core → crawl/core}/components/ui/card/card.html +11 -12
- package/docs/{core → crawl/core}/components/ui/divider/divider.html +14 -14
- 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/{core → crawl/core}/components/ui/form/form-actions/form-actions.html +23 -23
- 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/{core → crawl/core}/components/ui/icon/icon.html +9 -10
- package/docs/crawl/core/components/ui/image/image.html +298 -0
- package/docs/{core → crawl/core}/components/ui/link/link.html +11 -12
- package/docs/crawl/core/components/ui/loader/loader.html +124 -0
- package/docs/{core → crawl/core}/components/ui/menu/menu.html +33 -34
- package/docs/crawl/core/components/ui/modal/modal.html +342 -0
- package/docs/crawl/core/components/ui/pop/pop.html +296 -0
- package/docs/{core → crawl/core}/components/ui/progress/progress.html +7 -8
- 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/{docs/getting-started → crawl/docs/_core-concept}/dataFlow.html +29 -26
- 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/{docs/getting-started → crawl/docs/_getting-started}/ai-agents.html +11 -12
- 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/{docs/getting-started → crawl/docs/_getting-started}/create-a-component.html +14 -11
- package/docs/{docs/getting-started → crawl/docs/_getting-started}/my-first-component.html +22 -13
- 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/{docs/getting-started → crawl/docs/_getting-started}/theming.html +9 -10
- package/docs/{docs/misc → crawl/docs/_misc}/api-configuration.html +18 -18
- package/docs/{docs/misc → crawl/docs/_misc}/dataProviderKey.html +11 -12
- package/docs/{docs/misc → crawl/docs/_misc}/docs-mock-api.html +28 -25
- package/docs/{docs/misc → crawl/docs/_misc}/dynamic-path.html +15 -16
- package/docs/{docs/misc → crawl/docs/_misc}/endpoint.html +15 -16
- package/docs/crawl/docs/_misc/formelement-subscriber-removal.html +138 -0
- package/docs/{docs/misc → crawl/docs/_misc}/html-integration.html +15 -12
- 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/docs-mock-api-sw.js +223 -58
- package/docs/docs-mock-api-sw.js.map +4 -4
- package/docs/index.html +68 -95
- package/docs/llms-full.txt +3610 -2231
- package/docs/llms.txt +86 -94
- package/docs/robots.txt +10 -11
- package/docs/sitemap.xml +84 -78
- package/docs/src/core/components/functional/date/date.md +231 -91
- package/docs/src/core/components/functional/fetch/fetch.md +83 -66
- package/docs/src/core/components/functional/if/if.md +3 -28
- package/docs/src/core/components/functional/jsonata/jsonata.md +37 -42
- package/docs/src/core/components/functional/list/list.md +43 -99
- package/docs/src/core/components/functional/mix/mix.md +26 -31
- package/docs/src/core/components/functional/queue/queue.md +61 -40
- package/docs/src/core/components/functional/router/router.md +65 -64
- package/docs/src/core/components/functional/sdui/component-catalog.gaps.json +1 -1
- package/docs/src/core/components/functional/sdui/component-catalog.json +1 -1
- package/docs/src/core/components/functional/sdui/example.json +86 -19
- package/docs/src/core/components/functional/sdui/sdui-extension-points.md +1 -1
- package/docs/src/core/components/functional/sdui/sdui.md +358 -187
- package/docs/src/core/components/functional/states/states.md +61 -86
- package/docs/src/core/components/functional/submit/submit.md +72 -64
- package/docs/src/core/components/functional/value/value.md +22 -34
- package/docs/src/core/components/ui/alert/alert.md +58 -48
- package/docs/src/core/components/ui/badge/badge.md +34 -27
- package/docs/src/core/components/ui/button/button.md +106 -139
- package/docs/src/core/components/ui/captcha/captcha.md +32 -17
- package/docs/src/core/components/ui/card/card.md +6 -6
- package/docs/src/core/components/ui/divider/divider.md +11 -8
- package/docs/src/core/components/ui/form/checkbox/checkbox.md +42 -90
- package/docs/src/core/components/ui/form/fieldset/fieldset.md +75 -31
- package/docs/src/core/components/ui/form/form-actions/form-actions.md +16 -14
- package/docs/src/core/components/ui/form/form-layout/form-layout.md +29 -19
- package/docs/src/core/components/ui/form/input/input.md +95 -95
- package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +29 -0
- package/docs/src/core/components/ui/form/radio/radio.md +34 -55
- package/docs/src/core/components/ui/form/select/select.md +45 -60
- package/docs/src/core/components/ui/form/switch/switch.md +34 -57
- package/docs/src/core/components/ui/form/textarea/textarea.md +38 -55
- package/docs/src/core/components/ui/group/group.md +33 -35
- package/docs/src/core/components/ui/icon/icon.md +4 -4
- package/docs/src/core/components/ui/image/image.md +107 -41
- package/docs/src/core/components/ui/link/link.md +6 -6
- package/docs/src/core/components/ui/loader/loader.md +55 -30
- package/docs/src/core/components/ui/menu/menu.md +27 -27
- package/docs/src/core/components/ui/modal/modal.md +96 -72
- package/docs/src/core/components/ui/pop/pop.md +158 -80
- package/docs/src/core/components/ui/progress/progress.md +2 -2
- package/docs/src/core/components/ui/table/table.md +255 -91
- package/docs/src/core/components/ui/theme/theme.md +36 -11
- package/docs/src/core/components/ui/toast/toast.md +117 -48
- package/docs/src/core/components/ui/tooltip/tooltip.md +62 -27
- package/docs/{docs/getting-started → src/docs/_core-concept}/dataFlow.md +18 -17
- package/docs/src/docs/_core-concept/overview.md +57 -0
- package/docs/src/docs/_core-concept/subscriber.md +75 -0
- package/docs/src/docs/_decorators/ancestor-attribute.md +128 -0
- package/docs/src/docs/_decorators/auto-subscribe.md +202 -0
- package/docs/src/docs/_decorators/bind.md +167 -0
- package/docs/src/docs/_decorators/get.md +162 -0
- package/docs/src/docs/_decorators/handle.md +175 -0
- package/docs/src/docs/_decorators/on-assign.md +390 -0
- package/docs/src/docs/_decorators/patch.md +70 -0
- package/docs/src/docs/_decorators/post.md +146 -0
- package/docs/src/docs/_decorators/publish.md +55 -0
- package/docs/src/docs/_decorators/put.md +70 -0
- package/docs/src/docs/_decorators/subscribe.md +100 -0
- package/docs/src/docs/_decorators/wait-for-ancestors.md +163 -0
- package/docs/src/docs/_directives/sub.md +91 -0
- package/docs/src/docs/{getting-started → _getting-started}/ai-agents.md +3 -3
- package/docs/src/docs/_getting-started/concorde-manual-install.md +133 -0
- package/docs/src/docs/_getting-started/concorde-outside.md +33 -0
- package/docs/{docs/getting-started → src/docs/_getting-started}/create-a-component.md +6 -3
- package/docs/src/docs/{getting-started → _getting-started}/my-first-component.md +14 -5
- package/docs/src/docs/_getting-started/my-first-subscriber.md +120 -0
- package/docs/src/docs/_getting-started/pubsub.md +37 -0
- package/docs/src/docs/{getting-started → _getting-started}/start.md +13 -1
- package/docs/src/docs/{getting-started → _getting-started}/theming.md +2 -2
- package/docs/src/docs/{misc → _misc}/api-configuration.md +12 -10
- package/docs/src/docs/{misc → _misc}/dataProviderKey.md +4 -4
- package/docs/{docs/misc → src/docs/_misc}/docs-mock-api.md +13 -12
- package/docs/{docs/misc → src/docs/_misc}/dynamic-path.md +8 -8
- package/docs/{docs/misc → src/docs/_misc}/endpoint.md +8 -8
- package/docs/src/docs/_misc/formelement-subscriber-removal.md +115 -0
- package/docs/{docs/misc → src/docs/_misc}/html-integration.md +5 -4
- package/docs/src/docs/search/docs-search.json +4375 -2420
- package/docs/src/tsconfig.declarations.json +22 -0
- package/docs/src/tsconfig.emit.json +23 -0
- package/docs/src/tsconfig.json +2 -23
- package/gitlab/job_github_mirror.sh +39 -0
- package/index.html +89 -0
- package/package.json +22 -4
- package/public/img/og-concorde.jpg +0 -0
- package/scripts/ai-init.mjs +104 -379
- package/scripts/ai-init.test.mjs +81 -239
- package/scripts/docs-markdown-vite-plugin.ts +11 -5
- package/scripts/docs-public-url.mjs +6 -0
- package/scripts/docs.htaccess +7 -0
- package/scripts/generate-cem.mjs +244 -0
- package/scripts/generate-cem.test.mjs +122 -0
- package/scripts/generate-crawl-docs.mjs +29 -5
- package/scripts/generate-sdui-catalog.mjs +11 -10
- package/scripts/github-export.mjs +150 -0
- package/scripts/post-build-docs.js +3 -0
- 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 +1 -1
- package/src/core/components/functional/example/example.ts +3 -1
- package/src/core/components/functional/if/if.ts +0 -0
- package/src/core/components/functional/list/list.demo.ts +0 -0
- package/src/core/components/functional/list/list.md +6 -2
- package/src/core/components/functional/list/list.ts +17 -4
- package/src/core/components/functional/mix/mix.md +0 -0
- package/src/core/components/functional/router/router.demo.ts +0 -0
- 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 +0 -0
- package/src/core/components/functional/sdui/sdui-immutable.spec.ts +74 -0
- 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.ts +0 -0
- 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/value/value.md +0 -0
- 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/captcha/altchaStyles.ts +0 -0
- package/src/core/components/ui/card/card.md +1 -1
- package/src/core/components/ui/form/input/input.md +19 -1
- package/src/core/components/ui/form/input/input.ts +8 -2
- package/src/core/components/ui/form/radio/radio.md +14 -0
- package/src/core/components/ui/image/image.md +17 -17
- package/src/core/components/ui/modal/modal.md +2 -2
- 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/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 +3 -3
- package/src/docs/decorators/bind.md +23 -24
- package/src/docs/docs-location.spec.ts +10 -0
- package/src/docs/docs-location.ts +10 -0
- package/src/docs/example/decorators-demo-bind-demos.ts +11 -28
- package/src/docs/example/docs-toggle-demos.ts +1 -1
- package/src/docs/example/users.ts +0 -0
- package/src/docs/getting-started/ai-agents.md +29 -55
- package/src/docs/getting-started/dataFlow.md +2 -2
- package/src/docs/home/home.ts +3 -1
- 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/navigation/navigation.ts +5 -1
- package/src/docs/search/docs-search.json +358 -58
- package/src/docs/search/markdown-renderer.ts +6 -1
- 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/.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/PLAN-DOCS-AGENTS.md +0 -80
- 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/.htaccess +0 -75
- package/docs/404.html +0 -15
- package/docs/404.md +0 -5
- package/docs/assets/index-BgG6FFPt.js +0 -11765
- package/docs/assets/index-x89XINSG.css +0 -1
- package/docs/core/components/functional/date/date.html +0 -211
- package/docs/core/components/functional/date/date.md +0 -150
- package/docs/core/components/functional/fetch/fetch.html +0 -180
- package/docs/core/components/functional/fetch/fetch.md +0 -108
- package/docs/core/components/functional/if/if.html +0 -65
- package/docs/core/components/functional/if/if.md +0 -34
- package/docs/core/components/functional/jsonata/jsonata.html +0 -110
- package/docs/core/components/functional/jsonata/jsonata.md +0 -61
- package/docs/core/components/functional/list/list.html +0 -198
- package/docs/core/components/functional/list/list.md +0 -121
- package/docs/core/components/functional/mix/mix.html +0 -78
- package/docs/core/components/functional/mix/mix.md +0 -46
- package/docs/core/components/functional/queue/queue.html +0 -155
- package/docs/core/components/functional/queue/queue.md +0 -51
- package/docs/core/components/functional/router/router.html +0 -154
- package/docs/core/components/functional/router/router.md +0 -93
- package/docs/core/components/functional/sdui/sdui-extension-points.md +0 -94
- package/docs/core/components/functional/sdui/sdui.html +0 -397
- package/docs/core/components/functional/sdui/sdui.md +0 -307
- package/docs/core/components/functional/states/states.html +0 -141
- package/docs/core/components/functional/states/states.md +0 -112
- package/docs/core/components/functional/submit/submit.html +0 -178
- package/docs/core/components/functional/submit/submit.md +0 -106
- package/docs/core/components/functional/subscriber/subscriber.md +0 -91
- package/docs/core/components/functional/translation/translation.html +0 -60
- package/docs/core/components/functional/translation/translation.md +0 -38
- package/docs/core/components/functional/value/value.html +0 -81
- package/docs/core/components/functional/value/value.md +0 -47
- package/docs/core/components/ui/alert/alert.md +0 -186
- package/docs/core/components/ui/alert-messages/alert-messages.md +0 -85
- package/docs/core/components/ui/badge/badge.md +0 -181
- package/docs/core/components/ui/button/button.html +0 -309
- package/docs/core/components/ui/button/button.md +0 -216
- package/docs/core/components/ui/captcha/captcha.html +0 -80
- package/docs/core/components/ui/captcha/captcha.md +0 -56
- package/docs/core/components/ui/card/card.md +0 -215
- package/docs/core/components/ui/divider/divider.md +0 -126
- package/docs/core/components/ui/form/checkbox/checkbox.html +0 -200
- package/docs/core/components/ui/form/checkbox/checkbox.md +0 -125
- package/docs/core/components/ui/form/fieldset/fieldset.html +0 -238
- package/docs/core/components/ui/form/fieldset/fieldset.md +0 -161
- package/docs/core/components/ui/form/form-actions/form-actions.md +0 -98
- package/docs/core/components/ui/form/form-layout/form-layout.html +0 -115
- package/docs/core/components/ui/form/form-layout/form-layout.md +0 -109
- package/docs/core/components/ui/form/input/input.html +0 -235
- package/docs/core/components/ui/form/input/input.md +0 -142
- package/docs/core/components/ui/form/radio/radio.html +0 -144
- package/docs/core/components/ui/form/radio/radio.md +0 -78
- package/docs/core/components/ui/form/select/select.html +0 -178
- package/docs/core/components/ui/form/select/select.md +0 -86
- package/docs/core/components/ui/form/switch/switch.html +0 -146
- package/docs/core/components/ui/form/switch/switch.md +0 -80
- package/docs/core/components/ui/form/textarea/textarea.html +0 -162
- package/docs/core/components/ui/form/textarea/textarea.md +0 -82
- package/docs/core/components/ui/group/group.html +0 -113
- package/docs/core/components/ui/group/group.md +0 -77
- package/docs/core/components/ui/icon/icon.md +0 -214
- package/docs/core/components/ui/image/image.html +0 -194
- package/docs/core/components/ui/image/image.md +0 -167
- package/docs/core/components/ui/link/link.md +0 -81
- package/docs/core/components/ui/loader/loader.html +0 -114
- package/docs/core/components/ui/loader/loader.md +0 -87
- package/docs/core/components/ui/menu/menu.md +0 -370
- package/docs/core/components/ui/modal/modal.html +0 -324
- package/docs/core/components/ui/modal/modal.md +0 -211
- package/docs/core/components/ui/pop/pop.html +0 -250
- package/docs/core/components/ui/pop/pop.md +0 -216
- package/docs/core/components/ui/progress/progress.md +0 -109
- package/docs/core/components/ui/table/table.html +0 -333
- package/docs/core/components/ui/table/table.md +0 -267
- package/docs/core/components/ui/theme/theme.html +0 -116
- package/docs/core/components/ui/theme/theme.md +0 -97
- package/docs/core/components/ui/toast/toast.html +0 -185
- package/docs/core/components/ui/toast/toast.md +0 -147
- package/docs/core/components/ui/tooltip/tooltip.html +0 -112
- package/docs/core/components/ui/tooltip/tooltip.md +0 -89
- package/docs/docs/decorators/ancestor-attribute.html +0 -71
- package/docs/docs/decorators/ancestor-attribute.md +0 -59
- package/docs/docs/decorators/auto-subscribe.html +0 -61
- package/docs/docs/decorators/auto-subscribe.md +0 -40
- package/docs/docs/decorators/bind.html +0 -86
- package/docs/docs/decorators/bind.md +0 -77
- package/docs/docs/decorators/get.html +0 -166
- package/docs/docs/decorators/get.md +0 -160
- package/docs/docs/decorators/handle.html +0 -139
- package/docs/docs/decorators/handle.md +0 -119
- package/docs/docs/decorators/on-assign.html +0 -72
- package/docs/docs/decorators/on-assign.md +0 -63
- package/docs/docs/decorators/patch.html +0 -76
- package/docs/docs/decorators/patch.md +0 -44
- package/docs/docs/decorators/post.html +0 -150
- package/docs/docs/decorators/post.md +0 -134
- package/docs/docs/decorators/publish.html +0 -74
- package/docs/docs/decorators/publish.md +0 -56
- package/docs/docs/decorators/put.html +0 -83
- package/docs/docs/decorators/put.md +0 -51
- package/docs/docs/decorators/subscribe.html +0 -91
- package/docs/docs/decorators/subscribe.md +0 -87
- package/docs/docs/decorators/wait-for-ancestors.html +0 -82
- package/docs/docs/decorators/wait-for-ancestors.md +0 -76
- package/docs/docs/directives/sub.html +0 -79
- package/docs/docs/directives/sub.md +0 -75
- package/docs/docs/directives/t.html +0 -91
- package/docs/docs/directives/t.md +0 -73
- package/docs/docs/getting-started/ai-agents.md +0 -76
- package/docs/docs/getting-started/components.html +0 -27
- package/docs/docs/getting-started/components.md +0 -5
- package/docs/docs/getting-started/installation.html +0 -69
- package/docs/docs/getting-started/installation.md +0 -36
- package/docs/docs/getting-started/my-first-component.md +0 -227
- package/docs/docs/getting-started/start.html +0 -47
- package/docs/docs/getting-started/start.md +0 -35
- package/docs/docs/getting-started/theming.md +0 -253
- package/docs/docs/index.html +0 -99
- package/docs/docs/misc/api-configuration.md +0 -79
- package/docs/docs/misc/dataProviderKey.md +0 -168
- package/docs/hubs/decorators.html +0 -443
- package/docs/hubs/form-components.html +0 -404
- package/docs/hubs/remote-data.html +0 -371
- package/docs/img/archive/concorde-001-2cv.webp +0 -0
- package/docs/img/archive/concorde-red-arrows-2002-poster.jpg +0 -0
- package/docs/img/archive/concorde-red-arrows-2002.webm +0 -0
- package/docs/img/archive/credits.json +0 -28
- package/docs/index.md +0 -22
- package/docs/src/core/components/functional/translation/translation.md +0 -38
- package/docs/src/docs/decorators/ancestor-attribute.md +0 -59
- package/docs/src/docs/decorators/auto-subscribe.md +0 -40
- package/docs/src/docs/decorators/bind.md +0 -77
- package/docs/src/docs/decorators/get.md +0 -160
- package/docs/src/docs/decorators/handle.md +0 -119
- package/docs/src/docs/decorators/on-assign.md +0 -63
- package/docs/src/docs/decorators/patch.md +0 -44
- package/docs/src/docs/decorators/post.md +0 -134
- package/docs/src/docs/decorators/publish.md +0 -56
- package/docs/src/docs/decorators/put.md +0 -51
- package/docs/src/docs/decorators/subscribe.md +0 -87
- package/docs/src/docs/decorators/wait-for-ancestors.md +0 -76
- package/docs/src/docs/directives/sub.md +0 -75
- package/docs/src/docs/directives/t.md +0 -73
- package/docs/src/docs/getting-started/components.md +0 -5
- package/docs/src/docs/getting-started/create-a-component.md +0 -136
- package/docs/src/docs/getting-started/dataFlow.md +0 -87
- package/docs/src/docs/getting-started/installation.md +0 -36
- package/docs/src/docs/misc/docs-mock-api.md +0 -62
- package/docs/src/docs/misc/dynamic-path.md +0 -71
- package/docs/src/docs/misc/endpoint.md +0 -45
- package/docs/src/docs/misc/html-integration.md +0 -14
- /package/{docs → dist}/img/concorde/plane_01.jpg +0 -0
- /package/{docs → dist}/img/concorde/plane_02.jpg +0 -0
- /package/{docs → dist}/img/concorde/plane_03.jpg +0 -0
- /package/{docs → dist}/img/concorde/plane_04.jpg +0 -0
- /package/{docs → dist}/img/concorde/plane_05.jpg +0 -0
- /package/{docs → dist}/img/concorde/plane_06.jpg +0 -0
- /package/{docs → dist}/img/concorde/plane_07.jpg +0 -0
- /package/{docs → dist}/img/concorde/plane_08.jpg +0 -0
- /package/{docs → dist}/img/concorde/plane_09.jpg +0 -0
- /package/{docs → dist}/img/concorde/plane_10.jpg +0 -0
- /package/{docs → dist}/img/concorde/plane_11.jpg +0 -0
- /package/{docs → dist}/img/concorde/plane_12.jpg +0 -0
- /package/{docs → dist}/img/concorde/plane_13.jpg +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/AUDIT.md
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
# Audit Concorde — 2026-10-25
|
|
2
|
-
|
|
3
|
-
Périmètre : `@supersoniks/concorde` 5.1.0 (commit `bc799ae`), ~28 k lignes TS dans `src/core` (hors doc), 197 fichiers.
|
|
4
|
-
Méthode : typecheck, tests, build (dans une copie), `yarn audit`, `npm pack --dry-run`, doc lancée sur le port 3010 et parcourue, puis relecture du code. Chaque constat ci-dessous a été vérifié dans le code. Ceux marqués ✅ ont en plus été reproduits.
|
|
5
|
-
|
|
6
|
-
## Synthèse
|
|
7
|
-
|
|
8
|
-
| Indicateur | Résultat |
|
|
9
|
-
|---|---|
|
|
10
|
-
| `tsc --build` (strict) | ✅ 0 erreur |
|
|
11
|
-
| Tests vitest | ✅ 31 fichiers, 332 tests, tous verts |
|
|
12
|
-
| `yarn build` | ✅ OK, bundles de 460 Ko (UMD) et 648 Ko (ES) |
|
|
13
|
-
| `yarn audit` | ⚠️ 116 vulnérabilités (3 critiques, 60 hautes), **toutes dans l'outillage de dev** |
|
|
14
|
-
| Lint / format | ❌ Ni ESLint ni Prettier ; 227 `any` hors specs |
|
|
15
|
-
| CI | ⚠️ Tests seulement : ni build ni typecheck |
|
|
16
|
-
|
|
17
|
-
Le cœur est solide : bon typage de `DataProviderKey`, décorateurs récents bien conçus, bonne couverture sur l'API et SDUI. En revanche, la surface **XSS est large** : `unsafeHTML` par défaut un peu partout, un profil SDUI « safe » qui ne l'est pas, et un postMessage non filtré. Il y a aussi plusieurs **fuites et boucles** dans la couche données.
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## 🔴 Critique
|
|
22
|
-
|
|
23
|
-
### C1. XSS cross-origin via postMessage (toast)
|
|
24
|
-
- **Où :** `src/core/components/ui/toast/toast.ts:283-323`.
|
|
25
|
-
- **Problème :** le listener `message` s'installe au chargement du module et ne vérifie ni `e.origin` ni `e.source`. `addToast`/`addToasts` aboutissent à `renderToastContent`, qui rend les chaînes avec `unsafeHTML` (`render-content.ts:12`).
|
|
26
|
-
- **Exploitation :** une iframe tierce (pub, widget) ou une fenêtre ouverte par `window.open` envoie `postMessage({type:"addToast",toast:{text:'<img src=x onerror=…>'}},"*")`, et le code s'exécute.
|
|
27
|
-
- **Effet secondaire :** `{type:"sonicToastAvailable"}` active `delegateToasts`. Tous les toasts suivants partent alors vers `window.parent` avec la cible `"*"`.
|
|
28
|
-
- **Correctif :** vérifier `e.origin` (même origine ou liste blanche) ; `targetOrigin` explicite ; texte brut pour tout contenu reçu par postMessage.
|
|
29
|
-
|
|
30
|
-
### C2. Boucle infinie de requêtes sur HTTP 498
|
|
31
|
-
- **Où :** `src/core/utils/api.ts:210-229`.
|
|
32
|
-
- **Problème :** sans `tokenProvider`, `failledTokenUpdates` n'est jamais rempli. Chaque 498 relance la requête, qui renvoie à nouveau 498, sans fin.
|
|
33
|
-
- **Correctif :** un drapeau `retried` dans `lastCall`, pour une seule relance.
|
|
34
|
-
|
|
35
|
-
### C3. Les hooks de cycle de vie des sous-classes fuient vers la classe parente
|
|
36
|
-
- **Où :** `src/core/decorators/subscriber/common.ts:18-44`.
|
|
37
|
-
- **Problème :** `__is__setSubscribable__` et les `Set` de callbacks sont lus via la chaîne de prototypes. Avec `Child extends Base`, les `@subscribe` de `Child` s'enregistrent dans le `Set` de `Base`. Toutes les instances de `Base` s'abonnent alors aux chemins de `Child`. Reproduit en Node par l'agent d'audit.
|
|
38
|
-
- **Correctif :** `Object.hasOwn(target, …)`, un `Set` par prototype, et un appel en chaîne des hooks hérités.
|
|
39
|
-
|
|
40
|
-
## 🟠 Haute
|
|
41
|
-
|
|
42
|
-
### Sécurité
|
|
43
|
-
- **H1. Le profil SDUI `safe` est contournable.**
|
|
44
|
-
- **Où :** `sdui.ts:250` (tagName libre) et `sdui.ts:412-419` (`setAttribute` sans filtre). `sdui-safe.ts` ne bloque que `js`/`markup`/`innerHTML`/`prefix`/`suffix`.
|
|
45
|
-
- **Ce qui passe :** `script src=…`, `img onerror=…`, `iframe srcdoc`, `a href="javascript:"`, `::inner-html`, `css` chargées même en safe, labels rendus en HTML (voir H3).
|
|
46
|
-
- **Correctif :** liste blanche de tags ; refus de `on*`, `srcdoc`, `style` et `::*` ; filtrage des schémas `javascript:` et `data:` dans les URL.
|
|
47
|
-
- **H2. Messages d'API rendus en HTML.**
|
|
48
|
-
- **Où :** `toast/message-subscriber.ts:30` ; `sdui.ts:227` injecte ce subscriber automatiquement.
|
|
49
|
-
- **Problème :** `messages[].content` passe par `unsafeHTML`. Un message serveur qui reprend une saisie utilisateur (« l'email `<img onerror>` existe déjà ») devient une XSS.
|
|
50
|
-
- **H3. `label`, `description` et titres de modale passent en `unsafeHTML` par défaut.**
|
|
51
|
-
- **Où :** `input`, `select`, `textarea`, `checkbox`, `group`, `divider`, `legend`, `card-header`, `same-value-helper`, `modal.ts:434`.
|
|
52
|
-
- **Problème :** c'est dangereux dès qu'un label est lié à des données (`::label="$user.name"`, i18n, SDUI).
|
|
53
|
-
- **Correctif :** texte par défaut et HTML en opt-in (ou DOMPurify).
|
|
54
|
-
- **H4. Captcha.**
|
|
55
|
-
- **Script tiers :** `captcha.ts:78` charge `cdn.jsdelivr.net/gh/altcha-org/altcha/dist/altcha.min.js`, **non versionné et sans SRI**, alors que `altcha-widget.js` est déjà livré dans le paquet.
|
|
56
|
-
- **Cycle de vie cassé :** `captcha.ts:70` fait `return` avant `super.connectedCallback()` en HTTP, ce qui casse le cycle Lit.
|
|
57
|
-
|
|
58
|
-
### Données / runtime
|
|
59
|
-
- **H5. Collision d'identifiants de publisher.**
|
|
60
|
-
- **Où :** `mixins/Subscriber.ts:75,187,356`.
|
|
61
|
-
- **Problème :** `instanceCounter` est statique par classe issue du mixin (~20 classes) et incrémenté à chaque connexion. Deux composants de types différents peuvent donc partager `__subscriber__1`.
|
|
62
|
-
- **H6. Une restauration localStorage asynchrone écrase une valeur fraîche.**
|
|
63
|
-
- **Où :** `PublisherProxy.ts:658-664`.
|
|
64
|
-
- **Problème :** un cache qui peut dater de 12 h remplace un `set()` fait pendant la décompression.
|
|
65
|
-
- **H7. Le polling de `Fetcher` se duplique.**
|
|
66
|
-
- **Où :** `Fetcher.ts:220-259`.
|
|
67
|
-
- **Problème :** pas de `clearTimeout` avant de replanifier. Chaque `invalidate`, chaque changement d'endpoint ou de langue ajoute une chaîne de requêtes.
|
|
68
|
-
- **H8. `@get`/`@post` relancent fetch et polling après le disconnect.**
|
|
69
|
-
- **Où :** `decorators/api.ts:86-113,601-608`.
|
|
70
|
-
- **Problème :** le rAF du runner n'est jamais annulé. Le polling continue sur un élément détaché.
|
|
71
|
-
- **H9. `blockUntilDone` peut rester bloqué indéfiniment.**
|
|
72
|
-
- **Où :** `api.ts:377-411`.
|
|
73
|
-
- **Problème :** le drapeau `"loading"` n'est pas remis à zéro en cas d'exception, ni par `localGet`. Il faut un `try/finally`.
|
|
74
|
-
- **H10. `PublisherProxy.delete()` ne nettoie rien.**
|
|
75
|
-
- **Où :** `PublisherProxy.ts:117`.
|
|
76
|
-
- **Problème :** `for…in` sur `Map.keys()` ne fait aucune itération. Les sous-proxies et leurs listeners fuient, notamment dans `input-autocomplete`.
|
|
77
|
-
- **H11. Lazyload cassé après un déplacement dans le DOM.**
|
|
78
|
-
- **Où :** `Fetcher.ts:264-375`.
|
|
79
|
-
- **Problème :** `isFirstLoad=false` au disconnect empêche tout fetch. L'IntersectionObserver devient orphelin et le placeholder est dupliqué.
|
|
80
|
-
|
|
81
|
-
### Packaging
|
|
82
|
-
- **H12. `package.json#exports` incohérent.**
|
|
83
|
-
- **Entrées aberrantes :** 6 entrées `./undefined/docs-*`, à cause d'un bug de `scripts/pre-build.mjs` sur les fichiers `src/docs/components/*`.
|
|
84
|
-
- **Entrées périmées :** `./prism/index` est encore présent alors que prism a été remplacé par shiki (le package.json commité n'est pas régénéré).
|
|
85
|
-
- **Cible inexistante :** l'export `./rollup-plugin-*` pointe vers un dossier `rollup/` qui n'existe pas.
|
|
86
|
-
- **H13. `lit` n'est qu'en devDependencies, alors que les exports pointent vers des sources `.ts` qui importent `lit`.**
|
|
87
|
-
- **Pourquoi ça marche aujourd'hui :** par accident, via `@lit-labs/motion`. Risque d'échec avec pnpm strict ou de `lit` en double.
|
|
88
|
-
- **Correctif :** `peerDependencies: { lit: "^3" }`.
|
|
89
|
-
- **Dans le même fichier :** `@types/jest` est en `dependencies` sans raison.
|
|
90
|
-
|
|
91
|
-
## 🟡 Moyenne
|
|
92
|
-
|
|
93
|
-
### Sécurité et outillage de dev
|
|
94
|
-
- **M1. Un `Authorization: Bearer` est envoyé à n'importe quel hôte dès que l'endpoint est absolu** (`api.ts:580,593`). Endpoint lié à des données, pagination `next`, SDUI… Il faut restreindre à l'origine de `serviceURL`.
|
|
95
|
-
- **M2. Identifiants en attributs DOM** (`token`, `password` : `HTML.ts:146-157`) et cache d'API en clair dans localStorage, sans purge à la déconnexion.
|
|
96
|
-
- **M3. Serveur de dev exposé.** `yarn dev` écoute sur `0.0.0.0` avec Vite 7.1.5, qui a des CVE de lecture de fichiers arbitraires (`server.fs.deny` contournable, WebSocket). L'endpoint open-in-editor est aussi déclenchable depuis le LAN ou par un GET cross-site (nuisance, pas d'exécution de commande). **Montée de version de vite/vitest recommandée.** Les autres vulnérabilités `yarn audit` (tailwind 3, postcss, nanoid…) ne touchent que la toolchain.
|
|
97
|
-
- **M4. Doc : le service worker du mock API ne s'enregistre jamais.** ✅
|
|
98
|
-
- **Où :** `scripts/docs-mock-api-vite-plugin.ts:62`.
|
|
99
|
-
- **Problème :** `startsWith("/docs-mock-api")` capture aussi `/docs-mock-api-sw.js` et renvoie un 404 JSON. Erreur visible dans la console sur toutes les pages de la doc.
|
|
100
|
-
- **Correctif :** tester `"/docs-mock-api/"` (avec le slash final).
|
|
101
|
-
|
|
102
|
-
### Accessibilité
|
|
103
|
-
- **M5. Modale.**
|
|
104
|
-
- **Pas vraiment modale :** `show()` est utilisé au lieu de `showModal()`. Pas de focus trap, pas d'`aria-labelledby`, focus non restauré à la fermeture.
|
|
105
|
-
- **Échap perdu :** la touche Échap ne marche plus après un ré-attachement (listener ajouté dans `firstUpdated`, retiré au disconnect).
|
|
106
|
-
- **M6. Composants sans sémantique ARIA :**
|
|
107
|
-
- `table` : pas de rôles table/row/cell ;
|
|
108
|
-
- `tooltip` : pas de `role="tooltip"` ni d'`aria-describedby` ;
|
|
109
|
-
- `pop`/`menu` : pas d'`aria-expanded`/`haspopup` ;
|
|
110
|
-
- `input-autocomplete` : pas de rôles combobox/listbox.
|
|
111
|
-
|
|
112
|
-
### Bugs
|
|
113
|
-
- **M7. Bugs de logique :**
|
|
114
|
-
- `propertyMap` écrase la clé partagée de la boucle (`PublisherProxy.ts:195`) ;
|
|
115
|
-
- `PublisherManager.getInstance(id)` lève toujours une exception (code mort) ;
|
|
116
|
-
- courses sur `lastResult` partagé (`api.ts:460,503,544`, `Fetcher.ts:204`) ;
|
|
117
|
-
- `@handle` multi-clés appelé N fois avec des valeurs périmées (`onAssign.ts:446`) ;
|
|
118
|
-
- `button.ts:657` : `target=_blank` sans `rel=noopener` ;
|
|
119
|
-
- SDUI ajoute un message-subscriber en double à chaque mise à jour (`sdui.ts:227`).
|
|
120
|
-
- **M8. Gestion d'erreurs :**
|
|
121
|
-
- aucun `AbortController` ;
|
|
122
|
-
- `res.ok` n'est jamais vérifié (un 4xx/5xx est publié comme une donnée) ;
|
|
123
|
-
- `auth()` n'a pas de `try` ;
|
|
124
|
-
- une erreur transitoire arrête le polling de `@get` ;
|
|
125
|
-
- `catch {}` silencieux dans `Fetcher.ts:202`.
|
|
126
|
-
- **M9. Fuites de listeners et d'observers :**
|
|
127
|
-
- `FormElement` : `keydown` ajouté à chaque connexion ;
|
|
128
|
-
- `Subscriber` : IntersectionObserver de lazyRendering et listeners de debug jamais retirés ;
|
|
129
|
-
- `fetchersInError` et `PublisherProxy.instances` jamais purgés ;
|
|
130
|
-
- `SafariScrollGuard` observe sans jamais arrêter et annule tout saut vers le haut de 200 px ou plus (Début, `#top`).
|
|
131
|
-
|
|
132
|
-
## 🟢 Basse / dette
|
|
133
|
-
|
|
134
|
-
### Paquet npm (12 Mo décompressés, 480 fichiers)
|
|
135
|
-
- **Contenu en double ou inutile :** `public/` + `dist/` (img 2 Mo et fonts 1,3 Mo, chacun en double), bundles à la racine **et** dans `dist/`, `.tmp-cem/`, `src/docs`, specs, service worker de la doc.
|
|
136
|
-
- **Cause :** pas de champ `files`, et `.npmignore` remplace `.gitignore`.
|
|
137
|
-
- **Correctif :** ajouter `"files"`.
|
|
138
|
-
|
|
139
|
-
### Génération et fichiers générés
|
|
140
|
-
- **`src/tsconfig.json` :** 433 chemins absolus `/sites/concorde/…` (chemin du conteneur), générés et commités. Ils sont faux sur l'hôte, publiés sur npm et produisent un diff à chaque build. Il faut des chemins relatifs.
|
|
141
|
-
- **Artefacts commités :** `public/docs-mock-api-sw.js(.map)`, `src/tsconfig.tsbuildinfo`, `src/tag-list.json`.
|
|
142
|
-
- **Couplage au build :** `vite.config.mts` écrit `build-infos.json` à chaque chargement de config (y compris pour les tests).
|
|
143
|
-
|
|
144
|
-
### Outillage et CI
|
|
145
|
-
- **Lint :** ni lint ni formatage automatique. `PublisherProxy.ts` est entièrement sous `eslint-disable` (66 `any`).
|
|
146
|
-
- **CI :** la CI ne lance ni `tsc` ni `yarn build`. Les régressions de build ou d'exports passent donc inaperçues (cf. H12).
|
|
147
|
-
- **Dépendances en retard :** vite 7.1→7.3 (correctifs sécurité), vitest 3.2.4→3.2.7, `baseline-browser-mapping` (avertissement à chaque lancement), `@lit-labs/*` (mineures).
|
|
148
|
-
|
|
149
|
-
### Divers
|
|
150
|
-
- `api.ts:603` : la regex `[^(https?:)]` est une classe de caractères.
|
|
151
|
-
- `localGet` : comparaisons `===` nombre/chaîne.
|
|
152
|
-
- `derive.ts:103` : détection de cycles indexée par la racine.
|
|
153
|
-
- `HTML.ts:278` : `onerror` résout à `true`.
|
|
154
|
-
|
|
155
|
-
### Doc (port 3010)
|
|
156
|
-
- **Certificat :** le certificat `basicSsl` est refusé par le navigateur. Pour l'audit, la doc a été servie en HTTP via une config temporaire.
|
|
157
|
-
- **Avertissements console :** « Erreur lors de la récupération des variables CSS » (`theme.ts:157`) et Lit en mode dev.
|
|
158
|
-
- **Mise en page :** débordement horizontal en largeur étroite sur la page Modal (blocs de code).
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
## Revue du code des composants UI (`src/core/components/ui`)
|
|
163
|
-
|
|
164
|
-
Environ 9 600 lignes, 47 fichiers de styles, 74 custom elements au total.
|
|
165
|
-
|
|
166
|
-
### Ce qui est bien
|
|
167
|
-
- **Thème par variables CSS cohérent :** préfixe `--sc-*`, fallbacks systématiques, `--sc-btn-*` surchargeable. `type` / `variant` / `size` / `shape` sont alignés entre button, badge, alert et le reste. Le rendu dans la doc est propre et homogène.
|
|
168
|
-
- **Briques partagées :** `fontSize`, `formControl`, `label`, `description`.
|
|
169
|
-
- **i18n des libellés ARIA :** `_i18n/ui-aria-labels.ts`, 6 langues.
|
|
170
|
-
- **Pop moderne :** `pop` utilise l'API Popover (avec fallback) et un positionnement maison robuste aux ancêtres transformés. `toast-item` gère `role` / `aria-live`.
|
|
171
|
-
- **Composition par mixins :** `FormElement`, `FormInput`, `FormCheckable`. Brancher un champ sur un `formDataProvider` est trivial.
|
|
172
|
-
|
|
173
|
-
### Ce qui coince
|
|
174
|
-
1. **API trop large et logique dupliquée**
|
|
175
|
-
- `sonic-button` cumule bouton, lien, toggle (`FormCheckable`), champ de formulaire (`FormElement`), navigation (`pushState`, `goBack`, `autoActive`), reset de formulaire, auto-repeat et loader. Il expose aussi la mise en page flex en props (`direction`, `alignItems`, `justify`, `minWidth`, injectées en style inline).
|
|
176
|
-
- `label` / `description` / `hasSlotOrProps` sont réimplémentés dans 6 composants, et `select.ts:178` le note lui-même en TODO. `select` redéfinit `label` / `description` avec une logique `forceAutoFill` propre à lui.
|
|
177
|
-
- **Piste :** un contrôleur Lit (`FormFieldController`) ou un composant `sonic-field` partagé.
|
|
178
|
-
2. **Pas d'intégration aux formulaires natifs**
|
|
179
|
-
- Aucun composant n'utilise `ElementInternals` / `formAssociated` (`button.ts:531` le mentionne en TODO).
|
|
180
|
-
- Vérifié dans le navigateur : dans un `<form>`, `new FormData(form)` est vide et `sonic-button` ne déclenche pas `submit`.
|
|
181
|
-
- Tout passe par les data providers. C'est un choix, mais il ferme la porte aux formulaires classiques, à l'autofill navigateur et à `:invalid`.
|
|
182
|
-
3. **Accessibilité structurelle**
|
|
183
|
-
- **Lien-bouton :** `sonic-button` avec `href` rend un `<button>` dans un `<a>` (HTML invalide, **2 arrêts de tabulation** : vérifié, tabIndex 0 sur les deux).
|
|
184
|
-
- **Description non reliée :** `description` n'est pas reliée au champ (`aria-describedby` absent partout), et `error` ne pose pas `aria-invalid`.
|
|
185
|
-
- **Attribut `data-aria-label` :** c'est un contournement pour passer `aria-label`.
|
|
186
|
-
- **Disabled :** opacité 0.3 avec `pointer-events: none`.
|
|
187
|
-
- **Modale :** voir M5. **Table, menu, pop, autocomplete :** voir M6.
|
|
188
|
-
4. **Contrastes insuffisants (thème clair de la doc, ratios mesurés)**
|
|
189
|
-
|
|
190
|
-
| Bouton | Ratio | Constat |
|
|
191
|
-
|---|---|---|
|
|
192
|
-
| `success` | 2.5:1 | sous AA |
|
|
193
|
-
| `info` | 3.6:1 | sous AA |
|
|
194
|
-
| `warning outline` | 2.2:1 | sous AA |
|
|
195
|
-
| `danger` | 4.8:1 | limite |
|
|
196
|
-
|
|
197
|
-
Le hover (`brightness(0.98)`) est presque invisible.
|
|
198
|
-
5. **`<select>`**
|
|
199
|
-
- **Options lues une seule fois :** les `<option>` du light DOM sont lues une fois dans `connectedCallback`. Pas de `MutationObserver`, donc les options ajoutées ensuite sont ignorées.
|
|
200
|
-
- **`<slot>` dans `<select>` :** le parseur HTML ne l'autorise pas.
|
|
201
|
-
- **Sélection multiple :** `multiple` n'a qu'une `value` de type string.
|
|
202
|
-
6. **Petits défauts récurrents**
|
|
203
|
-
- **`!important` :** 22 fichiers en utilisent.
|
|
204
|
-
- **Code commenté :** blocs entiers, comme `input.ts:179-203`.
|
|
205
|
-
- **Doublons :** `part="input"` en double (`input.ts:232,234`), `connectedCallback` vide (`button.ts:596`).
|
|
206
|
-
- **Mélange de langues :** commentaires FR/EN, doc FR, libellés EN.
|
|
207
|
-
7. **Tests UI quasi absents**
|
|
208
|
-
- Un seul spec sur ~45 composants UI (`alert.spec.ts`). Les 31 fichiers de tests couvrent surtout le cœur, SDUI et les décorateurs.
|
|
209
|
-
- Rien ne protège le rendu, le clavier ou l'ARIA des composants.
|
|
210
|
-
- **Piste :** `@web/test-runner` ou vitest browser mode, avec `axe-core`.
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
## Plan d'action proposé
|
|
215
|
-
|
|
216
|
-
1. **Sécurité (rapide) :**
|
|
217
|
-
- C1 : origine postMessage + texte brut ;
|
|
218
|
-
- H4 : altcha local versionné ;
|
|
219
|
-
- M1 : Authorization limité à l'origine ;
|
|
220
|
-
- M3 : monter vite/vitest, `--host` en option.
|
|
221
|
-
2. **Bugs bloquants :** C2 (relance 498), C3 (`hasOwn`), H10 (`delete`), H7/H8 (timers), H9 (`finally`), M4 (une ligne).
|
|
222
|
-
3. **Défaut XSS :** H1/H2/H3, soit texte par défaut et HTML en opt-in, soit DOMPurify. C'est un changement cassant, à prévoir pour une version majeure (6.0), avec une note de migration.
|
|
223
|
-
4. **Packaging :**
|
|
224
|
-
- corriger pre-build (`undefined`, chemins relatifs) ;
|
|
225
|
-
- `files` + `peerDependencies.lit` ;
|
|
226
|
-
- supprimer l'export rollup ;
|
|
227
|
-
- ajouter `tsc` + `build` à la CI.
|
|
228
|
-
5. **Dette :** ESLint (règles `no-explicit-any` en warn, `lit-a11y`), ARIA des composants interactifs, purge des fuites listées en M9.
|
package/PLAN-AMELIORATION.md
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
# Plan d'amélioration — composants UI Concorde
|
|
2
|
-
|
|
3
|
-
Base : lecture intégrale de `src/core/components/ui` (~9 600 lignes, 45 composants) et des mixins `FormElement`, `FormInput`, `FormCheckable`, `TemplatesContainer`, plus des vérifications dans la doc lancée en local. Les constats sécurité et couche données sont dans [AUDIT.md](AUDIT.md) ; ce plan les reprend seulement là où ils touchent l'UI.
|
|
4
|
-
|
|
5
|
-
Légende :
|
|
6
|
-
- **Taille :** S < ½ j, M ≈ 1–3 j, L ≈ 1 semaine+
|
|
7
|
-
- **🔁 :** changement cassant, réservé à la 6.0
|
|
8
|
-
- **✅ :** constat vérifié dans le navigateur
|
|
9
|
-
|
|
10
|
-
## Diagnostic en une page
|
|
11
|
-
|
|
12
|
-
**Ce qui marche et qu'il faut garder**
|
|
13
|
-
- Les tokens `--sc-*` avec fallback.
|
|
14
|
-
- Le vocabulaire commun `type` / `variant` / `size` / `shape` / `status`.
|
|
15
|
-
- La mécanique Popover API et le positionnement de `pop` et `tooltip`.
|
|
16
|
-
- `toast-item` : pause au survol et au focus, rôles ARIA.
|
|
17
|
-
- `alert` et `loader` : `announce` opt-in, texte rendu en texte. **Ce sont les composants modèles :** les plus récents sont les plus propres, et ce plan consiste en grande partie à aligner les anciens sur eux.
|
|
18
|
-
|
|
19
|
-
**Les problèmes de fond**
|
|
20
|
-
1. **Pas de socle « champ de formulaire ».**
|
|
21
|
-
- Label, description, détection de slots et validation sont recopiés dans `input`, `select`, `textarea`, `checkbox`, `group` et `legend`. Chaque copie a ses variantes, par exemple `forceAutoFill` redéfini dans `select`.
|
|
22
|
-
- Le pattern `forceAutoFill` (l'attribut l'emporte sur la propriété) est surprenant : `el.label = "x"` est ignoré si l'attribut `label` existe.
|
|
23
|
-
2. **Pas d'intégration aux formulaires natifs.** ✅ Il n'y a aucun `ElementInternals` : `FormData` reste vide et `sonic-button` ne soumet pas un `<form>`.
|
|
24
|
-
3. **Sémantique ARIA absente pour les composants composites.**
|
|
25
|
-
- **Bouton-lien :** `<button>` dans `<a>`, donc 2 arrêts de tabulation. ✅
|
|
26
|
-
- **Radio :** un arrêt de tabulation par radio, pas de navigation aux flèches, pas de `radiogroup`. ✅
|
|
27
|
-
- **Switch :** pas de `role="switch"`. ✅
|
|
28
|
-
- **Tooltip :** pas de `aria-describedby`. ✅
|
|
29
|
-
- **Autres :** menu, table, pop et autocomplete sans rôles ; la modale ouvre en non modal.
|
|
30
|
-
4. **HTML injecté par défaut.** 37 `unsafeHTML` : labels, descriptions, toasts, modale, divider, card-header, legend.
|
|
31
|
-
5. **Les composants modifient le DOM de l'auteur.**
|
|
32
|
-
- `menu` écrit `size`, `align` et `shape` sur ses enfants.
|
|
33
|
-
- `group` écrit des variables d'arrondi sur ses enfants.
|
|
34
|
-
- `menu-item` force `variant` et `shape` au connect.
|
|
35
|
-
- Effets de bord à l'import : `_css/scroll.ts` installe `SafariScrollGuard` globalement, `toast.ts` installe un listener `message`.
|
|
36
|
-
6. **Couplage fort à la couche données.**
|
|
37
|
-
- `Subscriber` est utilisé là où ce n'est pas nécessaire (`fieldset`, `modal`, `table-tr`, les helpers).
|
|
38
|
-
- Les comportements passent par des chemins magiques (`formDataProvider + "/" + name + "/_available_values_"`).
|
|
39
|
-
- Des `setTimeout(…, 1)` servent à ordonner les mises à jour (`FormCheckable`).
|
|
40
|
-
7. **Quasi aucun test UI.** Un seul spec (`alert`) sur 45 composants.
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## Phase 0 — Garde-fous (avant de toucher au code)
|
|
45
|
-
|
|
46
|
-
Objectif : pouvoir refactorer sans régression. **Rien d'autre ne commence avant.**
|
|
47
|
-
|
|
48
|
-
| # | Action | Taille |
|
|
49
|
-
|---|---|---|
|
|
50
|
-
| 0.1 | **Tests en vrai navigateur :** vitest browser mode avec Playwright (Chromium, plus Firefox et WebKit en CI). jsdom ne gère ni Popover, ni `<dialog>`, ni le layout. | M |
|
|
51
|
-
| 0.2 | **Tests de caractérisation** des comportements actuels, sur les 12 composants les plus utilisés : button, input, select, checkbox, radio, switch, textarea, modal, pop, menu, toast, tooltip. Rendu, événements `change`, synchronisation avec le `formDataProvider`. Ils figent l'existant et servent de filet. | L |
|
|
52
|
-
| 0.3 | **`axe-core`** dans les tests, sur chaque page de démo. Rapport d'abord ; le build devient bloquant en phase 3. | S |
|
|
53
|
-
| 0.4 | **ESLint :** `typescript-eslint`, `eslint-plugin-lit`, `eslint-plugin-lit-a11y`, `eslint-plugin-wc`, plus Prettier. Démarrer en `warn`, puis passer règle par règle en `error`. | S |
|
|
54
|
-
| 0.5 | **CI :** ajouter `tsc`, `yarn build`, lint et tests navigateur au job GitLab. Aujourd'hui seul vitest jsdom tourne. | S |
|
|
55
|
-
| 0.6 | **Monter vite et vitest** (CVE du serveur de dev, cf. AUDIT M3). | S |
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## Phase 1 — Correctifs rapides, sans casse (5.1.x)
|
|
60
|
-
|
|
61
|
-
Corrections ciblées, une PR chacune, avec un test qui reproduit le bug.
|
|
62
|
-
|
|
63
|
-
| # | Composant | Problème → correctif | Taille |
|
|
64
|
-
|---|---|---|---|
|
|
65
|
-
| 1.1 | `textarea` | `${this.value}` dans `<textarea>` provoque une erreur Lit en dev ✅ (« Expressions are not supported inside textarea »). Garder seulement `.value`. Corriger aussi `placeholder` toujours posé (`""`) avec `ifDefined`. | S |
|
|
66
|
-
| 1.2 | `checkbox` | `</label>` fermé deux fois dans le template. `"indeterminate"` n'est pas transmis à `input.indeterminate`, donc les lecteurs d'écran ne voient pas l'état mixte : ajouter `.indeterminate=${…}`. | S |
|
|
67
|
-
| 1.3 | `input` | `part="input"` en double ; bloc commenté (l.179-203) à supprimer. | S |
|
|
68
|
-
| 1.4 | `password-helper` | `v.length > minChars` doit devenir `>=` (« 8 caractères » refuse 8 caractères). La liste doit être annoncée (`aria-live="polite"`). | S |
|
|
69
|
-
| 1.5 | `image` | Le `onload` n'est branché qu'en `firstUpdated`. Une image déjà en cache ne reçoit jamais `.loaded` et reste invisible avec `transition`. Tester aussi `img.complete`. | S |
|
|
70
|
-
| 1.6 | `modal` | `effect="fade"` est déclaré mais pas implémenté (seul `slide` est animé). Le listener `Escape` est perdu après un ré-attachement : le déplacer dans `connectedCallback`. `show()` est `private` alors que la doc dit de l'appeler : le rendre public. `Modal.modals.splice(indexOf(this))` retire le dernier élément si l'index vaut -1 : ajouter une garde. | S |
|
|
71
|
-
| 1.7 | `modal-actions` | `hideModal` n'est branché que sur les boutons présents au premier rendu. Le remplacer par un listener délégué `click` sur le slot. | S |
|
|
72
|
-
| 1.8 | `button` | Ajouter `rel="noopener noreferrer"` si `target=_blank` (comme `link`). Supprimer le `connectedCallback` vide. | S |
|
|
73
|
-
| 1.9 | `menu` | Le bouton « plus » n'a que l'icône, sans libellé : ajouter `aria-label` via `uiAriaLabels`. | S |
|
|
74
|
-
| 1.10 | `toast` | Ne plus faire d'effet de bord dans `render()` (`handleExistingToastDelegation`). Créer la zone live au premier `add` et non au premier toast : une région `aria-live` doit exister **avant** son contenu pour être annoncée. | S |
|
|
75
|
-
| 1.11 | `FormElement` | Le listener `keydown` de navigation clavier est ajouté à chaque connexion : le stocker et le retirer. Nettoyer `keyboardLoops` au disconnect. | S |
|
|
76
|
-
| 1.12 | `select` | Retirer le `<slot>` placé dans `<select>` (interdit par le parseur HTML). Observer les `<option>` du light DOM (`MutationObserver`) au lieu de les lire une seule fois au connect. | M |
|
|
77
|
-
| 1.13 | `same-value-helper` / `password-helper` | Libellés FR codés en dur : passer par `_i18n`. Les deux classes s'appellent `SonicComponent` : les renommer. | S |
|
|
78
|
-
| 1.14 | Sécurité UI | Vérification d'origine du postMessage du toast (AUDIT C1). Altcha en local et versionné (AUDIT H4). | S |
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
## Phase 2 — Socle des champs de formulaire (5.2, compatible)
|
|
83
|
-
|
|
84
|
-
C'est le chantier qui rapporte le plus : il supprime la duplication et règle d'un coup l'ARIA des formulaires.
|
|
85
|
-
|
|
86
|
-
### 2.1 `FormFieldController` (contrôleur Lit) — L
|
|
87
|
-
Il remplace les 6 copies de `label` / `description` / `hasSlotOrProps`. Il fournit :
|
|
88
|
-
- les ids stables `labelId`, `descriptionId`, `errorId` (compteur global) ;
|
|
89
|
-
- la détection des slots `label`, `description`, `prefix`, `suffix` par `slotchange` uniquement, plus de recalcul à chaque `willUpdate` ;
|
|
90
|
-
- les attributs ARIA à poser sur le contrôle interne : `aria-labelledby`, `aria-describedby` (description et erreur), `aria-invalid` (depuis `error` ou `status="error"`), `aria-required` ;
|
|
91
|
-
- le rendu partagé du label, de la description et du message d'erreur, avec les styles `label` / `description` existants.
|
|
92
|
-
|
|
93
|
-
Migration composant par composant : `input`, puis `textarea`, `select`, `checkbox` / `radio` / `switch`, `group`, `input-autocomplete`. Les tests de caractérisation de la phase 0 garantissent un rendu identique.
|
|
94
|
-
|
|
95
|
-
### 2.2 Intégration native avec `ElementInternals` — L
|
|
96
|
-
- **Activation :** `static formAssociated = true` dans `FormElement`.
|
|
97
|
-
- **Valeur :** `setFormValue()` à chaque changement de valeur. `FormData` et la soumission native fonctionnent alors, et le data provider continue d'être alimenté en parallèle.
|
|
98
|
-
- **Validation :** `setValidity()` alimenté par la validité du contrôle interne, ce qui active `:invalid` / `:user-invalid` sur l'hôte.
|
|
99
|
-
- **Cycle de vie :** `formResetCallback` et `formDisabledCallback`. Ce dernier règle le fait que `<sonic-fieldset disabled>` ne désactive pas les champs slottés, puisque leurs inputs sont dans un autre shadow root.
|
|
100
|
-
- **Sémantique :** `sonic-button[type=submit|reset]` passe par `internals.form.requestSubmit()` / `reset()`, et `internals.role` / `ariaLabel` au lieu des attributs `data-aria-*`.
|
|
101
|
-
- **Compatibilité :** garder `data-aria-label` comme alias déprécié.
|
|
102
|
-
|
|
103
|
-
### 2.3 Assainir `FormCheckable` — M
|
|
104
|
-
- **Ordonnancement :** remplacer les `setTimeout(…, 1)` par un ordonnancement explicite (`updateComplete` ou microtask unique).
|
|
105
|
-
- **« Tout cocher » :** isoler la logique (`_available_values_`) dans un contrôleur `CheckAllController` lisible et testé.
|
|
106
|
-
- **`checked` :** le typer en `boolean` plus `indeterminate: boolean` séparé (alias de l'ancien tri-état conservé en 5.x).
|
|
107
|
-
|
|
108
|
-
### 2.4 Radio et switch accessibles — M
|
|
109
|
-
- **`sonic-radio-group`** (nouveau, optionnel) : `role="radiogroup"`, roving tabindex, flèches haut/bas/gauche/droite, `aria-labelledby` vers sa légende. Les radios hors groupe continuent de fonctionner comme aujourd'hui.
|
|
110
|
-
- **`sonic-switch`** : `role="switch"` sur l'input.
|
|
111
|
-
|
|
112
|
-
### 2.5 `fieldset` / `legend` — S
|
|
113
|
-
- **Problème :** le `<legend>` est dans le shadow root de `sonic-legend`, pas enfant du `<fieldset>`, donc le groupe n'a pas de nom accessible.
|
|
114
|
-
- **Correctif :** rendre `<legend>` directement dans `sonic-fieldset`, ou poser `role="group"` et `aria-labelledby`.
|
|
115
|
-
- **Nettoyage :** retirer `Subscriber` de `fieldset` (inutile).
|
|
116
|
-
|
|
117
|
-
---
|
|
118
|
-
|
|
119
|
-
## Phase 3 — Accessibilité des composants composites (5.3)
|
|
120
|
-
|
|
121
|
-
Critère de sortie : **axe-core sans violation** sur toutes les démos, plus une checklist clavier par composant, documentée dans chaque `.md`.
|
|
122
|
-
|
|
123
|
-
| # | Composant | Travail | Taille |
|
|
124
|
-
|---|---|---|---|
|
|
125
|
-
| 3.1 | `button` (lien) | Avec `href`, rendre **un seul** `<a>` stylé comme bouton, sans `<button>` imbriqué. Ajouter `aria-current="page"` quand `active` vient de `autoActive` ; même chose dans `link`. ✅ | M |
|
|
126
|
-
| 3.2 | `button` (toggle) | Exposer `aria-pressed` quand le bouton est utilisé comme toggle (`name` / `FormCheckable`). | S |
|
|
127
|
-
| 3.3 | `modal` | `showModal()` au lieu de `show()` : focus trap natif, `inert` automatique, `::backdrop`. Il faut adapter le backdrop maison et les z-index (top layer). Ajouter `aria-labelledby` vers `sonic-modal-title` et rendre le focus au déclencheur à la fermeture. | M |
|
|
128
|
-
| 3.4 | `pop` | Sur le déclencheur : `aria-expanded`, `aria-haspopup`, `aria-controls`. Focus dans le contenu à l'ouverture si celle-ci vient du clavier. | M |
|
|
129
|
-
| 3.5 | `menu` / `menu-item` | Deux modes explicites : navigation (`<nav>` + liste, pas de rôle menu) ou menu d'actions (`role="menu"` / `menuitem`, roving tabindex, flèches, Home/End, saisie rapide). Aujourd'hui le composant ne choisit pas. | L |
|
|
130
|
-
| 3.6 | `input-autocomplete` | Pattern combobox ARIA 1.2 : `role="combobox"`, `aria-expanded`, `aria-controls` → `listbox`, `aria-activedescendant` (le focus reste dans l'input au lieu de passer sur les items), et un `aria-live` « N résultats ». | L |
|
|
131
|
-
| 3.7 | `tooltip` | `role="tooltip"` et `aria-describedby` sur le déclencheur. Fermeture par Escape (WCAG 1.4.13), et le tooltip ne doit pas disparaître quand on survole la bulle. | M |
|
|
132
|
-
| 3.8 | `table` | Rôles `table` / `rowgroup` / `row` / `columnheader` / `cell` posés sur les hôtes via `ElementInternals.role`, et `sonic-caption` relié. | M |
|
|
133
|
-
| 3.9 | `group` | `role="group"` avec `aria-labelledby` vers le label. | S |
|
|
134
|
-
| 3.10 | `progress` | Libellé accessible (`aria-label` / `aria-labelledby` vers le slot). | S |
|
|
135
|
-
| 3.11 | Global | Ajouter `prefers-reduced-motion` aux animations de modal, pop, toast, button loader, switch et checkbox (aujourd'hui seul `tooltip` en tient compte). | S |
|
|
136
|
-
| 3.12 | Global | Un **token de focus** (`--sc-focus-ring`) appliqué partout. Aujourd'hui seuls 4 composants ont un `:focus-visible`, et les styles diffèrent (box-shadow `base-300` sur le bouton, `primary` sur la checkbox). | S |
|
|
137
|
-
| 3.13 | Global | Remplacer l'état désactivé à `opacity: 0.3` + `pointer-events: none` par des couleurs dédiées (`--sc-disabled-*`), lisibles. | S |
|
|
138
|
-
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
## Phase 4 — Thème et tokens (5.3 / 5.4)
|
|
142
|
-
|
|
143
|
-
| # | Action | Taille |
|
|
144
|
-
|---|---|---|
|
|
145
|
-
| 4.1 | **Contrastes AA.** Mesuré : `success` 2.5:1, `info` 3.6:1, `warning` outline 2.2:1. Recalculer les couleurs sémantiques des thèmes light et dark pour atteindre 4.5:1 (texte) et 3:1 (bordures, focus). Ajouter un test automatique de contraste sur les paires token / contenu. | M |
|
|
146
|
-
| 4.2 | **Tokens hors `sonic-theme`.** Les tokens ne sont définis que sur `:host` de `sonic-theme` ; un composant en dehors n'a que des fallbacks codés en dur (`#000`, `rgba(0,0,0,.07)`). Fournir aussi une feuille `:root` (`concorde/theme.css`) et réduire les fallbacks en cascade à un seul niveau. | M |
|
|
147
|
-
| 4.3 | **Documenter l'API de tokens.** Lister les variables publiques (`--sc-btn-*`, `--sc-input-*`…) et les distinguer des privées (`--sc-_*`), puis générer la liste dans le Custom Elements Manifest (`@cssprop`). | M |
|
|
148
|
-
| 4.4 | **`Theme.getCssVariables()`.** La fonction parcourt toutes les feuilles du document, ce qui déclenche une erreur sur les feuilles cross-origin (warning visible dans la doc), puis envoie le résultat à **toutes** les iframes avec `"*"`. Il faut limiter à une liste de tokens connue, ne poster qu'aux iframes qui le demandent, avec une origine vérifiée. | S |
|
|
149
|
-
| 4.5 | **Hover visible.** `brightness(0.98)` est imperceptible : passer à `color-mix()` sur `--btn-bg`. | S |
|
|
150
|
-
| 4.6 | **Moins de `!important`** (22 fichiers). Remplacer par des sélecteurs plus spécifiques ou par `@layer`. | M |
|
|
151
|
-
|
|
152
|
-
---
|
|
153
|
-
|
|
154
|
-
## Phase 5 — Effets de bord, couplage, performances (5.4)
|
|
155
|
-
|
|
156
|
-
| # | Action | Taille |
|
|
157
|
-
|---|---|---|
|
|
158
|
-
| 5.1 | **Plus d'effets à l'import.** `_css/scroll.ts` appelle `installSafariScrollGuard()` au chargement du module : importer une feuille CSS active un correctif global qui annule les sauts de scroll ≥ 200 px. Il faut un opt-in explicite (`<sonic-theme safari-scroll-guard>` ou import dédié). Même principe pour le listener `message` de `toast`. | S |
|
|
159
|
-
| 5.2 | **Ne plus écrire chez les enfants.** `menu` (size, align, shape, margin), `group` (arrondis) et `menu-item` (variant, shape) modifient le DOM de l'auteur. Passer par l'héritage de variables CSS ou du contexte Lit (`@lit/context`) : par exemple `menu` fournit `size` et `align`, que les items consomment. | M |
|
|
160
|
-
| 5.3 | **Retirer `Subscriber` là où il ne sert pas** : `fieldset`, `modal`, `table-tr`, `password-helper`, `same-value-helper`. Ces composants paient le coût du mixin (observers, lazy rendering) pour rien. | S |
|
|
161
|
-
| 5.4 | **Positionnement sans rAF permanent.** `pop` et `tooltip` recalculent la position à chaque frame tant qu'ils sont ouverts (`getBoundingClientRect` → layout). Passer à CSS Anchor Positioning là où c'est supporté, et sinon à des recalculs sur scroll, resize et `ResizeObserver` uniquement. | M |
|
|
162
|
-
| 5.5 | **Simplifier `input-autocomplete`.** Le composant crée 5 data providers internes, deux `sonic-queue` (dont une cachée pour retrouver la valeur initiale) et plusieurs contournements par `rAF` / `setTimeout`. Le réécrire sur le socle combobox de la phase 3.6 avec un seul store interne. | L |
|
|
163
|
-
| 5.6 | **Icônes.** Les bibliothèques externes sont chargées depuis 4 CDN au runtime (CSP, vie privée, hors ligne) puis injectées en `unsafeHTML`. Permettre l'enregistrement local d'un sprite ou d'un dictionnaire d'icônes, et sanitiser le SVG (pas de `<script>`, pas d'`on*`). Le CDN reste en option. | M |
|
|
164
|
-
| 5.7 | **Ne plus forcer `aria-hidden` sur les icônes.** `sonic-icon` le pose toujours. Ajouter une prop `label` qui le retire et pose `role="img"` + `aria-label`. | S |
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## Phase 6 — API publique 6.0 (🔁 changements cassants)
|
|
169
|
-
|
|
170
|
-
À regrouper dans une seule version majeure, avec un guide de migration et des avertissements de dépréciation dès la 5.x.
|
|
171
|
-
|
|
172
|
-
| # | Changement | Pourquoi |
|
|
173
|
-
|---|---|---|
|
|
174
|
-
| 6.1 | **Texte par défaut au lieu de `unsafeHTML`** pour `label`, `description`, toast `text`, options de modale, divider, card-header, legend. HTML seulement via `TemplateResult` ou une prop explicite (`labelHtml`), éventuellement assaini (DOMPurify). | XSS (AUDIT H2/H3) ; c'est déjà le comportement d'`alert` |
|
|
175
|
-
| 6.2 | **Découper `sonic-button`.** Garder bouton / lien / toggle. Sortir la navigation (`pushState`, `goBack`, `autoActive`) dans un contrôleur partagé avec `link`. Sortir `reset` (remplacé par `type="reset"` natif grâce à 2.2) et `autoRepeat` (contrôleur opt-in). | 675 lignes, trop de responsabilités |
|
|
176
|
-
| 6.3 | **Retirer les props de mise en page** (`direction`, `alignItems`, `justify`, `minWidth`) de button et form-actions, remplacées par `::part()` et des variables CSS. Les styles inline empêchent la surcharge depuis l'extérieur. | API plus petite, thémable |
|
|
177
|
-
| 6.4 | **Retirer `forceAutoFill`.** L'attribut ne doit plus l'emporter sur la propriété. | Comportement surprenant, recopié 5 fois |
|
|
178
|
-
| 6.5 | **`checked` en `boolean`** (et `indeterminate` séparé), `data-aria-*` remplacés par les attributs ARIA standards. | Conformité aux attentes HTML |
|
|
179
|
-
| 6.6 | **Événements cohérents.** `input` à chaque frappe, `change` à la validation, comme en natif. Aujourd'hui `handleChange` émet un `change` à chaque frappe, et l'événement n'est ni `bubbles` ni `composed`. Ajouter des événements typés (`sonic-change` avec `detail`). | Interop avec les frameworks |
|
|
180
|
-
| 6.7 | **Supprimer les alias dépréciés** : `Toast.title`, placement de pop avec espace, `data-aria-label`. | Nettoyage |
|
|
181
|
-
|
|
182
|
-
---
|
|
183
|
-
|
|
184
|
-
## Phase 7 — Documentation et outillage développeur (en continu)
|
|
185
|
-
|
|
186
|
-
| # | Action | Taille |
|
|
187
|
-
|---|---|---|
|
|
188
|
-
| 7.1 | **JSDoc complète** sur les props, slots, events, `cssprop` et `csspart` : 66 composants sont signalés « annotations insuffisantes » par le générateur du catalogue SDUI. Les rendre obligatoires via une règle de lint sur le CEM. | M |
|
|
189
|
-
| 7.2 | **Table d'API générée** depuis le CEM dans chaque page `.md` (props, events, slots, parts, tokens) au lieu de la maintenir à la main. | M |
|
|
190
|
-
| 7.3 | **Section accessibilité par composant** : interactions clavier, rôles, ce que l'intégrateur doit fournir (ex. `aria-label` pour un bouton icône). | M |
|
|
191
|
-
| 7.4 | **Une seule langue** pour les commentaires et la doc (aujourd'hui mélange FR/EN). Les libellés par défaut passent tous par `_i18n`. | S |
|
|
192
|
-
| 7.5 | **Doc :** corriger le service worker du mock API (AUDIT M4) et le débordement horizontal des blocs de code en mobile. | S |
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
## Séquencement proposé
|
|
197
|
-
|
|
198
|
-
```
|
|
199
|
-
Sprint 1 Phase 0 (garde-fous) + Phase 1 (correctifs rapides) → 5.1.x
|
|
200
|
-
Sprint 2 2.1 FormFieldController + migration input/textarea/select → 5.2
|
|
201
|
-
Sprint 3 2.2 ElementInternals + 2.3 FormCheckable + 2.4/2.5 → 5.2
|
|
202
|
-
Sprint 4 Phase 3 : button-lien, modal, pop, tooltip, focus, motion → 5.3
|
|
203
|
-
Sprint 5 Phase 3 : menu, combobox/autocomplete, table + Phase 4 → 5.3/5.4
|
|
204
|
-
Sprint 6 Phase 5 (effets de bord, couplage, perfs) → 5.4
|
|
205
|
-
Sprint 7 Phase 6 (6.0) + guide de migration → 6.0
|
|
206
|
-
En continu : Phase 7 (doc) à chaque composant touché
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
**Pourquoi cet ordre**
|
|
210
|
-
- **Phase 0 en premier :** sans tests navigateur, les phases 2 à 6 sont risquées.
|
|
211
|
-
- **Phase 2 ensuite :** le socle formulaire conditionne l'ARIA des champs (3.x) et la sortie de `reset` / `forceAutoFill` (6.x).
|
|
212
|
-
- **Changements cassants en dernier :** ils sont regroupés en 6.0, et chacun est précédé d'un avertissement de dépréciation en 5.x.
|
|
213
|
-
|
|
214
|
-
**Définition de « terminé » pour chaque composant touché**
|
|
215
|
-
- Tests navigateur (rendu, clavier, événements, data provider).
|
|
216
|
-
- axe-core sans violation.
|
|
217
|
-
- Contraste AA.
|
|
218
|
-
- JSDoc / CEM complets, section accessibilité dans le `.md`.
|
|
219
|
-
- Aucun effet de bord à l'import.
|
|
220
|
-
- Aucun `unsafeHTML` sans opt-in explicite.
|
package/PLAN-DOCS-AGENTS.md
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
# Plan d’amélioration — doc Concorde / agents
|
|
2
|
-
|
|
3
|
-
État : pathnames = sources (`/docs/getting-started/…`) ; composants sans doublon (`/…/button` ↔ `…/button/button.md`). Pas de mapping `_` sections.
|
|
4
|
-
|
|
5
|
-
Objectif : **une URL = une page**, lisible par humains (SPA) et machines (HTML ou Markdown).
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Phase 0 — Stabiliser
|
|
10
|
-
|
|
11
|
-
- [x] Apache : `mod_rewrite`, `mod_headers`, `.htaccess` (SPA + Markdown + 404)
|
|
12
|
-
- [x] Smoke : nav, search (vide + fermeture), deep link, legacy `#…md/…`
|
|
13
|
-
- [ ] Publier `yarn build-docs` → `concorde_doc` et re-vérifier Ora / curl Accept en prod
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## Phase 1 — Décision produit — **fait : option B**
|
|
18
|
-
|
|
19
|
-
| Option | Statut |
|
|
20
|
-
|--------|--------|
|
|
21
|
-
| A. Garder `/crawl/` | écartée |
|
|
22
|
-
| **B. Fusionner** | **retenue et implémentée** |
|
|
23
|
-
| C. Markdown-first only | partiellement couverte par B (Accept markdown) |
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## Phase 2 — Même URL pour le contenu machine — **fait**
|
|
28
|
-
|
|
29
|
-
- [x] Build : HTML + MD à `docs/**` et `core/**` (plus sous `/crawl/`)
|
|
30
|
-
- [x] MD public = pathname + `.md` ; SPA `markdownsURL=""` ; Vite sert `/docs|core/**.md` depuis `src/`
|
|
31
|
-
- [x] Hubs à `/hubs/*.html`
|
|
32
|
-
- [x] Apache : Accept → `/$1.md` ; bots → `*.html` ; navigateur → SPA ; 301 `/src/(docs|core)/*.md`
|
|
33
|
-
- [x] Canonical / `llms.txt` / sitemap → pathnames `/docs/…`, `/core/…`
|
|
34
|
-
- [x] Tests `scripts/generate-crawl-docs.test.mjs`
|
|
35
|
-
|
|
36
|
-
Critère de done local :
|
|
37
|
-
`/docs/getting-started/start.md` et `Accept: text/markdown` sur le pathname → Markdown ; navigateur → SPA.
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## Phase 3 — Retirer `/crawl/` — **fait (code + artefacts locaux)**
|
|
42
|
-
|
|
43
|
-
- [x] 301 `/crawl/**` → pathnames équivalents (`.htaccess`)
|
|
44
|
-
- [x] Plus d’arbre `docs/crawl/` (`removeLegacyCrawlDir`)
|
|
45
|
-
- [x] `robots.txt`, homepage agent, `llms*` sans `/crawl/`
|
|
46
|
-
- [x] Smoke sur `concorde-docs.localhost` (MD / bot HTML / 301 crawl / SPA)
|
|
47
|
-
- [x] MD public = `….md` ; Accept → sibling ; 301 `/src/…md` ; sync `concorde_doc`
|
|
48
|
-
- [x] Pretty URLs : sans `_` sections ; composants sans `name/name` ; pas de legacy ; `DirectorySlash Off`
|
|
49
|
-
- [ ] Commit / push `concorde_doc` vers la prod (+ `yarn build-docs` pour index SPA source)
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## Phase 4 — Qualité agent / SEO
|
|
54
|
-
|
|
55
|
-
| Sujet | Statut |
|
|
56
|
-
|-------|--------|
|
|
57
|
-
| Homepage H1 + 500+ chars | fait |
|
|
58
|
-
| 404 Markdown (+ HTML) | fait |
|
|
59
|
-
| Titre d’onglet = H1 page | à faire |
|
|
60
|
-
| Brand / discoverability Ora | hors code / post-publish |
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## Phase 5 — DX / dette doc (optionnel)
|
|
65
|
-
|
|
66
|
-
- Intercepter liens `/docs|core/…` + e2e nav/search
|
|
67
|
-
- Liens markdown vers `../../core/utils/*.ts` en prod
|
|
68
|
-
- [x] Contrat d’URL dans skill `concorde-docs` (pathnames, pas `/crawl/`)
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
## Ordre restant
|
|
73
|
-
|
|
74
|
-
```
|
|
75
|
-
3b Smoke localhost + publish concorde_doc
|
|
76
|
-
↓
|
|
77
|
-
4 Titres onglet / polish Ora
|
|
78
|
-
↓
|
|
79
|
-
5 DX optionnel
|
|
80
|
-
```
|
package/ai/AGENTS.md
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# Agents — Concorde
|
|
2
|
-
|
|
3
|
-
Guide pour les agents IA sur un projet **Concorde** (Lit + DataProvider).
|
|
4
|
-
|
|
5
|
-
## Skills / rules (après installation)
|
|
6
|
-
|
|
7
|
-
| Fichier | Rôle |
|
|
8
|
-
|---------|------|
|
|
9
|
-
| `.cursor/skills/concorde/SKILL.md` | Patterns framework |
|
|
10
|
-
| `.cursor/skills/concorde-imports/SKILL.md` | Imports courts |
|
|
11
|
-
| `.cursor/skills/concorde-scope/SKILL.md` | Scope + APIConfiguration |
|
|
12
|
-
| `.cursor/skills/concorde-theme/SKILL.md` | Design tokens sonic-theme |
|
|
13
|
-
| `.cursor/skills/concorde-menu/SKILL.md` | Navigation sonic-menu |
|
|
14
|
-
| `.cursor/skills/concorde-get-set-dp/SKILL.md` | Migration get/set/dp + DataProviderKey statique |
|
|
15
|
-
| `.cursor/rules/concorde.mdc` | Règles Cursor (patterns) |
|
|
16
|
-
| `.aiassistant/rules/concorde.md` | Règles JetBrains AI Assistant |
|
|
17
|
-
|
|
18
|
-
Installation :
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
node node_modules/@supersoniks/concorde/scripts/ai-init.mjs
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Source : `@supersoniks/concorde/ai/`
|
|
25
|
-
|
|
26
|
-
## Imports dans ce dépôt (lib + doc)
|
|
27
|
-
|
|
28
|
-
Les chemins courts (`@supersoniks/concorde/list`, `/menu`, `/queue`, …) sont des **exports npm** pour les apps **externes**. Dans le repo Concorde (`src/docs`, `src/core`, démos), utiliser les chemins **réels** :
|
|
29
|
-
|
|
30
|
-
- Composants : `@supersoniks/concorde/core/components/…` ou import relatif (`../../core/components/functional/list/list`)
|
|
31
|
-
- Décorateurs : `@supersoniks/concorde/core/decorators/Subscriber` (ou `src/decorators.ts` via `@supersoniks/concorde/decorators` si résolu par l’alias Vite racine)
|
|
32
|
-
- `DataProviderKey` : `@supersoniks/concorde/core/utils/dataProviderKey`
|
|
33
|
-
|
|
34
|
-
Skill **`concorde-imports`** : section « Dans le dépôt Concorde ».
|
|
35
|
-
|
|
36
|
-
## Conventions impératives
|
|
37
|
-
|
|
38
|
-
- Toujours **DataProvider**, accès via **`get` / `set`**
|
|
39
|
-
- Pas de **`sonic-fetch`**, pas de **`PublisherManager`**
|
|
40
|
-
- Pas de `@onAssign` — **`@handle`** + `DataProviderKey`
|
|
41
|
-
- Pas de **`@bind`** sur les composants métier — **`@subscribe`** + `DataProviderKey<T, U>` (type + contraintes hôte `${…}`)
|
|
42
|
-
- Formulaires : **`formDataProvider`** + `name` sur `sonic-input`
|
|
43
|
-
- Listes : templates **Lit** (`.items`, `.separator`, `.noItems`, `.skeleton`) — pas de promotion des `<template>` HTML
|
|
44
|
-
- **Scope** (API/forms) ≠ **theme** (couleurs) — skills `concorde-scope` / `concorde-theme`
|
|
45
|
-
|
|
46
|
-
## Migration get / set / dp
|
|
47
|
-
|
|
48
|
-
Skill **`concorde-get-set-dp`** : chemins sans placeholder **`${…}`** / **`{$…}`** pour `get` / `set` / `dp` ; chemins JS évalués OK ; clés dynamiques → décorateurs, `dp(idRésolu)`, ou **`sub(clé)`** dans les templates Lit.
|
|
49
|
-
|
|
50
|
-
## Migration Subscriber / sonic-fetch
|
|
51
|
-
|
|
52
|
-
Skill **`concorde`** — section **« Piège migration Subscriber → LitElement »** : ne pas laisser des `@property` orphelines après retrait du mixin ; `@get` + `@subscribe` feuille ; `apiConfigKey` en modale ; sync des noms de props pour les `Endpoint` dynamiques.
|
|
53
|
-
|
|
54
|
-
## Documentation
|
|
55
|
-
|
|
56
|
-
Fichiers `.md` dans le package : `node_modules/@supersoniks/concorde/src/` (composants, décorateurs, getting-started).
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Navigation Concorde — sonic-menu, sonic-menu-item, sonic-divider
|
|
3
|
-
globs: **/{layout,sidebar,nav,docs-shell,routes}/**
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Navigation Concorde
|
|
8
|
-
|
|
9
|
-
1. **`sonic-menu`** + **`sonic-menu-item`** — pas une liste de boutons ghost.
|
|
10
|
-
2. Sections : **`sonic-divider`** (`label`, `align="left"`, `size="sm"`).
|
|
11
|
-
3. Liens internes : `pushstate` + `href` + `autoActive="strict"`.
|
|
12
|
-
|
|
13
|
-
Référence : `.cursor/skills/concorde-menu/SKILL.md`
|
|
14
|
-
|
|
15
|
-
Pas de tirets dans les noms de dossiers de routes (générateur Concorde).
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Scope — inherited API, form, icon defaults (not theme)
|
|
3
|
-
globs: **/*.{ts,tsx,html}
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Scope
|
|
8
|
-
|
|
9
|
-
Skill **`concorde-scope`**
|
|
10
|
-
|
|
11
|
-
- `<sonic-scope>` — light DOM, attributes inherited by descendants
|
|
12
|
-
- API: `serviceURL`, `token`, `credentials` → `@get`, list, queue
|
|
13
|
-
- Or: `DataProviderKey<APIConfiguration>` as 2nd arg to `@get`
|
|
14
|
-
- Not for colors/fonts — use **`concorde-theme`**
|