@supersoniks/concorde 5.0.5 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/.github/workflows/ci.yml +21 -0
  2. package/.github-export-ignore +30 -0
  3. package/.tmp-cem/custom-elements.json +13705 -0
  4. package/CONTRIBUTING.md +59 -0
  5. package/DEV.md +54 -0
  6. package/LICENSE +21 -0
  7. package/OPEN_SOURCE_CHECKPOINT.md +133 -0
  8. package/build-infos.json +1 -1
  9. package/concorde-3d.bundle.js +3960 -0
  10. package/concorde-3d.es.js +33433 -0
  11. package/concorde-core.bundle.js +196 -196
  12. package/concorde-core.es.js +3685 -3405
  13. package/concorde-hugging-face-infer.bundle.js +32 -0
  14. package/concorde-hugging-face-infer.es.js +2952 -0
  15. package/concorde-interactive.bundle.js +1157 -0
  16. package/concorde-interactive.es.js +10734 -0
  17. package/concorde-shader.bundle.js +116 -0
  18. package/concorde-shader.es.js +8353 -0
  19. package/concorde-webgpu.bundle.js +307 -0
  20. package/concorde-webgpu.es.js +8627 -0
  21. package/custom-elements-manifest.config.mjs +14 -0
  22. package/dist/concorde-core.bundle.js +196 -196
  23. package/dist/concorde-core.es.js +3685 -3405
  24. package/docs/assets/{index-wVZpLVYW.js → index-D8MVWqY6.js} +1351 -1222
  25. package/docs/assets/index-DiD0qYvE.css +1 -0
  26. package/docs/crawl/core/components/ui/alert/alert.html +71 -172
  27. package/docs/crawl/core/components/ui/alert-messages/alert-messages.html +5 -113
  28. package/docs/crawl/core/components/ui/badge/badge.html +79 -157
  29. package/docs/crawl/core/components/ui/button/button.html +0 -1
  30. package/docs/crawl/core/components/ui/captcha/captcha.html +8 -90
  31. package/docs/crawl/core/components/ui/card/card.html +68 -222
  32. package/docs/crawl/core/components/ui/divider/divider.html +31 -117
  33. package/docs/crawl/core/components/ui/form/fieldset/fieldset.html +101 -232
  34. package/docs/crawl/core/components/ui/form/form-actions/form-actions.html +52 -95
  35. package/docs/crawl/core/components/ui/form/form-layout/form-layout.html +38 -97
  36. package/docs/crawl/core/components/ui/form/input/input.html +3 -3
  37. package/docs/crawl/core/components/ui/form/textarea/textarea.html +3 -3
  38. package/docs/crawl/core/components/ui/group/group.html +38 -60
  39. package/docs/crawl/core/components/ui/icon/icon.html +47 -136
  40. package/docs/crawl/core/components/ui/image/image.html +56 -244
  41. package/docs/crawl/core/components/ui/link/link.html +9 -67
  42. package/docs/crawl/core/components/ui/loader/loader.html +23 -97
  43. package/docs/crawl/core/components/ui/menu/menu.html +90 -162
  44. package/docs/crawl/core/components/ui/modal/modal.html +50 -275
  45. package/docs/crawl/core/components/ui/pop/pop.html +66 -260
  46. package/docs/crawl/core/components/ui/progress/progress.html +30 -103
  47. package/docs/crawl/core/components/ui/table/table.html +171 -303
  48. package/docs/crawl/core/components/ui/toast/toast.html +59 -170
  49. package/docs/crawl/core/components/ui/tooltip/tooltip.html +29 -90
  50. package/docs/crawl/docs/_decorators/ancestor-attribute.html +2 -3
  51. package/docs/crawl/docs/_getting-started/concorde-outside.html +3 -3
  52. package/docs/crawl/docs/_getting-started/start.html +1 -1
  53. package/docs/crawl/docs/_getting-started/theming.html +63 -311
  54. package/docs/crawl/hubs/form-components.html +53 -75
  55. package/docs/crawl/index.html +6 -7
  56. package/docs/docs-mock-api-sw.js +0 -2
  57. package/docs/docs-mock-api-sw.js.map +2 -2
  58. package/docs/index.html +7 -9
  59. package/docs/llms-full.txt +456 -1703
  60. package/docs/llms.txt +32 -25
  61. package/docs/sitemap.xml +0 -3
  62. package/docs/src/core/components/functional/fetch/fetch.md +0 -0
  63. package/docs/src/core/components/functional/if/if.md +0 -0
  64. package/docs/src/core/components/functional/list/list.md +0 -0
  65. package/docs/src/core/components/functional/router/router.md +0 -0
  66. package/docs/src/core/components/functional/sdui/sdui.md +0 -0
  67. package/docs/src/core/components/functional/states/states.md +0 -0
  68. package/docs/src/core/components/functional/submit/submit.md +0 -0
  69. package/docs/src/core/components/ui/alert/alert.md +72 -147
  70. package/docs/src/core/components/ui/alert-messages/alert-messages.md +0 -85
  71. package/docs/src/core/components/ui/badge/badge.md +80 -141
  72. package/docs/src/core/components/ui/button/button.md +0 -1
  73. package/docs/src/core/components/ui/captcha/captcha.md +6 -65
  74. package/docs/src/core/components/ui/card/card.md +65 -183
  75. package/docs/src/core/components/ui/divider/divider.md +13 -107
  76. package/docs/src/core/components/ui/form/fieldset/fieldset.md +99 -175
  77. package/docs/src/core/components/ui/form/form-actions/form-actions.md +52 -75
  78. package/docs/src/core/components/ui/form/form-layout/form-layout.md +34 -109
  79. package/docs/src/core/components/ui/form/input/input.md +1 -1
  80. package/docs/src/core/components/ui/form/radio/radio.md +0 -0
  81. package/docs/src/core/components/ui/form/select/select.md +0 -0
  82. package/docs/src/core/components/ui/form/switch/switch.md +0 -0
  83. package/docs/src/core/components/ui/form/textarea/textarea.md +1 -1
  84. package/docs/src/core/components/ui/group/group.md +36 -36
  85. package/docs/src/core/components/ui/icon/icon.md +43 -132
  86. package/docs/src/core/components/ui/image/image.md +53 -179
  87. package/docs/src/core/components/ui/link/link.md +7 -45
  88. package/docs/src/core/components/ui/loader/loader.md +22 -79
  89. package/docs/src/core/components/ui/menu/menu.md +92 -133
  90. package/docs/src/core/components/ui/modal/modal.md +47 -163
  91. package/docs/src/core/components/ui/pop/pop.md +64 -262
  92. package/docs/src/core/components/ui/progress/progress.md +30 -76
  93. package/docs/src/core/components/ui/table/table.md +171 -147
  94. package/docs/src/core/components/ui/toast/toast.md +58 -108
  95. package/docs/src/core/components/ui/tooltip/tooltip.md +26 -68
  96. package/docs/src/docs/_core-concept/subscriber.md +0 -0
  97. package/docs/src/docs/_decorators/ancestor-attribute.md +2 -3
  98. package/docs/src/docs/_getting-started/concorde-outside.md +3 -3
  99. package/docs/src/docs/_getting-started/my-first-subscriber.md +0 -0
  100. package/docs/src/docs/_getting-started/pubsub.md +0 -0
  101. package/docs/src/docs/_getting-started/start.md +1 -1
  102. package/docs/src/docs/_getting-started/theming.md +61 -223
  103. package/docs/src/docs/search/docs-search.json +348 -3083
  104. package/docs/src/tsconfig.declarations.json +22 -0
  105. package/docs/src/tsconfig.emit.json +23 -0
  106. package/docs/src/tsconfig.json +3 -63
  107. package/gitlab/job_github_mirror.sh +39 -0
  108. package/package.json +36 -2
  109. package/scripts/generate-sdui-catalog.mjs +250 -0
  110. package/scripts/generate-sdui-catalog.spec.ts +91 -0
  111. package/scripts/github-export.mjs +150 -0
  112. package/scripts/post-build-docs.js +0 -0
  113. package/scripts/post-build.mjs +0 -0
  114. package/scripts/pre-build.mjs +15 -0
  115. package/src/core/components/functional/fetch/fetch.md +0 -0
  116. package/src/core/components/functional/if/if.md +0 -0
  117. package/src/core/components/functional/if/if.ts +0 -0
  118. package/src/core/components/functional/list/list.demo.ts +0 -0
  119. package/src/core/components/functional/list/list.md +0 -0
  120. package/src/core/components/functional/router/router.md +0 -0
  121. package/src/core/components/functional/router/router.ts +0 -0
  122. package/src/core/components/functional/sdui/SDUIDescriptorTransformer.ts +5 -5
  123. package/src/core/components/functional/sdui/__fixtures__/descriptors.ts +251 -0
  124. package/src/core/components/functional/sdui/__snapshots__/sdui-action.spec.ts.snap +73 -0
  125. package/src/core/components/functional/sdui/__snapshots__/sdui-incremental.spec.ts.snap +50 -0
  126. package/src/core/components/functional/sdui/__snapshots__/sdui-partial.spec.ts.snap +50 -0
  127. package/src/core/components/functional/sdui/__snapshots__/sdui.regression.spec.ts.snap +461 -0
  128. package/src/core/components/functional/sdui/component-catalog.gaps.json +511 -0
  129. package/src/core/components/functional/sdui/component-catalog.json +3103 -0
  130. package/src/core/components/functional/sdui/component-catalog.spec.ts +23 -0
  131. package/src/core/components/functional/sdui/sdui-action.spec.ts +99 -0
  132. package/src/core/components/functional/sdui/sdui-dom-snapshot.ts +61 -0
  133. package/src/core/components/functional/sdui/sdui-extension-points.md +94 -0
  134. package/src/core/components/functional/sdui/sdui-incremental.spec.ts +137 -0
  135. package/src/core/components/functional/sdui/sdui-partial.spec.ts +83 -0
  136. package/src/core/components/functional/sdui/sdui-partial.ts +19 -0
  137. package/src/core/components/functional/sdui/sdui-safe.spec.ts +188 -0
  138. package/src/core/components/functional/sdui/sdui-safe.ts +100 -0
  139. package/src/core/components/functional/sdui/sdui.md +122 -0
  140. package/src/core/components/functional/sdui/sdui.regression.spec.ts +64 -0
  141. package/src/core/components/functional/sdui/sdui.ts +442 -34
  142. package/src/core/components/functional/sdui/types.ts +49 -0
  143. package/src/core/components/functional/states/states.md +0 -0
  144. package/src/core/components/functional/submit/submit.md +0 -0
  145. package/src/core/components/functional/subscriber/subscriber.ts +0 -0
  146. package/src/core/components/functional/value/value.ts +0 -0
  147. package/src/core/components/ui/_css/size.ts +0 -0
  148. package/src/core/components/ui/captcha/altchaStyles.ts +0 -0
  149. package/src/core/components/ui/form/radio/radio.md +0 -0
  150. package/src/core/components/ui/form/select/select.md +0 -0
  151. package/src/core/components/ui/form/switch/switch.md +0 -0
  152. package/src/core/mixins/Subscriber.ts +0 -0
  153. package/src/core/utils/DataBindObserver.ts +0 -0
  154. package/src/core/utils/Objects.ts +0 -0
  155. package/src/core/utils/route.ts +0 -0
  156. package/src/css.d.ts +19 -0
  157. package/src/docs/_core-concept/subscriber.md +0 -0
  158. package/src/docs/_getting-started/my-first-subscriber.md +0 -0
  159. package/src/docs/_getting-started/pubsub.md +0 -0
  160. package/src/docs/example/users.ts +0 -0
  161. package/src/docs/search/page.ts +0 -0
  162. package/src/tsconfig.declarations.json +22 -0
  163. package/src/tsconfig.emit.json +23 -0
  164. package/src/tsconfig.json +90 -0
  165. package/src/tsconfig.tsbuildinfo +1 -1
  166. package/docs/assets/index-CD4WyL6o.css +0 -1
  167. package/docs/crawl/core/components/ui/theme/theme.html +0 -131
  168. package/docs/src/core/components/ui/theme/theme.md +0 -122
