@supersoniks/concorde 4.7.4 → 4.8.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.
- package/README.md +1 -1
- package/ai/cursor/rules/concorde.mdc +1 -1
- package/ai/skills/concorde-scope/SKILL.md +2 -2
- package/build-infos.json +1 -1
- package/concorde-core.bundle.js +289 -289
- package/concorde-core.es.js +4837 -4544
- package/dist/concorde-core.bundle.js +289 -289
- package/dist/concorde-core.es.js +4837 -4544
- package/dist/docs-mock-api-sw.js +19 -0
- package/dist/docs-mock-api-sw.js.map +2 -2
- package/docs/assets/index-wyNMyWT9.js +11196 -0
- package/docs/docs-mock-api-sw.js +19 -0
- package/docs/docs-mock-api-sw.js.map +2 -2
- package/docs/index.html +1 -1
- package/package.json +9 -1
- package/public/docs-mock-api-sw.js +19 -0
- package/public/docs-mock-api-sw.js.map +2 -2
- package/src/core/components/functional/example/example.ts +3 -3
- package/src/core/components/ui/icon/icon.ts +17 -2
- package/src/core/components/ui/menu/menu.ts +12 -3
- package/src/core/decorators/api.post.spec.ts +293 -0
- package/src/core/decorators/api.spec.ts +6 -6
- package/src/core/decorators/api.ts +643 -12
- package/src/core/decorators/subscriber/bind.ts +13 -5
- package/src/core/decorators/subscriber/dynamicPath.spec.ts +53 -0
- package/src/core/decorators/subscriber/dynamicPath.ts +23 -1
- package/src/core/decorators/subscriber/handle.ts +3 -1
- package/src/core/decorators/subscriber/onAssign.ts +10 -2
- package/src/core/decorators/subscriber/publish.ts +12 -2
- package/src/core/utils/PublisherProxy.ts +95 -11
- package/src/core/utils/api.ts +72 -3
- package/src/core/utils/dpOptions.spec.ts +56 -0
- package/src/core/utils/endpoint.ts +3 -3
- package/src/decorators.ts +17 -1
- package/src/docs/_core-concept/dataFlow.md +9 -3
- package/src/docs/_decorators/bind.md +2 -2
- package/src/docs/_decorators/get.md +13 -4
- package/src/docs/_decorators/handle.md +5 -1
- package/src/docs/_decorators/on-assign.md +2 -0
- package/src/docs/_decorators/patch.md +45 -0
- package/src/docs/_decorators/post.md +93 -0
- package/src/docs/_decorators/publish.md +1 -1
- package/src/docs/_decorators/put.md +43 -0
- package/src/docs/_decorators/subscribe.md +4 -1
- package/src/docs/_directives/sub.md +1 -1
- package/src/docs/_getting-started/my-first-component.md +1 -1
- package/src/docs/_misc/api-configuration.md +3 -1
- package/src/docs/_misc/dataProviderKey.md +2 -2
- package/src/docs/_misc/dynamic-path.md +71 -0
- package/src/docs/_misc/endpoint.md +5 -3
- package/src/docs/components/docs-demo-sources.ts +102 -3
- package/src/docs/components/docs-lit-demo-raw.ts +2 -26
- package/src/docs/components/docs-lit-demo.ts +9 -42
- package/src/docs/components/docs-source-excerpt.ts +53 -0
- package/src/docs/components/docs-source-link.ts +24 -8
- package/src/docs/components/docs-source-raw.ts +34 -0
- package/src/docs/example/decorators-demo-geo.ts +2 -2
- package/src/docs/example/decorators-demo-post.ts +249 -0
- package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +5 -5
- package/src/docs/example/decorators-demo.ts +1 -0
- package/src/docs/example/docs-api-config-demos.ts +5 -5
- package/src/docs/mock-api/router.ts +20 -0
- package/src/docs/navigation/navigation.ts +16 -0
- package/src/docs/search/docs-search.json +540 -15
- package/src/tsconfig.json +24 -0
- package/src/tsconfig.tsbuildinfo +1 -1
- package/vite.config.mts +1 -1
- package/docs/assets/index-CwtPzTFq.js +0 -7508
- package/docs/src/core/components/functional/date/date.md +0 -290
- package/docs/src/core/components/functional/fetch/fetch.md +0 -125
- package/docs/src/core/components/functional/if/if.md +0 -9
- package/docs/src/core/components/functional/list/list.md +0 -65
- package/docs/src/core/components/functional/mix/mix.md +0 -41
- package/docs/src/core/components/functional/queue/queue.md +0 -72
- package/docs/src/core/components/functional/router/router.md +0 -94
- package/docs/src/core/components/functional/sdui/default-library.json +0 -108
- package/docs/src/core/components/functional/sdui/example.json +0 -99
- package/docs/src/core/components/functional/sdui/sdui.md +0 -356
- package/docs/src/core/components/functional/states/states.md +0 -87
- package/docs/src/core/components/functional/submit/submit.md +0 -114
- package/docs/src/core/components/functional/subscriber/subscriber.md +0 -91
- package/docs/src/core/components/functional/value/value.md +0 -35
- package/docs/src/core/components/ui/alert/alert.md +0 -121
- package/docs/src/core/components/ui/alert-messages/alert-messages.md +0 -0
- package/docs/src/core/components/ui/badge/badge.md +0 -127
- package/docs/src/core/components/ui/button/button.md +0 -182
- package/docs/src/core/components/ui/captcha/captcha.md +0 -12
- package/docs/src/core/components/ui/card/card.md +0 -97
- package/docs/src/core/components/ui/divider/divider.md +0 -35
- package/docs/src/core/components/ui/form/checkbox/checkbox.md +0 -77
- package/docs/src/core/components/ui/form/fieldset/fieldset.md +0 -129
- package/docs/src/core/components/ui/form/form-actions/form-actions.md +0 -77
- package/docs/src/core/components/ui/form/form-layout/form-layout.md +0 -44
- package/docs/src/core/components/ui/form/input/input.md +0 -142
- package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +0 -133
- package/docs/src/core/components/ui/form/radio/radio.md +0 -57
- package/docs/src/core/components/ui/form/select/select.md +0 -71
- package/docs/src/core/components/ui/form/switch/switch.md +0 -57
- package/docs/src/core/components/ui/form/textarea/textarea.md +0 -65
- package/docs/src/core/components/ui/group/group.md +0 -75
- package/docs/src/core/components/ui/icon/icon.md +0 -125
- package/docs/src/core/components/ui/icon/icons.json +0 -1
- package/docs/src/core/components/ui/image/image.md +0 -107
- package/docs/src/core/components/ui/link/link.md +0 -43
- package/docs/src/core/components/ui/loader/loader.md +0 -55
- package/docs/src/core/components/ui/menu/menu.md +0 -329
- package/docs/src/core/components/ui/modal/modal.md +0 -119
- package/docs/src/core/components/ui/pop/pop.md +0 -96
- package/docs/src/core/components/ui/progress/progress.md +0 -63
- package/docs/src/core/components/ui/table/table.md +0 -455
- package/docs/src/core/components/ui/toast/toast.md +0 -166
- package/docs/src/core/components/ui/tooltip/tooltip.md +0 -82
- package/docs/src/docs/_core-concept/dataFlow.md +0 -73
- package/docs/src/docs/_core-concept/overview.md +0 -57
- package/docs/src/docs/_core-concept/subscriber.md +0 -75
- package/docs/src/docs/_decorators/ancestor-attribute.md +0 -79
- package/docs/src/docs/_decorators/auto-subscribe.md +0 -202
- package/docs/src/docs/_decorators/bind.md +0 -167
- package/docs/src/docs/_decorators/get.md +0 -68
- package/docs/src/docs/_decorators/handle.md +0 -171
- package/docs/src/docs/_decorators/on-assign.md +0 -388
- package/docs/src/docs/_decorators/publish.md +0 -55
- package/docs/src/docs/_decorators/subscribe.md +0 -97
- package/docs/src/docs/_decorators/wait-for-ancestors.md +0 -163
- package/docs/src/docs/_directives/sub.md +0 -91
- package/docs/src/docs/_getting-started/ai-agents.md +0 -56
- package/docs/src/docs/_getting-started/concorde-manual-install.md +0 -133
- package/docs/src/docs/_getting-started/concorde-outside.md +0 -33
- package/docs/src/docs/_getting-started/create-a-component.md +0 -139
- package/docs/src/docs/_getting-started/my-first-component.md +0 -236
- package/docs/src/docs/_getting-started/my-first-subscriber.md +0 -120
- package/docs/src/docs/_getting-started/pubsub.md +0 -37
- package/docs/src/docs/_getting-started/start.md +0 -47
- package/docs/src/docs/_getting-started/theming.md +0 -91
- package/docs/src/docs/_misc/api-configuration.md +0 -79
- package/docs/src/docs/_misc/dataProviderKey.md +0 -168
- package/docs/src/docs/_misc/docs-mock-api.md +0 -60
- package/docs/src/docs/_misc/endpoint.md +0 -43
- package/docs/src/docs/_misc/html-integration.md +0 -13
- package/docs/src/docs/search/docs-search.json +0 -8532
- package/docs/src/tag-list.json +0 -1
- package/docs/src/tsconfig-model.json +0 -23
- package/docs/src/tsconfig.json +0 -1095
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# Router
|
|
2
|
-
|
|
3
|
-
**sonic-router** watches `document.location` (pathname + hash) and renders the matching view.
|
|
4
|
-
|
|
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
|
-
|
|
7
|
-
Legacy HTML **`<template data-route="…">`** remains for hosts without Lit — [HTML integration](#docs/_misc/html-integration.md/html-integration).
|
|
8
|
-
|
|
9
|
-
## Static routes (no parameters)
|
|
10
|
-
|
|
11
|
-
Route keys are matched against `pathname + hash`. A simple hash route `#home` matches when the location contains that segment.
|
|
12
|
-
|
|
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`).
|
|
14
|
-
|
|
15
|
-
<docs-lit-demo for="docs-router-basic-demo"></docs-lit-demo>
|
|
16
|
-
|
|
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
|
-
};
|
|
24
|
-
|
|
25
|
-
html`
|
|
26
|
-
<sonic-button href="#home">Home</sonic-button>
|
|
27
|
-
<sonic-router .routes=${this.routes}></sonic-router>
|
|
28
|
-
`;
|
|
29
|
-
```
|
|
30
|
-
|
|
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) |
|
|
35
|
-
|
|
36
|
-
## Routes with parameters
|
|
37
|
-
|
|
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
|
-
```
|
|
49
|
-
|
|
50
|
-
### RegExp (capturing groups)
|
|
51
|
-
|
|
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.
|
|
75
|
-
|
|
76
|
-
<sonic-code>
|
|
77
|
-
<template>
|
|
78
|
-
<sonic-redirect to="#core/components/functional/router/router.md/router#data-is-set" dataProvider="stupid-data-set-id" onData="theData"></sonic-redirect>
|
|
79
|
-
<div class="flex gap-2 mb-4" formDataProvider="stupid-data-set-id">
|
|
80
|
-
<sonic-button radio name="theData" value="Some Data" size="xs">
|
|
81
|
-
Enter data
|
|
82
|
-
</sonic-button>
|
|
83
|
-
<sonic-button radio name="theData" value="" href="javascript:history.back();" size="xs">
|
|
84
|
-
Delete the data and do a history.back()
|
|
85
|
-
</sonic-button>
|
|
86
|
-
</div>
|
|
87
|
-
</template>
|
|
88
|
-
</sonic-code>
|
|
89
|
-
|
|
90
|
-
Example: combine with **`.routes`** and **submit** for login / logout / profile steps.
|
|
91
|
-
|
|
92
|
-
## Package demo
|
|
93
|
-
|
|
94
|
-
`sonic-router-demo` (`router.demo.ts`) — home, user profile (`#user/:id/:slug`), products RegExp, **fallback** 404.
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"checkbox": {
|
|
3
|
-
"tagName": "sonic-checkbox"
|
|
4
|
-
},
|
|
5
|
-
"date": {
|
|
6
|
-
"tagName": "sonic-input",
|
|
7
|
-
"attributes": {
|
|
8
|
-
"type": "date"
|
|
9
|
-
}
|
|
10
|
-
},
|
|
11
|
-
"fieldset": {
|
|
12
|
-
"tagName": "sonic-fieldset",
|
|
13
|
-
"nodes":[{"libraryKey":"formLayout"}],
|
|
14
|
-
"contentElementSelector":"sonic-form-layout"
|
|
15
|
-
},
|
|
16
|
-
"managed_file": {
|
|
17
|
-
"tagName": "sonic-input",
|
|
18
|
-
"attributes": {
|
|
19
|
-
"variant":"ghost",
|
|
20
|
-
"type": "file"
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
"password": {
|
|
24
|
-
"tagName": "sonic-input",
|
|
25
|
-
"attributes": {
|
|
26
|
-
"type": "password"
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
"radio": {
|
|
30
|
-
"tagName": "sonic-radio"
|
|
31
|
-
},
|
|
32
|
-
"select": {
|
|
33
|
-
"tagName": "sonic-select"
|
|
34
|
-
},
|
|
35
|
-
"textarea": {
|
|
36
|
-
"tagName": "sonic-textarea"
|
|
37
|
-
},
|
|
38
|
-
"textfield": {
|
|
39
|
-
"tagName": "sonic-input",
|
|
40
|
-
"attributes": {
|
|
41
|
-
"type": "text"
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
"hidden": {
|
|
45
|
-
"tagName": "sonic-input",
|
|
46
|
-
"attributes": {
|
|
47
|
-
"type": "hidden"
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
"button": {
|
|
51
|
-
"tagName": "sonic-button"
|
|
52
|
-
},
|
|
53
|
-
"form": {
|
|
54
|
-
"tagName": "sonic-submit",
|
|
55
|
-
"attributes": {
|
|
56
|
-
"onEnterKey": true
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
"submit": {
|
|
60
|
-
"tagName": "sonic-submit",
|
|
61
|
-
"attributes": {
|
|
62
|
-
"onClick": true
|
|
63
|
-
},
|
|
64
|
-
"contentElementSelector":"sonic-button",
|
|
65
|
-
"nodes":[
|
|
66
|
-
{
|
|
67
|
-
"libraryKey":"button",
|
|
68
|
-
"attributes":{"type":"success"},
|
|
69
|
-
"nodes":[
|
|
70
|
-
{
|
|
71
|
-
"tagName":"sonic-icon",
|
|
72
|
-
"attributes":{
|
|
73
|
-
"name":"check",
|
|
74
|
-
"slot":"prefix"
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
]
|
|
78
|
-
}
|
|
79
|
-
]
|
|
80
|
-
},
|
|
81
|
-
"email": {
|
|
82
|
-
"tagName": "sonic-input",
|
|
83
|
-
"attributes": {
|
|
84
|
-
"type": "email"
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
"formItemContainer": {
|
|
88
|
-
"tagName": "div",
|
|
89
|
-
"attributes": {
|
|
90
|
-
"class": "form-item-container"
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
"formLayout": {
|
|
94
|
-
"tagName": "sonic-form-layout"
|
|
95
|
-
},
|
|
96
|
-
"formActions": {
|
|
97
|
-
"tagName": "sonic-form-actions"
|
|
98
|
-
},
|
|
99
|
-
"passwordHelper": {
|
|
100
|
-
"tagName": "sonic-password-helper"
|
|
101
|
-
},
|
|
102
|
-
"sameValueHelper": {
|
|
103
|
-
"tagName": "sonic-same-value-helper"
|
|
104
|
-
},
|
|
105
|
-
"divider": {
|
|
106
|
-
"tagName": "sonic-divider"
|
|
107
|
-
}
|
|
108
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"nodes": [
|
|
3
|
-
{
|
|
4
|
-
"tagName": "div",
|
|
5
|
-
"attributes": {
|
|
6
|
-
"class": "flex gap-2 items-center",
|
|
7
|
-
"formdataprovider": "states-basic-example"
|
|
8
|
-
},
|
|
9
|
-
"nodes": [
|
|
10
|
-
{
|
|
11
|
-
"tagName": "sonic-button",
|
|
12
|
-
"attributes": {
|
|
13
|
-
"radio": "",
|
|
14
|
-
"name": "selection",
|
|
15
|
-
"value": "#home",
|
|
16
|
-
"checked": "",
|
|
17
|
-
"size": "xs"
|
|
18
|
-
},
|
|
19
|
-
"innerHTML": "Home"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"tagName": "sonic-button",
|
|
23
|
-
"attributes": {
|
|
24
|
-
"radio": "",
|
|
25
|
-
"name": "selection",
|
|
26
|
-
"value": "#about",
|
|
27
|
-
"size": "xs"
|
|
28
|
-
},
|
|
29
|
-
"innerHTML": "About"
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"tagName": "sonic-button",
|
|
33
|
-
"attributes": {
|
|
34
|
-
"radio": "",
|
|
35
|
-
"name": "selection",
|
|
36
|
-
"value": "#work",
|
|
37
|
-
"size": "xs"
|
|
38
|
-
},
|
|
39
|
-
"innerHTML": "Work"
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
"tagName": "sonic-button",
|
|
43
|
-
"attributes": {
|
|
44
|
-
"radio": "",
|
|
45
|
-
"name": "selection",
|
|
46
|
-
"value": "#contact",
|
|
47
|
-
"size": "xs"
|
|
48
|
-
},
|
|
49
|
-
"innerHTML": "Contact"
|
|
50
|
-
}
|
|
51
|
-
]
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
"tagName": "div",
|
|
55
|
-
"attributes": {
|
|
56
|
-
"class": "text-center text-neutral-700 border rounded text-4xl my-6 p-3 "
|
|
57
|
-
},
|
|
58
|
-
"nodes": [
|
|
59
|
-
{
|
|
60
|
-
"tagName": "sonic-states",
|
|
61
|
-
"attributes": {
|
|
62
|
-
"dataprovider": "states-basic-example",
|
|
63
|
-
"data-path": "selection"
|
|
64
|
-
},
|
|
65
|
-
"nodes": [
|
|
66
|
-
{
|
|
67
|
-
"tagName": "template",
|
|
68
|
-
"attributes": {
|
|
69
|
-
"data-value": "#home"
|
|
70
|
-
},
|
|
71
|
-
"innerHTML": "Home"
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
"tagName": "template",
|
|
75
|
-
"attributes": {
|
|
76
|
-
"data-value": "#about"
|
|
77
|
-
},
|
|
78
|
-
"innerHTML": "About"
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
"tagName": "template",
|
|
82
|
-
"attributes": {
|
|
83
|
-
"data-value": "#work"
|
|
84
|
-
},
|
|
85
|
-
"innerHTML": "Work"
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
"tagName": "template",
|
|
89
|
-
"attributes": {
|
|
90
|
-
"data-value": "#contact"
|
|
91
|
-
},
|
|
92
|
-
"innerHTML": "Contact"
|
|
93
|
-
}
|
|
94
|
-
]
|
|
95
|
-
}
|
|
96
|
-
]
|
|
97
|
-
}
|
|
98
|
-
]
|
|
99
|
-
}
|
|
@@ -1,356 +0,0 @@
|
|
|
1
|
-
# SDUI
|
|
2
|
-
|
|
3
|
-
## What is SDUI?
|
|
4
|
-
|
|
5
|
-
SDUI stands for `Server Driven User Interfaces`.
|
|
6
|
-
Basically, it generates a user interface based on a JSON SDUI Descriptor.
|
|
7
|
-
|
|
8
|
-
### Subscriber extension:
|
|
9
|
-
|
|
10
|
-
SDUI extends the mixin [Subscriber](#docs/_core-concept/subscriber.md/subscriber).
|
|
11
|
-
This means that you must set a dataProvider with an id pointing to the publisher that will hold your SDUI Descriptor.
|
|
12
|
-
This also means that it has a reactive property named `props` that you can set with the JSON SDUI Descriptor in order to configure it.
|
|
13
|
-
|
|
14
|
-
### Fetcher extension:
|
|
15
|
-
|
|
16
|
-
SDUI extends the mixin Fetcher as [Fetch](#core/components/functional/fetch/fetch.md/fetch) and [List](#core/components/functional/list/list.md/list).
|
|
17
|
-
|
|
18
|
-
In this case, it will parse the JSON coming from the request.
|
|
19
|
-
The JSON must comply with the SDUI descriptor format.
|
|
20
|
-
|
|
21
|
-
As a fetcher, invalidating the publisher or updating the endpoint will trigger a new fetch and update accordingly.
|
|
22
|
-
|
|
23
|
-
### Rendering:
|
|
24
|
-
|
|
25
|
-
It has no shadowdom, and its display style is set to `contents`, so an empty SDUI has the fewest impact on the layout.
|
|
26
|
-
|
|
27
|
-
## SDUI descriptor
|
|
28
|
-
|
|
29
|
-
### TypeScript definition:
|
|
30
|
-
<sonic-code language="typescript">
|
|
31
|
-
<template>
|
|
32
|
-
export type SDUIDescriptor = {
|
|
33
|
-
js?: Array<string>;
|
|
34
|
-
css?: Array<string>;
|
|
35
|
-
library?: Record<string, SDUINode>;
|
|
36
|
-
nodes?: Array<SDUINode>;
|
|
37
|
-
};
|
|
38
|
-
</template>
|
|
39
|
-
</sonic-code>
|
|
40
|
-
|
|
41
|
-
### Meaning of the keys:
|
|
42
|
-
|
|
43
|
-
* **js**: An array of URLs pointing to JavaScript files to load.
|
|
44
|
-
* **css**: An array of URLs pointing to CSS files to load.
|
|
45
|
-
* **library**: A record of SDUINode definitions intended to be used as a model for other nodes. The keys of the record can be used as the libraryKey of the node. This node will then specialize the model with its own descriptor.
|
|
46
|
-
* **nodes**: An array of SDUINode descriptors. Each SDUINode will result in an HTMLElement added to the root of the component.
|
|
47
|
-
|
|
48
|
-
## SDUINode
|
|
49
|
-
|
|
50
|
-
### Descriptor
|
|
51
|
-
|
|
52
|
-
An SDUINode represents an HTMLElement.
|
|
53
|
-
|
|
54
|
-
TypeScript definition:
|
|
55
|
-
|
|
56
|
-
<sonic-code language="typescript">
|
|
57
|
-
<template>
|
|
58
|
-
export type SDUINode = {
|
|
59
|
-
markup?: string;
|
|
60
|
-
tagName?: string;
|
|
61
|
-
attributes?: Record<string, string>;
|
|
62
|
-
nodes?: Array<SDUINode>;
|
|
63
|
-
innerHTML?: string;
|
|
64
|
-
prefix?: string;
|
|
65
|
-
suffix?: string;
|
|
66
|
-
libraryKey?: string;
|
|
67
|
-
contentElementSelector?: string;
|
|
68
|
-
parentElementSelector?: string;
|
|
69
|
-
};
|
|
70
|
-
</template>
|
|
71
|
-
</sonic-code>
|
|
72
|
-
|
|
73
|
-
Summary of properties:
|
|
74
|
-
* **markup**: Use it if you prefer to define your node entirely using an HTML string.
|
|
75
|
-
* **tagName**: The tag name of the HTML element.
|
|
76
|
-
* **attributes**: A string key/value pair storing each attribute name/value of the HTML element created.
|
|
77
|
-
* **nodes**: An array of SDUINode descriptors. The children of the HTMLElement are created this way.
|
|
78
|
-
* **innerHTML**: The inner HTML of the current node is defined here if needed.
|
|
79
|
-
* **prefix**: Use it if you want to wrap the component with some HTML string in conjunction with the suffix.
|
|
80
|
-
* **suffix**: Use it if you want to wrap the component with some HTML string in conjunction with the prefix.
|
|
81
|
-
* **libraryKey**: An identifier that points to an SDUINode to be used as a model for this node.
|
|
82
|
-
* **contentElementSelector**: For SDUINodes defined in the library only. It is a CSS selector that defines where child nodes are added.
|
|
83
|
-
* **parentElementSelector**: If the current node, as a future child, has a `parentElementSelector` attribute, it is added to the node corresponding to the associated CSS selector rather than directly to the element.
|
|
84
|
-
|
|
85
|
-
### Markup
|
|
86
|
-
Use it if you prefer to define your node entirely using an HTML string.
|
|
87
|
-
|
|
88
|
-
<sonic-code>
|
|
89
|
-
<template>
|
|
90
|
-
<sonic-sdui
|
|
91
|
-
dataProvider="sdui-markup-example"
|
|
92
|
-
props='{
|
|
93
|
-
"nodes":[
|
|
94
|
-
{
|
|
95
|
-
"markup":"keep shouting <sonic-badge>foo</sonic-badge> <sonic-badge>bar</sonic-badge> !"
|
|
96
|
-
}
|
|
97
|
-
]}'
|
|
98
|
-
></sonic-sdui>
|
|
99
|
-
</template>
|
|
100
|
-
</sonic-code>
|
|
101
|
-
|
|
102
|
-
### Tag name
|
|
103
|
-
Here we use the field `tagName` of SDUINode to create an element with tag name `sonic-input`.
|
|
104
|
-
|
|
105
|
-
<sonic-code>
|
|
106
|
-
<template>
|
|
107
|
-
<sonic-sdui
|
|
108
|
-
dataProvider="sdui-tagName-example"
|
|
109
|
-
props='{
|
|
110
|
-
"nodes":[
|
|
111
|
-
{
|
|
112
|
-
"tagName":"sonic-input"
|
|
113
|
-
}
|
|
114
|
-
]}'
|
|
115
|
-
></sonic-sdui>
|
|
116
|
-
</template>
|
|
117
|
-
</sonic-code>
|
|
118
|
-
|
|
119
|
-
### Attributes
|
|
120
|
-
A string key/value pair storing each attribute name/value of the HTML element created.
|
|
121
|
-
As no tag name is defined, a div element is created.
|
|
122
|
-
Here we define the style attribute to create a tiny red square.
|
|
123
|
-
|
|
124
|
-
<sonic-code>
|
|
125
|
-
<template>
|
|
126
|
-
<sonic-sdui
|
|
127
|
-
dataProvider="sdui-attributes-example"
|
|
128
|
-
props='{
|
|
129
|
-
"nodes":[{
|
|
130
|
-
"attributes":{
|
|
131
|
-
"style":"width:50px;height:10px;background:red;"
|
|
132
|
-
}
|
|
133
|
-
}]
|
|
134
|
-
}'
|
|
135
|
-
></sonic-sdui>
|
|
136
|
-
</template>
|
|
137
|
-
</sonic-code>
|
|
138
|
-
|
|
139
|
-
### Nodes
|
|
140
|
-
Children of the current node can be added using the field `nodes` recursively.
|
|
141
|
-
|
|
142
|
-
<sonic-code>
|
|
143
|
-
<template>
|
|
144
|
-
<sonic-sdui
|
|
145
|
-
dataProvider="sdui-nodes-example"
|
|
146
|
-
props='{
|
|
147
|
-
"nodes":[{
|
|
148
|
-
"nodes":[
|
|
149
|
-
{"innerHTML":"A"},
|
|
150
|
-
{
|
|
151
|
-
"prefix":"B",
|
|
152
|
-
"nodes":[
|
|
153
|
-
{"innerHTML":"👉 B.1"},
|
|
154
|
-
{"innerHTML":"👉 B.2"}
|
|
155
|
-
]
|
|
156
|
-
}
|
|
157
|
-
]
|
|
158
|
-
}]
|
|
159
|
-
}'
|
|
160
|
-
></sonic-sdui>
|
|
161
|
-
</template>
|
|
162
|
-
</sonic-code>
|
|
163
|
-
|
|
164
|
-
### InnerHTML
|
|
165
|
-
As no tag name is defined, a div element is created, and then we use `innerHTML` to add content to it.
|
|
166
|
-
|
|
167
|
-
<sonic-code>
|
|
168
|
-
<template>
|
|
169
|
-
<sonic-sdui
|
|
170
|
-
dataProvider="sdui-html-example"
|
|
171
|
-
props='{
|
|
172
|
-
"nodes":[{
|
|
173
|
-
"innerHTML":"keep shouting <sonic-badge>foo</sonic-badge> <sonic-badge>bar</sonic-badge> !"
|
|
174
|
-
}]
|
|
175
|
-
}'
|
|
176
|
-
></sonic-sdui>
|
|
177
|
-
</template>
|
|
178
|
-
</sonic-code>
|
|
179
|
-
|
|
180
|
-
### Prefix and suffix
|
|
181
|
-
Use them if you want to wrap the component with some HTML string.
|
|
182
|
-
|
|
183
|
-
<sonic-code>
|
|
184
|
-
<template>
|
|
185
|
-
<sonic-sdui
|
|
186
|
-
dataProvider="sdui-prefixSuffix-example"
|
|
187
|
-
props='{
|
|
188
|
-
"nodes":[{
|
|
189
|
-
"prefix":"👇",
|
|
190
|
-
"suffix":"☝️",
|
|
191
|
-
"innerHTML":"The node content"
|
|
192
|
-
}]
|
|
193
|
-
}'
|
|
194
|
-
></sonic-sdui>
|
|
195
|
-
</template>
|
|
196
|
-
</sonic-code>
|
|
197
|
-
|
|
198
|
-
### Library key and contentElementSelector
|
|
199
|
-
The libraryKey of SDUINode is an identifier that points to an SDUINode description in the library to be used as a model for this node.
|
|
200
|
-
|
|
201
|
-
Note that the SDUI has a default library containing some basic component definitions useful for form declaration (see default-library.json).
|
|
202
|
-
|
|
203
|
-
This example uses the library key `submit` which points to a `sonic-submit` containing a button also coming from the library.
|
|
204
|
-
|
|
205
|
-
The element named `button` in the library is a `sonic-button` of type `success` containing a check icon as a prefix.
|
|
206
|
-
|
|
207
|
-
Since the `submit` library element contains an attribute `contentElementSelector` with the value `sonic-button`, the "injected content" is put inside the button.
|
|
208
|
-
|
|
209
|
-
We used `innerHTML` for the sake of simplicity, but you can use nodes to add any complex content.
|
|
210
|
-
|
|
211
|
-
<sonic-code>
|
|
212
|
-
<template>
|
|
213
|
-
<sonic-sdui dataProvider="sdui-library-example" props='
|
|
214
|
-
{
|
|
215
|
-
"nodes":[
|
|
216
|
-
{
|
|
217
|
-
"libraryKey":"submit",
|
|
218
|
-
"innerHTML":"Injected content"
|
|
219
|
-
}
|
|
220
|
-
]
|
|
221
|
-
}
|
|
222
|
-
'></sonic-sdui>
|
|
223
|
-
</template>
|
|
224
|
-
</sonic-code>
|
|
225
|
-
|
|
226
|
-
### parentElementSelector
|
|
227
|
-
|
|
228
|
-
This special field lets you inject the content at any place in the HTML flow already set inside the parent SDUI component by using a CSS selector.
|
|
229
|
-
|
|
230
|
-
⚠️ Note that it doesn't work with top-level nodes.
|
|
231
|
-
|
|
232
|
-
<sonic-code>
|
|
233
|
-
<template>
|
|
234
|
-
<sonic-sdui dataProvider="sdui-parentElementSelector-example" props='
|
|
235
|
-
{
|
|
236
|
-
"nodes":[
|
|
237
|
-
{
|
|
238
|
-
"nodes":[
|
|
239
|
-
{
|
|
240
|
-
"prefix":"👇 Selected parent element",
|
|
241
|
-
"suffix":"☝️ End of selected parent element",
|
|
242
|
-
"tagName":"span"
|
|
243
|
-
},
|
|
244
|
-
{
|
|
245
|
-
"parentElementSelector":"span",
|
|
246
|
-
"innerHTML":"Content having a parentElementSelector attribute"
|
|
247
|
-
}
|
|
248
|
-
]
|
|
249
|
-
}
|
|
250
|
-
]
|
|
251
|
-
}
|
|
252
|
-
'></sonic-sdui>
|
|
253
|
-
</template>
|
|
254
|
-
</sonic-code>
|
|
255
|
-
|
|
256
|
-
### Fetch example:
|
|
257
|
-
|
|
258
|
-
<sonic-code>
|
|
259
|
-
<template>
|
|
260
|
-
<sonic-sdui dataProvider="sdui-fetch-example" endPoint="/src/core/components/functional/sdui/example.json"></sonic-sdui>
|
|
261
|
-
</template>
|
|
262
|
-
</sonic-code>
|
|
263
|
-
|
|
264
|
-
## Transformers:
|
|
265
|
-
|
|
266
|
-
The transformers let you transform the structure of the SDUI Descriptor into a new one before parsing and rendering it.
|
|
267
|
-
|
|
268
|
-
To enable it, you must fill the `transformation` attribute of the component with a URL pointing to a Transform descriptor.
|
|
269
|
-
|
|
270
|
-
<sonic-code language="typescript">
|
|
271
|
-
<template>
|
|
272
|
-
export type SDUITransformDescription = {
|
|
273
|
-
library?: Record<string, SDUINode>;
|
|
274
|
-
transforms: Array<SDUITransformAction>;
|
|
275
|
-
};
|
|
276
|
-
</template>
|
|
277
|
-
</sonic-code>
|
|
278
|
-
|
|
279
|
-
### The library:
|
|
280
|
-
|
|
281
|
-
Each key of the library will be merged with the current library in the SDUI Descriptor, by replacing or creating items library key by key.
|
|
282
|
-
|
|
283
|
-
### The transform actions:
|
|
284
|
-
|
|
285
|
-
Each transform represents an action that will be done on the SDUI descriptor before the creation of the entire UI.
|
|
286
|
-
|
|
287
|
-
<sonic-code language="typescript">
|
|
288
|
-
<template>
|
|
289
|
-
export type SDUITransformAction = {
|
|
290
|
-
action: SDUITransformActionName;
|
|
291
|
-
patterns?: Array<SDUINode>;
|
|
292
|
-
after?: SDUINode;
|
|
293
|
-
before?: SDUINode;
|
|
294
|
-
in?: SDUINode;
|
|
295
|
-
ui?: SDUINode;
|
|
296
|
-
};
|
|
297
|
-
</template>
|
|
298
|
-
</sonic-code>
|
|
299
|
-
|
|
300
|
-
The action that will be done is a verb:
|
|
301
|
-
|
|
302
|
-
<sonic-code language="typescript">
|
|
303
|
-
<template>
|
|
304
|
-
export type SDUITransformActionName = "remap" | "unwrap" | "wrap" | "delete" | "insert" | "move";
|
|
305
|
-
</template>
|
|
306
|
-
</sonic-code>
|
|
307
|
-
|
|
308
|
-
* **remap**: The properties (tagName, innerHTML, etc.) of the targeted SDUINode will be created/changed according to their presence in the `ui` (SDUINode) property of the transformAction.
|
|
309
|
-
* **unwrap**: Replaces the targeted SDUINode in place with its children.
|
|
310
|
-
* **wrap**: Groups all SDUINodes targeted by the patterns into the new SDUINode described in the `ui` prop of the transformAction.
|
|
311
|
-
* **delete**: Deletes the targeted item.
|
|
312
|
-
* **insert**: Inserts a new SDUINode described by the `ui` prop into the flow. The position of insertion depends on the presence of the attributes `before`, `after`, `in`, which is a pattern to target an existing SDUINode.
|
|
313
|
-
|
|
314
|
-
## Misc Tricks:
|
|
315
|
-
|
|
316
|
-
### sduiKey
|
|
317
|
-
|
|
318
|
-
This is an HTML attribute to set on the component if needed. In this case, the component will not treat its props value directly as an SDUI descriptor. Internally, it will basically extract the SDUIDescriptor by doing something like this: `const sduiDescriptor = this.props[this.sduikey]`.
|
|
319
|
-
|
|
320
|
-
### messageKey
|
|
321
|
-
|
|
322
|
-
This is an HTML attribute to set on the component if needed. In this case, the component will automatically create a `sonic-toast-message-subscriber` component. The data found in `props[messageKey]` will be treated as the data expected by the `sonic-toast-message-subscriber`. So, by respecting the format of data supported by this component, you will be able to show multiple toasts in the result of a request.
|
|
323
|
-
|
|
324
|
-
Example of JSON with `messageKey`=`messages`:
|
|
325
|
-
<sonic-code language="typescript">
|
|
326
|
-
<template>
|
|
327
|
-
{
|
|
328
|
-
"messages": [{
|
|
329
|
-
"content": "The product has been added to your cart",
|
|
330
|
-
"status": "success",
|
|
331
|
-
"type": "public"
|
|
332
|
-
}]
|
|
333
|
-
}
|
|
334
|
-
</template>
|
|
335
|
-
</sonic-code>
|
|
336
|
-
|
|
337
|
-
### library
|
|
338
|
-
|
|
339
|
-
This is an HTML attribute to set on the component if needed. You can set a URL pointing to a JSON describing a library with the same structure as the library in the SDUIDescriptor. The component will simply override its library with the given one.
|
|
340
|
-
|
|
341
|
-
## Playground
|
|
342
|
-
|
|
343
|
-
Here is a little playground to let you test some simple tricks.
|
|
344
|
-
|
|
345
|
-
<sonic-code>
|
|
346
|
-
<template>
|
|
347
|
-
<sonic-textarea
|
|
348
|
-
rows="10"
|
|
349
|
-
onChange="SonicPublisherManager.get('sdui-playground').set(JSON.parse(this.value))"
|
|
350
|
-
value='{"nodes":[{"tagName":"div", "innerHTML":"test"}]}'
|
|
351
|
-
>
|
|
352
|
-
</sonic-textarea>
|
|
353
|
-
<sonic-sdui dataProvider="sdui-playground" props='{"nodes":[{"tagName":"div", "innerHTML":"test"}]}'>
|
|
354
|
-
</sonic-sdui>
|
|
355
|
-
</template>
|
|
356
|
-
</sonic-code>
|