@supersoniks/concorde 5.0.2 → 5.0.4
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/.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/build-infos.json +1 -1
- package/concorde-core.bundle.js +66 -66
- package/concorde-core.es.js +1368 -1318
- package/dist/concorde-core.bundle.js +66 -66
- package/dist/concorde-core.es.js +1368 -1318
- package/docs/altcha-widget.js +2662 -0
- package/docs/assets/index-D8MVWqY6.js +12251 -0
- package/docs/assets/index-DiD0qYvE.css +1 -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.html +269 -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 +110 -0
- package/docs/crawl/core/components/ui/alert-messages/alert-messages.html +23 -0
- package/docs/crawl/core/components/ui/badge/badge.html +119 -0
- package/docs/crawl/core/components/ui/button/button.html +149 -0
- package/docs/crawl/core/components/ui/captcha/captcha.html +30 -0
- package/docs/crawl/core/components/ui/card/card.html +99 -0
- package/docs/crawl/core/components/ui/divider/divider.html +58 -0
- package/docs/crawl/core/components/ui/form/checkbox/checkbox.html +73 -0
- package/docs/crawl/core/components/ui/form/fieldset/fieldset.html +135 -0
- package/docs/crawl/core/components/ui/form/form-actions/form-actions.html +79 -0
- package/docs/crawl/core/components/ui/form/form-layout/form-layout.html +62 -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 +82 -0
- package/docs/crawl/core/components/ui/icon/icon.html +133 -0
- package/docs/crawl/core/components/ui/image/image.html +110 -0
- package/docs/crawl/core/components/ui/link/link.html +42 -0
- package/docs/crawl/core/components/ui/loader/loader.html +50 -0
- package/docs/crawl/core/components/ui/menu/menu.html +322 -0
- package/docs/crawl/core/components/ui/modal/modal.html +117 -0
- package/docs/crawl/core/components/ui/pop/pop.html +102 -0
- package/docs/crawl/core/components/ui/progress/progress.html +58 -0
- package/docs/crawl/core/components/ui/table/table.html +413 -0
- package/docs/crawl/core/components/ui/toast/toast.html +122 -0
- package/docs/crawl/core/components/ui/tooltip/tooltip.html +79 -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 +116 -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 +85 -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 +359 -0
- package/docs/crawl/hubs/remote-data.html +452 -0
- package/docs/crawl/index.html +101 -0
- package/docs/css/docs.css +0 -0
- package/docs/docs-mock-api-sw.js +724 -0
- package/docs/docs-mock-api-sw.js.map +7 -0
- package/docs/fonts/ClashGrotesk-Bold.eot +0 -0
- package/docs/fonts/ClashGrotesk-Bold.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Bold.woff +0 -0
- package/docs/fonts/ClashGrotesk-Bold.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.eot +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.woff +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Light.eot +0 -0
- package/docs/fonts/ClashGrotesk-Light.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Light.woff +0 -0
- package/docs/fonts/ClashGrotesk-Light.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Medium.eot +0 -0
- package/docs/fonts/ClashGrotesk-Medium.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Medium.woff +0 -0
- package/docs/fonts/ClashGrotesk-Medium.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Regular.eot +0 -0
- package/docs/fonts/ClashGrotesk-Regular.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Regular.woff +0 -0
- package/docs/fonts/ClashGrotesk-Regular.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.eot +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.woff +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Variable.eot +0 -0
- package/docs/fonts/ClashGrotesk-Variable.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Variable.woff +0 -0
- package/docs/fonts/ClashGrotesk-Variable.woff2 +0 -0
- package/docs/img/concorde-icon.svg +5 -0
- package/docs/img/concorde-logo.svg +1 -0
- package/docs/img/concorde.png +0 -0
- package/docs/img/concorde_def.png +0 -0
- package/docs/img/concorde_seuil.png.webp +0 -0
- package/docs/img/concorde_seuil_invert.png +0 -0
- package/docs/img/paul_metrand.jpg +0 -0
- package/docs/img/paul_metrand_xs.jpg +0 -0
- package/docs/index.html +93 -0
- package/docs/llms-full.txt +5761 -0
- package/docs/llms.txt +104 -0
- package/docs/robots.txt +16 -0
- package/docs/sitemap.xml +237 -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/default-library.json +108 -0
- package/docs/src/core/components/functional/sdui/example.json +99 -0
- package/docs/src/core/components/functional/sdui/sdui.md +356 -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 +121 -0
- package/docs/src/core/components/ui/alert-messages/alert-messages.md +0 -0
- package/docs/src/core/components/ui/badge/badge.md +127 -0
- package/docs/src/core/components/ui/button/button.md +182 -0
- package/docs/src/core/components/ui/captcha/captcha.md +12 -0
- package/docs/src/core/components/ui/card/card.md +97 -0
- package/docs/src/core/components/ui/divider/divider.md +35 -0
- package/docs/src/core/components/ui/form/checkbox/checkbox.md +77 -0
- package/docs/src/core/components/ui/form/fieldset/fieldset.md +129 -0
- package/docs/src/core/components/ui/form/form-actions/form-actions.md +77 -0
- package/docs/src/core/components/ui/form/form-layout/form-layout.md +44 -0
- package/docs/src/core/components/ui/form/input/input.md +142 -0
- package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +29 -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 +125 -0
- package/docs/src/core/components/ui/icon/icons.json +1 -0
- package/docs/src/core/components/ui/image/image.md +107 -0
- package/docs/src/core/components/ui/link/link.md +43 -0
- package/docs/src/core/components/ui/loader/loader.md +55 -0
- package/docs/src/core/components/ui/menu/menu.md +329 -0
- package/docs/src/core/components/ui/modal/modal.md +119 -0
- package/docs/src/core/components/ui/pop/pop.md +96 -0
- package/docs/src/core/components/ui/progress/progress.md +63 -0
- package/docs/src/core/components/ui/table/table.md +455 -0
- package/docs/src/core/components/ui/toast/toast.md +166 -0
- package/docs/src/core/components/ui/tooltip/tooltip.md +82 -0
- package/docs/src/docs/_core-concept/dataFlow.md +88 -0
- 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 +127 -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/ai-agents.md +76 -0
- 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/src/docs/_getting-started/create-a-component.md +139 -0
- package/docs/src/docs/_getting-started/my-first-component.md +236 -0
- 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/start.md +47 -0
- package/docs/src/docs/_getting-started/theming.md +91 -0
- package/docs/src/docs/_misc/api-configuration.md +81 -0
- package/docs/src/docs/_misc/dataProviderKey.md +168 -0
- package/docs/src/docs/_misc/docs-mock-api.md +63 -0
- package/docs/src/docs/_misc/dynamic-path.md +71 -0
- package/docs/src/docs/_misc/endpoint.md +45 -0
- package/docs/src/docs/_misc/formelement-subscriber-removal.md +115 -0
- package/docs/src/docs/_misc/html-integration.md +15 -0
- package/docs/src/docs/search/docs-search.json +9507 -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 +1182 -0
- package/docs/svg/regular/plane.svg +1 -0
- package/docs/svg/solid/plane.svg +1 -0
- package/gitlab/job_github_mirror.sh +39 -0
- package/gitlab/job_tests.sh +0 -0
- package/package.json +1 -1
- package/scripts/github-export.mjs +150 -0
- package/scripts/post-build-docs.js +0 -0
- package/scripts/post-build.mjs +0 -0
- package/src/core/components/functional/fetch/fetch.md +0 -0
- package/src/core/components/functional/if/if.md +0 -0
- package/src/core/components/functional/list/list.demo.ts +0 -0
- package/src/core/components/functional/list/list.md +0 -0
- package/src/core/components/functional/router/router.md +0 -0
- package/src/core/components/functional/router/router.ts +0 -0
- package/src/core/components/functional/sdui/sdui.md +0 -0
- package/src/core/components/functional/states/states.md +0 -0
- package/src/core/components/functional/submit/submit.md +0 -0
- package/src/core/components/functional/subscriber/subscriber.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/captcha/captcha.md +0 -0
- package/src/core/components/ui/form/radio/radio.md +0 -0
- package/src/core/components/ui/form/select/select.md +0 -0
- package/src/core/components/ui/form/switch/switch.md +0 -0
- package/src/core/components/ui/loader/loader.md +0 -0
- package/src/core/components/ui/menu/menu.md +0 -0
- package/src/core/components/ui/modal/modal.md +0 -0
- package/src/core/components/ui/table/table-caption.ts +0 -0
- package/src/core/components/ui/table/table.md +0 -0
- package/src/core/decorators/subscriber/ancestorAttribute.spec.ts +26 -0
- package/src/core/decorators/subscriber/ancestorAttribute.ts +3 -4
- package/src/core/mixins/Subscriber.ts +0 -0
- package/src/core/utils/AncestorAttributeObserver.ts +183 -70
- package/src/core/utils/DataBindObserver.ts +0 -0
- package/src/core/utils/Objects.ts +0 -0
- package/src/core/utils/route.ts +0 -0
- package/src/css.d.ts +19 -0
- package/src/docs/_core-concept/subscriber.md +0 -0
- package/src/docs/_decorators/ancestor-attribute.md +3 -2
- package/src/docs/_getting-started/my-first-subscriber.md +0 -0
- package/src/docs/_getting-started/pubsub.md +0 -0
- package/src/docs/_getting-started/start.md +0 -0
- package/src/docs/example/users.ts +0 -0
- package/src/docs/search/page.ts +0 -0
- package/src/tsconfig.declarations.json +22 -0
- package/src/tsconfig.emit.json +23 -0
- package/src/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M576 256C576 305 502.1 336 464.2 336H382.2L282.4 496C276.4 506 266.4 512 254.4 512H189.5C179.5 512 169.5 508 163.5 500C157.6 492 155.6 480.1 158.6 471L201.5 336H152.5L113.6 388C107.6 396 98.61 400 88.62 400H31.7C22.72 400 12.73 396 6.74 388C.7485 380-1.248 370 1.747 360L31.7 256L.7488 152C-1.248 143 .7488 133 6.74 125C12.73 117 22.72 112 31.7 112H88.62C98.61 112 107.6 117 113.6 125L152.5 176H201.5L158.6 41C155.6 32 157.6 21 163.5 13C169.5 5 179.5 0 189.5 0H254.4C265.4 0 277.4 7 281.4 16L381.2 176H463.2C502.1 176 576 208 576 256H576zM527.1 256C525.1 246 489.1 224 463.2 224H355.3L245.4 48H211.5L266.4 224H128.6L80.63 160H53.67L81.63 256L53.67 352H80.63L128.6 288H266.4L211.5 464H245.4L355.3 288H463.2C490.1 288 526.1 267 527.1 256V256z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M482.3 192c34.2 0 93.7 29 93.7 64c0 36-59.5 64-93.7 64l-116.6 0L265.2 495.9c-5.7 10-16.3 16.1-27.8 16.1l-56.2 0c-10.6 0-18.3-10.2-15.4-20.4l49-171.6L112 320 68.8 377.6c-3 4-7.8 6.4-12.8 6.4l-42 0c-7.8 0-14-6.3-14-14c0-1.3 .2-2.6 .5-3.9L32 256 .5 145.9c-.4-1.3-.5-2.6-.5-3.9c0-7.8 6.3-14 14-14l42 0c5 0 9.8 2.4 12.8 6.4L112 192l102.9 0-49-171.6C162.9 10.2 170.6 0 181.2 0l56.2 0c11.5 0 22.1 6.2 27.8 16.1L365.7 192l116.6 0z"/></svg>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Pousse un export filtré (lib publique) vers GitHub.
|
|
3
|
+
# Remplace le push mirror « tout le dépôt » : pas de doc, pas de captcha, pas de gitlab/.
|
|
4
|
+
#
|
|
5
|
+
# Variables CI requises :
|
|
6
|
+
# GITHUB_REPO_URL — ex. https://github.com/supersoniks/concorde.git
|
|
7
|
+
# GITHUB_TOKEN — PAT avec scope repo (masqué)
|
|
8
|
+
#
|
|
9
|
+
# Usage manuel (hors CI) :
|
|
10
|
+
# GITHUB_REPO_URL=https://github.com/supersoniks/concorde.git \
|
|
11
|
+
# GITHUB_TOKEN=ghp_… \
|
|
12
|
+
# bash gitlab/job_github_mirror.sh
|
|
13
|
+
#
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
EXPORT_DIR="${CI_PROJECT_DIR:-$(cd "$(dirname "$0")/.." && pwd)}/.github-export"
|
|
17
|
+
BRANCH="${GITHUB_BRANCH:-master}"
|
|
18
|
+
|
|
19
|
+
if [[ -z "${GITHUB_REPO_URL:-}" || -z "${GITHUB_TOKEN:-}" ]]; then
|
|
20
|
+
echo "❌ GITHUB_REPO_URL et GITHUB_TOKEN sont requis."
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
echo "=== Export filtré ==="
|
|
25
|
+
node "${CI_PROJECT_DIR:-.}/scripts/github-export.mjs" "$EXPORT_DIR"
|
|
26
|
+
|
|
27
|
+
echo "=== Push vers GitHub ($BRANCH) ==="
|
|
28
|
+
cd "$EXPORT_DIR"
|
|
29
|
+
git init -q
|
|
30
|
+
git config user.email "ci@supersoniks.org"
|
|
31
|
+
git config user.name "GitLab CI"
|
|
32
|
+
git add -A
|
|
33
|
+
git commit -q -m "sync: export lib depuis GitLab ${CI_COMMIT_SHORT_SHA:-local}"
|
|
34
|
+
|
|
35
|
+
PUSH_URL="${GITHUB_REPO_URL/https:\/\//https://${GITHUB_TOKEN}@}"
|
|
36
|
+
git branch -M "$BRANCH"
|
|
37
|
+
git push -f "$PUSH_URL" "$BRANCH"
|
|
38
|
+
|
|
39
|
+
echo "=== Miroir GitHub à jour ==="
|
package/gitlab/job_tests.sh
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Prépare une arborescence « lib publique » pour GitHub :
|
|
4
|
+
* - sans site doc (src/docs, index.html, …)
|
|
5
|
+
* - sans sonic-captcha (altcha.supersoniks.org)
|
|
6
|
+
* - sans scripts / jobs GitLab internes
|
|
7
|
+
*
|
|
8
|
+
* Usage :
|
|
9
|
+
* node scripts/github-export.mjs [répertoire_cible]
|
|
10
|
+
*
|
|
11
|
+
* Par défaut : ../concorde-github-export
|
|
12
|
+
*/
|
|
13
|
+
import fs from "fs";
|
|
14
|
+
import path from "path";
|
|
15
|
+
import { fileURLToPath } from "url";
|
|
16
|
+
|
|
17
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const ROOT = path.resolve(__dirname, "..");
|
|
19
|
+
const IGNORE_FILE = path.join(ROOT, ".github-export-ignore");
|
|
20
|
+
const DEFAULT_OUT = path.resolve(ROOT, "../concorde-github-export");
|
|
21
|
+
|
|
22
|
+
const EXPORT_FILTER_KEY =
|
|
23
|
+
/(?:^|\/)(?:docs|mock-api|undefined)(?:\/|$)|captcha|\.demo\.|\.stories\.|TestUtils|\/prism\/|\/search\/|\/tailwind\/|\/header\/|\/navigation\/|\/layout\.ts$|\/code\.ts$|^code$|^docs$|^layout$/;
|
|
24
|
+
|
|
25
|
+
function readIgnorePatterns() {
|
|
26
|
+
if (!fs.existsSync(IGNORE_FILE)) return [];
|
|
27
|
+
return fs
|
|
28
|
+
.readFileSync(IGNORE_FILE, "utf8")
|
|
29
|
+
.split("\n")
|
|
30
|
+
.map((l) => l.trim())
|
|
31
|
+
.filter((l) => l && !l.startsWith("#"));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function globToRegExp(pattern) {
|
|
35
|
+
const escaped = pattern
|
|
36
|
+
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
|
37
|
+
.replace(/\*\*/g, "{{GLOBSTAR}}")
|
|
38
|
+
.replace(/\*/g, "[^/]*")
|
|
39
|
+
.replace(/\{\{GLOBSTAR\}\}/g, ".*");
|
|
40
|
+
return new RegExp(`^${escaped}$`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function shouldExclude(relativePath, patterns) {
|
|
44
|
+
const normalized = relativePath.replace(/\\/g, "/");
|
|
45
|
+
for (const pattern of patterns) {
|
|
46
|
+
const re = globToRegExp(pattern);
|
|
47
|
+
if (re.test(normalized)) return true;
|
|
48
|
+
if (normalized.startsWith(pattern.endsWith("/") ? pattern : `${pattern}/`))
|
|
49
|
+
return true;
|
|
50
|
+
if (normalized === pattern) return true;
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function listAllFiles(dir, base = dir) {
|
|
56
|
+
const out = [];
|
|
57
|
+
for (const name of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
58
|
+
if (name.name === ".git" || name.name === "node_modules") continue;
|
|
59
|
+
const full = path.join(dir, name.name);
|
|
60
|
+
const rel = path.relative(base, full).replace(/\\/g, "/");
|
|
61
|
+
if (name.isDirectory()) {
|
|
62
|
+
if (shouldExclude(rel, ignorePatterns)) continue;
|
|
63
|
+
out.push(...listAllFiles(full, base));
|
|
64
|
+
} else {
|
|
65
|
+
if (!shouldExclude(rel, ignorePatterns)) out.push(rel);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function copyFile(rel, destRoot) {
|
|
72
|
+
const src = path.join(ROOT, rel);
|
|
73
|
+
const dest = path.join(destRoot, rel);
|
|
74
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
75
|
+
fs.copyFileSync(src, dest);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function patchUiTs(destRoot) {
|
|
79
|
+
const uiPath = path.join(
|
|
80
|
+
destRoot,
|
|
81
|
+
"src/core/components/ui/ui.ts",
|
|
82
|
+
);
|
|
83
|
+
if (!fs.existsSync(uiPath)) return;
|
|
84
|
+
const content = fs.readFileSync(uiPath, "utf8");
|
|
85
|
+
const patched = content.replace(
|
|
86
|
+
/import "\.\/captcha\/captcha";\n?/,
|
|
87
|
+
"",
|
|
88
|
+
);
|
|
89
|
+
fs.writeFileSync(uiPath, patched);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function exportHaystack(value) {
|
|
93
|
+
if (typeof value === "string") return value;
|
|
94
|
+
if (value && typeof value === "object") {
|
|
95
|
+
return `${value.types ?? ""}${value.default ?? ""}`;
|
|
96
|
+
}
|
|
97
|
+
return String(value);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function filterPackageJson(destRoot) {
|
|
101
|
+
const pkgPath = path.join(destRoot, "package.json");
|
|
102
|
+
if (!fs.existsSync(pkgPath)) return;
|
|
103
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
104
|
+
if (pkg.exports && typeof pkg.exports === "object") {
|
|
105
|
+
const next = {};
|
|
106
|
+
for (const [key, value] of Object.entries(pkg.exports)) {
|
|
107
|
+
const hay = `${key}:${exportHaystack(value)}`;
|
|
108
|
+
if (EXPORT_FILTER_KEY.test(hay)) continue;
|
|
109
|
+
if (exportHaystack(value).includes("/captcha/")) continue;
|
|
110
|
+
if (exportHaystack(value).includes("/docs/")) continue;
|
|
111
|
+
if (exportHaystack(value).includes(".demo.")) continue;
|
|
112
|
+
if (exportHaystack(value).includes(".stories.")) continue;
|
|
113
|
+
next[key] = value;
|
|
114
|
+
}
|
|
115
|
+
pkg.exports = next;
|
|
116
|
+
}
|
|
117
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function patchReadme(destRoot) {
|
|
121
|
+
const readmePath = path.join(destRoot, "README.md");
|
|
122
|
+
if (!fs.existsSync(readmePath)) return;
|
|
123
|
+
let text = fs.readFileSync(readmePath, "utf8");
|
|
124
|
+
text = text.replace(
|
|
125
|
+
/Le dépôt GitHub est un \*\*miroir\*\* synchronisé depuis GitLab \(voir \[OPEN_SOURCE_CHECKPOINT\.md\]\(OPEN_SOURCE_CHECKPOINT\.md\)\)\./,
|
|
126
|
+
"Le dépôt GitHub est un **export filtré** depuis GitLab (librairie uniquement, sans site doc ni composant captcha — voir [OPEN_SOURCE_CHECKPOINT.md](OPEN_SOURCE_CHECKPOINT.md)).",
|
|
127
|
+
);
|
|
128
|
+
fs.writeFileSync(readmePath, text);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const ignorePatterns = readIgnorePatterns();
|
|
132
|
+
const outDir = path.resolve(process.argv[2] || DEFAULT_OUT);
|
|
133
|
+
|
|
134
|
+
if (fs.existsSync(outDir)) {
|
|
135
|
+
fs.rmSync(outDir, { recursive: true, force: true });
|
|
136
|
+
}
|
|
137
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
138
|
+
|
|
139
|
+
const files = listAllFiles(ROOT);
|
|
140
|
+
for (const rel of files) {
|
|
141
|
+
copyFile(rel, outDir);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
patchUiTs(outDir);
|
|
145
|
+
filterPackageJson(outDir);
|
|
146
|
+
patchReadme(outDir);
|
|
147
|
+
|
|
148
|
+
console.log(`✅ Export GitHub : ${files.length} fichiers → ${outDir}`);
|
|
149
|
+
console.log(" Exclusions : .github-export-ignore");
|
|
150
|
+
console.log(" Patches : ui.ts (sans captcha), package.json exports");
|
|
File without changes
|
package/scripts/post-build.mjs
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -236,4 +236,30 @@ describe("ancestorAttribute", () => {
|
|
|
236
236
|
|
|
237
237
|
expect(el.dataProvider).toBe("scope-a");
|
|
238
238
|
});
|
|
239
|
+
|
|
240
|
+
it("suit un wrapper plus proche après reparent (sans opt-in)", async () => {
|
|
241
|
+
const tag = "test-ancestor-attr-dynamic-reparent";
|
|
242
|
+
class C extends HTMLElement {
|
|
243
|
+
@ancestorAttribute("dataProvider", { dynamic: true })
|
|
244
|
+
dataProvider: string | null = null;
|
|
245
|
+
}
|
|
246
|
+
if (!customElements.get(tag)) {
|
|
247
|
+
customElements.define(tag, C);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const outer = document.createElement("div");
|
|
251
|
+
outer.setAttribute("dataProvider", "from-outer");
|
|
252
|
+
const el = document.createElement(tag) as InstanceType<typeof C>;
|
|
253
|
+
outer.appendChild(el);
|
|
254
|
+
document.body.appendChild(outer);
|
|
255
|
+
expect(el.dataProvider).toBe("from-outer");
|
|
256
|
+
|
|
257
|
+
const closer = document.createElement("div");
|
|
258
|
+
closer.setAttribute("dataProvider", "from-closer");
|
|
259
|
+
closer.appendChild(el);
|
|
260
|
+
outer.appendChild(closer);
|
|
261
|
+
await flushFrames();
|
|
262
|
+
|
|
263
|
+
expect(el.dataProvider).toBe("from-closer");
|
|
264
|
+
});
|
|
239
265
|
});
|
|
@@ -5,10 +5,9 @@ import { ConnectedComponent, setSubscribable } from "./common";
|
|
|
5
5
|
|
|
6
6
|
export type AncestorAttributeOptions = {
|
|
7
7
|
/**
|
|
8
|
-
* Si true,
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* Défaut : false (lecture unique au connect, rétrocompat).
|
|
8
|
+
* Si true, reste synchronisé quand un attribut ancêtre change **et** au
|
|
9
|
+
* reparenting (sans flag séparé). MO attributs partagés ; childList seulement
|
|
10
|
+
* sur le parent direct (ignoré pour les siblings). Défaut : false.
|
|
12
11
|
*/
|
|
13
12
|
dynamic?: boolean;
|
|
14
13
|
};
|
|
File without changes
|
|
@@ -3,13 +3,14 @@ import HTML, { SearchableDomElement } from "./HTML";
|
|
|
3
3
|
/**
|
|
4
4
|
* Observateur pour `@ancestorAttribute({ dynamic: true })`.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* `watchScopedConfiguration` dans `api.ts`.
|
|
6
|
+
* ## Perf (FF / listes denses d'icônes)
|
|
7
|
+
* Ancien modèle : 1 MO/abonnement avec `childList` sur **toute** la chaîne +
|
|
8
|
+
* `reconnect()` à chaque mutation → O(n²) quand une list insert des siblings.
|
|
10
9
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Modèle actuel :
|
|
11
|
+
* 1. **MO attributs partagés** — 1 observer par `(ancêtre, attributeName)`.
|
|
12
|
+
* 2. **Reparent** — 1 MO `childList` partagé sur le parent direct ; on ne
|
|
13
|
+
* réagit que si *notre* nœud est dans added/removed (insert sibling → no-op).
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
16
|
type SyncOptions = {
|
|
@@ -22,7 +23,18 @@ type Subscription = {
|
|
|
22
23
|
attributeName: string;
|
|
23
24
|
propertyKey: string;
|
|
24
25
|
syncOptions: SyncOptions;
|
|
25
|
-
|
|
26
|
+
watchedAncestors: Element[];
|
|
27
|
+
parentForReparent: Element | null;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type AttrSlot = {
|
|
31
|
+
observer: MutationObserver;
|
|
32
|
+
subscriptions: Set<Subscription>;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type ParentSlot = {
|
|
36
|
+
observer: MutationObserver;
|
|
37
|
+
byComponent: Map<Element, Set<Subscription>>;
|
|
26
38
|
};
|
|
27
39
|
|
|
28
40
|
/** Chaîne composant → ancêtres, en traversant les shadow roots. */
|
|
@@ -40,58 +52,17 @@ function walkAncestorElements(node: Node): Element[] {
|
|
|
40
52
|
return elements;
|
|
41
53
|
}
|
|
42
54
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
subscription: Subscription,
|
|
49
|
-
onMutation: () => void,
|
|
50
|
-
): () => void {
|
|
51
|
-
const observers: MutationObserver[] = [];
|
|
52
|
-
let disconnected = false;
|
|
53
|
-
const attributeFilter = HTML.scopeAttributeNames(subscription.attributeName);
|
|
54
|
-
|
|
55
|
-
const reconnect = () => {
|
|
56
|
-
for (const observer of observers) {
|
|
57
|
-
observer.disconnect();
|
|
58
|
-
}
|
|
59
|
-
observers.length = 0;
|
|
60
|
-
if (disconnected) return;
|
|
61
|
-
|
|
62
|
-
for (const element of walkAncestorElements(subscription.component)) {
|
|
63
|
-
const observer = new MutationObserver((records) => {
|
|
64
|
-
if (disconnected) return;
|
|
65
|
-
if (records.some((record) => record.type === "childList")) {
|
|
66
|
-
reconnect();
|
|
67
|
-
}
|
|
68
|
-
onMutation();
|
|
69
|
-
});
|
|
70
|
-
observer.observe(element, {
|
|
71
|
-
attributes: true,
|
|
72
|
-
attributeFilter,
|
|
73
|
-
childList: true,
|
|
74
|
-
subtree: false,
|
|
75
|
-
});
|
|
76
|
-
observers.push(observer);
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
reconnect();
|
|
81
|
-
|
|
82
|
-
return () => {
|
|
83
|
-
disconnected = true;
|
|
84
|
-
for (const observer of observers) {
|
|
85
|
-
observer.disconnect();
|
|
86
|
-
}
|
|
87
|
-
observers.length = 0;
|
|
88
|
-
};
|
|
55
|
+
function directParentElement(component: HTMLElement): Element | null {
|
|
56
|
+
const parent =
|
|
57
|
+
component.parentNode ||
|
|
58
|
+
((component.getRootNode() as ShadowRoot)?.host ?? null);
|
|
59
|
+
return parent instanceof Element ? parent : null;
|
|
89
60
|
}
|
|
90
61
|
|
|
91
62
|
/**
|
|
92
63
|
* Point unique de synchronisation DOM → propriété du composant.
|
|
93
64
|
* N'assigne que si la valeur change (`Object.is`) pour limiter les re-renders Lit
|
|
94
|
-
* et éviter de reboucler inutilement `observeDynamicProperty` (@bind /
|
|
65
|
+
* et éviter de reboucler inutilement `observeDynamicProperty` (@bind / `@subscribe`).
|
|
95
66
|
*/
|
|
96
67
|
export function syncAncestorAttributeValue(
|
|
97
68
|
component: object,
|
|
@@ -115,8 +86,11 @@ export default class AncestorAttributeObserver {
|
|
|
115
86
|
private static pendingRefresh = new Set<Subscription>();
|
|
116
87
|
private static animationFrameId: number | null = null;
|
|
117
88
|
|
|
89
|
+
private static attrSlots = new WeakMap<Element, Map<string, AttrSlot>>();
|
|
90
|
+
private static parentSlots = new WeakMap<Element, ParentSlot>();
|
|
91
|
+
|
|
118
92
|
/**
|
|
119
|
-
* Enregistre un composant en mode `{ dynamic: true }
|
|
93
|
+
* Enregistre un composant en mode `{ dynamic: true }` (attributs + reparent).
|
|
120
94
|
* Le `unsubscribe` retourné doit être appelé au `disconnectedCallback`.
|
|
121
95
|
*/
|
|
122
96
|
static subscribe(
|
|
@@ -130,32 +104,172 @@ export default class AncestorAttributeObserver {
|
|
|
130
104
|
attributeName,
|
|
131
105
|
propertyKey,
|
|
132
106
|
syncOptions,
|
|
133
|
-
|
|
107
|
+
watchedAncestors: [],
|
|
108
|
+
parentForReparent: null,
|
|
134
109
|
};
|
|
135
110
|
|
|
136
|
-
subscription.disconnectObservers = attachAncestorChainObservers(
|
|
137
|
-
subscription,
|
|
138
|
-
() => {
|
|
139
|
-
if (!AncestorAttributeObserver.subscriptions.has(subscription)) return;
|
|
140
|
-
AncestorAttributeObserver.pendingRefresh.add(subscription);
|
|
141
|
-
AncestorAttributeObserver.scheduleRefresh();
|
|
142
|
-
},
|
|
143
|
-
);
|
|
144
|
-
|
|
145
111
|
AncestorAttributeObserver.subscriptions.add(subscription);
|
|
112
|
+
AncestorAttributeObserver.bindSubscription(subscription);
|
|
146
113
|
|
|
147
114
|
return () => {
|
|
148
115
|
AncestorAttributeObserver.unsubscribe(subscription);
|
|
149
116
|
};
|
|
150
117
|
}
|
|
151
118
|
|
|
152
|
-
|
|
119
|
+
private static bindSubscription(subscription: Subscription): void {
|
|
120
|
+
AncestorAttributeObserver.unbindWatchers(subscription);
|
|
121
|
+
|
|
122
|
+
const ancestors = walkAncestorElements(subscription.component);
|
|
123
|
+
subscription.watchedAncestors = ancestors;
|
|
124
|
+
|
|
125
|
+
for (const ancestor of ancestors) {
|
|
126
|
+
AncestorAttributeObserver.addAttrSlot(
|
|
127
|
+
ancestor,
|
|
128
|
+
subscription.attributeName,
|
|
129
|
+
subscription,
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const parent = directParentElement(subscription.component);
|
|
134
|
+
subscription.parentForReparent = parent;
|
|
135
|
+
if (parent) {
|
|
136
|
+
AncestorAttributeObserver.addParentSlot(parent, subscription);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
AncestorAttributeObserver.pendingRefresh.add(subscription);
|
|
140
|
+
AncestorAttributeObserver.scheduleRefresh();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private static unbindWatchers(subscription: Subscription): void {
|
|
144
|
+
for (const ancestor of subscription.watchedAncestors) {
|
|
145
|
+
AncestorAttributeObserver.removeAttrSlot(
|
|
146
|
+
ancestor,
|
|
147
|
+
subscription.attributeName,
|
|
148
|
+
subscription,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
subscription.watchedAncestors = [];
|
|
152
|
+
|
|
153
|
+
if (subscription.parentForReparent) {
|
|
154
|
+
AncestorAttributeObserver.removeParentSlot(
|
|
155
|
+
subscription.parentForReparent,
|
|
156
|
+
subscription,
|
|
157
|
+
);
|
|
158
|
+
subscription.parentForReparent = null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private static addAttrSlot(
|
|
163
|
+
element: Element,
|
|
164
|
+
attributeName: string,
|
|
165
|
+
subscription: Subscription,
|
|
166
|
+
): void {
|
|
167
|
+
let byAttr = AncestorAttributeObserver.attrSlots.get(element);
|
|
168
|
+
if (!byAttr) {
|
|
169
|
+
byAttr = new Map();
|
|
170
|
+
AncestorAttributeObserver.attrSlots.set(element, byAttr);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
let slot = byAttr.get(attributeName);
|
|
174
|
+
if (!slot) {
|
|
175
|
+
const attributeFilter = HTML.scopeAttributeNames(attributeName);
|
|
176
|
+
const subscriptions = new Set<Subscription>();
|
|
177
|
+
const observer = new MutationObserver(() => {
|
|
178
|
+
for (const sub of subscriptions) {
|
|
179
|
+
if (!AncestorAttributeObserver.subscriptions.has(sub)) continue;
|
|
180
|
+
AncestorAttributeObserver.pendingRefresh.add(sub);
|
|
181
|
+
}
|
|
182
|
+
AncestorAttributeObserver.scheduleRefresh();
|
|
183
|
+
});
|
|
184
|
+
observer.observe(element, {
|
|
185
|
+
attributes: true,
|
|
186
|
+
attributeFilter,
|
|
187
|
+
});
|
|
188
|
+
slot = { observer, subscriptions };
|
|
189
|
+
byAttr.set(attributeName, slot);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
slot.subscriptions.add(subscription);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private static removeAttrSlot(
|
|
196
|
+
element: Element,
|
|
197
|
+
attributeName: string,
|
|
198
|
+
subscription: Subscription,
|
|
199
|
+
): void {
|
|
200
|
+
const byAttr = AncestorAttributeObserver.attrSlots.get(element);
|
|
201
|
+
if (!byAttr) return;
|
|
202
|
+
const slot = byAttr.get(attributeName);
|
|
203
|
+
if (!slot) return;
|
|
204
|
+
|
|
205
|
+
slot.subscriptions.delete(subscription);
|
|
206
|
+
if (slot.subscriptions.size > 0) return;
|
|
207
|
+
|
|
208
|
+
slot.observer.disconnect();
|
|
209
|
+
byAttr.delete(attributeName);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private static addParentSlot(
|
|
213
|
+
parent: Element,
|
|
214
|
+
subscription: Subscription,
|
|
215
|
+
): void {
|
|
216
|
+
let slot = AncestorAttributeObserver.parentSlots.get(parent);
|
|
217
|
+
if (!slot) {
|
|
218
|
+
const byComponent = new Map<Element, Set<Subscription>>();
|
|
219
|
+
const observer = new MutationObserver((records) => {
|
|
220
|
+
const touched = new Set<Element>();
|
|
221
|
+
for (const record of records) {
|
|
222
|
+
record.removedNodes.forEach((n) => {
|
|
223
|
+
if (n instanceof Element) touched.add(n);
|
|
224
|
+
});
|
|
225
|
+
record.addedNodes.forEach((n) => {
|
|
226
|
+
if (n instanceof Element) touched.add(n);
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
for (const el of touched) {
|
|
230
|
+
const subs = byComponent.get(el);
|
|
231
|
+
if (!subs) continue;
|
|
232
|
+
for (const sub of [...subs]) {
|
|
233
|
+
if (!AncestorAttributeObserver.subscriptions.has(sub)) continue;
|
|
234
|
+
AncestorAttributeObserver.bindSubscription(sub);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
observer.observe(parent, { childList: true });
|
|
239
|
+
slot = { observer, byComponent };
|
|
240
|
+
AncestorAttributeObserver.parentSlots.set(parent, slot);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
let set = slot.byComponent.get(subscription.component);
|
|
244
|
+
if (!set) {
|
|
245
|
+
set = new Set();
|
|
246
|
+
slot.byComponent.set(subscription.component, set);
|
|
247
|
+
}
|
|
248
|
+
set.add(subscription);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private static removeParentSlot(
|
|
252
|
+
parent: Element,
|
|
253
|
+
subscription: Subscription,
|
|
254
|
+
): void {
|
|
255
|
+
const slot = AncestorAttributeObserver.parentSlots.get(parent);
|
|
256
|
+
if (!slot) return;
|
|
257
|
+
|
|
258
|
+
const set = slot.byComponent.get(subscription.component);
|
|
259
|
+
if (set) {
|
|
260
|
+
set.delete(subscription);
|
|
261
|
+
if (set.size === 0) slot.byComponent.delete(subscription.component);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (slot.byComponent.size > 0) return;
|
|
265
|
+
slot.observer.disconnect();
|
|
266
|
+
AncestorAttributeObserver.parentSlots.delete(parent);
|
|
267
|
+
}
|
|
268
|
+
|
|
153
269
|
private static unsubscribe(subscription: Subscription): void {
|
|
154
270
|
if (!AncestorAttributeObserver.subscriptions.has(subscription)) return;
|
|
155
271
|
|
|
156
|
-
|
|
157
|
-
subscription.disconnectObservers = null;
|
|
158
|
-
|
|
272
|
+
AncestorAttributeObserver.unbindWatchers(subscription);
|
|
159
273
|
AncestorAttributeObserver.subscriptions.delete(subscription);
|
|
160
274
|
AncestorAttributeObserver.pendingRefresh.delete(subscription);
|
|
161
275
|
|
|
@@ -187,7 +301,6 @@ export default class AncestorAttributeObserver {
|
|
|
187
301
|
|
|
188
302
|
for (const subscription of subscriptions) {
|
|
189
303
|
if (!AncestorAttributeObserver.subscriptions.has(subscription)) continue;
|
|
190
|
-
if (!subscription.component.isConnected) continue;
|
|
191
304
|
syncAncestorAttributeValue(
|
|
192
305
|
subscription.component,
|
|
193
306
|
subscription.attributeName,
|
|
File without changes
|
|
File without changes
|
package/src/core/utils/route.ts
CHANGED
|
File without changes
|
package/src/css.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
declare module "*.css" {
|
|
2
|
+
const css: import("lit").CSSResult;
|
|
3
|
+
export default css;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
declare module "*.css?inline" {
|
|
7
|
+
const css: string;
|
|
8
|
+
export default css;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
declare module "*.scss" {
|
|
12
|
+
const css: import("lit").CSSResult;
|
|
13
|
+
export default css;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
declare module "*.scss?inline" {
|
|
17
|
+
const css: string;
|
|
18
|
+
export default css;
|
|
19
|
+
}
|
|
File without changes
|
|
@@ -69,8 +69,9 @@ This decorator is particularly useful for:
|
|
|
69
69
|
- By default (`dynamic: false`), the value is read once at connect time and is not updated afterward
|
|
70
70
|
- With `{ dynamic: true }`, the property stays in sync when:
|
|
71
71
|
- an ancestor **changes** the attribute value
|
|
72
|
-
- a **closer** ancestor **gains** the attribute (
|
|
73
|
-
- the
|
|
72
|
+
- a **closer** ancestor **gains** / **loses** the attribute (fallback / `null`)
|
|
73
|
+
- the component is **reparented** (no extra opt-in) — parent `childList` only reacts if *this* node moves
|
|
74
|
+
- Observers are **shared** (one per ancestor attribute / one per parent) so large lists of `sonic-icon` stay cheap on Firefox.
|
|
74
75
|
- When `dynamic` is enabled, updates also propagate to `@subscribe` / `@bind` paths that depend on the decorated property (e.g. `${dataProvider}`)
|
|
75
76
|
|
|
76
77
|
### Dynamic mode
|