@supersoniks/concorde 4.9.0 → 4.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/build-infos.json +1 -1
  2. package/concorde-core.bundle.js +195 -195
  3. package/concorde-core.es.js +3390 -3370
  4. package/dist/concorde-core.bundle.js +195 -195
  5. package/dist/concorde-core.es.js +3390 -3370
  6. package/dist/docs-mock-api-sw.js +3 -1
  7. package/dist/docs-mock-api-sw.js.map +2 -2
  8. package/dist/js/core/decorators/api.js +64 -12
  9. package/dist/js/core/decorators/api.js.map +1 -1
  10. package/dist/js/core/utils/HTML.js +4 -5
  11. package/dist/js/core/utils/HTML.js.map +1 -1
  12. package/dist/robots.txt +15 -1
  13. package/dist/types/core/decorators/api.d.ts +14 -1
  14. package/dist/types/core/decorators/api.d.ts.map +1 -1
  15. package/dist/types/core/utils/HTML.d.ts.map +1 -1
  16. package/docs/assets/{index-t0-i22oI.css → index-Bnp7gVaA.css} +1 -1
  17. package/docs/assets/{index-BEgZEIbv.js → index-hElUgV9_.js} +894 -552
  18. package/docs/crawl/core/components/functional/date/date.html +190 -0
  19. package/docs/crawl/core/components/functional/fetch/fetch.html +109 -0
  20. package/docs/crawl/core/components/functional/if/if.html +27 -0
  21. package/docs/crawl/core/components/functional/list/list.html +70 -0
  22. package/docs/crawl/core/components/functional/mix/mix.html +45 -0
  23. package/docs/crawl/core/components/functional/queue/queue.html +96 -0
  24. package/docs/crawl/core/components/functional/router/router.html +106 -0
  25. package/docs/crawl/core/components/functional/sdui/sdui.html +269 -0
  26. package/docs/crawl/core/components/functional/states/states.html +66 -0
  27. package/docs/crawl/core/components/functional/submit/submit.html +160 -0
  28. package/docs/crawl/core/components/functional/subscriber/subscriber.html +67 -0
  29. package/docs/crawl/core/components/functional/value/value.html +51 -0
  30. package/docs/crawl/core/components/ui/alert/alert.html +110 -0
  31. package/docs/crawl/core/components/ui/alert-messages/alert-messages.html +23 -0
  32. package/docs/crawl/core/components/ui/badge/badge.html +119 -0
  33. package/docs/crawl/core/components/ui/button/button.html +149 -0
  34. package/docs/crawl/core/components/ui/captcha/captcha.html +30 -0
  35. package/docs/crawl/core/components/ui/card/card.html +99 -0
  36. package/docs/crawl/core/components/ui/divider/divider.html +58 -0
  37. package/docs/crawl/core/components/ui/form/checkbox/checkbox.html +73 -0
  38. package/docs/crawl/core/components/ui/form/fieldset/fieldset.html +135 -0
  39. package/docs/crawl/core/components/ui/form/form-actions/form-actions.html +79 -0
  40. package/docs/crawl/core/components/ui/form/form-layout/form-layout.html +62 -0
  41. package/docs/crawl/core/components/ui/form/input/input.html +109 -0
  42. package/docs/crawl/core/components/ui/form/input-autocomplete/input-autocomplete.html +106 -0
  43. package/docs/crawl/core/components/ui/form/radio/radio.html +56 -0
  44. package/docs/crawl/core/components/ui/form/select/select.html +73 -0
  45. package/docs/crawl/core/components/ui/form/switch/switch.html +56 -0
  46. package/docs/crawl/core/components/ui/form/textarea/textarea.html +59 -0
  47. package/docs/crawl/core/components/ui/group/group.html +82 -0
  48. package/docs/crawl/core/components/ui/icon/icon.html +133 -0
  49. package/docs/crawl/core/components/ui/image/image.html +110 -0
  50. package/docs/crawl/core/components/ui/link/link.html +42 -0
  51. package/docs/crawl/core/components/ui/loader/loader.html +50 -0
  52. package/docs/crawl/core/components/ui/menu/menu.html +322 -0
  53. package/docs/crawl/core/components/ui/modal/modal.html +117 -0
  54. package/docs/crawl/core/components/ui/pop/pop.html +102 -0
  55. package/docs/crawl/core/components/ui/progress/progress.html +58 -0
  56. package/docs/crawl/core/components/ui/table/table.html +413 -0
  57. package/docs/crawl/core/components/ui/toast/toast.html +122 -0
  58. package/docs/crawl/core/components/ui/tooltip/tooltip.html +79 -0
  59. package/docs/crawl/docs/_core-concept/dataFlow.html +166 -0
  60. package/docs/crawl/docs/_core-concept/overview.html +66 -0
  61. package/docs/crawl/docs/_core-concept/subscriber.html +75 -0
  62. package/docs/crawl/docs/_decorators/ancestor-attribute.html +116 -0
  63. package/docs/crawl/docs/_decorators/auto-subscribe.html +202 -0
  64. package/docs/crawl/docs/_decorators/bind.html +141 -0
  65. package/docs/crawl/docs/_decorators/get.html +120 -0
  66. package/docs/crawl/docs/_decorators/handle.html +165 -0
  67. package/docs/crawl/docs/_decorators/on-assign.html +355 -0
  68. package/docs/crawl/docs/_decorators/patch.html +52 -0
  69. package/docs/crawl/docs/_decorators/post.html +102 -0
  70. package/docs/crawl/docs/_decorators/publish.html +61 -0
  71. package/docs/crawl/docs/_decorators/put.html +49 -0
  72. package/docs/crawl/docs/_decorators/subscribe.html +109 -0
  73. package/docs/crawl/docs/_decorators/wait-for-ancestors.html +137 -0
  74. package/docs/crawl/docs/_directives/sub.html +93 -0
  75. package/docs/crawl/docs/_getting-started/ai-agents.html +134 -0
  76. package/docs/crawl/docs/_getting-started/concorde-manual-install.html +100 -0
  77. package/docs/crawl/docs/_getting-started/concorde-outside.html +58 -0
  78. package/docs/crawl/docs/_getting-started/create-a-component.html +111 -0
  79. package/docs/crawl/docs/_getting-started/my-first-component.html +189 -0
  80. package/docs/crawl/docs/_getting-started/my-first-subscriber.html +110 -0
  81. package/docs/crawl/docs/_getting-started/pubsub.html +62 -0
  82. package/docs/crawl/docs/_getting-started/start.html +76 -0
  83. package/docs/crawl/docs/_getting-started/theming.html +85 -0
  84. package/docs/crawl/docs/_misc/api-configuration.html +149 -0
  85. package/docs/crawl/docs/_misc/dataProviderKey.html +135 -0
  86. package/docs/crawl/docs/_misc/docs-mock-api.html +146 -0
  87. package/docs/crawl/docs/_misc/dynamic-path.html +180 -0
  88. package/docs/crawl/docs/_misc/endpoint.html +50 -0
  89. package/docs/crawl/docs/_misc/html-integration.html +47 -0
  90. package/docs/crawl/hubs/decorators.html +467 -0
  91. package/docs/crawl/hubs/form-components.html +357 -0
  92. package/docs/crawl/hubs/remote-data.html +374 -0
  93. package/docs/crawl/index.html +99 -0
  94. package/docs/docs-mock-api-sw.js +3 -1
  95. package/docs/docs-mock-api-sw.js.map +2 -2
  96. package/docs/index.html +3 -3
  97. package/docs/llms-full.txt +5423 -0
  98. package/docs/llms.txt +102 -0
  99. package/docs/robots.txt +15 -1
  100. package/docs/sitemap.xml +231 -0
  101. package/docs/src/docs/_decorators/ancestor-attribute.md +56 -8
  102. package/docs/src/docs/_decorators/get.md +47 -1
  103. package/docs/src/docs/search/docs-search.json +92 -2
  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 -285
  107. package/index.html +1 -0
  108. package/package.json +1 -1
  109. package/public/docs-mock-api-sw.js +3 -1
  110. package/public/docs-mock-api-sw.js.map +2 -2
  111. package/public/robots.txt +15 -1
  112. package/scripts/generate-crawl-docs.mjs +569 -0
  113. package/scripts/post-build-docs.js +18 -14
  114. package/src/core/decorators/api.spec.ts +74 -4
  115. package/src/core/decorators/api.ts +103 -20
  116. package/src/core/decorators/subscriber/ancestorAttribute.spec.ts +42 -0
  117. package/src/core/utils/HTML.ts +4 -5
  118. package/src/docs/_decorators/get.md +47 -1
  119. package/src/docs/components/docs-demo-sources.ts +7 -2
  120. package/src/docs/example/decorators-demo-geo.ts +5 -0
  121. package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +72 -31
  122. package/src/docs/mock-api/router.ts +3 -1
  123. package/src/docs/search/docs-search.json +92 -2
