@supersoniks/concorde 4.6.0 → 4.7.3

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 (182) 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 +273 -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 +152 -152
  18. package/concorde-core.es.js +1853 -1689
  19. package/dist/altcha-widget.js +2662 -0
  20. package/dist/concorde-core.bundle.js +152 -152
  21. package/dist/concorde-core.es.js +1853 -1689
  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/decorators/api.spec.ts +8 -1
  108. package/src/core/decorators/api.ts +126 -15
  109. package/src/core/directives/DataProvider.sub.spec.ts +96 -0
  110. package/src/core/directives/DataProvider.ts +109 -40
  111. package/src/core/utils/HTML.ts +42 -10
  112. package/src/core/utils/PublisherProxy.ts +33 -18
  113. package/src/core/utils/dataProviderKey.ts +23 -0
  114. package/src/core/utils/publisherPathKey.spec.ts +58 -0
  115. package/src/docs/_core-concept/dataFlow.md +73 -0
  116. package/src/docs/_core-concept/subscriber.md +9 -10
  117. package/src/docs/_decorators/ancestor-attribute.md +4 -3
  118. package/src/docs/_decorators/auto-subscribe.md +19 -16
  119. package/src/docs/_decorators/bind.md +19 -16
  120. package/src/docs/_decorators/get.md +7 -4
  121. package/src/docs/_decorators/handle.md +15 -13
  122. package/src/docs/_decorators/on-assign.md +53 -53
  123. package/src/docs/_decorators/publish.md +2 -1
  124. package/src/docs/_decorators/subscribe.md +70 -9
  125. package/src/docs/_decorators/wait-for-ancestors.md +13 -10
  126. package/src/docs/_directives/sub.md +91 -0
  127. package/src/docs/_getting-started/ai-agents.md +56 -0
  128. package/src/docs/_getting-started/concorde-manual-install.md +133 -0
  129. package/src/docs/_getting-started/concorde-outside.md +13 -123
  130. package/src/docs/_getting-started/create-a-component.md +2 -0
  131. package/src/docs/_getting-started/my-first-component.md +236 -0
  132. package/src/docs/_getting-started/my-first-subscriber.md +29 -83
  133. package/src/docs/_getting-started/pubsub.md +21 -134
  134. package/src/docs/_getting-started/start.md +26 -18
  135. package/src/docs/_misc/api-configuration.md +79 -0
  136. package/src/docs/_misc/dataProviderKey.md +34 -1
  137. package/src/docs/_misc/docs-mock-api.md +60 -0
  138. package/src/docs/_misc/endpoint.md +2 -1
  139. package/src/docs/_misc/html-integration.md +13 -0
  140. package/src/docs/code.ts +58 -12
  141. package/src/docs/components/docs-demo-sources.ts +397 -0
  142. package/src/docs/components/docs-lit-demo-raw.ts +28 -0
  143. package/src/docs/components/docs-lit-demo.ts +166 -0
  144. package/src/docs/components/docs-source-link.ts +72 -0
  145. package/src/docs/docs-location.ts +54 -0
  146. package/src/docs/docs.ts +12 -0
  147. package/src/docs/example/decorators-demo-bind-demos.ts +41 -46
  148. package/src/docs/example/decorators-demo-geo.ts +16 -11
  149. package/src/docs/example/decorators-demo-init.ts +2 -228
  150. package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +54 -14
  151. package/src/docs/example/decorators-demo.ts +71 -70
  152. package/src/docs/example/docs-api-config-demos.ts +234 -0
  153. package/src/docs/example/docs-joke-demos.ts +297 -0
  154. package/src/docs/example/docs-list-demos.ts +179 -0
  155. package/src/docs/example/docs-provider-keys.ts +315 -0
  156. package/src/docs/example/docs-queue-demos.ts +114 -0
  157. package/src/docs/example/docs-router-demos.ts +89 -0
  158. package/src/docs/example/docs-submit-demos.ts +455 -0
  159. package/src/docs/example/docs-toggle-demos.ts +73 -0
  160. package/src/docs/example/docs-user-two-scopes.ts +37 -0
  161. package/src/docs/example/docs-users-list.ts +71 -0
  162. package/src/docs/example/users.ts +41 -24
  163. package/src/docs/mock-api/api-config-mock.ts +152 -0
  164. package/src/docs/mock-api/fixtures.ts +377 -0
  165. package/src/docs/mock-api/register.ts +25 -0
  166. package/src/docs/mock-api/router.ts +234 -0
  167. package/src/docs/mock-api/service-worker.ts +23 -0
  168. package/src/docs/mock-api/urls.ts +11 -0
  169. package/src/docs/navigation/navigation.ts +39 -7
  170. package/src/docs/search/docs-search.json +4021 -936
  171. package/src/docs/search/markdown-renderer.ts +7 -3
  172. package/src/docs/search/page.ts +11 -14
  173. package/src/docs/search/sonic-code-markdown.spec.ts +29 -0
  174. package/src/docs/search/sonic-code-markdown.ts +28 -0
  175. package/src/docs.ts +4 -0
  176. package/src/tsconfig.json +87 -0
  177. package/src/tsconfig.tsbuildinfo +1 -1
  178. package/vite.config.mts +8 -0
  179. package/docs/assets/index-CaysOMFz.js +0 -5046
  180. package/docs/assets/index-D8mGoXzF.css +0 -1
  181. package/docs/src/docs/_misc/templates-demo.md +0 -19
  182. package/src/docs/_misc/templates-demo.md +0 -19
