@supersoniks/concorde 4.6.0 → 4.7.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 (179) hide show
  1. package/.gitlab-ci.yml +23 -0
  2. package/README.md +106 -55
  3. package/ai/AGENTS.md +52 -0
  4. package/ai/README.md +30 -0
  5. package/ai/cursor/rules/concorde-menu.mdc +15 -0
  6. package/ai/cursor/rules/concorde-scope.mdc +14 -0
  7. package/ai/cursor/rules/concorde-theme.mdc +13 -0
  8. package/ai/cursor/rules/concorde.mdc +49 -0
  9. package/ai/jetbrains/rules/concorde.md +39 -0
  10. package/ai/skills/concorde/SKILL.md +220 -0
  11. package/ai/skills/concorde-get-set-dp/SKILL.md +194 -0
  12. package/ai/skills/concorde-imports/SKILL.md +78 -0
  13. package/ai/skills/concorde-menu/SKILL.md +74 -0
  14. package/ai/skills/concorde-scope/SKILL.md +70 -0
  15. package/ai/skills/concorde-theme/SKILL.md +46 -0
  16. package/build-infos.json +1 -1
  17. package/concorde-core.bundle.js +127 -127
  18. package/concorde-core.es.js +1435 -1364
  19. package/dist/altcha-widget.js +2662 -0
  20. package/dist/concorde-core.bundle.js +127 -127
  21. package/dist/concorde-core.es.js +1435 -1364
  22. package/dist/docs-mock-api-sw.js +589 -0
  23. package/dist/docs-mock-api-sw.js.map +7 -0
  24. package/docs/altcha-widget.js +2662 -0
  25. package/docs/assets/index-D9pxaQYK.js +7508 -0
  26. package/docs/assets/index-t0-i22oI.css +1 -0
  27. package/docs/docs-mock-api-sw.js +589 -0
  28. package/docs/docs-mock-api-sw.js.map +7 -0
  29. package/docs/index.html +2 -2
  30. package/docs/src/core/components/functional/fetch/fetch.md +13 -11
  31. package/docs/src/core/components/functional/if/if.md +4 -11
  32. package/docs/src/core/components/functional/list/list.md +60 -194
  33. package/docs/src/core/components/functional/queue/queue.md +70 -85
  34. package/docs/src/core/components/functional/router/router.md +62 -97
  35. package/docs/src/core/components/functional/states/states.md +2 -2
  36. package/docs/src/core/components/functional/submit/submit.md +86 -55
  37. package/docs/src/core/components/ui/captcha/captcha.md +2 -2
  38. package/docs/src/core/components/ui/card/card.md +1 -1
  39. package/docs/src/core/components/ui/form/checkbox/checkbox.md +5 -32
  40. package/docs/src/core/components/ui/form/input/input.md +5 -30
  41. package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +6 -4
  42. package/docs/src/core/components/ui/form/radio/radio.md +5 -32
  43. package/docs/src/core/components/ui/form/select/select.md +5 -31
  44. package/docs/src/core/components/ui/form/switch/switch.md +5 -32
  45. package/docs/src/core/components/ui/loader/loader.md +1 -13
  46. package/docs/src/core/components/ui/table/table.md +3 -3
  47. package/docs/src/docs/_core-concept/dataFlow.md +73 -0
  48. package/docs/src/docs/_core-concept/subscriber.md +9 -10
  49. package/docs/src/docs/_decorators/ancestor-attribute.md +4 -3
  50. package/docs/src/docs/_decorators/auto-subscribe.md +19 -16
  51. package/docs/src/docs/_decorators/bind.md +20 -17
  52. package/docs/src/docs/_decorators/get.md +7 -4
  53. package/docs/src/docs/_decorators/handle.md +171 -0
  54. package/docs/src/docs/_decorators/on-assign.md +99 -73
  55. package/docs/src/docs/_decorators/publish.md +2 -1
  56. package/docs/src/docs/_decorators/subscribe.md +70 -9
  57. package/docs/src/docs/_decorators/wait-for-ancestors.md +13 -10
  58. package/docs/src/docs/_directives/sub.md +91 -0
  59. package/docs/src/docs/_getting-started/ai-agents.md +56 -0
  60. package/docs/src/docs/_getting-started/concorde-manual-install.md +133 -0
  61. package/docs/src/docs/_getting-started/concorde-outside.md +13 -123
  62. package/docs/src/docs/_getting-started/create-a-component.md +2 -0
  63. package/docs/src/docs/_getting-started/my-first-component.md +236 -0
  64. package/docs/src/docs/_getting-started/my-first-subscriber.md +29 -83
  65. package/docs/src/docs/_getting-started/pubsub.md +21 -134
  66. package/docs/src/docs/_getting-started/start.md +26 -18
  67. package/docs/src/docs/_misc/api-configuration.md +79 -0
  68. package/docs/src/docs/_misc/dataProviderKey.md +38 -5
  69. package/docs/src/docs/_misc/docs-mock-api.md +60 -0
  70. package/docs/src/docs/_misc/endpoint.md +2 -1
  71. package/docs/src/docs/_misc/html-integration.md +13 -0
  72. package/docs/src/docs/search/docs-search.json +4163 -873
  73. package/docs/src/tsconfig.json +380 -317
  74. package/gitlab/job_tests.sh +55 -0
  75. package/package.json +34 -3
  76. package/public/altcha-widget.js +2662 -0
  77. package/public/docs-mock-api-sw.js +589 -0
  78. package/public/docs-mock-api-sw.js.map +7 -0
  79. package/scripts/ai-init.mjs +167 -0
  80. package/scripts/docs-mock-api-vite-plugin.ts +116 -0
  81. package/scripts/docs-open-in-editor-plugin.ts +130 -0
  82. package/scripts/pre-publish.mjs +2 -1
  83. package/src/core/components/functional/example/example.ts +1 -1
  84. package/src/core/components/functional/fetch/fetch.md +13 -11
  85. package/src/core/components/functional/if/if.md +4 -11
  86. package/src/core/components/functional/list/list.demo.ts +4 -4
  87. package/src/core/components/functional/list/list.md +60 -194
  88. package/src/core/components/functional/list/list.ts +8 -7
  89. package/src/core/components/functional/queue/queue.demo.ts +1 -1
  90. package/src/core/components/functional/queue/queue.md +70 -85
  91. package/src/core/components/functional/queue/queue.ts +4 -4
  92. package/src/core/components/functional/router/router.md +62 -97
  93. package/src/core/components/functional/router/router.ts +1 -1
  94. package/src/core/components/functional/states/states.md +2 -2
  95. package/src/core/components/functional/submit/submit.md +86 -55
  96. package/src/core/components/functional/submit/submit.ts +10 -3
  97. package/src/core/components/ui/captcha/captcha.md +2 -2
  98. package/src/core/components/ui/card/card.md +1 -1
  99. package/src/core/components/ui/form/checkbox/checkbox.md +5 -32
  100. package/src/core/components/ui/form/input/input.md +5 -30
  101. package/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +6 -4
  102. package/src/core/components/ui/form/radio/radio.md +5 -32
  103. package/src/core/components/ui/form/select/select.md +5 -31
  104. package/src/core/components/ui/form/switch/switch.md +5 -32
  105. package/src/core/components/ui/loader/loader.md +1 -13
  106. package/src/core/components/ui/table/table.md +3 -3
  107. package/src/core/directives/DataProvider.sub.spec.ts +96 -0
  108. package/src/core/directives/DataProvider.ts +109 -40
  109. package/src/core/utils/PublisherProxy.ts +33 -18
  110. package/src/core/utils/dataProviderKey.ts +23 -0
  111. package/src/core/utils/publisherPathKey.spec.ts +58 -0
  112. package/src/docs/_core-concept/dataFlow.md +73 -0
  113. package/src/docs/_core-concept/subscriber.md +9 -10
  114. package/src/docs/_decorators/ancestor-attribute.md +4 -3
  115. package/src/docs/_decorators/auto-subscribe.md +19 -16
  116. package/src/docs/_decorators/bind.md +19 -16
  117. package/src/docs/_decorators/get.md +7 -4
  118. package/src/docs/_decorators/handle.md +15 -13
  119. package/src/docs/_decorators/on-assign.md +53 -53
  120. package/src/docs/_decorators/publish.md +2 -1
  121. package/src/docs/_decorators/subscribe.md +70 -9
  122. package/src/docs/_decorators/wait-for-ancestors.md +13 -10
  123. package/src/docs/_directives/sub.md +91 -0
  124. package/src/docs/_getting-started/ai-agents.md +56 -0
  125. package/src/docs/_getting-started/concorde-manual-install.md +133 -0
  126. package/src/docs/_getting-started/concorde-outside.md +13 -123
  127. package/src/docs/_getting-started/create-a-component.md +2 -0
  128. package/src/docs/_getting-started/my-first-component.md +236 -0
  129. package/src/docs/_getting-started/my-first-subscriber.md +29 -83
  130. package/src/docs/_getting-started/pubsub.md +21 -134
  131. package/src/docs/_getting-started/start.md +26 -18
  132. package/src/docs/_misc/api-configuration.md +79 -0
  133. package/src/docs/_misc/dataProviderKey.md +34 -1
  134. package/src/docs/_misc/docs-mock-api.md +60 -0
  135. package/src/docs/_misc/endpoint.md +2 -1
  136. package/src/docs/_misc/html-integration.md +13 -0
  137. package/src/docs/code.ts +58 -12
  138. package/src/docs/components/docs-demo-sources.ts +397 -0
  139. package/src/docs/components/docs-lit-demo-raw.ts +28 -0
  140. package/src/docs/components/docs-lit-demo.ts +166 -0
  141. package/src/docs/components/docs-source-link.ts +72 -0
  142. package/src/docs/docs-location.ts +54 -0
  143. package/src/docs/docs.ts +12 -0
  144. package/src/docs/example/decorators-demo-bind-demos.ts +41 -46
  145. package/src/docs/example/decorators-demo-geo.ts +16 -11
  146. package/src/docs/example/decorators-demo-init.ts +2 -228
  147. package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +54 -14
  148. package/src/docs/example/decorators-demo.ts +71 -70
  149. package/src/docs/example/docs-api-config-demos.ts +234 -0
  150. package/src/docs/example/docs-joke-demos.ts +297 -0
  151. package/src/docs/example/docs-list-demos.ts +179 -0
  152. package/src/docs/example/docs-provider-keys.ts +315 -0
  153. package/src/docs/example/docs-queue-demos.ts +114 -0
  154. package/src/docs/example/docs-router-demos.ts +89 -0
  155. package/src/docs/example/docs-submit-demos.ts +455 -0
  156. package/src/docs/example/docs-toggle-demos.ts +73 -0
  157. package/src/docs/example/docs-user-two-scopes.ts +37 -0
  158. package/src/docs/example/docs-users-list.ts +71 -0
  159. package/src/docs/example/users.ts +41 -24
  160. package/src/docs/mock-api/api-config-mock.ts +152 -0
  161. package/src/docs/mock-api/fixtures.ts +377 -0
  162. package/src/docs/mock-api/register.ts +25 -0
  163. package/src/docs/mock-api/router.ts +234 -0
  164. package/src/docs/mock-api/service-worker.ts +23 -0
  165. package/src/docs/mock-api/urls.ts +11 -0
  166. package/src/docs/navigation/navigation.ts +39 -7
  167. package/src/docs/search/docs-search.json +4021 -936
  168. package/src/docs/search/markdown-renderer.ts +7 -3
  169. package/src/docs/search/page.ts +11 -14
  170. package/src/docs/search/sonic-code-markdown.spec.ts +29 -0
  171. package/src/docs/search/sonic-code-markdown.ts +28 -0
  172. package/src/docs.ts +4 -0
  173. package/src/tsconfig.json +87 -0
  174. package/src/tsconfig.tsbuildinfo +1 -1
  175. package/vite.config.mts +8 -0
  176. package/docs/assets/index-CaysOMFz.js +0 -5046
  177. package/docs/assets/index-D8mGoXzF.css +0 -1
  178. package/docs/src/docs/_misc/templates-demo.md +0 -19
  179. package/src/docs/_misc/templates-demo.md +0 -19