@@ -0,0 +1,22 @@
1
+ {
2
+ "extends": "./tsconfig-model.json",
3
+ "compilerOptions": {
4
+ "noEmit": false,
5
+ "emitDeclarationOnly": true,
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "outDir": "../dist/types",
9
+ "rootDir": "."
10
+ },
11
+ "include": ["**/*.ts"],
12
+ "exclude": [
13
+ "node_modules/**/*",
14
+ "**/*.spec.ts",
15
+ "**/*.test.ts",
16
+ "**/*.demo.ts",
17
+ "**/*.stories.ts",
18
+ "**/*.type-test.ts",
19
+ "docs.ts",
20
+ "docs/**/*"
21
+ ]
22
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "extends": "./tsconfig-model.json",
3
+ "compilerOptions": {
4
+ "noEmit": false,
5
+ "emitDeclarationOnly": false,
6
+ "declaration": false,
7
+ "sourceMap": true,
8
+ "outDir": "../dist/js",
9
+ "rootDir": ".",
10
+ "lib": ["ES2021", "DOM", "DOM.Iterable"]
11
+ },
12
+ "include": ["**/*.ts"],
13
+ "exclude": [
14
+ "node_modules/**/*",
15
+ "**/*.spec.ts",
16
+ "**/*.test.ts",
17
+ "**/*.demo.ts",
18
+ "**/*.stories.ts",
19
+ "**/*.type-test.ts",
20
+ "docs.ts",
21
+ "docs/**/*"
22
+ ]
23
+ }
@@ -234,24 +234,6 @@
234
234
  "./functional/value": [
235
235
  "/sites/concorde/src/core/components/functional/value/value.ts"
236
236
  ],
