@supersoniks/concorde 4.5.2 → 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 (185) 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 +159 -159
  18. package/concorde-core.es.js +1915 -1809
  19. package/dist/altcha-widget.js +2662 -0
  20. package/dist/concorde-core.bundle.js +159 -159
  21. package/dist/concorde-core.es.js +1915 -1809
  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 +37 -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/Subscriber.ts +2 -0
  108. package/src/core/decorators/subscriber/handle.disambig.spec.ts +20 -0
  109. package/src/core/decorators/subscriber/handle.skip.spec.ts +37 -0
  110. package/src/core/decorators/subscriber/handle.ts +128 -0
  111. package/src/core/decorators/subscriber/onAssign.ts +94 -4
  112. package/src/core/directives/DataProvider.sub.spec.ts +96 -0
  113. package/src/core/directives/DataProvider.ts +109 -40
  114. package/src/core/utils/PublisherProxy.ts +33 -18
  115. package/src/core/utils/dataProviderKey.ts +23 -0
  116. package/src/core/utils/publisherPathKey.spec.ts +58 -0
  117. package/src/decorators.ts +6 -0
  118. package/src/docs/_core-concept/dataFlow.md +73 -0
  119. package/src/docs/_core-concept/subscriber.md +9 -10
  120. package/src/docs/_decorators/ancestor-attribute.md +4 -3
  121. package/src/docs/_decorators/auto-subscribe.md +19 -16
  122. package/src/docs/_decorators/bind.md +20 -17
  123. package/src/docs/_decorators/get.md +7 -4
  124. package/src/docs/_decorators/handle.md +171 -0
  125. package/src/docs/_decorators/on-assign.md +99 -47
  126. package/src/docs/_decorators/publish.md +2 -1
  127. package/src/docs/_decorators/subscribe.md +70 -9
  128. package/src/docs/_decorators/wait-for-ancestors.md +13 -10
  129. package/src/docs/_directives/sub.md +91 -0
  130. package/src/docs/_getting-started/ai-agents.md +56 -0
  131. package/src/docs/_getting-started/concorde-manual-install.md +133 -0
  132. package/src/docs/_getting-started/concorde-outside.md +13 -123
  133. package/src/docs/_getting-started/create-a-component.md +2 -0
  134. package/src/docs/_getting-started/my-first-component.md +236 -0
  135. package/src/docs/_getting-started/my-first-subscriber.md +29 -83
  136. package/src/docs/_getting-started/pubsub.md +21 -134
  137. package/src/docs/_getting-started/start.md +26 -18
  138. package/src/docs/_misc/api-configuration.md +79 -0
  139. package/src/docs/_misc/dataProviderKey.md +38 -5
  140. package/src/docs/_misc/docs-mock-api.md +60 -0
  141. package/src/docs/_misc/endpoint.md +2 -1
  142. package/src/docs/_misc/html-integration.md +13 -0
  143. package/src/docs/code.ts +58 -12
  144. package/src/docs/components/docs-demo-sources.ts +397 -0
  145. package/src/docs/components/docs-lit-demo-raw.ts +28 -0
  146. package/src/docs/components/docs-lit-demo.ts +166 -0
  147. package/src/docs/components/docs-source-link.ts +72 -0
  148. package/src/docs/docs-location.ts +54 -0
  149. package/src/docs/docs.ts +12 -0
  150. package/src/docs/example/decorators-demo-bind-demos.ts +41 -46
  151. package/src/docs/example/decorators-demo-geo.ts +16 -11
  152. package/src/docs/example/decorators-demo-init.ts +2 -228
  153. package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +142 -12
  154. package/src/docs/example/decorators-demo.ts +71 -70
  155. package/src/docs/example/docs-api-config-demos.ts +234 -0
  156. package/src/docs/example/docs-joke-demos.ts +297 -0
  157. package/src/docs/example/docs-list-demos.ts +179 -0
  158. package/src/docs/example/docs-provider-keys.ts +315 -0
  159. package/src/docs/example/docs-queue-demos.ts +114 -0
  160. package/src/docs/example/docs-router-demos.ts +89 -0
  161. package/src/docs/example/docs-submit-demos.ts +455 -0
  162. package/src/docs/example/docs-toggle-demos.ts +73 -0
  163. package/src/docs/example/docs-user-two-scopes.ts +37 -0
  164. package/src/docs/example/docs-users-list.ts +71 -0
  165. package/src/docs/example/users.ts +41 -24
  166. package/src/docs/mock-api/api-config-mock.ts +152 -0
  167. package/src/docs/mock-api/fixtures.ts +377 -0
  168. package/src/docs/mock-api/register.ts +25 -0
  169. package/src/docs/mock-api/router.ts +234 -0
  170. package/src/docs/mock-api/service-worker.ts +23 -0
  171. package/src/docs/mock-api/urls.ts +11 -0
  172. package/src/docs/navigation/navigation.ts +43 -7
  173. package/src/docs/search/docs-search.json +4193 -858
  174. package/src/docs/search/markdown-renderer.ts +7 -3
  175. package/src/docs/search/page.ts +11 -14
  176. package/src/docs/search/sonic-code-markdown.spec.ts +29 -0
  177. package/src/docs/search/sonic-code-markdown.ts +28 -0
  178. package/src/docs.ts +4 -0
  179. package/src/tsconfig.json +96 -0
  180. package/src/tsconfig.tsbuildinfo +1 -1
  181. package/vite.config.mts +8 -0
  182. package/docs/assets/index-CaysOMFz.js +0 -5046
  183. package/docs/assets/index-D8mGoXzF.css +0 -1
  184. package/docs/src/docs/_misc/templates-demo.md +0 -19
  185. package/src/docs/_misc/templates-demo.md +0 -19