@@ -1,199 +1,65 @@
1
1
  # List
2
2
 
3
- The **sonic-list** component creates list items.
4
-
5
-
6
- List extends the mixins [Subscriber](#docs/_core-concept/subscriber.md/subscriber) and Fetcher :
7
- * As a Subscriber it as a **props** reactive property (basically an array of data) and its data is associated to a publisher via its dataProvider attribute.
8
- * List doesn't Fetch by default (see below for activation).
9
-
10
-
11
- ## Template
12
-
13
- The list component loops over its template children to render each items of its props data.
14
- Consider the following example using **2 templates** and **9 items** :
15
- - First template will render the first item.
16
- - Second template will render the second item.
17
- - Then back to the first template and so on and so forth.
18
-
19
- Note that for each line there is a dataProvider found at *[list dataProvider name]/liste-item/[line index or key]*
20
- You can hover the list items in the examples to see it.
21
-
22
- <sonic-code>
23
- <template>
24
- <sonic-list dataProvider="listTemplateExample" class="grid grid-cols-3 gap-4" props='[{"id": "1"}, {"id": "2"}, {"id": "3"}, {"id": "4"}, {"id": "5"}, {"id": "6"}, {"id": "7"}, {"id": "8"}, {"id": "9"}]' debug>
25
- <template>
26
- <div class="bg-neutral-100 text-center p-3">
27
- <sonic-value key="id"></sonic-value>
28
- <div class="text-xs">1st template</div>
29
- </div>
30
- </template>
31
- <template>
32
- <div class="bg-neutral-100 text-info text-center p-3">
33
- <sonic-value key="id"></sonic-value>
34
- <div class="text-xs">2nd template</div>
35
- </div>
36
- </template>
37
- </sonic-list>
38
- </template>
39
- </sonic-code>
40
-
41
-
42
-
43
- ## TemplateKey / data-value
44
-
45
- The **templateKey** attribute allows you to bind a template to a props item.
46
- Consider the following example :
47
- - The list **templateKey** attribute is set to the value **tpl** (any name would do)
48
- - Items 4,5 and 6 are each one **referencing** a templates with a matching **data-value** attribute
49
-
50
- <sonic-code>
51
- <template>
52
- <sonic-list
53
- templateKey="tpl"
54
- class="grid gap-3"
55
- dataProvider="TemplateKeyExample"
56
- props='[
57
- {"id":"1", "default": "The first template with no data-value is used"},
58
- {"id":"2", "default": "The second template with no data-value is used"},
59
- {"id":"3", "default": "Back to the first template with no data-value"},
60
- {"id":"4", "tpl":"custom-tpl-danger"},
61
- {"id":"5", "tpl":"custom-tpl-info"},
62
- {"id":"6", "tpl":"custom-tpl-success"},
63
- {"id":"7", "tpl": "Non-valid tpl name, Back to the first template with no data-value"}
64
- ]'
65
- debug
66
- >
67
- <template>
68
- <div class="p-2 border rounded text-neutral-900">
69
- <sonic-value key="id"> : </sonic-value>
70
- <b>First</b> template with no <b>data-value</b> attribute
71
- </div>
72
- </template>
73
- <template data-value="custom-tpl-danger">
74
- <div class="p-2 border rounded text-danger">
75
- <sonic-value key="id"> : </sonic-value>
76
- data-value : <b>custom-tpl-danger</b>
77
- </div>
78
- </template>
79
- <template data-value="custom-tpl-info">
80
- <div class="p-2 border rounded text-info">
81
- <sonic-value key="id"> : </sonic-value>
82
- data-value : <b>custom-tpl-info</b>
83
- </div>
84
- </template>
85
- <template data-value="custom-tpl-success">
86
- <div class="p-2 border rounded text-success">
87
- <sonic-value key="id"> : </sonic-value>
88
- data-value : <b>custom-tpl-success</b>
89
- </div>
90
- </template>
91
- <template>
92
- <div class="p-2 border rounded text-neutral-400">
93
- <sonic-value key="id"> : </sonic-value>
94
- <b>Second</b> template with no <b>data-value</b> attribute <br>
95
- This one is used if it <b>follows another data-item</b> with <b>no tpl</b> specified in the props
96
- </div>
97
- </template>
98
- </sonic-list>
99
- </template>
100
- </sonic-code>
101
-
102
- ## Special templates : list item separator / empty list view
103
-
104
- A special template with attribute **data-value="separator"** will act as a separator between each list item
105
-
106
- <sonic-code>
107
- <template>
108
- <sonic-list props='[{"id":"1"},{"id":"2"},{"id":"3"}]' dataProvider="ListSeparatorDemo">
109
- <template><sonic-value key="id"></sonic-value></template>
110
- <template data-value="separator"> 🤜 </template>
111
- </sonic-list>
112
- </template>
113
- </sonic-code>
114
-
115
- The same principle can be used to handle empty lists using a template with attribute **data-value="no-item"**
116
-
117
-
118
- ## Fetch
119
-
120
- Enables the list to get data from an external API in order to fill its **props** attribute with an **array of items**
121
- See the [Fetch] web component(#core/components/functional/fetch/fetch.md/fetch)
122
- <sonic-code>
123
- <template>
124
- <sonic-list
125
- props='["a", "b", "c"]' fetch
126
- serviceURL="https://reqres.in"
127
- dataProvider="api/users"
128
- key="data"
129
- class="grid grid-cols-1" debug>
130
- <template>
131
- <docs-user></docs-user>
132
- </template>
133
- </sonic-list>
134
- </template>
135
- </sonic-code>
136
-
137
- ## Extract Values
138
-
139
- Example of using the `extractValues` attribute with a service.
140
- As in the previous example, the `fetch` attribute indicates that a service call should be made.
141
- Note that we use:
142
- * the property `_metadata_` added by the list component to display the key of the extracted value
143
- * the special property `_self_` that allows targeting the item itself. This is useful here because there is no sub-property; we are directly dealing with a string.
144
- <sonic-code>
145
- <template>
146
- <sonic-list
147
- debug
148
- fetch
149
- serviceURL="https://reqres.in"
150
- dataProvider="list-extract-values-test"
151
- endPoint="api/users/2"
152
- key="data"
153
- extractValues
154
- >
155
- <template>
156
- <div class="flex items-center">
157
- <span data-bind ::inner-html="$_metadata_.key : " class="bold w-24"></span>
158
- <span data-bind ::inner-html="$_self_"></span>
159
- <sonic-if data-bind ::condition="|'$_metadata_.key' == 'avatar'">
160
- <sonic-image data-bind ::src="$_self_" rounded="full" ratio="1/1" class="w-20 block"></sonic-image>
161
- </sonic-if>
162
- </div>
163
- </template>
164
- </sonic-list>
165
- </template>
166
- </sonic-code>
3
+ > **Try offline:** `serviceURL="/docs-mock-api"` and `dataProvider="api/users"` with `key="data"` — see [Local API demos](#docs/_misc/docs-mock-api.md/docs-mock-api). Recommended patterns: [Data flow](#docs/_core-concept/dataFlow.md/dataFlow).
4
+
5
+ The **sonic-list** component renders one row per entry in **`props`** (array from fetch or set on the element).
6
+
7
+ List extends [Subscriber](#docs/_core-concept/subscriber.md/subscriber) and **Fetcher**:
8
+ * **Subscriber** `props` + `dataProvider`
9
+ * **Fetcher** — optional `fetch` + `serviceURL` / `key` (see [Fetch](#core/components/functional/fetch/fetch.md/fetch))
10
+
11
+ ## Row renderer (`items`) — recommended
12
+
13
+ From a **Lit** parent, pass a function on the **`items`** property (`ListItems`). Each row is wrapped in a `sonic-subscriber` with `dataProvider="…/list-item/n"` (hover rows with `debug`).
14
+
15
+ ```typescript
16
+ private items = ({ first_name, last_name, email, avatar }) => html`
17
+ <sonic-image src=${avatar} …></sonic-image>
18
+ <div>${first_name} <b>${last_name}</b></div>
19
+ <div>${email}</div>
20
+ `;
21
+
22
+ html`<sonic-list
23
+ fetch
24
+ dataProvider="api/users"
25
+ key="data"
26
+ serviceURL="/docs-mock-api"
27
+ .items=${this.items}
28
+ ></sonic-list>`;
29
+ ```
30
+
31
+ Use **`.items=${fn}`** (property binding): Lit passes functions only as properties, not as HTML attributes — `@property({ type: Function })` does not change that. Same for **`.noItems`**, **`.separator`**, **`.skeleton`**. The callback receives each row object (replacing `data-bind` / `<sonic-value>` in a `<template>`).
32
+
33
+ Live demo + TypeScript source (one file, no Markdown copy):
34
+
35
+ <docs-lit-demo for="docs-users-list"></docs-lit-demo>
36
+
37
+ Implementation: `src/docs/example/docs-users-list.ts` — row markup in the **`items`** callback (`item.first_name`, …), same idea as replacing `data-bind` / `<sonic-value>` in a `<template>`.
38
+
39
+ ## Alternating row layouts
40
+
41
+ Use **`metadata`** (`even`, `odd`, `firstChild`, …) or fields on each item (e.g. `tpl` with `templateKey`):
42
+
43
+ <docs-lit-demo for="docs-list-alternate-demo"></docs-lit-demo>
44
+
45
+ <docs-lit-demo for="docs-list-template-key-demo"></docs-lit-demo>
46
+
47
+ ## Separator and empty list
48
+
49
+ <docs-lit-demo for="docs-list-separator-demo"></docs-lit-demo>
50
+
51
+ ## Fetch + `extractValues`
52
+
53
+ <docs-lit-demo for="docs-list-extract-values-demo"></docs-lit-demo>
54
+
55
+ ## HTML `<template>` children (integration without Lit)
56
+
57
+ For **plain HTML** hosts, you can still declare **`<template>`** children (and `data-value` for `templateKey`, `separator`, `no-item`). That path is for [HTML integration](#docs/_misc/html-integration.md/html-integration) — not used in Concorde doc live demos.
58
+
59
+ Each list row still gets `dataProvider="[list]/list-item/[index]"`.
167
60
 
168
61
  ## Additionnal tips
169
62
 
170
- * If the result of the request is an object, it is nested within an array to ensure functionality.
171
- * The invalidate() method can be called on its publisher to trigger data reloading.
172
- * Each list item publisher has a "_parent_" property pointing to the list publisher
173
-
174
-
175
-
176
- <!--
177
- ## FormDataProvider
178
-
179
- <sonic-alert status="error" background>À déplacer dans la bonne doc</sonic-alert>
180
-
181
- <sonic-code>
182
- <template>
183
- <div formDataProvider="profileInfos">
184
- <form>
185
- <sonic-fieldset label="Edit profile">
186
- <sonic-form-layout>
187
- <sonic-input label="First name" type="text" name="first_name" value="Sponge" size="sm"></sonic-input>
188
- <sonic-input label="Last name" type="text" name="last_name" value="Bob" size="sm"></sonic-input>
189
- <sonic-input label="email" type="email" name="email" value="bob@krustykrab.com" size="sm"></sonic-input>
190
- <sonic-input label="Image url" type="text" name="avatar" value="http://www.bobleponge.fr/goodies/avatars/avatar-bob-eponge_Bob-Eponge-coiffure.jpg" size="sm"></sonic-input>
191
- </sonic-form-layout>
192
- </sonic-fieldset>
193
- </form>
194
- </div>
195
- <sonic-card dataProvider="profileInfos">
196
- <docs-user ></docs-user>
197
- </sonic-card>
198
- </template>
199
- </sonic-code> -->
63
+ * If the request returns an object, it is wrapped in an array (unless `extractValues` is set).
64
+ * Call **`invalidate()`** on the list publisher to reload fetch data.
65
+ * Each row publisher exposes **`_parent_`** pointing at the list publisher.
@@ -21,7 +21,7 @@ const tagName = "sonic-list";
21
21
  * Voir [fetcher](./?path=/docs/core-components-functional-fetch--basic) pour la configuration des autres attributs.
22
22
  * * Chaque élément créé est englobé dans un objet [Subscriber](./?path=/docs/miscallenous-🔔-subscriber--page).<br>
23
23
  * Un dataProvider y est associé a l'adresse suivante *dataProvider-de-la-liste$/*index-de-la-ligne-courante*
24
- * Les données de la ligne sont donc disponible pour les élements internes (subscribers, data-binding)
24
+ * Les données de la ligne sont donc disponible pour les élements internes (subscribers)
25
25
  * * Lors du chargement un objet loader inline est affiché.
26
26
  * * Si le résultat de la requête est un objet, il est imbriqué dans un tableau pour garantir le fonctionnement.<br>
27
27
  * Cependant, si l'attribut `extractValues` est présent, les valeurs des propriétés de l'objet sont mises dans dans un tableau pour le rendu.
@@ -48,7 +48,7 @@ export type ListItemMetadata = {
48
48
  // Simplifier le type ListItems pour n'être qu'une fonction
49
49
  export type ListItems = (
50
50
  item: any,
51
- metadata: ListItemMetadata
51
+ metadata: ListItemMetadata,
52
52
  ) => DirectiveResult;
53
53
 
54
54
  @customElement(tagName)
@@ -73,6 +73,7 @@ export class List extends Fetcher(Subscriber(TemplatesContainer(LitElement))) {
73
73
 
74
74
  @property({
75
75
  type: Function,
76
+ attribute: false,
76
77
  }) /**add a getter setter check if the value is a ListItems befor assignation */
77
78
  get items(): ListItems | undefined {
78
79
  return this._items;
@@ -83,9 +84,9 @@ export class List extends Fetcher(Subscriber(TemplatesContainer(LitElement))) {
83
84
  this.requestUpdate();
84
85
  }
85
86
 
86
- @property({ type: Function }) noItems?: () => DirectiveResult;
87
- @property({ type: Function }) skeleton?: () => DirectiveResult;
88
- @property({ type: Function }) separator?: () => DirectiveResult;
87
+ @property({ type: Function, attribute: false }) noItems?: () => DirectiveResult;
88
+ @property({ type: Function, attribute: false }) skeleton?: () => DirectiveResult;
89
+ @property({ type: Function, attribute: false }) separator?: () => DirectiveResult;
89
90
 
90
91
  connectedCallback() {
91
92
  this.noShadowDom = "";
@@ -245,7 +246,7 @@ export class List extends Fetcher(Subscriber(TemplatesContainer(LitElement))) {
245
246
  private handleProgrammaticTemplates(
246
247
  item: any,
247
248
  metadata: ListItemMetadata,
248
- key: string | number
249
+ key: string | number,
249
250
  ): DirectiveResult | null {
250
251
  if (!this.items) return null;
251
252
 
@@ -347,7 +348,7 @@ export class List extends Fetcher(Subscriber(TemplatesContainer(LitElement))) {
347
348
  const programmaticTemplate = this.handleProgrammaticTemplates(
348
349
  item,
349
350
  metadata,
350
- key
351
+ key,
351
352
  );
352
353
  if (programmaticTemplate) {
353
354
  return html`${programmaticTemplate}${!isLastChild
@@ -24,7 +24,7 @@ export class QueueDemo extends LitElement {
24
24
  return html`
25
25
  <sonic-queue
26
26
  class="grid grid-cols-3 gap-3"
27
- serviceurl="https://geo.api.gouv.fr/"
27
+ serviceurl="/docs-mock-api/geo/"
28
28
  dataproviderexpression="communes?limit=$limit"
29
29
  limit="30"
30
30
  .items=${this.items}
@@ -1,87 +1,72 @@
1
1
  # Queue
2
2
 
3
- **sonic-queue** loads content in batches based on the expression provided in the dataProviderExpression attribute.
4
-
5
- * Each batch is loaded by a [List component](#core/components/functional/list/list.md/list) whose dataProvider is created from the dataProviderExpression attribute.
6
- * Upon initialization, it looks at the dataFilterProvider attribute, which provides the address of a publisher.
7
- If this attribute is found, Queue listens to the provided publisher and resets itself whenever the content of the publisher is modified.
8
- The values provided in this publisher are added as parameters to each request.
9
- * The key property can be used to target a specific property in the API response as fetch does.
10
-
11
- List extends the mixin [Subscriber](#docs/_core-concept/subscriber.md/subscriber)
12
-
13
-
14
- <sonic-code>
15
- <template>
16
- <sonic-queue
17
- class="grid grid-cols-3 gap-3"
18
- dataProviderExpression="communes?limit=$limit"
19
- limit="30"
20
- serviceURL="https://geo.api.gouv.fr/"
21
- debug
22
- >
23
- <template>
24
- <div data-bind ::inner-html="$nom" class="bg-neutral-100 p-2">
25
- queue
26
- </div>
27
- </template>
28
- </sonic-queue>
29
- </template>
30
- </sonic-code>
31
-
32
- <sonic-code>
33
- <template>
34
- <sonic-queue
35
- lazyload
36
- dataProviderExpression="api/users?page=$offset&per_page=$limit"
37
- offset="2"
38
- limit="5"
39
- dataFilterProvider="filter"
40
- targetRequestDuration="500"
41
- serviceURL="https://reqres.in"
42
- key="data"
43
- debug
44
- >
45
- <template>
46
- <div class="flex px-4 py-3 items-center gap-4">
47
- <sonic-image data-bind ::src="$avatar" rounded="full" ratio="1/1" class="w-20 block"></sonic-image>
48
- <div>
49
- <div class="text-bold text-2xl mb-2">
50
- <span data-bind ::inner-html="$first_name"></span>
51
- <span data-bind ::inner-html="$last_name"></span>
52
- </div>
53
- <sonic-button data-bind ::href="mailto|$email" size="xs" variant="outline"> Contact </sonic-button>
54
- </div>
55
- </div>
56
- <div class="border-0 border-t-2 border-t-neutral-200 w-full border-solid"></div>
57
- </template>
58
- </sonic-queue>
59
- </template>
60
- </sonic-code>
61
-
62
- <sonic-code>
63
- <template>
64
- <sonic-list
65
- lazyload
66
- fetch
67
- dataProvider="api/users?page=2&per_page=5"
68
- serviceURL="https://reqres.in"
69
- key="data"
70
- debug
71
- >
72
- <template>
73
- <div class="flex px-4 py-3 items-center gap-4">
74
- <sonic-image data-bind ::src="$avatar" rounded="full" ratio="1/1" class="w-20 block"></sonic-image>
75
- <div>
76
- <div class="text-bold text-2xl mb-2">
77
- <span data-bind ::inner-html="$first_name"></span>
78
- <span data-bind ::inner-html="$last_name"></span>
79
- </div>
80
- <sonic-button data-bind ::href="mailto|$email" size="xs" variant="outline"> Contact </sonic-button>
81
- </div>
82
- </div>
83
- <div class="border-0 border-t-2 border-t-neutral-200 w-full border-solid"></div>
84
- </template>
85
- </sonic-list>
86
- </template>
87
- </sonic-code>
3
+ > **Try offline:** `serviceURL="/docs-mock-api"` see [Local API demos](#docs/_misc/docs-mock-api.md/docs-mock-api). Row rendering: [Data flow](#docs/_core-concept/dataFlow.md/dataFlow) (`.items` property binding).
4
+
5
+ **sonic-queue** loads data in **batches**. Each batch is an internal [List](#core/components/functional/list/list.md/list) with its own `dataProvider` (`…/list-item/0`, `…/1`, …).
6
+
7
+ | Mechanism | Role |
8
+ |-----------|------|
9
+ | **`dataProviderExpression`** | API path template; `$offset` and `$limit` are replaced per batch |
10
+ | **`lazyload`** | Load the next batch when the user scrolls near the end |
11
+ | **`dataFilterProvider`** | Publisher id of a form (`formDataProvider`); field values are merged into the request query string |
12
+ | **`filteredFields`** | Optional list of form field names to **exclude** from the query (space-separated) — omit when every field should be sent |
13
+ | **`.items`**, **`.noItems`**, **`.separator`**, **`.skeleton`** | Lit callbacks forwarded to each batch list (use the **dot** — functions are properties, not attributes) |
14
+
15
+ ## Lazy load — `$offset` and `$limit`
16
+
17
+ When the expression contains **`$offset`** and **`$limit`**, the queue:
18
+
19
+ 1. Fetches the first batch with `offset=0` (or the initial `offset` attribute) and `per_page=$limit`.
20
+ 2. On scroll, appends a batch with `offset` increased by the previous batch size.
21
+ 3. Stops when a batch returns fewer rows than `limit` (or none).
22
+
23
+ The doc mock implements this on `GET /docs-mock-api/api/users?offset=…&per_page=…` (`paginateUsers` in `src/docs/mock-api/router.ts`).
24
+
25
+ <docs-lit-demo for="docs-queue-users-demo"></docs-lit-demo>
26
+
27
+ Wrap the queue in a **fixed height** with **`overflow-y-auto`** so lazy load triggers when scrolling inside the box (same layout as the [TS starter](https://github.com/supersoniks/create-concorde-ts-starter) `demo-queue-templates`).
28
+
29
+ Try scrolling after load — batches of 4 users. Search e.g. `George`, `Bluth`, or `zzz` for empty results.
30
+
31
+ ### Expression example
32
+
33
+ ```typescript
34
+ html`<sonic-queue
35
+ lazyload
36
+ serviceURL="/docs-mock-api"
37
+ dataProviderExpression="api/users?offset=$offset&limit=$limit"
38
+ key="data"
39
+ limit="4"
40
+ class="grid max-h-96 overflow-y-auto"
41
+ .items=${this.renderUser}
42
+ ></sonic-queue>`;
43
+ ```
44
+
45
+ Without **`$offset`** in the expression, the queue behaves like a single list (one batch), e.g. geo communes below.
46
+
47
+ ## Filter `dataFilterProvider` + `q`
48
+
49
+ One search field (`name="q"`) on `formDataProvider="filter"`. The queue listens via **`dataFilterProvider="filter"`** and, on change:
50
+
51
+ 1. Resets loaded batches.
52
+ 2. Appends each non-empty form field to the query (here only **`q`** — no `filteredFields` needed).
53
+ 3. Fetches again from offset `0`.
54
+
55
+ Use **`filteredFields`** only when the form has extra fields that must **not** be sent to the API (e.g. `filteredFields="rememberMe internalId"`).
56
+
57
+ The mock API filters before pagination — same haystack logic as the starter (`filterDocsUsers` in `src/docs/mock-api/fixtures.ts`, used by `paginateUsers` in `router.ts` / Service Worker):
58
+
59
+ ```typescript
60
+ const haystack = `${first_name} ${last_name} ${email}`.toLowerCase();
61
+ return haystack.includes(q);
62
+ ```
63
+
64
+ ## Simple batch (no lazy scroll)
65
+
66
+ Geo communes: expression uses **`$limit` only** (no `$offset`) — one request, one batch.
67
+
68
+ <docs-lit-demo for="docs-queue-geo-demo"></docs-lit-demo>
69
+
70
+ ## HTML `<template>` children
71
+
72
+ Optional for hosts without Lit — see [HTML integration](#docs/_misc/html-integration.md/html-integration).
@@ -32,9 +32,9 @@ const tagName = "sonic-queue";
32
32
  export default class Queue extends Subscriber(LitElement, {} as QueueProps) {
33
33
  @property({ type: Array }) templates: Array<HTMLTemplateElement> | null =
34
34
  null;
35
- @property({ type: Function }) items: ListItems | null = null;
36
- @property({ type: Function }) noItems: ListItems | null = null;
37
- @property({ type: Function }) skeleton: ListItems | null = null;
35
+ @property({ type: Function, attribute: false }) items: ListItems | null = null;
36
+ @property({ type: Function, attribute: false }) noItems: ListItems | null = null;
37
+ @property({ type: Function, attribute: false }) skeleton: ListItems | null = null;
38
38
  lastRequestTime = 0;
39
39
  key = "";
40
40
 
@@ -151,7 +151,7 @@ export default class Queue extends Subscriber(LitElement, {} as QueueProps) {
151
151
  if (Array.isArray(value))
152
152
  value = value.filter((v: string | null) => v !== null);
153
153
  if (
154
- (this.filteredFields && !filteredFieldsArray.includes(f)) ||
154
+ (this.filteredFields && filteredFieldsArray.includes(f)) ||
155
155
  value == null ||
156
156
  value.toString() === ""
157
157
  )