237
- "./align": [
238
- "/sites/concorde/src/core/components/ui/_css/align.ts"
239
- ],
240
- "./ui/align": [
241
- "/sites/concorde/src/core/components/ui/_css/align.ts"
242
- ],
243
- "./ui/_css/align": [
244
- "/sites/concorde/src/core/components/ui/_css/align.ts"
245
- ],
246
- "./rounded": [
247
- "/sites/concorde/src/core/components/ui/_css/rounded.ts"
248
- ],
249
- "./ui/rounded": [
250
- "/sites/concorde/src/core/components/ui/_css/rounded.ts"
251
- ],
252
- "./ui/_css/rounded": [
253
- "/sites/concorde/src/core/components/ui/_css/rounded.ts"
254
- ],
255
237
  "./scroll": [
256
238
  "/sites/concorde/src/core/components/ui/_css/scroll.ts"
257
239
  ],
@@ -288,24 +270,6 @@
288
270
  "./ui/_css/type": [
289
271
  "/sites/concorde/src/core/components/ui/_css/type.ts"
290
272
  ],
291
- "./ui-aria-labels": [
292
- "/sites/concorde/src/core/components/ui/_i18n/ui-aria-labels.ts"
293
- ],
294
- "./ui/ui-aria-labels": [
295
- "/sites/concorde/src/core/components/ui/_i18n/ui-aria-labels.ts"
296
- ],
297
- "./ui/_i18n/ui-aria-labels": [
298
- "/sites/concorde/src/core/components/ui/_i18n/ui-aria-labels.ts"
299
- ],
300
- "./alert.spec": [
301
- "/sites/concorde/src/core/components/ui/alert/alert.spec.ts"
302
- ],
303
- "./ui/alert.spec": [
304
- "/sites/concorde/src/core/components/ui/alert/alert.spec.ts"
305
- ],
306
- "./ui/alert/alert.spec": [
307
- "/sites/concorde/src/core/components/ui/alert/alert.spec.ts"
308
- ],
309
273
  "./alert": [
310
274
  "/sites/concorde/src/core/components/ui/alert/alert.ts"
311
275
  ],