@@ -1,32 +1,37 @@
1
1
  import { html, LitElement } from "lit";
2
2
  import { customElement, property, state } from "lit/decorators.js";
3
3
  import { get, handle, publish, subscribe } from "@supersoniks/concorde/decorators";
4
- import type {
5
- APIConfiguration,
6
- ApiResult,
7
- } from "@supersoniks/concorde/core/utils/api";
4
+ import type { ApiResult } from "@supersoniks/concorde/core/utils/api";
8
5
  import { DataProviderKey } from "@supersoniks/concorde/core/utils/dataProviderKey";
9
6
  import { sub } from "@supersoniks/concorde/directives";
10
7
  import {
8
+ dp,
11
9
  get as storeGet,
12
10
  set,
13
11
  } from "@supersoniks/concorde/core/utils/PublisherProxy";
14
12
  import { publishDemoKey } from "./docs-provider-keys";
15
- import {
16
- docsDemoDynApiConfAKey,
17
- docsDemoDynApiConfBKey,
18
- } from "./decorators-demo-geo";
19
13
  import { tailwind } from "../tailwind";
20
14
  import "./decorators-demo-init";
21
15
  import {
22
16
  docsDemoDynApiConfKeyTemplate,
23
17
  docsDemoGeoApiConfigurationKey,
18
+ docsDemoGeoCommunesRefreshKey,
24
19
  geoCommunesApiGetEndpoint,
25
20
  geoCommunesApiGetEndpointDynamic,
26
21
  geoCommunesApiGetPublishKey,
27
22
  type GeoCommuneRow,
28
23
  } from "./decorators-demo-geo";