@@ -0,0 +1,179 @@
1
+ import { html, LitElement, nothing } from "lit";
2
+ import { customElement } from "lit/decorators.js";
3
+ import { tailwind } from "../tailwind";
4
+
5
+ import "../../core/components/functional/list/list";
6
+ import "../../core/components/ui/image/image";
7
+
8
+ const GRID_PROPS = [
9
+ { id: "1" },
10
+ { id: "2" },
11
+ { id: "3" },
12
+ { id: "4" },
13
+ { id: "5" },
14
+ { id: "6" },
15
+ { id: "7" },
16
+ { id: "8" },
17
+ { id: "9" },
18
+ ];
19
+
20
+ const TEMPLATE_KEY_PROPS = [
21
+ { id: "1", default: "The first template with no data-value is used" },
22
+ { id: "2", default: "The second template with no data-value is used" },
23
+ { id: "3", default: "Back to the first template with no data-value" },
24
+ { id: "4", tpl: "custom-tpl-danger" },
25
+ { id: "5", tpl: "custom-tpl-info" },
26
+ { id: "6", tpl: "custom-tpl-success" },
27
+ { id: "7", tpl: "Non-valid tpl name, Back to the first template with no data-value" },
28
+ ];
29
+
30
+ const TPL_PARTS: Record<string, (item: { id: string }) => ReturnType<typeof html>> = {
31
+ "custom-tpl-danger": (item) => html`
32
+ <div class="rounded border border-danger p-2 text-danger">
33
+ ${item.id} :
34
+ data-value : <b>custom-tpl-danger</b>
35
+ </div>
36
+ `,
37
+ "custom-tpl-info": (item) => html`
38
+ <div class="rounded border border-info p-2 text-info">
39
+ ${item.id} :
40
+ data-value : <b>custom-tpl-info</b>
41
+ </div>
42
+ `,
43
+ "custom-tpl-success": (item) => html`
44
+ <div class="rounded border border-success p-2 text-success">
45
+ ${item.id} :
46
+ data-value : <b>custom-tpl-success</b>
47
+ </div>
48
+ `,
49
+ };
50
+
51
+ @customElement("docs-list-alternate-demo")
52
+ export class DocsListAlternateDemo extends LitElement {
53
+ static styles = [tailwind];
54
+
55
+ private items = (item: { id: string }, meta: { even?: boolean }) =>
56
+ meta.even
57
+ ? html`<div class="bg-neutral-100 p-3 text-center">
58
+ ${item.id}
59
+ <div class="text-xs">1st template</div>
60
+ </div>`
61
+ : html`<div class="bg-neutral-100 p-3 text-center text-info">
62
+ ${item.id}
63
+ <div class="text-xs">2nd template</div>
64
+ </div>`;
65
+
66
+ render() {
67
+ return html`
68
+ <sonic-list
69
+ dataProvider="listTemplateExample"
70
+ class="grid grid-cols-3 gap-4"
71
+ .props=${GRID_PROPS}
72
+ .items=${this.items}
73
+ debug
74
+ ></sonic-list>
75
+ `;
76
+ }
77
+ }
78
+
79
+ @customElement("docs-list-template-key-demo")
80
+ export class DocsListTemplateKeyDemo extends LitElement {
81
+ static styles = [tailwind];
82
+
83
+ render() {
84
+ let counter = -1;
85
+ const items = (item: (typeof TEMPLATE_KEY_PROPS)[number]) => {
86
+ const tplName = item.tpl;
87
+ const part = tplName ? TPL_PARTS[tplName] : undefined;
88
+ if (part) {
89
+ counter = -1;
90
+ return part(item);
91
+ }
92
+ counter++;
93
+ return counter % 2 === 0
94
+ ? html`<div class="rounded border p-2 text-neutral-900">
95
+ ${item.id} :
96
+ <b>First</b> template with no <b>data-value</b> attribute
97
+ </div>`
98
+ : html`<div class="rounded border p-2 text-neutral-400">
99
+ ${item.id} :
100
+ <b>Second</b> template with no <b>data-value</b> attribute <br />
101
+ Used when it <b>follows</b> another row with <b>no tpl</b> in props
102
+ </div>`;
103
+ };
104
+
105
+ return html`
106
+ <sonic-list
107
+ templateKey="tpl"
108
+ class="grid gap-3"
109
+ dataProvider="TemplateKeyExample"
110
+ .props=${TEMPLATE_KEY_PROPS}
111
+ .items=${items}
112
+ debug
113
+ ></sonic-list>
114
+ `;
115
+ }
116
+ }
117
+
118
+ @customElement("docs-list-separator-demo")
119
+ export class DocsListSeparatorDemo extends LitElement {
120
+ private items = (item: { id: string }) => html`${item.id}`;
121
+ private separator = () => html` 🤜 `;
122
+ private noItems = () =>
123
+ html`<p class="text-neutral-500">No items (noItems callback)</p>`;
124
+
125
+ render() {
126
+ return html`
127
+ <sonic-list
128
+ dataProvider="ListSeparatorDemo"
129
+ .props=${[{ id: "1" }, { id: "2" }, { id: "3" }]}
130
+ .items=${this.items}
131
+ .separator=${this.separator}
132
+ debug
133
+ ></sonic-list>
134
+ <hr class="my-6 border-neutral-200" />
135
+ <sonic-list
136
+ dataProvider="ListEmptyDemo"
137
+ .props=${[]}
138
+ .items=${this.items}
139
+ .noItems=${this.noItems}
140
+ debug
141
+ ></sonic-list>
142
+ `;
143
+ }
144
+ }
145
+
146
+ @customElement("docs-list-extract-values-demo")
147
+ export class DocsListExtractValuesDemo extends LitElement {
148
+ static styles = [tailwind];
149
+
150
+ private items = (item: { key: string; value: string }) => html`
151
+ <div class="flex items-center gap-3">
152
+ <span class="w-24 font-bold">${item.key}</span>
153
+ <span>${item.value}</span>
154
+ ${item.key === "avatar"
155
+ ? html`<sonic-image
156
+ src=${item.value}
157
+ rounded="full"
158
+ ratio="1/1"
159
+ class="w-20 block"
160
+ ></sonic-image>`
161
+ : nothing}
162
+ </div>
163
+ `;
164
+
165
+ render() {
166
+ return html`
167
+ <sonic-list
168
+ debug
169
+ fetch
170
+ serviceURL="/docs-mock-api"
171
+ dataProvider="list-extract-values-test"
172
+ endPoint="api/users/2"
173
+ key="data"
174
+ extractValues
175
+ .items=${this.items}
176
+ ></sonic-list>
177
+ `;
178
+ }
179
+ }
@@ -0,0 +1,315 @@
1
+ import type { APIConfiguration } from "@supersoniks/concorde/core/utils/api";
2
+ import type { Message } from "@supersoniks/concorde/core/_types/types";
3
+ import { DataProviderKey } from "@supersoniks/concorde/core/utils/dataProviderKey";
4
+ import { set } from "@supersoniks/concorde/core/utils/PublisherProxy";
5
+ import {
6
+ DOCS_MOCK_TOKEN_FRESH,
7
+ DOCS_MOCK_TOKEN_STALE,
8
+ DOCS_MOCK_TOKEN_VALID,
9
+ } from "../mock-api/api-config-mock";
10
+ import { DOCS_MOCK_API_BASE } from "../mock-api/urls";
11
+ import type { DocsUserData } from "./users";
12
+
13
+ type RegisterForm = { email?: string; password?: string };
14
+ type RegisterResult = {
15
+ id?: number;
16
+ token?: string;
17
+ email?: string;
18
+ error?: string;
19
+ messages?: Message[];
20
+ method?: string;
21
+ query?: { email?: string; password?: string };
22
+ note?: string;
23
+ };
24
+
25
+ const apiConfigBase = (): APIConfiguration => ({
26
+ serviceURL: DOCS_MOCK_API_BASE,
27
+ token: null,
28
+ userName: null,
29
+ password: null,
30
+ authToken: null,
31
+ tokenProvider: null,
32
+ });
33
+
34
+ /** Submit demos — `path` values match former attribute strings */
35
+ export const submitExampleFormKey = new DataProviderKey<RegisterForm>(
36
+ "submit-example",
37
+ );
38
+ export const submitExampleResultKey = new DataProviderKey<RegisterResult>(
39
+ "submit-example-result",
40
+ );
41
+ export const submitClearFormKey = new DataProviderKey<RegisterForm>(
42
+ "submit-clear-form",
43
+ );
44
+ export const submitNestedFormKey = new DataProviderKey<RegisterForm>(
45
+ "submit-nested-form",
46
+ );
47
+ export const submitNestedResultKey = new DataProviderKey<RegisterResult>(
48
+ "submit-nested-result",
49
+ );
50
+ export const submitFormDataFormKey = new DataProviderKey<RegisterForm>(
51
+ "submit-formdata-form",
52
+ );
53
+ export const submitFormDataResultKey = new DataProviderKey<RegisterResult>(
54
+ "submit-formdata-result",
55
+ );
56
+ export const submitGetFormKey = new DataProviderKey<RegisterForm>(
57
+ "submit-get-form",
58
+ );
59
+ export const submitGetResultKey = new DataProviderKey<RegisterResult>(
60
+ "submit-get-result",
61
+ );
62
+ export const submitNativeFormKey = new DataProviderKey<RegisterForm>(
63
+ "submit-native-form",
64
+ );
65
+ export const submitEventFormKey = new DataProviderKey<RegisterForm>(
66
+ "submit-event-form",
67
+ );
68
+ export const submitEndpointFormKey = new DataProviderKey<RegisterForm>(
69
+ "submit-endpoint-form",
70
+ );
71
+ export const submitEndpointResultKey = new DataProviderKey<RegisterResult>(
72
+ "submit-endpoint-result",
73
+ );
74
+
75
+ /** API configuration demos */
76
+ export const docsApiConfBearerKey = new DataProviderKey<APIConfiguration>(
77
+ "docsApiConfBearer",
78
+ );
79
+ export const docsApiConfTokenProviderKey = new DataProviderKey<APIConfiguration>(
80
+ "docsApiConfTokenProvider",
81
+ );
82
+ export const docsApiConfStaleTokenKey = new DataProviderKey<APIConfiguration>(
83
+ "docsApiConfStaleToken",
84
+ );
85
+ export const docsApiConfWordingVersionKey = new DataProviderKey<number>(
86
+ "docsApiConfWordingVersion",
87
+ );
88
+
89
+ /** Joke / queue / toggle filters */
90
+ export const docsJokeInputFilterKey = new DataProviderKey<{ contains?: string }>(
91
+ "input-filter",
92
+ );
93
+ export const docsJokeSelectFilterKey = new DataProviderKey<{ lang?: string }>(
94
+ "select-filter",
95
+ );
96
+ export const docsJokeCheckboxFilterKey = new DataProviderKey<{
97
+ blacklistFlags?: string;
98
+ }>("jokeFilter");
99
+ export const docsJokeRadioFilterKey = new DataProviderKey<{
100
+ blacklistFlags?: string;
101
+ }>("jokeFilterRadio");
102
+ export const docsJokeSwitchFilterKey = new DataProviderKey<{
103
+ blacklistFlags?: string;
104
+ }>("jokeFilterswitch");
105
+ export const docsQueueUsersFilterKey = new DataProviderKey<{ q?: string }>(
106
+ "filter",
107
+ );
108
+ export const docsToggleVisibilityKey = new DataProviderKey<{ togglePlan?: string }>(
109
+ "visibilitySettings",
110
+ );
111
+ export const docsToggleLoaderFormKey = new DataProviderKey<{ toggleLoader?: string }>(
112
+ "toggleLoaderForm",
113
+ );
114
+
115
+ /** User / preview scopes */
116
+ export const docsUserScopeAKey = new DataProviderKey<DocsUserData>(
117
+ "docsUserScopeA",
118
+ );
119
+ export const docsUserScopeBKey = new DataProviderKey<DocsUserData>(
120
+ "docsUserScopeB",
121
+ );
122
+ export const docsUserPreviewKey = new DataProviderKey<DocsUserData>(
123
+ "docsUserPreview",
124
+ );
125
+ export const docsUserStaticKey = new DataProviderKey<DocsUserData>(
126
+ "docsUserStatic",
127
+ );
128
+
129
+ /** Decorator live demos (see decorators-demo-init) */
130
+ export const demoDataKey = new DataProviderKey<{
131
+ title: string;
132
+ user: { name: string };
133
+ count: number;
134
+ }>("demoData");
135
+ export const demoUserKey = new DataProviderKey<{
136
+ name: string;
137
+ email: string;
138
+ }>("demoUser");
139
+ export const demoSettingsKey = new DataProviderKey<{
140
+ theme: string;
141
+ language: string;
142
+ }>("demoSettings");
143
+ export const demoUserSettingsKey = new DataProviderKey<{
144
+ theme: string;
145
+ language: string;
146
+ }>("demoUserSettings");
147
+ export const publishDemoKey = new DataProviderKey<{
148
+ email: string;
149
+ message: string;
150
+ }>("publishDemo");
151
+ export const waitAncestorDemoKey = new DataProviderKey<{ message: string }>(
152
+ "waitAncestorDemo",
153
+ );
154
+ export const autoValue1Key = new DataProviderKey<number>("autoValue1");
155
+ export const autoValue2Key = new DataProviderKey<number>("autoValue2");
156
+ export const bindReflectDemoKey = new DataProviderKey<{ count: number }>(
157
+ "bindReflectDemo",
158
+ );
159
+ export const demoUsersKey = new DataProviderKey<
160
+ Array<{
161
+ id: number;
162
+ firstName: string;
163
+ lastName: string;
164
+ email: string;
165
+ }>
166
+ >("demoUsers");
167
+ export const demoUsersAltKey = new DataProviderKey<
168
+ Array<{
169
+ id: number;
170
+ firstName: string;
171
+ lastName: string;
172
+ email: string;
173
+ }>
174
+ >("demoUsersAlt");
175
+ export const demoUsersSettingsKey = new DataProviderKey<
176
+ Array<{ theme: string; language: string }>
177
+ >("demoUsersSettings");
178
+ export const demoUsersAltSettingsKey = new DataProviderKey<
179
+ Array<{ theme: string; language: string }>
180
+ >("demoUsersAltSettings");
181
+
182
+ const defaultRegisterForm = (): RegisterForm => ({
183
+ email: "eve.holt@reqres.in",
184
+ password: "pistol",
185
+ });
186
+
187
+ export function initDocsProviderDefaults(): void {
188
+ set(submitExampleFormKey, defaultRegisterForm());
189
+ set(submitClearFormKey, defaultRegisterForm());
190
+ set(submitNestedFormKey, defaultRegisterForm());
191
+ set(submitFormDataFormKey, defaultRegisterForm());
192
+ set(submitGetFormKey, {
193
+ email: "demo@example.com",
194
+ password: "secret",
195
+ });
196
+ set(submitNativeFormKey, defaultRegisterForm());
197
+ set(submitEventFormKey, defaultRegisterForm());
198
+ set(submitEndpointFormKey, defaultRegisterForm());
199
+
200
+ set(docsApiConfBearerKey, {
201
+ ...apiConfigBase(),
202
+ token: DOCS_MOCK_TOKEN_VALID,
203
+ });
204
+ set(docsApiConfTokenProviderKey, {
205
+ ...apiConfigBase(),
206
+ userName: "demo",
207
+ password: "secret",
208
+ tokenProvider: "auth/token",
209
+ });
210
+ set(docsApiConfStaleTokenKey, {
211
+ ...apiConfigBase(),
212
+ token: DOCS_MOCK_TOKEN_STALE,
213
+ userName: "demo",
214
+ password: "secret",
215
+ tokenProvider: "auth/token",
216
+ });
217
+ set(docsApiConfWordingVersionKey, 1);
218
+
219
+ set(docsJokeInputFilterKey, { contains: "chien" });
220
+ set(docsJokeSelectFilterKey, { lang: "fr" });
221
+ set(docsQueueUsersFilterKey, { q: "" });
222
+
223
+ set(docsToggleVisibilityKey, { togglePlan: "true" });
224
+ set(docsToggleLoaderFormKey, { toggleLoader: "" });
225
+
226
+ set(docsUserScopeAKey, {
227
+ first_name: "Paul",
228
+ last_name: "Metrand",
229
+ email: "paul@example.com",
230
+ avatar: "https://i.pravatar.cc/150?u=paul",
231
+ });
232
+ set(docsUserScopeBKey, {
233
+ first_name: "Marie",
234
+ last_name: "Dupont",
235
+ email: "marie@example.com",
236
+ avatar: "https://i.pravatar.cc/150?u=marie",
237
+ });
238
+ set(docsUserPreviewKey, {
239
+ first_name: "Paul",
240
+ last_name: "Metrand",
241
+ email: "paul@example.com",
242
+ avatar: "https://i.pravatar.cc/150?u=paul",
243
+ });
244
+ set(docsUserStaticKey, {
245
+ first_name: "Paul",
246
+ last_name: "Metrand",
247
+ email: "paul@example.com",
248
+ avatar: "https://i.pravatar.cc/150?u=paul",
249
+ });
250
+
251
+ set(demoDataKey, {
252
+ title: "Initial Title",
253
+ user: { name: "Initial User" },
254
+ count: 0,
255
+ });
256
+ set(demoUserKey, { name: "Demo User", email: "demo@example.com" });
257
+ set(demoSettingsKey, { theme: "light", language: "en" });
258
+ set(demoUserSettingsKey, { theme: "light", language: "en" });
259
+ set(publishDemoKey, { email: "", message: "" });
260
+ set(waitAncestorDemoKey, { message: "Context from ancestor" });
261
+ set(autoValue1Key, 10);
262
+ set(autoValue2Key, 20);
263
+ set(bindReflectDemoKey, { count: 0 });
264
+
265
+ set(demoUsersKey, [
266
+ { id: 1, firstName: "Alice", lastName: "Smith", email: "alice.smith@example.com" },
267
+ { id: 2, firstName: "Bob", lastName: "Johnson", email: "bob.johnson@example.com" },
268
+ { id: 3, firstName: "Carol", lastName: "Williams", email: "carol.williams@example.com" },
269
+ { id: 4, firstName: "David", lastName: "Brown", email: "david.brown@example.com" },
270
+ { id: 5, firstName: "Eve", lastName: "Jones", email: "eve.jones@example.com" },
271
+ { id: 6, firstName: "Frank", lastName: "Garcia", email: "frank.garcia@example.com" },
272
+ { id: 7, firstName: "Grace", lastName: "Miller", email: "grace.miller@example.com" },
273
+ { id: 8, firstName: "Henry", lastName: "Davis", email: "henry.davis@example.com" },
274
+ { id: 9, firstName: "Ivy", lastName: "Martinez", email: "ivy.martinez@example.com" },
275
+ { id: 10, firstName: "Jack", lastName: "Taylor", email: "jack.taylor@example.com" },
276
+ ]);
277
+ set(demoUsersAltKey, [
278
+ { id: 11, firstName: "Sophie", lastName: "Lindquist", email: "sophie.lindquist@example.com" },
279
+ { id: 12, firstName: "Mateo", lastName: "Ortega", email: "mateo.ortega@example.com" },
280
+ { id: 13, firstName: "Jin", lastName: "Park", email: "jin.park@example.com" },
281
+ { id: 14, firstName: "Fatima", lastName: "El-Sayed", email: "fatima.el-sayed@example.com" },
282
+ { id: 15, firstName: "Lars", lastName: "Johansson", email: "lars.johansson@example.com" },
283
+ { id: 16, firstName: "Amara", lastName: "Singh", email: "amara.singh@example.com" },
284
+ { id: 17, firstName: "Zuri", lastName: "Okafor", email: "zuri.okafor@example.com" },
285
+ { id: 18, firstName: "Luca", lastName: "Rossi", email: "luca.rossi@example.com" },
286
+ { id: 19, firstName: "Ava", lastName: "Murphy", email: "ava.murphy@example.com" },
287
+ { id: 20, firstName: "Noah", lastName: "Keller", email: "noah.keller@example.com" },
288
+ ]);
289
+ set(demoUsersSettingsKey, [
290
+ { theme: "light", language: "en" },
291
+ { theme: "dark", language: "fr" },
292
+ { theme: "auto", language: "es" },
293
+ { theme: "light", language: "en" },
294
+ { theme: "dark", language: "fr" },
295
+ { theme: "auto", language: "es" },
296
+ { theme: "light", language: "en" },
297
+ { theme: "dark", language: "fr" },
298
+ { theme: "auto", language: "es" },
299
+ { theme: "light", language: "en" },
300
+ ]);
301
+ set(demoUsersAltSettingsKey, [
302
+ { theme: "dark", language: "de" },
303
+ { theme: "light", language: "it" },
304
+ { theme: "auto", language: "ja" },
305
+ { theme: "dark", language: "pt" },
306
+ { theme: "light", language: "ru" },
307
+ { theme: "auto", language: "zh" },
308
+ { theme: "dark", language: "ar" },
309
+ { theme: "light", language: "sv" },
310
+ { theme: "auto", language: "nl" },
311
+ { theme: "dark", language: "pl" },
312
+ ]);
313
+ }
314
+
315
+ initDocsProviderDefaults();
@@ -0,0 +1,114 @@
1
+ import { html, LitElement } from "lit";
2
+ import { customElement } from "lit/decorators.js";
3
+ import {
4
+ DOCS_MOCK_GEO_SERVICE,
5
+ DOCS_MOCK_REQRES_SERVICE,
6
+ } from "../mock-api/urls";
7
+ import { docsQueueUsersFilterKey } from "./docs-provider-keys";
8
+ import { tailwind } from "../tailwind";
9
+
10
+ import "../../core/components/functional/queue/queue";
11
+ import "../../core/components/ui/image/image";
12
+ import "../../core/components/ui/form/input/input";
13
+
14
+ type CommuneRow = { nom: string; code?: string };
15
+
16
+ type UserRow = {
17
+ first_name: string;
18
+ last_name: string;
19
+ email: string;
20
+ avatar: string;
21
+ };
22
+
23
+ const userRow = ({ first_name, last_name, email, avatar }: UserRow) =>
24
+ html`<div class="flex items-center gap-3 rounded-md p-2 hover:bg-neutral-50">
25
+ <sonic-image
26
+ src=${avatar}
27
+ rounded="md"
28
+ ratio="1/1"
29
+ class="w-12 block"
30
+ ></sonic-image>
31
+ <div>
32
+ <div>${first_name} <span class="font-bold">${last_name}</span></div>
33
+ <div class="text-sm text-neutral-500">${email}</div>
34
+ </div>
35
+ </div>`;
36
+
37
+ /** Communes — one batch (`limit` only, no `$offset` in the expression). */
38
+ @customElement("docs-queue-geo-demo")
39
+ export class DocsQueueGeoDemo extends LitElement {
40
+ private items = (item: CommuneRow) =>
41
+ html`<div class="rounded bg-neutral-100 p-2 text-sm">
42
+ <div class="font-medium">${item.nom}</div>
43
+ ${item.code
44
+ ? html`<div class="text-neutral-500">${item.code}</div>`
45
+ : null}
46
+ </div>`;
47
+
48
+ render() {
49
+ return html`
50
+ <sonic-queue
51
+ class="grid grid-cols-3 gap-3"
52
+ dataProviderExpression="communes?limit=$limit"
53
+ limit="6"
54
+ serviceURL=${DOCS_MOCK_GEO_SERVICE}
55
+ .items=${this.items}
56
+ debug
57
+ ></sonic-queue>
58
+ `;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Users — lazy load + search (`q`), aligned with create-concorde-ts-starter demo-queue.
64
+ * Mock: `filterDocsUsers` + `paginateUsers` in `src/docs/mock-api/`.
65
+ */
66
+ @customElement("docs-queue-users-demo")
67
+ export class DocsQueueUsersDemo extends LitElement {
68
+ static styles = [tailwind];
69
+
70
+ private items = userRow;
71
+
72
+ private separator = () => html`
73
+ <div class="my-1 border-t border-dashed border-neutral-200"></div>
74
+ `;
75
+
76
+ private noItems = () => html`
77
+ <p class="p-4 text-center text-sm italic text-neutral-500">
78
+ No users — try another search (e.g. <code>zzz</code>)
79
+ </p>
80
+ `;
81
+
82
+ render() {
83
+ return html`
84
+ <div formDataProvider=${docsQueueUsersFilterKey.path} class="mb-3 max-w-md">
85
+ <sonic-input
86
+ name="q"
87
+ type="search"
88
+ label="Search"
89
+ placeholder="First name, last name, or email"
90
+ size="sm"
91
+ ></sonic-input>
92
+ </div>
93
+ <p class="mb-3 text-sm text-neutral-500">
94
+ Typing updates <code>?q=…</code> on each request. Scroll inside the box
95
+ to load the next batch (<code>offset</code> += <code>limit</code>).
96
+ </p>
97
+ <sonic-queue
98
+ lazyload
99
+ dataProviderExpression="api/users?offset=$offset&limit=$limit"
100
+ dataFilterProvider="filter"
101
+ limit="4"
102
+ offset="0"
103
+ idKey="id"
104
+ serviceURL=${DOCS_MOCK_REQRES_SERVICE}
105
+ key="data"
106
+ class="grid max-h-96 max-w-md gap-2 overflow-y-auto"
107
+ .items=${this.items}
108
+ .separator=${this.separator}
109
+ .noItems=${this.noItems}
110
+ debug
111
+ ></sonic-queue>
112
+ `;
113
+ }
114
+ }
@@ -0,0 +1,89 @@
1
+ import { html, LitElement } from "lit";
2
+ import { customElement, state } from "lit/decorators.js";
3
+ import { tailwind } from "../tailwind";
4
+ import { DOC_ROUTER_PAGE_HASH, setDocsDemoSubHash } from "../docs-location";
5
+
6
+ import "../../core/components/functional/router/router";
7
+ import "../../core/components/ui/button/button";
8
+
9
+ const panel = (title: string, body?: string) => html`
10
+ <div
11
+ class="my-4 rounded border border-neutral-200 p-6 text-center text-2xl text-neutral-700"
12
+ >
13
+ ${title}
14
+ ${body ? html`<p class="mt-2 text-base text-neutral-500">${body}</p>` : null}
15
+ </div>
16
+ `;
17
+
18
+ function navButton(label: string, subRoute: string, variant?: string) {
19
+ const href = `${DOC_ROUTER_PAGE_HASH}#${subRoute.replace(/^#/, "")}`;
20
+ return html`<sonic-button
21
+ size="xs"
22
+ variant=${variant ?? "default"}
23
+ autoActive="strict"
24
+ href=${href}
25
+ @click=${(e: Event) => {
26
+ e.preventDefault();
27
+ setDocsDemoSubHash(subRoute, DOC_ROUTER_PAGE_HASH);
28
+ }}
29
+ >${label}</sonic-button
30
+ >`;
31
+ }
32
+
33
+ @customElement("docs-router-basic-demo")
34
+ export class DocsRouterBasicDemo extends LitElement {
35
+ static styles = [tailwind];
36
+
37
+ @state()
38
+ private routes = {
39
+ "#home": () => panel("Home"),
40
+ "#about": () => panel("About"),
41
+ "#work": () => panel("Work"),
42
+ "#contact": () => panel("Contact"),
43
+ fallback: () =>
44
+ panel("404", "No route matched — `routes.fallback` is rendered."),
45
+ };
46
+
47
+ render() {
48
+ return html`
49
+ <div class="mb-4 flex flex-wrap gap-2">
50
+ ${navButton("Home", "home")}
51
+ ${navButton("About", "about")}
52
+ ${navButton("Work", "work")}
53
+ ${navButton("Contact", "contact")}
54
+ ${navButton("Unknown", "unknown", "outline")}
55
+ </div>
56
+ <sonic-router .routes=${this.routes}></sonic-router>
57
+ `;
58
+ }
59
+ }
60
+
61
+ @customElement("docs-router-params-demo")
62
+ export class DocsRouterParamsDemo extends LitElement {
63
+ static styles = [tailwind];
64
+
65
+ @state()
66
+ private routes = {
67
+ "#couleur/:id": ({ id }: { id: string }) =>
68
+ panel("Url-pattern", `Param :id = ${id}`),
69
+ "#products/(\\d+)/(\\w+)": ([productId, slug]: [string, string]) =>
70
+ panel("RegExp", `productId = ${productId}, slug = ${slug}`),
71
+ fallback: () => panel("No match", "Try a link below."),
72
+ };
73
+
74
+ render() {
75
+ return html`
76
+ <p class="mb-3 text-sm text-neutral-500">
77
+ Dynamic segments are passed to the route function (object for
78
+ <code>url-pattern</code>, array for capturing groups). Navigation uses
79
+ <code>history.replaceState</code> with a second hash segment so the doc
80
+ page does not reload.
81
+ </p>
82
+ <div class="mb-4 flex flex-wrap gap-2">
83
+ ${navButton("#couleur/3", "couleur/3")}
84
+ ${navButton("#products/42/widget", "products/42/widget")}
85
+ </div>
86
+ <sonic-router .routes=${this.routes}></sonic-router>
87
+ `;
88
+ }
89
+ }