@@ -1,94 +1,77 @@
1
1
  # Router
2
2
 
3
- The router observes the document.location changes and updates its view as follows
3
+ **sonic-router** watches `document.location` (pathname + hash) and renders the matching view.
4
4
 
5
- ## Data-route / Basic
5
+ From a **Lit** parent, pass a **`.routes`** map (property binding — same rule as [`.items` on list](#core/components/functional/list/list.md/list)): keys are path patterns, values are render functions. Use **`fallback`** when nothing matches.
6
6
 
7
- When the data-route attribute of a template matches the current url, the content of this template is rendered
7
+ Legacy HTML **`<template data-route="…">`** remains for hosts without Lit [HTML integration](#docs/_misc/html-integration.md/html-integration).
8
8
 
9
- <sonic-code>
10
- <template>
11
- <div class="flex gap-2 items-center">
12
- <sonic-button href="#core/components/functional/router/router.md/router#home" size="xs">Home</sonic-button>
13
- <sonic-button href="#core/components/functional/router/router.md/router#about" size="xs">About</sonic-button>
14
- <sonic-button href="#core/components/functional/router/router.md/router#work" size="xs">Work</sonic-button>
15
- <sonic-button href="#core/components/functional/router/router.md/router#contact" size="xs">Contact</sonic-button>
16
- </div>
17
- <sonic-router>
18
- <template data-route="#home">
19
- <div class="text-center text-neutral-700 border rounded text-4xl my-6 p-3 ">Home</div>
20
- </template>
21
- <template data-route="#about">
22
- <div class="text-center text-neutral-700 border rounded text-4xl my-6 p-3 ">About</div>
23
- </template>
24
- <template data-route="#work">
25
- <div class="text-center text-neutral-700 border rounded text-4xl my-6 p-3 ">Work</div>
26
- </template>
27
- <template data-route="#contact">
28
- <div class="text-center text-neutral-700 border rounded text-4xl my-6 p-3 ">Contact</div>
29
- </template>
30
- </sonic-router>
31
- </template>
32
- </sonic-code>
9
+ ## Static routes (no parameters)
33
10
 
34
- ## Data-route / Regexp
11
+ Route keys are matched against `pathname + hash`. A simple hash route `#home` matches when the location contains that segment.
35
12
 
36
- You can use any RegExp in the data-route attribute of your templates to match the current location and to extract variables from it using capturing groups.
37
- A dataProvider attribute is generated using the dataProviderExpression where $1, $2... are replaced with this variables.
13
+ On the **doc site**, the page URL is already a hash (`#…/router.md/router`). Demos append a **second** hash for in-page routes (`#…/router#home`), use **`href` + `autoActive="strict"`** on `sonic-button` for the active state, and `history.replaceState` on click so markdown is not reloaded (`setDocsDemoSubHash` in `src/docs/docs-location.ts`).
38
14
 
39
- **e.g.**, data-route="#couleur_<b class="text-danger">(\d+)</b>" => dataProviderExpression="api/unknown/<b class="text-danger">$1</b>"
15
+ <docs-lit-demo for="docs-router-basic-demo"></docs-lit-demo>
40
16
 
41
- The rendered content of the matching template is scoped with this **dataProvider**.
42
- You can make creative usage on this feature to generate dynamic content based on services.
17
+ ```typescript
18
+ @state()
19
+ private routes = {
20
+ "#home": () => html`<div>Home</div>`,
21
+ "#about": () => html`<div>About</div>`,
22
+ fallback: () => html`<div>Not found</div>`,
23
+ };
43
24
 
44
- <sonic-code>
45
- <template>
46
- <sonic-list fetch dataProvider="api/unknown" key="data" class="flex gap-2 items-center" >
47
- <template>
48
- <sonic-button radio size="xs" data-bind ::href="#core/components/functional/router/router.md/router#couleur_$id">
49
- <span data-bind ::inner-html="ucFirst|$name"></span>
50
- </sonic-button>
51
- </template>
52
- </sonic-list>
53
- <sonic-router>
54
- <template data-route="#couleur_(\d+)" dataProviderExpression="api/unknown/$1">
55
- <sonic-fetch>
56
- <input type="color" disabled data-bind ::value="$data.color" class=" w-full h-10 my-3" />
57
- </sonic-fetch>
58
- </template>
59
- </sonic-router>
60
- </template>
61
- </sonic-code>
25
+ html`
26
+ <sonic-button href="#home">Home</sonic-button>
27
+ <sonic-router .routes=${this.routes}></sonic-router>
28
+ `;
29
+ ```
62
30
 
63
- ## Data-route / Url-pattern
31
+ | Key | When it runs |
32
+ |-----|----------------|
33
+ | `"#home"`, `"#about"`, … | `RegExp` or [url-pattern](https://www.npmjs.com/package/url-pattern) test succeeds on current location |
34
+ | **`fallback`** | No other route matched (not an attribute — a key on the same object) |
64
35
 
65
- Same as RegExp but using <a href="https://www.npmjs.com/package/url-pattern" target="_blank">url patterns</a>
66
- **e.g.**, data-route="#couleur_<b class="text-danger">:id</b>" => dataProviderExpression="api/unknown/<b class="text-danger">:id</b>"
36
+ ## Routes with parameters
67
37
 
68
- <sonic-code>
69
- <template>
70
- <sonic-list fetch dataProvider="api/unknown" key="data" class="flex gap-2 items-center" >
71
- <template>
72
- <sonic-button radio size="xs" data-bind ::href="#core/components/functional/router/router.md/router#couleur_$id">
73
- <span data-bind ::inner-html="ucFirst|$name"></span>
74
- </sonic-button>
75
- </template>
76
- </sonic-list>
77
- <sonic-router>
78
- <template data-route="/*#couleur_:id" dataProviderExpression="api/unknown/:id">
79
- <sonic-fetch>
80
- <input type="color" disabled data-bind ::value="$data.color" class=" w-full h-10 my-3" />
81
- </sonic-fetch>
82
- </template>
83
- </sonic-router>
84
- </template>
85
- </sonic-code>
38
+ Two styles (see `router.demo.ts` and `docs-router-params-demo`):
39
+
40
+ ### Url-pattern (`:name`)
41
+
42
+ Key uses **`:param`** segments. The render function receives an **object** `{ param: string }`.
43
+
44
+ <docs-lit-demo for="docs-router-params-demo"></docs-lit-demo>
45
+
46
+ ```typescript
47
+ "#couleur/:id": ({ id }) => html`<p>Colour id: ${id}</p>`,
48
+ ```
86
49
 
87
- ## Redirect
50
+ ### RegExp (capturing groups)
88
51
 
89
- Redirect allows to redirect to a url when a data is provided.
90
- Here Redirect waits that a data is available in the property *theData* of the dataProvider *stupid-data-set-id*
91
- We are then redirected to the url *#data-is-set* which does nothing in itself.
52
+ Key is a **RegExp** string with `(\d+)` / `(\w+)` groups. The render function receives an **array** of captured strings (in order).
53
+
54
+ ```typescript
55
+ "#products/(\\d+)/(\\w+)": ([productId, slug]) =>
56
+ html`<p>Product ${productId}, slug ${slug}</p>`,
57
+ ```
58
+
59
+ With parameters you usually render data directly in Lit (`${id}`). The old **`<template data-route>` + `dataProviderExpression`** pattern scoped a `dataProvider` for `data-bind` / fetch children — prefer **`@subscribe`** or explicit props when using `.routes`.
60
+
61
+ ## `.routes` binding
62
+
63
+ Always use **`.routes=${…}`** in Lit templates: route handlers are functions and must be set as **properties**, not HTML attributes.
64
+
65
+ ## Optional attributes
66
+
67
+ | Attribute | Role |
68
+ |-----------|------|
69
+ | **`basePath`** | Prefix for pattern matching (default allows optional leading segments) |
70
+ | **`fallBackRoute`** | If set and no template/route matches, navigates to this URL (redirect). Distinct from **`routes.fallback`** which only renders content |
71
+
72
+ ## `sonic-redirect`
73
+
74
+ Separate component: redirect when data appears on a publisher (login steps, wizards). Not part of the `.routes` map.
92
75
 
93
76
  <sonic-code>
94
77
  <template>
@@ -101,29 +84,11 @@ We are then redirected to the url *#data-is-set* which does nothing in itself.
101
84
  Delete the data and do a history.back()
102
85
  </sonic-button>
103
86
  </div>
104
-
105
87
  </template>
106
88
  </sonic-code>
107
89
 
108
- Example of use : use with a router and a submit to manage the steps of login/logout, display of user info.
109
-
110
- ## Fallback
111
-
112
- The fallback route is rendered when no other route matches the current location.
113
-
114
- <sonic-code>
115
- <sonic-router>
116
- <template data-route="#home">
117
- <div>Home</div>
118
- </template>
119
- <template data-route="#fallback">
120
- <div>Fallback</div>
121
- </template>
122
- </sonic-router>
123
- </sonic-code>
124
-
125
- ## Programmatic routes
126
-
127
-
90
+ Example: combine with **`.routes`** and **submit** for login / logout / profile steps.
128
91
 
92
+ ## Package demo
129
93
 
94
+ `sonic-router-demo` (`router.demo.ts`) — home, user profile (`#user/:id/:slug`), products RegExp, **fallback** 404.
@@ -50,7 +50,7 @@ export class SonicRouter extends TemplatesContainer(LitElement) {
50
50
  templateValueAttribute = "data-route";
51
51
 
52
52
  @property({ type: String }) fallBackRoute?: string;
53
- @property({ type: Object }) routes?: RoutesToRenderer;
53
+ @property({ type: Object, attribute: false }) routes?: RoutesToRenderer;
54
54
  @property({ type: String }) basePath?: string;
55
55
 
56
56
  protected createRenderRoot(): HTMLElement | DocumentFragment {
@@ -41,7 +41,7 @@ When using **capturing groups ()** the stored values are accessible via the **da
41
41
 
42
42
  <sonic-code>
43
43
  <template>
44
- <div serviceURL="https://reqres.in">
44
+ <div serviceURL="/docs-mock-api">
45
45
  <sonic-list formDataProvider="states-regexp-example" fetch dataProvider="api/unknown" key="data" class="flex gap-2 items-center" >
46
46
  <template>
47
47
  <sonic-button radio size="xs" name="selection" data-bind ::value="#couleur_$id">
@@ -67,7 +67,7 @@ Same as RegExp but using <a href="https://www.npmjs.com/package/url-pattern" tar
67
67
 
68
68
  <sonic-code>
69
69
  <template>
70
- <div serviceURL="https://reqres.in">
70
+ <div serviceURL="/docs-mock-api">
71
71
  <sonic-list formDataProvider="states-regexp-example" fetch dataProvider="api/unknown" key="data" class="flex gap-2 items-center" >
72
72
  <template>
73
73
  <sonic-button radio size="xs" name="selection" data-bind ::value="#couleur_$id">
@@ -1,58 +1,90 @@
1
1
  # Submit
2
2
 
3
- ## The submit element is used to send data to a rest service
4
- * The api is set up like a [fetcher](#core/components/functional/fetch/fetch.md/fetch).
5
- * The *formDataProvider* attribute points to the adress where the data is held by a publisher.
6
- * This attribute is also used by form elements such as *sonic-input*, or *sonic-select*, which fill this publisher with their *value* attribute according to their *name* attribute
7
- * The *method* attribute allows you to choose the sending method: *put/delete/post*, *post* being the default method.
8
- * If the *onClick* attribute is present, the data is sent when the content is clicked on
9
- * If the *onEnterKey* attribute is present, data is sent when the enter key of an element contained in the *sonic-submit* with focus is pressed
10
- * During sending, *sonic-submit* elements with the same *dataProvider* attribute have the *disabled="disabled "* property, which has the effect of disabling their content
11
- * The *clearedDataOnSuccess* attribute can be used to clear the data from the corresponding dataProvider when the call to the api has provided a result.
12
-
13
- ## Form example
14
- <sonic-code>
15
- <template>
16
- <sonic-scope
17
- serviceURL="https://reqres.in" dataProvider="api/register"
18
- formDataProvider="submit-example" submitResultDataProvider="submit-example-result"
19
- method="post"
20
- class="max-w-lg block"
21
- >
22
- <sonic-submit onEnterKey>
23
- <div class="grid grid-cols-2 gap-4 mb-4 ">
24
- <sonic-input required name="email" type="email" value="eve.holt@reqres.in"></sonic-input>
25
- <sonic-input required type="password" name="password" value="pistol"></sonic-input>
26
- </div>
27
- </sonic-submit>
28
- <sonic-submit onClick>
29
- <sonic-button type="success" class="w-full">Submit</sonic-button>
30
- </sonic-submit>
31
- </sonic-scope>
32
- </template>
33
- </sonic-code>
3
+ > **Live demos:** `<docs-lit-demo>` + `src/docs/example/docs-submit-demos.ts`. Use [Local API demos](#docs/_misc/docs-mock-api.md/docs-mock-api) (`serviceURL="/docs-mock-api"`).
34
4
 
5
+ ## Overview
35
6
 
7
+ **sonic-submit** sends the **formDataProvider** publisher to a REST endpoint (same configuration model as [fetch](#core/components/functional/fetch/fetch.md/fetch): `serviceURL` on an ancestor, path via `dataProvider` or `endPoint`).
36
8
 
9
+ | Trigger | Attribute |
10
+ |---------|-----------|
11
+ | Click inside the slot | `onClick` |
12
+ | Enter in a focused field inside the slot | `onEnterKey` |
37
13
 
14
+ | Data / API | Attribute / property | Notes |
15
+ |------------|----------------------|--------|
16
+ | Form fields | `formDataProvider` on ancestor | Filled by `sonic-input`, `sonic-select`, etc. via `name` |
17
+ | Result after call | `submitResultDataProvider` on ancestor | Whole result object (after optional `submit-result-key`) |
18
+ | Slice of JSON result | `submit-result-key` on **sonic-submit** | Dot path, e.g. `data` when the API returns `{ data: { … } }` |
19
+ | HTTP verb | `method` on **sonic-submit** | `post` (default), `put`, `patch`, `delete`, `get` — not inherited from `sonic-scope` |
20
+ | Path override | `endPoint` on **sonic-submit** | Wins over ancestor `dataProvider` |
21
+ | JSON vs multipart | `sendAsFormData` on **sonic-submit** | `FormData` body, still expects JSON response |
22
+ | Reset publishers | `clearedDataOnSuccess` on ancestor | Space-separated `DataProviderKey.path` values; runs when a **result object** is returned (including error payloads with `messages`) |
23
+ | Browser form POST | `native` on **sonic-submit** | See [Native HTML form](#native-html-form) |
24
+ | Result event | — | Bubbles `submit` `CustomEvent` with `detail` = result |
25
+ | Credential Management API | `usernameKey`, `passwordKey` on **sonic-submit** | After a **successful** HTTP response, stores login if those keys exist in the payload (defaults: `username`, `password`) |
26
+ | ALTCHA / captcha | `needsCaptchaValidation` on form/header publisher | Defers send until token is set — see [Captcha](#core/components/ui/captcha/captcha.md/captcha) |
38
27
 
39
- ## Result handling example
28
+ While a REST submit runs, the slot is wrapped with `data-disabled` (faded, no pointer events). With **`native`**, validation and loader still run, then the browser performs a normal form submission.
40
29
 
41
- Result will show when something has been submit because the **dataprovider** used in this example is the same as the **submitResultDataProvider** used in the previous form.
42
- <sonic-code>
43
- <template>
44
- <div dataProvider="submit-example-result">
45
- <div>Id : <span data-bind ::inner-html="$id"></span></div>
46
- <div>Token : <span data-bind ::inner-html="$token"></span></div>
47
- <div data-bind ::inner-html="$error"></div>
48
- </div>
49
- </template>
50
- </sonic-code>
30
+ ## Form and result handling
31
+
32
+ POST to mock `api/register`; result publisher `submit-example-result`.
33
+
34
+ <docs-lit-demo for="docs-submit-demo"></docs-lit-demo>
35
+
36
+ ## Native HTML form
37
+
38
+ With **`native`**, Concorde does **not** call `fetch`. After form validation it:
39
+
40
+ 1. Copies **formDataProvider** values into matching `<input>` / `<select>` / `<textarea>` inside the closest **`<form>`** (creates hidden inputs if needed).
41
+ 2. Programmatically clicks a hidden native `type="submit"` control (`name` / `value` on **sonic-submit** if you need them).
42
+
43
+ Use a real `<form action="…" method="post">` ancestor. For SPAs, a named **`target`** (e.g. iframe) avoids leaving the doc page.
44
+
45
+ <docs-lit-demo for="docs-submit-native-demo"></docs-lit-demo>
46
+
47
+ ## sendAsFormData
48
+
49
+ Sends fields as **`multipart/form-data`** instead of `application/json` (response is still parsed as JSON).
51
50
 
51
+ <docs-lit-demo for="docs-submit-formdata-demo"></docs-lit-demo>
52
52
 
53
- ## dot notation
53
+ ## submit-result-key
54
54
 
55
- You can write the folowing code where the name attribute is written in dot notation.
55
+ When the API wraps the payload (e.g. `{ data: { id, token } }`), set **`submit-result-key="data"`** on **sonic-submit** so **submitResultDataProvider** receives only the inner object.
56
+
57
+ <docs-lit-demo for="docs-submit-result-key-demo"></docs-lit-demo>
58
+
59
+ Mock endpoint: `POST /docs-mock-api/api/register/nested`.
60
+
61
+ ## clearedDataOnSuccess
62
+
63
+ Lists one or more publisher ids (space-separated). After the API returns a result object, each is set to `{}` — useful to reset the form publisher.
64
+
65
+ <docs-lit-demo for="docs-submit-clear-demo"></docs-lit-demo>
66
+
67
+ ## Custom `submit` event
68
+
69
+ Listen for the bubbling **`submit`** event; **`event.detail`** is the same result written to **submitResultDataProvider** (if configured).
70
+
71
+ <docs-lit-demo for="docs-submit-event-demo"></docs-lit-demo>
72
+
73
+ ## endPoint vs dataProvider
74
+
75
+ Ancestor **`dataProvider`** is the default path; **`endPoint`** on **sonic-submit** overrides it for that button only.
76
+
77
+ <docs-lit-demo for="docs-submit-endpoint-demo"></docs-lit-demo>
78
+
79
+ ## method="get"
80
+
81
+ Appends publisher fields as a query string on the endpoint, then performs a GET. The mock route `api/register/echo` returns the query for inspection.
82
+
83
+ <docs-lit-demo for="docs-submit-get-demo"></docs-lit-demo>
84
+
85
+ ## dot notation (formDataProvider shape)
86
+
87
+ You can use dot notation in **`name`** on form controls; the publisher stores nested objects:
56
88
 
57
89
  <sonic-code>
58
90
  <template>
@@ -65,19 +97,18 @@ You can write the folowing code where the name attribute is written in dot notat
65
97
  </template>
66
98
  </sonic-code>
67
99
 
68
- The data will be stored in the following format:
100
+ Stored shape:
69
101
 
70
- <sonic-code language="typescript">
102
+ <sonic-code language="typescript">
71
103
  <template>
72
104
  {
73
- email: {
74
- value: "eve.holt@reqres.in",
75
- },
76
- details: {
77
- password: {
78
- value: "pistol",
79
- },
80
- },
105
+ email: { value: "eve.holt@reqres.in" },
106
+ details: { password: { value: "pistol" } }
81
107
  }
82
108
  </template>
83
- </sonic-code>
109
+ </sonic-code>
110
+
111
+ ## Related
112
+
113
+ - [Captcha](#core/components/ui/captcha/captcha.md/captcha) — submit waits for `captchaToken` when validation is required.
114
+ - [HTML integration](#docs/_misc/html-integration.md/html-integration) — legacy `data-bind` result blocks; prefer **submitResultDataProvider** + `@subscribe` in Lit demos.
@@ -26,11 +26,16 @@ declare const window: ConcordeWindow;
26
26
  * * Les données envoyées sont celles présentes dans le publisher dont l'adresse est renseignée via l'attribut *formDataProvider*.
27
27
  * Cet attribut est également utilisé par les éléments de form comme *sonic-input*, ou *sonic-select*, qui remplissent ce publisher avec leur attribut *value* en fonction de leur attribut *name*
28
28
  * * L'api est configuré à la manière d'un fetcher.
29
- * * L'attribut *method* permet de choisir la méthode d'envoie : *put/delete/post*, *post* étant la méthode par défaut.
29
+ * * L'attribut *method* sur sonic-submit permet de choisir la méthode : *post* (défaut), *put*, *patch*, *delete*, *get*.
30
+ * * *endPoint* sur sonic-submit remplace le *dataProvider* ancêtre pour l'URL de la requête.
31
+ * * *sendAsFormData* envoie un corps multipart/form-data au lieu de JSON.
32
+ * * *native* : après validation, copie le publisher dans un &lt;form&gt; HTML ancêtre et déclenche un submit navigateur (pas d'appel fetch).
33
+ * * *submitResultKey* / submit-result-key : ne conserve qu'une sous-partie du JSON avant écriture dans *submitResultDataProvider*.
30
34
  * * Si l'attribut *onClick* est présent, les données sont envoyées quand on click dans son contenu
31
35
  * * Si l'attribut *onEnterKey* est présent, les données sont envoyées quand on appuie sur la touche entrée d'un élément contenu dans le *sonic-submit* ayant le focus
32
- * * Pendant l'envoi, les éléments *sonic-submit* ayant le même attribut *dataProvider* ont la propriété *disabled="disabled"* ce qui a pour effet de désactiver leur contenu
33
- * * L'attribut *clearedDataOnSuccess* peut être utilisé pour vider les données des dataProvider correspondants lorsque l'appel à l'api a fourni un résultat.
36
+ * * Pendant l'envoi REST, le slot est désactivé visuellement (*data-disabled*).
37
+ * * *clearedDataOnSuccess* (ancêtre) : ids de publishers séparés par des espaces, remis à {} lorsqu'un résultat est retourné.
38
+ * * Événement *submit* (bubbles) avec *detail* = résultat. *usernameKey* / *passwordKey* : Credential Management API après succès HTTP.
34
39
  */
35
40
  @customElement(tagName)
36
41
  export class Submit extends Subscriber(LitElement) {
@@ -123,6 +128,8 @@ export class Submit extends Subscriber(LitElement) {
123
128
  const native = this.hasAttribute("native");
124
129
  if (native) {
125
130
  this.submitNativeForm();
131
+ Loader.hide();
132
+ this.disabled = false;
126
133
  return;
127
134
  }
128
135
  //
@@ -3,7 +3,7 @@
3
3
  <sonic-code>
4
4
  <template>
5
5
  <sonic-captcha formDataProvider="captchaTestDataProvider" key="6Leq5V0iAAAAAB-41DlWN335jDlcIuXmhNtdd00t">
6
- <sonic-submit serviceURL="https://reqres.in" endPoint="api/unknown" onclick>
6
+ <sonic-submit serviceURL="/docs-mock-api" endPoint="api/unknown" onclick>
7
7
  <sonic-button class="mt-4">Submit with captcha</sonic-button>
8
8
  </sonic-submit>
9
9
  </sonic-captcha>
@@ -21,4 +21,4 @@
21
21
  </sonic-captcha>
22
22
  </template>
23
23
  </sonic-code>
24
-
24
+
@@ -51,7 +51,7 @@
51
51
  <sonic-card-main >
52
52
  <h3>Main area</h3>
53
53
  <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Iure id dolor debitis deleniti eligendi natus dolorem a commodi sunt dicta? Ipsa asperiores magni consequuntur dolor voluptatibus. Maxime, nemo? Facere, odio.</p>
54
- <iframe width="560" height="315" src="https://www.youtube.com/embed/IZTOtyksyPs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
54
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/aqz-KE-bpKQ" title="Big Buck Bunny (Blender Foundation)" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
55
55
  </sonic-card-main>
56
56
  </sonic-card>
57
57
  </template>
@@ -70,35 +70,8 @@
70
70
  </template>
71
71
  </sonic-code>
72
72
 
73
- ## Example of use
74
- <sonic-code>
75
- <template>
76
- <sonic-subscriber dataProvider="jokeFilter" class="text-xl my-4 block font-bold">
77
- Remove following jokes :
78
- <sonic-value key="blacklistFlags" class="block text-sm"></sonic-value>
79
- </sonic-subscriber>
80
- <div formDataProvider="jokeFilter" class="grid grid-cols-2 lg:grid-cols-3 gap-x-6 gap-y-2 mt-2 mb-3">
81
- <sonic-checkbox name="blacklistFlags" value="nsfw">nsfw</sonic-checkbox>
82
- <sonic-checkbox name="blacklistFlags" value="religious">religious</sonic-checkbox>
83
- <sonic-checkbox name="blacklistFlags" value="political">political</sonic-checkbox>
84
- <sonic-checkbox name="blacklistFlags" value="racist" checked disabled>racist</sonic-checkbox>
85
- <sonic-checkbox name="blacklistFlags" value="sexist" checked disabled>sexist</sonic-checkbox>
86
- <sonic-checkbox name="blacklistFlags" value="explicit">explicit</sonic-checkbox>
87
- </div>
88
- <sonic-queue
89
- lazyload
90
- dataProviderExpression="joke/Any?amount=10&lang=en"
91
- dataFilterProvider="jokeFilter"
92
- serviceURL="https://v2.jokeapi.dev"
93
- key="jokes"
94
- >
95
- <template>
96
- <div class="border-0 border-b-[1px] border-b-neutral-300 py-3 leading-tight">
97
- <sonic-value key="joke"></sonic-value>
98
- <sonic-value key="setup" class="font-bold"></sonic-value><br>
99
- <sonic-value key="delivery"></sonic-value>
100
- </div>
101
- </template>
102
- </sonic-queue>
103
- </template>
104
- </sonic-code>
73
+ ## Example of use — blacklist + queue
74
+
75
+ Checked **`blacklistFlags`** values are sent to the mock API (`?blacklistFlags=racist,sexist,…`), which excludes jokes whose **`flags`** match (see `filterDocsJokes` in `src/docs/mock-api/fixtures.ts`).
76
+
77
+ <docs-lit-demo for="docs-joke-blacklist-demo"></docs-lit-demo>
@@ -1,6 +1,5 @@
1
1
  # Input
2
2
 
3
-
4
3
  <sonic-button type="info" size="sm" target="_blank" href="https://www.w3schools.com/tags/tag_input.asp#midcontentadcontainer">
5
4
  <sonic-icon library="iconoir" name="open-new-window" slot="prefix" ></sonic-icon>
6
5
  Native attibutes list
@@ -124,35 +123,11 @@
124
123
 
125
124
 
126
125
 
127
- ## Example of use
128
- <sonic-code>
129
- <template>
130
- <sonic-input
131
- formDataProvider="input-filter"
132
- name="contains"
133
- value="chien"
134
- class="mb-4"
135
- ></sonic-input>
136
- <sonic-subscriber dataProvider="input-filter" class="text-xl my-4 block font-bold">
137
- Blagues trouvées pour "<span data-bind ::inner-html="$contains"></span>" :
138
- </sonic-subscriber>
139
- <sonic-queue
140
- lazyload
141
- dataProviderExpression="joke/Any?amount=10&lang=fr"
142
- dataFilterProvider="input-filter"
143
- serviceURL="https://v2.jokeapi.dev"
144
- key="jokes"
145
- >
146
- <template>
147
- <div class="border-0 border-b-[1px] border-b-neutral-300 border-dotted py-3">
148
- <div data-bind ::inner-html="$joke"></div>
149
- <div data-bind ::inner-html="$setup"></div>
150
- <div data-bind ::inner-html="$delivery"></div>
151
- </div>
152
- </template>
153
- </sonic-queue>
154
- </template>
155
- </sonic-code>
126
+ ## Example of use — search + queue
127
+
128
+ Filter with **`formDataProvider`** + **`name="contains"`** (mock API: substring on joke text). Caption and rows via Lit (`@subscribe`, `.items` on `sonic-queue`):
129
+
130
+ <docs-lit-demo for="docs-joke-search-demo"></docs-lit-demo>
156
131
 
157
132
 
158
133
  <sonic-code>
@@ -6,6 +6,8 @@ Please note that only basic text input params and methods are implemented at thi
6
6
 
7
7
  Here are some of the features of the input-autocomplete component:
8
8
 
9
+ Doc examples below use HTML binding on suggestion rows. The Lit equivalent uses an **`items`** callback with the row object (see `docs-queue-geo-demo` in `src/docs/example/docs-queue-demos.ts`). Embedding without Lit: [HTML integration](#docs/_misc/html-integration.md/html-integration).
10
+
9
11
  * It provides a suggest behavior, where the user can type a few letters and the component will suggest possible matches.
10
12
  * It can be used with a variety of data providers, such as an API.
11
13
  * It is fully customizable, so you can change the look and feel of the component to match your needs.
@@ -34,7 +36,7 @@ The result is that when you select an item, the input takes the value of the sel
34
36
  name="nom"
35
37
  propertyName="bloop"
36
38
  placeholder="Paris, Lyon, Tours, ..."
37
- serviceurl="https://geo.api.gouv.fr"
39
+ serviceurl="/docs-mock-api/geo"
38
40
  dataproviderexpression="communes?limit=5&boost=population"
39
41
  >
40
42
  <template>
@@ -65,7 +67,7 @@ By using these attributes, we can separate the search parameter from the name of
65
67
  name="siren"
66
68
  value="212703771"
67
69
  placeholder="Paris, Lyon, Tours, ..."
68
- serviceurl="https://geo.api.gouv.fr"
70
+ serviceurl="/docs-mock-api/geo"
69
71
  dataproviderexpression="communes?limit=5&boost=population"
70
72
  searchParameter="nom"
71
73
  >
@@ -95,7 +97,7 @@ The following code shows how to use the `select` attribute in an autocomplete in
95
97
  name="siren"
96
98
  value="212703771"
97
99
  placeholder="Paris, Lyon, Tours, ..."
98
- serviceurl="https://geo.api.gouv.fr"
100
+ serviceurl="/docs-mock-api/geo"
99
101
  dataproviderexpression="communes?limit=5&boost=population"
100
102
  searchParameter="nom"
101
103
  >
@@ -119,7 +121,7 @@ At the moment you can enable keyboard up/down by adding an attribut "data-keyboa
119
121
  name="nom"
120
122
  data-keyboard-nav="nav-autocomplete"
121
123
  placeholder="Paris, Lyon, Tours, ..."
122
- serviceurl="https://geo.api.gouv.fr"
124
+ serviceurl="/docs-mock-api/geo"
123
125
  dataproviderexpression="communes?limit=60&boost=population"
124
126
  >
125
127
  <template>
@@ -50,35 +50,8 @@
50
50
  </sonic-code>
51
51
 
52
52
 
53
- ## Example of use
54
- <sonic-code>
55
- <template>
56
- <sonic-subscriber dataProvider="jokeFilterRadio" class="text-xl my-4 block font-bold">
57
- Remove following jokes :
58
- <sonic-value key="blacklistFlags" class="block text-sm"></sonic-value>
59
- </sonic-subscriber>
60
- <div formDataProvider="jokeFilterRadio" class="grid grid-cols-2 lg:grid-cols-3 gap-x-6 gap-y-2 mt-2 mb-3">
61
- <sonic-radio name="blacklistFlags" value="nsfw">nsfw</sonic-radio>
62
- <sonic-radio name="blacklistFlags" value="religious">religious</sonic-radio>
63
- <sonic-radio name="blacklistFlags" value="political">political</sonic-radio>
64
- <sonic-radio name="blacklistFlags" value="racist" checked >racist</sonic-radio>
65
- <sonic-radio name="blacklistFlags" value="sexist" >sexist</sonic-radio>
66
- <sonic-radio name="blacklistFlags" value="explicit">explicit</sonic-radio>
67
- </div>
68
- <sonic-queue
69
- lazyload
70
- dataProviderExpression="joke/Any?amount=10&lang=en"
71
- dataFilterProvider="jokeFilterRadio"
72
- serviceURL="https://v2.jokeapi.dev"
73
- key="jokes"
74
- >
75
- <template>
76
- <div class="border-0 border-b-[1px] border-b-neutral-300 py-3 leading-tight">
77
- <sonic-value key="joke"></sonic-value>
78
- <sonic-value key="setup" class="font-bold"></sonic-value><br>
79
- <sonic-value key="delivery"></sonic-value>
80
- </div>
81
- </template>
82
- </sonic-queue>
83
- </template>
84
- </sonic-code>
53
+ ## Example of use — blacklist + queue
54
+
55
+ Same mock filter as [Checkbox](#core/components/ui/form/checkbox/checkbox.md/checkbox) (`blacklistFlags` query param). Radio sends **one** flag at a time.
56
+
57
+ <docs-lit-demo for="docs-joke-blacklist-radio-demo"></docs-lit-demo>