29
24
 
25
+ function formatFetchedAt(response: Response | null | undefined): string {
26
+ const raw = response?.headers.get("X-Fetched-At");
27
+ if (!raw) return "—";
28
+ try {
29
+ return new Date(raw).toLocaleTimeString();
30
+ } catch {
31
+ return raw;
32
+ }
33
+ }
34
+
30
35
  type PublishDemoData = {
31
36
  email: string;
32
37
  message: string;
@@ -90,22 +95,35 @@ export class DemoPublish extends LitElement {
90
95
  export class DemoApiGet extends LitElement {
91
96
  static styles = [tailwind];
92
97
 
93
- @get(geoCommunesApiGetEndpoint, docsDemoGeoApiConfigurationKey)
98
+ @get(geoCommunesApiGetEndpoint, docsDemoGeoApiConfigurationKey, {
99
+ triggerKey: docsDemoGeoCommunesRefreshKey,
100
+ })
94
101
  @state()
95
102
  geoApiPayload?: ApiResult<GeoCommuneRow[]>;
96
103
 
104
+ private refresh() {
105
+ dp(docsDemoGeoCommunesRefreshKey).invalidate();
106
+ }
107
+
97
108
  render() {
98
109
  const rows = this.geoApiPayload?.result;
99
110
  const status = this.geoApiPayload?.response?.status;
111
+ const fetchedAt = formatFetchedAt(this.geoApiPayload?.response ?? null);
100
112
  return html`
101
113
  <div class="space-y-2">
102
114
  <p class="text-sm text-neutral-600 dark:text-neutral-400">
103
115
  <code>@get</code> — même service que
104
116
  <code>sonic-queue</code> (<code>/docs-mock-api/geo/</code>).
105
117
  Propriété typée <code>ApiResult&lt;T&gt;</code>.
118
+ Refetch via <code>triggerKey</code> (<code
119
+ >docsDemoGeoCommunesRefresh</code
120
+ >).
106
121
  </p>
122
+ <sonic-button size="sm" @click=${this.refresh}>Rafraîchir</sonic-button>
107
123
  ${status != null
108
- ? html`<p class="text-xs text-neutral-500">HTTP ${status}</p>`
124
+ ? html`<p class="text-xs text-neutral-500">
125
+ HTTP ${status} · fetch ${fetchedAt}
126
+ </p>`
109
127
  : ""}
110
128
  ${this.geoApiPayload === null
111
129
  ? html`<p class="text-neutral-500">Chargement…</p>`
@@ -139,29 +157,23 @@ export class DemoApiGetConfigurationKey extends LitElement {
139
157
  @property({ type: Number })
140
158
  communeLimit = 5;
141
159
 
142
- @get(geoCommunesApiGetEndpointDynamic, docsDemoDynApiConfKeyTemplate)
160
+ @get(geoCommunesApiGetEndpointDynamic, docsDemoDynApiConfKeyTemplate, {
161
+ triggerKey: docsDemoGeoCommunesRefreshKey,
162
+ })
143
163
  @state()
144
164
  geoApiPayloadDyn?: ApiResult<GeoCommuneRow[]>;
145
165
 
146
- private touchCurrentConfigPublisher() {
147
- const key =
148
- this.configSlot === "A" ? docsDemoDynApiConfAKey : docsDemoDynApiConfBKey;
149
- const cur = storeGet(key) as APIConfiguration;
150
- set(key, {
151
- ...cur,
152
- blockUntilDone: !cur.blockUntilDone,
153
- });
154
- }
155
-
156
166
  render() {
157
167
  const rows = this.geoApiPayloadDyn?.result;
158
168
  const status = this.geoApiPayloadDyn?.response?.status;
169
+ const fetchedAt = formatFetchedAt(this.geoApiPayloadDyn?.response ?? null);
159
170
  return html`
160
171
  <div class="space-y-3">
161
172
  <p class="text-sm text-neutral-600 dark:text-neutral-400">
162
173
  Config dynamique (<code>docsDemoDynApiConf\${configSlot}</code>) +
163
- path d’endpoint avec <code>communeLimit</code>. « Toucher la config »
164
- déclenche un nouveau GET.
174
+ path d’endpoint avec <code>communeLimit</code>. Le refetch manuel
175
+ passe par <code>triggerKey</code> — voir le bouton « ailleurs »
176
+ ci-dessous dans la doc.
165
177
  </p>
166
178
  <div class="flex flex-wrap gap-2 items-center">
167
179
  <span class="text-xs text-neutral-500">Limite API :</span>
@@ -196,16 +208,11 @@ export class DemoApiGetConfigurationKey extends LitElement {
196
208
  }}
197
209
  >docsDemoDynApiConfB</sonic-button
198
210
  >
199
- <sonic-button
200
- size="sm"
201
- @click=${() => this.touchCurrentConfigPublisher()}
202
- >Toucher la config</sonic-button
203
- >
204
211
  </div>
205
212
  ${status != null
206
213
  ? html`<p class="text-xs text-neutral-500">
207
- HTTP ${status} · limit=${this.communeLimit} · conf=
208
- docsDemoDynApiConf${this.configSlot}
214
+ HTTP ${status} · fetch ${fetchedAt} · limit=${this.communeLimit} ·
215
+ conf=docsDemoDynApiConf${this.configSlot}
209
216
  </p>`
210
217
  : ""}
211
218
  ${this.geoApiPayloadDyn === null
@@ -230,6 +237,35 @@ export class DemoApiGetConfigurationKey extends LitElement {
230
237
  }
231
238
  }
232
239
 
240
+ /** Déclenche le refetch d’un `@get` distant via `triggerKey` (sans toucher la config). */
241
+ @customElement("demo-api-get-refresh-remote")
242
+ export class DemoApiGetRefreshRemote extends LitElement {
243
+ static styles = [tailwind];
244
+
245
+ private refreshFromElsewhere() {
246
+ dp(docsDemoGeoCommunesRefreshKey).invalidate();
247
+ }
248
+
249
+ render() {
250
+ return html`
251
+ <div
252
+ class="rounded border border-dashed border-neutral-300 dark:border-neutral-600 p-3 space-y-2"
253
+ >
254
+ <p class="text-sm text-neutral-600 dark:text-neutral-400">
255
+ Composant séparé — même publisher
256
+ <code>docsDemoGeoCommunesRefresh</code> :
257
+ </p>
258
+ <pre
259
+ class="text-xs bg-neutral-100 dark:bg-neutral-800 p-2 rounded overflow-x-auto"
260
+ ><code>dp(docsDemoGeoCommunesRefreshKey).invalidate();</code></pre>
261
+ <sonic-button size="sm" variant="secondary" @click=${this.refreshFromElsewhere}>
262
+ Rafraîchir le GET (depuis ailleurs)
263
+ </sonic-button>
264
+ </div>
265
+ `;
266
+ }
267
+ }
268
+
233
269
  @customElement("demo-api-get-publish-subscribe")
234
270
  export class DemoApiGetPublishSubscribe extends LitElement {
235
271
  static styles = [tailwind];
@@ -247,6 +283,9 @@ export class DemoApiGetPublishSubscribe extends LitElement {
247
283
  const rows =
248
284
  this.geoCommunesFromSubscribe ?? this.geoApiPayloadPublished?.result;
249
285
  const status = this.geoApiPayloadPublished?.response?.status;
286
+ const fetchedAt = formatFetchedAt(
287
+ this.geoApiPayloadPublished?.response ?? null,
288
+ );
250
289
  return html`
251
290
  <div class="space-y-2">
252
291
  <p class="text-sm text-neutral-600 dark:text-neutral-400">
@@ -255,7 +294,9 @@ export class DemoApiGetPublishSubscribe extends LitElement {
255
294
  rendu que <code>&lt;demo-api-get&gt;</code> (doc @get).
256
295
  </p>
257
296
  ${status != null
258
- ? html`<p class="text-xs text-neutral-500">HTTP ${status}</p>`
297
+ ? html`<p class="text-xs text-neutral-500">
298
+ HTTP ${status} · fetch ${fetchedAt}
299
+ </p>`
259
300
  : ""}
260
301
  ${this.geoApiPayloadPublished === null
261
302
  ? html`<p class="text-neutral-500">Chargement…</p>`
@@ -242,7 +242,9 @@ export async function handleDocsMockApiRequest(
242
242
  }
243
243
 
244
244
  if (subPath === "/geo/communes" || subPath.startsWith("/geo/communes")) {
245
- return json(geoCommunes(url));
245
+ return json(geoCommunes(url), {
246
+ headers: { "X-Fetched-At": new Date().toISOString() },
247
+ });
246
248
  }
247
249
 
248
250
  const jokeMatch = subPath.match(/^\/jokes\/joke\/([^/]+)$/);
@@ -4030,7 +4030,22 @@
4030
4030
  }
4031
4031
  },
4032
4032
  {
4033
- "search": "Use { dynamic: true } when the decorated property must follow the DOM. The live demo below shows only the resolved attribute value no store, no reparenting.\n",
4033
+ "search": "Use { dynamic: true } when the decorated property must follow the DOM. With Lit, add @state() on the same property so template updates are visible when the observer assigns a new value.\n",
4034
+ "files": {
4035
+ "docs/_decorators/ancestor-attribute.md": {
4036
+ "title": "@ancestorAttribute",
4037
+ "hashes": {
4038
+ "dynamic-mode": {
4039
+ "count": 1,
4040
+ "title": "Dynamic mode",
4041
+ "type": "paragraph"
4042
+ }
4043
+ }
4044
+ }
4045
+ }
4046
+ },
4047
+ {
4048
+ "search": "The live demo below shows only the resolved attribute value — no store, no reparenting.\n",
4034
4049
  "files": {
4035
4050
  "docs/_decorators/ancestor-attribute.md": {
4036
4051
  "title": "@ancestorAttribute",
@@ -4729,6 +4744,66 @@
4729
4744
  }
4730
4745
  }
4731
4746
  },
4747
+ {
4748
+ "search": "Pass as the second argument (scoped config) or third (with a configuration key). Same shape as send decorators where applicable:\n",
4749
+ "files": {
4750
+ "docs/_decorators/get.md": {
4751
+ "title": "@get",
4752
+ "hashes": {
4753
+ "options-getoptions": {
4754
+ "count": 1,
4755
+ "title": "Options (`GetOptions`)",
4756
+ "type": "paragraph"
4757
+ }
4758
+ }
4759
+ }
4760
+ }
4761
+ },
4762
+ {
4763
+ "search": "Same pattern as @post: a publisher acts as a signal, independent of the response payload.\n",
4764
+ "files": {
4765
+ "docs/_decorators/get.md": {
4766
+ "title": "@get",
4767
+ "hashes": {
4768
+ "manual-refetch-triggerkey": {
4769
+ "count": 1,
4770
+ "title": "Manual refetch (`triggerKey`)",
4771
+ "type": "paragraph"
4772
+ }
4773
+ }
4774
+ }
4775
+ }
4776
+ },
4777
+ {
4778
+ "search": "Prefer triggerKey over mutating the API configuration publisher when you only want to reload the same URL — no need to touch serviceURL, tokens, etc.\n",
4779
+ "files": {
4780
+ "docs/_decorators/get.md": {
4781
+ "title": "@get",
4782
+ "hashes": {
4783
+ "manual-refetch-triggerkey": {
4784
+ "count": 1,
4785
+ "title": "Manual refetch (`triggerKey`)",
4786
+ "type": "paragraph"
4787
+ }
4788
+ }
4789
+ }
4790
+ }
4791
+ },
4792
+ {
4793
+ "search": "The docs mock adds an X-Fetched-At response header on /docs-mock-api/geo/communes so live demos can show when the last fetch happened (response.headers.get(&quot;X-Fetched-At&quot;)).\n",
4794
+ "files": {
4795
+ "docs/_decorators/get.md": {
4796
+ "title": "@get",
4797
+ "hashes": {
4798
+ "manual-refetch-triggerkey": {
4799
+ "count": 1,
4800
+ "title": "Manual refetch (`triggerKey`)",
4801
+ "type": "paragraph"
4802
+ }
4803
+ }
4804
+ }
4805
+ }
4806
+ },
4732
4807
  {
4733
4808
  "search": "Same demo service as sonic-queue (/docs-mock-api/geo/). Publisher setup lives in decorators-demo-geo.ts and decorators-demo-subscribe-publish-get-demos.ts.\n",
4734
4809
  "files": {
@@ -4745,7 +4820,22 @@
4745
4820
  }
4746
4821
  },
4747
4822
  {
4748
- "search": "Dynamic config and endpoint path (demo-api-get-configuration-key in doc sources):\n",
4823
+ "search": "@get with triggerKey refresh button + X-Fetched-At timestamp in the UI:\n",
4824
+ "files": {
4825
+ "docs/_decorators/get.md": {
4826
+ "title": "@get",
4827
+ "hashes": {
4828
+ "live-demos": {
4829
+ "count": 1,
4830
+ "title": "Live demos",
4831
+ "type": "paragraph"
4832
+ }
4833
+ }
4834
+ }
4835
+ }
4836
+ },
4837
+ {
4838
+ "search": "Dynamic config and endpoint path. Manual refetch is triggered from a separate component (same triggerKey publisher):\n",
4749
4839
  "files": {
4750
4840
  "docs/_decorators/get.md": {
4751
4841
  "title": "@get",