@@ -759,15 +723,6 @@
759
723
  "./ui/table": [
760
724
  "/sites/concorde/src/core/components/ui/table/table.ts"
761
725
  ],
762
- "./auto": [
763
- "/sites/concorde/src/core/components/ui/theme/theme-collection/auto.ts"
764
- ],
765
- "./ui/auto": [
766
- "/sites/concorde/src/core/components/ui/theme/theme-collection/auto.ts"
767
- ],
768
- "./ui/theme/auto": [
769
- "/sites/concorde/src/core/components/ui/theme/theme-collection/auto.ts"
770
- ],
771
726
  "./core-variables": [
772
727
  "/sites/concorde/src/core/components/ui/theme/theme-collection/core-variables.ts"
773
728
  ],
@@ -801,15 +756,6 @@
801
756
  "./ui/theme": [
802
757
  "/sites/concorde/src/core/components/ui/theme/theme.ts"
803
758
  ],
804
- "./dismissed": [
805
- "/sites/concorde/src/core/components/ui/toast/dismissed.ts"
806
- ],
807
- "./ui/dismissed": [
808
- "/sites/concorde/src/core/components/ui/toast/dismissed.ts"
809
- ],
810
- "./ui/toast/dismissed": [
811
- "/sites/concorde/src/core/components/ui/toast/dismissed.ts"
812
- ],
813
759
  "./message-subscriber": [
814
760
  "/sites/concorde/src/core/components/ui/toast/message-subscriber.ts"
815
761
  ],
@@ -945,6 +891,9 @@
945
891
  "./directives/Wording": [
946
892
  "/sites/concorde/src/core/directives/Wording.ts"
947
893
  ],
894
+ "./directives/stableTemplateContent": [
895
+ "/sites/concorde/src/core/directives/stableTemplateContent.ts"
896
+ ],
948
897
  "./mixins/Fetcher": [
949
898
  "/sites/concorde/src/core/mixins/Fetcher.ts"
950
899
  ],
@@ -1020,9 +969,6 @@
1020
969
  "./utils/derive": [
1021
970
  "/sites/concorde/src/core/utils/derive.ts"
1022
971
  ],
1023
- "./utils/dismissed": [
1024
- "/sites/concorde/src/core/utils/dismissed.ts"
1025
- ],
1026
972
  "./utils/dpOptions.spec": [
1027
973
  "/sites/concorde/src/core/utils/dpOptions.spec.ts"
1028
974
  ],
@@ -1038,12 +984,6 @@
1038
984
  "./utils/jsonataRuntime": [
1039
985
  "/sites/concorde/src/core/utils/jsonataRuntime.ts"
1040
986
  ],
1041
- "./utils/positioning.spec": [
1042
- "/sites/concorde/src/core/utils/positioning.spec.ts"
1043
- ],
1044
- "./utils/positioning": [
1045
- "/sites/concorde/src/core/utils/positioning.ts"
1046
- ],
1047
987
  "./utils/publisherPathKey.spec": [
1048
988
  "/sites/concorde/src/core/utils/publisherPathKey.spec.ts"
1049
989
  ],
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supersoniks/concorde",
3
- "version": "5.0.5",
3
+ "version": "5.1.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "",
@@ -12,6 +12,7 @@
12
12
  "build-docs": "LIB_NAME=docs vite build",
13
13
  "postbuild-docs": "node scripts/post-build-docs.js",
14
14
  "prepublishOnly": "node scripts/pre-publish.mjs",
15
+ "generate:sdui-catalog": "node scripts/generate-sdui-catalog.mjs",
15
16
  "test": "vitest --reporter verbose --watch",
16
17
  "test:ci": "vitest run --reporter verbose",
17
18
  "ai-init": "node scripts/ai-init.mjs"
@@ -19,6 +20,8 @@
19
20
  "exports": {
20
21
  "./core/components/ui/icon/icons.json": "./src/core/components/ui/icon/icons.json",
21
22
  "./core/components/functional/sdui/default-library.json": "./src/core/components/functional/sdui/default-library.json",
23
+ "./core/components/functional/sdui/component-catalog.json": "./src/core/components/functional/sdui/component-catalog.json",
24
+ "./sdui/component-catalog.json": "./src/core/components/functional/sdui/component-catalog.json",
22
25
  "./dataProviderKey": "./src/core/utils/dataProviderKey.ts",
23
26
  "./*": "./src/*.ts",
24
27
  "./vite-config": "./vite/config.js",
@@ -73,9 +76,39 @@
73
76
  "./SDUIDescriptorTransformer": "./src/core/components/functional/sdui/SDUIDescriptorTransformer.ts",
74
77
  "./functional/SDUIDescriptorTransformer": "./src/core/components/functional/sdui/SDUIDescriptorTransformer.ts",
75
78
  "./functional/sdui/SDUIDescriptorTransformer": "./src/core/components/functional/sdui/SDUIDescriptorTransformer.ts",
79
+ "./descriptors": "./src/core/components/functional/sdui/__fixtures__/descriptors.ts",
80
+ "./functional/descriptors": "./src/core/components/functional/sdui/__fixtures__/descriptors.ts",
81
+ "./functional/sdui/descriptors": "./src/core/components/functional/sdui/__fixtures__/descriptors.ts",
82
+ "./component-catalog.spec": "./src/core/components/functional/sdui/component-catalog.spec.ts",
83
+ "./functional/component-catalog.spec": "./src/core/components/functional/sdui/component-catalog.spec.ts",
84
+ "./functional/sdui/component-catalog.spec": "./src/core/components/functional/sdui/component-catalog.spec.ts",
85
+ "./sdui-action.spec": "./src/core/components/functional/sdui/sdui-action.spec.ts",
86
+ "./functional/sdui-action.spec": "./src/core/components/functional/sdui/sdui-action.spec.ts",
87
+ "./functional/sdui/sdui-action.spec": "./src/core/components/functional/sdui/sdui-action.spec.ts",
88
+ "./sdui-dom-snapshot": "./src/core/components/functional/sdui/sdui-dom-snapshot.ts",
89
+ "./functional/sdui-dom-snapshot": "./src/core/components/functional/sdui/sdui-dom-snapshot.ts",
90
+ "./functional/sdui/sdui-dom-snapshot": "./src/core/components/functional/sdui/sdui-dom-snapshot.ts",
91
+ "./sdui-incremental.spec": "./src/core/components/functional/sdui/sdui-incremental.spec.ts",
92
+ "./functional/sdui-incremental.spec": "./src/core/components/functional/sdui/sdui-incremental.spec.ts",
93
+ "./functional/sdui/sdui-incremental.spec": "./src/core/components/functional/sdui/sdui-incremental.spec.ts",
94
+ "./sdui-partial.spec": "./src/core/components/functional/sdui/sdui-partial.spec.ts",
95
+ "./functional/sdui-partial.spec": "./src/core/components/functional/sdui/sdui-partial.spec.ts",
96
+ "./functional/sdui/sdui-partial.spec": "./src/core/components/functional/sdui/sdui-partial.spec.ts",
97
+ "./sdui-partial": "./src/core/components/functional/sdui/sdui-partial.ts",
98
+ "./functional/sdui-partial": "./src/core/components/functional/sdui/sdui-partial.ts",
99
+ "./functional/sdui/sdui-partial": "./src/core/components/functional/sdui/sdui-partial.ts",
100
+ "./sdui-safe.spec": "./src/core/components/functional/sdui/sdui-safe.spec.ts",
101
+ "./functional/sdui-safe.spec": "./src/core/components/functional/sdui/sdui-safe.spec.ts",
102
+ "./functional/sdui/sdui-safe.spec": "./src/core/components/functional/sdui/sdui-safe.spec.ts",
103
+ "./sdui-safe": "./src/core/components/functional/sdui/sdui-safe.ts",
104
+ "./functional/sdui-safe": "./src/core/components/functional/sdui/sdui-safe.ts",
105
+ "./functional/sdui/sdui-safe": "./src/core/components/functional/sdui/sdui-safe.ts",
76
106
  "./sdui-utils": "./src/core/components/functional/sdui/sdui-utils.ts",
77
107
  "./functional/sdui-utils": "./src/core/components/functional/sdui/sdui-utils.ts",
78
108
  "./functional/sdui/sdui-utils": "./src/core/components/functional/sdui/sdui-utils.ts",
109
+ "./sdui.regression.spec": "./src/core/components/functional/sdui/sdui.regression.spec.ts",
110
+ "./functional/sdui.regression.spec": "./src/core/components/functional/sdui/sdui.regression.spec.ts",
111
+ "./functional/sdui/sdui.regression.spec": "./src/core/components/functional/sdui/sdui.regression.spec.ts",
79
112
  "./sdui": "./src/core/components/functional/sdui/sdui.ts",
80
113
  "./functional/sdui": "./src/core/components/functional/sdui/sdui.ts",
81
114
  "./sonic-scope": "./src/core/components/functional/sonic-scope/sonic-scope.ts",
@@ -426,6 +459,7 @@
426
459
  "./TestUtils": "./src/test-utils/TestUtils.ts"
427
460
  },
428
461
  "devDependencies": {
462
+ "@custom-elements-manifest/analyzer": "^0.11.0",
429
463
  "@tailwindcss/typography": "^0.5.12",
430
464
  "@types/node": "^24.5.2",
431
465
  "@vitejs/plugin-basic-ssl": "^2.1.0",
@@ -452,4 +486,4 @@
452
486
  "url-pattern": "^1.0.3"
453
487
  },
454
488
  "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
455
- }
489
+ }
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Génère un catalogue neutre de composants pour SDUI / agents externes.
3
+ * Build-only : lit le Custom Elements Manifest + les tagName sources.
4
+ *
5
+ * Sorties :
6
+ * - src/core/components/functional/sdui/component-catalog.json
7
+ * - src/core/components/functional/sdui/component-catalog.gaps.json
8
+ */
9
+ import { execFileSync } from "child_process";
10
+ import fs from "fs";
11
+ import path from "path";
12
+ import { fileURLToPath } from "url";
13
+
14
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
+ const ROOT = path.resolve(__dirname, "..");
16
+ const CEM_DIR = path.join(ROOT, ".tmp-cem");
17
+ const CEM_PATH = path.join(CEM_DIR, "custom-elements.json");
18
+ const OUT_CATALOG = path.join(
19
+ ROOT,
20
+ "src/core/components/functional/sdui/component-catalog.json"
21
+ );
22
+ const OUT_GAPS = path.join(
23
+ ROOT,
24
+ "src/core/components/functional/sdui/component-catalog.gaps.json"
25
+ );
26
+
27
+ function extractTagNameFromSource(filePath) {
28
+ if (!fs.existsSync(filePath)) return undefined;
29
+ const src = fs.readFileSync(filePath, "utf8");
30
+ const literal = src.match(/@customElement\(\s*["'`]([^"'`]+)["'`]\s*\)/);
31
+ if (literal) return literal[1];
32
+ const constTag = src.match(
33
+ /(?:const|let|var)\s+tagName\s*=\s*["'`]([^"'`]+)["'`]/
34
+ );
35
+ if (constTag && /@customElement\(\s*tagName\s*\)/.test(src)) {
36
+ return constTag[1];
37
+ }
38
+ return undefined;
39
+ }
40
+
41
+ function parseAllowedValues(typeText) {
42
+ if (!typeText) return undefined;
43
+ const values = [...typeText.matchAll(/["']([^"']+)["']/g)].map((m) => m[1]);
44
+ // Ignore if it looks like a single non-enum string type annotation noise
45
+ if (values.length < 2) return undefined;
46
+ return [...new Set(values)];
47
+ }
48
+
49
+ function stripDefaultQuotes(value) {
50
+ if (value == null) return undefined;
51
+ const s = String(value).trim();
52
+ if (
53
+ (s.startsWith('"') && s.endsWith('"')) ||
54
+ (s.startsWith("'") && s.endsWith("'"))
55
+ ) {
56
+ return s.slice(1, -1);
57
+ }
58
+ return s;
59
+ }
60
+
61
+ function isPublicProp(member) {
62
+ if (member.kind !== "field") return false;
63
+ if (member.privacy === "private" || member.privacy === "protected")
64
+ return false;
65
+ if (member.static) return false;
66
+ // Lit reactive props typically have attribute or are @property
67
+ return member.attribute != null || member.reflects || member.type;
68
+ }
69
+
70
+ /**
71
+ * Transforme un CEM Package en catalogue neutre.
72
+ * Exportée pour les tests unitaires.
73
+ */
74
+ export function cemToCatalog(cem, { resolveTagName } = {}) {
75
+ const components = [];
76
+ const insufficientAnnotations = [];
77
+
78
+ for (const mod of cem.modules || []) {
79
+ const modulePath = mod.path;
80
+ for (const decl of mod.declarations || []) {
81
+ if (decl.kind !== "class" || !decl.customElement) continue;
82
+
83
+ const tag =
84
+ decl.tagName ||
85
+ (resolveTagName ? resolveTagName(modulePath, decl) : undefined);
86
+ if (!tag) {
87
+ insufficientAnnotations.push({
88
+ className: decl.name,
89
+ module: modulePath,
90
+ reasons: ["tagName introuvable (const tagName non résolu par CEM)"],
91
+ });
92
+ continue;
93
+ }
94
+
95
+ const props = (decl.members || []).filter(isPublicProp).map((m) => {
96
+ const typeText = m.type?.text?.replace(/\s+/g, " ").trim();
97
+ const prop = {
98
+ name: m.name,
99
+ attribute: m.attribute ?? m.name,
100
+ type: typeText || "unknown",
101
+ };
102
+ const values = parseAllowedValues(typeText);
103
+ if (values) prop.values = values;
104
+ const def = stripDefaultQuotes(m.default);
105
+ if (def !== undefined) prop.default = def;
106
+ if (m.description) prop.description = m.description.trim();
107
+ return prop;
108
+ });
109
+
110
+ const component = {
111
+ tag,
112
+ className: decl.name,
113
+ module: modulePath,
114
+ description: (decl.description || "").trim() || undefined,
115
+ props,
116
+ };
117
+
118
+ if (decl.slots?.length) {
119
+ component.slots = decl.slots.map((s) => ({
120
+ name: s.name || "",
121
+ description: s.description?.trim() || undefined,
122
+ }));
123
+ }
124
+ if (decl.events?.length) {
125
+ component.events = decl.events.map((e) => ({
126
+ name: e.name,
127
+ description: e.description?.trim() || undefined,
128
+ type: e.type?.text || undefined,
129
+ }));
130
+ }
131
+
132
+ // Exemple : premier @example du JSDoc si le CEM l'expose
133
+ const example = decl.examples?.[0]?.text || decl.example;
134
+ if (example) component.example = String(example).trim();
135
+
136
+ components.push(component);
137
+
138
+ const reasons = [];
139
+ if (!component.description) reasons.push("pas de description de classe");
140
+ const propsWithoutDesc = props.filter((p) => !p.description);
141
+ if (propsWithoutDesc.length > 0) {
142
+ reasons.push(
143
+ `${propsWithoutDesc.length} prop(s) sans description (${propsWithoutDesc
144
+ .slice(0, 5)
145
+ .map((p) => p.name)
146
+ .join(", ")}${propsWithoutDesc.length > 5 ? ", …" : ""})`
147
+ );
148
+ }
149
+ const propsUnknownType = props.filter((p) => p.type === "unknown");
150
+ if (propsUnknownType.length > 0) {
151
+ reasons.push(
152
+ `${propsUnknownType.length} prop(s) sans type (${propsUnknownType
153
+ .slice(0, 5)
154
+ .map((p) => p.name)
155
+ .join(", ")})`
156
+ );
157
+ }
158
+ // Pas d'exemple JSDoc : fréquent, non bloquant — omis des gaps.
159
+ if (reasons.length) {
160
+ insufficientAnnotations.push({ tag, module: modulePath, reasons });
161
+ }
162
+ }
163
+ }
164
+
165
+ components.sort((a, b) => a.tag.localeCompare(b.tag));
166
+ insufficientAnnotations.sort((a, b) =>
167
+ (a.tag || a.className || "").localeCompare(b.tag || b.className || "")
168
+ );
169
+
170
+ return {
171
+ version: 1,
172
+ generatedAt: new Date().toISOString(),
173
+ componentCount: components.length,
174
+ components,
175
+ insufficientAnnotations,
176
+ };
177
+ }
178
+
179
+ function runCem() {
180
+ fs.mkdirSync(CEM_DIR, { recursive: true });
181
+ const cemBin = path.join(
182
+ ROOT,
183
+ "node_modules/@custom-elements-manifest/analyzer/cem.js"
184
+ );
185
+ execFileSync(
186
+ process.execPath,
187
+ [
188
+ cemBin,
189
+ "analyze",
190
+ "--config",
191
+ path.join(ROOT, "custom-elements-manifest.config.mjs"),
192
+ ],
193
+ { cwd: ROOT, stdio: ["ignore", "pipe", "pipe"] }
194
+ );
195
+ // Ne pas laisser cem écrire customElements dans package.json
196
+ const pkgPath = path.join(ROOT, "package.json");
197
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
198
+ if (pkg.customElements) {
199
+ delete pkg.customElements;
200
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
201
+ }
202
+ }
203
+
204
+ function main() {
205
+ console.log("🚀 SDUI component catalog — CEM analyze…");
206
+ runCem();
207
+ const cem = JSON.parse(fs.readFileSync(CEM_PATH, "utf8"));
208
+ const catalog = cemToCatalog(cem, {
209
+ resolveTagName(modulePath) {
210
+ const abs = path.isAbsolute(modulePath)
211
+ ? modulePath
212
+ : path.join(ROOT, modulePath);
213
+ return extractTagNameFromSource(abs);
214
+ },
215
+ });
216
+
217
+ const { insufficientAnnotations, ...published } = catalog;
218
+ // Garder un résumé léger dans le catalogue publié
219
+ published.insufficientAnnotationCount = insufficientAnnotations.length;
220
+
221
+ fs.writeFileSync(OUT_CATALOG, JSON.stringify(published, null, 2) + "\n");
222
+ fs.writeFileSync(
223
+ OUT_GAPS,
224
+ JSON.stringify(
225
+ {
226
+ version: 1,
227
+ generatedAt: catalog.generatedAt,
228
+ count: insufficientAnnotations.length,
229
+ items: insufficientAnnotations,
230
+ },
231
+ null,
232
+ 2
233
+ ) + "\n"
234
+ );
235
+
236
+ console.log(
237
+ `✅ Catalog: ${published.componentCount} composants → ${path.relative(ROOT, OUT_CATALOG)}`
238
+ );
239
+ console.log(
240
+ `ℹ️ Annotations insuffisantes: ${insufficientAnnotations.length} → ${path.relative(ROOT, OUT_GAPS)}`
241
+ );
242
+ }
243
+
244
+ const isMain =
245
+ process.argv[1] &&
246
+ path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
247
+
248
+ if (isMain) {
249
+ main();
250
+ }
@@ -0,0 +1,91 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { cemToCatalog } from "./generate-sdui-catalog.mjs";
3
+
4
+ const fixtureCem = {
5
+ schemaVersion: "1.0.0",
6
+ modules: [
7
+ {
8
+ kind: "javascript-module",
9
+ path: "src/core/components/ui/button/button.ts",
10
+ declarations: [
11
+ {
12
+ kind: "class",
13
+ customElement: true,
14
+ name: "Button",
15
+ description: "Un bouton.",
16
+ members: [
17
+ {
18
+ kind: "field",
19
+ name: "type",
20
+ attribute: "type",
21
+ type: { text: '"default" | "success"' },
22
+ default: '"default"',
23
+ description: "Couleur",
24
+ },
25
+ {
26
+ kind: "field",
27
+ name: "secret",
28
+ privacy: "private",
29
+ type: { text: "string" },
30
+ },
31
+ {
32
+ kind: "field",
33
+ name: "undocumented",
34
+ attribute: "undocumented",
35
+ type: { text: "string" },
36
+ },
37
+ ],
38
+ slots: [{ name: "", description: "contenu" }],
39
+ events: [{ name: "click", type: { text: "Event" } }],
40
+ },
41
+ ],
42
+ },
43
+ ],
44
+ };
45
+
46
+ describe("cemToCatalog", () => {
47
+ it("produit un catalogue neutre avec props publiques", () => {
48
+ const catalog = cemToCatalog(fixtureCem, {
49
+ resolveTagName: () => "sonic-button",
50
+ });
51
+ expect(catalog.componentCount).toBe(1);
52
+ const btn = catalog.components[0];
53
+ expect(btn.tag).toBe("sonic-button");
54
+ expect(btn.description).toBe("Un bouton.");
55
+ expect(btn.props.map((p: { name: string }) => p.name)).toEqual([
56
+ "type",
57
+ "undocumented",
58
+ ]);
59
+ expect(btn.props[0]).toMatchObject({
60
+ name: "type",
61
+ attribute: "type",
62
+ type: '"default" | "success"',
63
+ values: ["default", "success"],
64
+ default: "default",
65
+ description: "Couleur",
66
+ });
67
+ expect(btn.slots?.[0].name).toBe("");
68
+ expect(btn.events?.[0].name).toBe("click");
69
+ });
70
+
71
+ it("liste les annotations insuffisantes", () => {
72
+ const catalog = cemToCatalog(fixtureCem, {
73
+ resolveTagName: () => "sonic-button",
74
+ });
75
+ const gap = catalog.insufficientAnnotations.find(
76
+ (g: { tag?: string }) => g.tag === "sonic-button"
77
+ );
78
+ expect(gap).toBeTruthy();
79
+ expect(gap.reasons.some((r: string) => r.includes("sans description"))).toBe(
80
+ true
81
+ );
82
+ });
83
+
84
+ it("signale un custom element sans tag résolu", () => {
85
+ const catalog = cemToCatalog(fixtureCem, {
86
+ resolveTagName: () => undefined,
87
+ });
88
+ expect(catalog.componentCount).toBe(0);
89
+ expect(catalog.insufficientAnnotations[0].reasons[0]).toMatch(/tagName/);
90
+ });
91
+ });