@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.
- package/.gitlab-ci.yml +23 -0
- package/README.md +106 -55
- package/ai/AGENTS.md +52 -0
- package/ai/README.md +30 -0
- package/ai/cursor/rules/concorde-menu.mdc +15 -0
- package/ai/cursor/rules/concorde-scope.mdc +14 -0
- package/ai/cursor/rules/concorde-theme.mdc +13 -0
- package/ai/cursor/rules/concorde.mdc +49 -0
- package/ai/jetbrains/rules/concorde.md +39 -0
- package/ai/skills/concorde/SKILL.md +220 -0
- package/ai/skills/concorde-get-set-dp/SKILL.md +194 -0
- package/ai/skills/concorde-imports/SKILL.md +78 -0
- package/ai/skills/concorde-menu/SKILL.md +74 -0
- package/ai/skills/concorde-scope/SKILL.md +70 -0
- package/ai/skills/concorde-theme/SKILL.md +46 -0
- package/build-infos.json +1 -1
- package/concorde-core.bundle.js +159 -159
- package/concorde-core.es.js +1915 -1809
- package/dist/altcha-widget.js +2662 -0
- package/dist/concorde-core.bundle.js +159 -159
- package/dist/concorde-core.es.js +1915 -1809
- package/dist/docs-mock-api-sw.js +589 -0
- package/dist/docs-mock-api-sw.js.map +7 -0
- package/docs/altcha-widget.js +2662 -0
- package/docs/assets/index-D9pxaQYK.js +7508 -0
- package/docs/assets/index-t0-i22oI.css +1 -0
- package/docs/docs-mock-api-sw.js +589 -0
- package/docs/docs-mock-api-sw.js.map +7 -0
- package/docs/index.html +2 -2
- package/docs/src/core/components/functional/fetch/fetch.md +13 -11
- package/docs/src/core/components/functional/if/if.md +4 -11
- package/docs/src/core/components/functional/list/list.md +60 -194
- package/docs/src/core/components/functional/queue/queue.md +70 -85
- package/docs/src/core/components/functional/router/router.md +62 -97
- package/docs/src/core/components/functional/states/states.md +2 -2
- package/docs/src/core/components/functional/submit/submit.md +86 -55
- package/docs/src/core/components/ui/captcha/captcha.md +2 -2
- package/docs/src/core/components/ui/card/card.md +1 -1
- package/docs/src/core/components/ui/form/checkbox/checkbox.md +5 -32
- package/docs/src/core/components/ui/form/input/input.md +5 -30
- package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +6 -4
- package/docs/src/core/components/ui/form/radio/radio.md +5 -32
- package/docs/src/core/components/ui/form/select/select.md +5 -31
- package/docs/src/core/components/ui/form/switch/switch.md +5 -32
- package/docs/src/core/components/ui/loader/loader.md +1 -13
- package/docs/src/core/components/ui/table/table.md +3 -3
- package/docs/src/docs/_core-concept/dataFlow.md +73 -0
- package/docs/src/docs/_core-concept/subscriber.md +9 -10
- package/docs/src/docs/_decorators/ancestor-attribute.md +4 -3
- package/docs/src/docs/_decorators/auto-subscribe.md +19 -16
- package/docs/src/docs/_decorators/bind.md +20 -17
- package/docs/src/docs/_decorators/get.md +7 -4
- package/docs/src/docs/_decorators/handle.md +171 -0
- package/docs/src/docs/_decorators/on-assign.md +99 -73
- package/docs/src/docs/_decorators/publish.md +2 -1
- package/docs/src/docs/_decorators/subscribe.md +70 -9
- package/docs/src/docs/_decorators/wait-for-ancestors.md +13 -10
- package/docs/src/docs/_directives/sub.md +91 -0
- package/docs/src/docs/_getting-started/ai-agents.md +56 -0
- package/docs/src/docs/_getting-started/concorde-manual-install.md +133 -0
- package/docs/src/docs/_getting-started/concorde-outside.md +13 -123
- package/docs/src/docs/_getting-started/create-a-component.md +2 -0
- package/docs/src/docs/_getting-started/my-first-component.md +236 -0
- package/docs/src/docs/_getting-started/my-first-subscriber.md +29 -83
- package/docs/src/docs/_getting-started/pubsub.md +21 -134
- package/docs/src/docs/_getting-started/start.md +26 -18
- package/docs/src/docs/_misc/api-configuration.md +79 -0
- package/docs/src/docs/_misc/dataProviderKey.md +38 -5
- package/docs/src/docs/_misc/docs-mock-api.md +60 -0
- package/docs/src/docs/_misc/endpoint.md +2 -1
- package/docs/src/docs/_misc/html-integration.md +13 -0
- package/docs/src/docs/search/docs-search.json +4163 -873
- package/docs/src/tsconfig.json +380 -317
- package/gitlab/job_tests.sh +55 -0
- package/package.json +37 -3
- package/public/altcha-widget.js +2662 -0
- package/public/docs-mock-api-sw.js +589 -0
- package/public/docs-mock-api-sw.js.map +7 -0
- package/scripts/ai-init.mjs +167 -0
- package/scripts/docs-mock-api-vite-plugin.ts +116 -0
- package/scripts/docs-open-in-editor-plugin.ts +130 -0
- package/scripts/pre-publish.mjs +2 -1
- package/src/core/components/functional/example/example.ts +1 -1
- package/src/core/components/functional/fetch/fetch.md +13 -11
- package/src/core/components/functional/if/if.md +4 -11
- package/src/core/components/functional/list/list.demo.ts +4 -4
- package/src/core/components/functional/list/list.md +60 -194
- package/src/core/components/functional/list/list.ts +8 -7
- package/src/core/components/functional/queue/queue.demo.ts +1 -1
- package/src/core/components/functional/queue/queue.md +70 -85
- package/src/core/components/functional/queue/queue.ts +4 -4
- package/src/core/components/functional/router/router.md +62 -97
- package/src/core/components/functional/router/router.ts +1 -1
- package/src/core/components/functional/states/states.md +2 -2
- package/src/core/components/functional/submit/submit.md +86 -55
- package/src/core/components/functional/submit/submit.ts +10 -3
- package/src/core/components/ui/captcha/captcha.md +2 -2
- package/src/core/components/ui/card/card.md +1 -1
- package/src/core/components/ui/form/checkbox/checkbox.md +5 -32
- package/src/core/components/ui/form/input/input.md +5 -30
- package/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +6 -4
- package/src/core/components/ui/form/radio/radio.md +5 -32
- package/src/core/components/ui/form/select/select.md +5 -31
- package/src/core/components/ui/form/switch/switch.md +5 -32
- package/src/core/components/ui/loader/loader.md +1 -13
- package/src/core/components/ui/table/table.md +3 -3
- package/src/core/decorators/Subscriber.ts +2 -0
- package/src/core/decorators/subscriber/handle.disambig.spec.ts +20 -0
- package/src/core/decorators/subscriber/handle.skip.spec.ts +37 -0
- package/src/core/decorators/subscriber/handle.ts +128 -0
- package/src/core/decorators/subscriber/onAssign.ts +94 -4
- package/src/core/directives/DataProvider.sub.spec.ts +96 -0
- package/src/core/directives/DataProvider.ts +109 -40
- package/src/core/utils/PublisherProxy.ts +33 -18
- package/src/core/utils/dataProviderKey.ts +23 -0
- package/src/core/utils/publisherPathKey.spec.ts +58 -0
- package/src/decorators.ts +6 -0
- package/src/docs/_core-concept/dataFlow.md +73 -0
- package/src/docs/_core-concept/subscriber.md +9 -10
- package/src/docs/_decorators/ancestor-attribute.md +4 -3
- package/src/docs/_decorators/auto-subscribe.md +19 -16
- package/src/docs/_decorators/bind.md +20 -17
- package/src/docs/_decorators/get.md +7 -4
- package/src/docs/_decorators/handle.md +171 -0
- package/src/docs/_decorators/on-assign.md +99 -47
- package/src/docs/_decorators/publish.md +2 -1
- package/src/docs/_decorators/subscribe.md +70 -9
- package/src/docs/_decorators/wait-for-ancestors.md +13 -10
- package/src/docs/_directives/sub.md +91 -0
- package/src/docs/_getting-started/ai-agents.md +56 -0
- package/src/docs/_getting-started/concorde-manual-install.md +133 -0
- package/src/docs/_getting-started/concorde-outside.md +13 -123
- package/src/docs/_getting-started/create-a-component.md +2 -0
- package/src/docs/_getting-started/my-first-component.md +236 -0
- package/src/docs/_getting-started/my-first-subscriber.md +29 -83
- package/src/docs/_getting-started/pubsub.md +21 -134
- package/src/docs/_getting-started/start.md +26 -18
- package/src/docs/_misc/api-configuration.md +79 -0
- package/src/docs/_misc/dataProviderKey.md +38 -5
- package/src/docs/_misc/docs-mock-api.md +60 -0
- package/src/docs/_misc/endpoint.md +2 -1
- package/src/docs/_misc/html-integration.md +13 -0
- package/src/docs/code.ts +58 -12
- package/src/docs/components/docs-demo-sources.ts +397 -0
- package/src/docs/components/docs-lit-demo-raw.ts +28 -0
- package/src/docs/components/docs-lit-demo.ts +166 -0
- package/src/docs/components/docs-source-link.ts +72 -0
- package/src/docs/docs-location.ts +54 -0
- package/src/docs/docs.ts +12 -0
- package/src/docs/example/decorators-demo-bind-demos.ts +41 -46
- package/src/docs/example/decorators-demo-geo.ts +16 -11
- package/src/docs/example/decorators-demo-init.ts +2 -228
- package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +142 -12
- package/src/docs/example/decorators-demo.ts +71 -70
- package/src/docs/example/docs-api-config-demos.ts +234 -0
- package/src/docs/example/docs-joke-demos.ts +297 -0
- package/src/docs/example/docs-list-demos.ts +179 -0
- package/src/docs/example/docs-provider-keys.ts +315 -0
- package/src/docs/example/docs-queue-demos.ts +114 -0
- package/src/docs/example/docs-router-demos.ts +89 -0
- package/src/docs/example/docs-submit-demos.ts +455 -0
- package/src/docs/example/docs-toggle-demos.ts +73 -0
- package/src/docs/example/docs-user-two-scopes.ts +37 -0
- package/src/docs/example/docs-users-list.ts +71 -0
- package/src/docs/example/users.ts +41 -24
- package/src/docs/mock-api/api-config-mock.ts +152 -0
- package/src/docs/mock-api/fixtures.ts +377 -0
- package/src/docs/mock-api/register.ts +25 -0
- package/src/docs/mock-api/router.ts +234 -0
- package/src/docs/mock-api/service-worker.ts +23 -0
- package/src/docs/mock-api/urls.ts +11 -0
- package/src/docs/navigation/navigation.ts +43 -7
- package/src/docs/search/docs-search.json +4193 -858
- package/src/docs/search/markdown-renderer.ts +7 -3
- package/src/docs/search/page.ts +11 -14
- package/src/docs/search/sonic-code-markdown.spec.ts +29 -0
- package/src/docs/search/sonic-code-markdown.ts +28 -0
- package/src/docs.ts +4 -0
- package/src/tsconfig.json +96 -0
- package/src/tsconfig.tsbuildinfo +1 -1
- package/vite.config.mts +8 -0
- package/docs/assets/index-CaysOMFz.js +0 -5046
- package/docs/assets/index-D8mGoXzF.css +0 -1
- package/docs/src/docs/_misc/templates-demo.md +0 -19
- package/src/docs/_misc/templates-demo.md +0 -19
|
@@ -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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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="
|
|
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="
|
|
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="
|
|
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="
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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>
|
|
@@ -64,34 +64,8 @@
|
|
|
64
64
|
</template>
|
|
65
65
|
</sonic-code>
|
|
66
66
|
|
|
67
|
-
## Example of use
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
name="lang"
|
|
73
|
-
value="fr"
|
|
74
|
-
>
|
|
75
|
-
<option value="fr">fr<option>
|
|
76
|
-
<optionn value="en">en<option>
|
|
77
|
-
</sonic-select>
|
|
78
|
-
<sonic-subscriber dataProvider="select-filter" class="text-xl my-4 block font-bold">
|
|
79
|
-
Blagues trouvées pour le code de langue"<span data-bind ::inner-html="$lang"></span>" :
|
|
80
|
-
</sonic-subscriber>
|
|
81
|
-
<sonic-queue
|
|
82
|
-
lazyload
|
|
83
|
-
dataProviderExpression="joke/Any?amount=10"
|
|
84
|
-
dataFilterProvider="select-filter"
|
|
85
|
-
serviceURL="https://v2.jokeapi.dev"
|
|
86
|
-
key="jokes"
|
|
87
|
-
>
|
|
88
|
-
<template>
|
|
89
|
-
<div class="border-0 border-b-[1px] border-b-neutral-300 border-dotted py-3">
|
|
90
|
-
<div data-bind ::inner-html="$joke"></div>
|
|
91
|
-
<div data-bind ::inner-html="$setup"></div>
|
|
92
|
-
<div data-bind ::inner-html="$delivery"></div>
|
|
93
|
-
</div>
|
|
94
|
-
</template>
|
|
95
|
-
</sonic-queue>
|
|
96
|
-
</template>
|
|
97
|
-
</sonic-code>
|
|
67
|
+
## Example of use — language filter + queue
|
|
68
|
+
|
|
69
|
+
**`name="lang"`** is sent as `?lang=fr|en` to the [doc mock API](#docs/_misc/docs-mock-api.md/docs-mock-api) (`filterDocsJokes`). Same pattern as [Input](#core/components/ui/form/input/input.md/input) (`contains`):
|
|
70
|
+
|
|
71
|
+
<docs-lit-demo for="docs-joke-lang-demo"></docs-lit-demo>
|
|
@@ -50,35 +50,8 @@
|
|
|
50
50
|
</sonic-code>
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
## Example of use
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
<sonic-value key="blacklistFlags" class="block text-sm"></sonic-value>
|
|
59
|
-
</sonic-subscriber>
|
|
60
|
-
<div formDataProvider="jokeFilterswitch" class="grid grid-cols-2 lg:grid-cols-3 gap-x-6 gap-y-2 mt-2 mb-3">
|
|
61
|
-
<sonic-switch name="blacklistFlags" value="nsfw">nsfw</sonic-switch>
|
|
62
|
-
<sonic-switch name="blacklistFlags" value="religious">religious</sonic-switch>
|
|
63
|
-
<sonic-switch name="blacklistFlags" value="political">political</sonic-switch>
|
|
64
|
-
<sonic-switch name="blacklistFlags" value="racist" checked >racist</sonic-switch>
|
|
65
|
-
<sonic-switch name="blacklistFlags" value="sexist" >sexist</sonic-switch>
|
|
66
|
-
<sonic-switch name="blacklistFlags" value="explicit">explicit</sonic-switch>
|
|
67
|
-
</div>
|
|
68
|
-
<sonic-queue
|
|
69
|
-
lazyload
|
|
70
|
-
dataProviderExpression="joke/Any?amount=10&lang=en"
|
|
71
|
-
dataFilterProvider="jokeFilterswitch"
|
|
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); switches can enable several flags (comma-separated in the query).
|
|
56
|
+
|
|
57
|
+
<docs-lit-demo for="docs-joke-blacklist-switch-demo"></docs-lit-demo>
|
|
@@ -29,19 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
## Fixed mode
|
|
31
31
|
|
|
32
|
-
<
|
|
33
|
-
<template>
|
|
34
|
-
<div dataProvider="toggleLoaderForm" formDataProvider="toggleLoaderForm">
|
|
35
|
-
<sonic-checkbox label="Show fixed loader"
|
|
36
|
-
name="toggleLoader"
|
|
37
|
-
unique value="true">
|
|
38
|
-
</sonic-checkbox>
|
|
39
|
-
<sonic-if data-bind ::condition="$toggleLoader" >
|
|
40
|
-
<sonic-loader></sonic-loader>
|
|
41
|
-
</sonic-if>
|
|
42
|
-
</div>
|
|
43
|
-
</template>
|
|
44
|
-
</sonic-code>
|
|
32
|
+
<docs-lit-demo for="docs-toggle-loader-demo"></docs-lit-demo>
|
|
45
33
|
|
|
46
34
|
|
|
47
35
|
## Loading button
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
</sonic-tr>
|
|
43
43
|
</sonic-thead>
|
|
44
44
|
<sonic-tbody>
|
|
45
|
-
<sonic-list debug fetch serviceURL="
|
|
45
|
+
<sonic-list debug fetch serviceURL="/docs-mock-api" dataProvider="api/users" key="data" displayContents>
|
|
46
46
|
<template>
|
|
47
47
|
<sonic-tr>
|
|
48
48
|
<sonic-td data-bind ::inner-html="$id"></sonic-td>
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
</sonic-tr>
|
|
136
136
|
</sonic-thead>
|
|
137
137
|
<sonic-tbody>
|
|
138
|
-
<sonic-list fetch serviceURL="
|
|
138
|
+
<sonic-list fetch serviceURL="/docs-mock-api" dataProvider="api/users" key="data" displayContents>
|
|
139
139
|
<template>
|
|
140
140
|
<sonic-tr>
|
|
141
141
|
<sonic-td data-bind ::inner-html="$id"></sonic-td>
|
|
@@ -256,7 +256,7 @@ Every table is responsive by default
|
|
|
256
256
|
</sonic-tr>
|
|
257
257
|
</sonic-thead>
|
|
258
258
|
<sonic-tbody>
|
|
259
|
-
<sonic-list fetch serviceURL="
|
|
259
|
+
<sonic-list fetch serviceURL="/docs-mock-api" dataProvider="api/users" key="data" displayContents>
|
|
260
260
|
<template>
|
|
261
261
|
<sonic-tr>
|
|
262
262
|
<sonic-td data-bind ::inner-html="$id"></sonic-td>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Data flow
|
|
2
|
+
|
|
3
|
+
Recommended patterns for new Concorde apps (Lit + TypeScript). Under the hood, data lives in a **DataProvider** store (legacy **Publisher** API: [Legacy: Sharing data](#docs/_getting-started/pubsub.md/pubsub)).
|
|
4
|
+
|
|
5
|
+
## Quick map
|
|
6
|
+
|
|
7
|
+
| Need | Use |
|
|
8
|
+
|------|-----|
|
|
9
|
+
| Read/write in code | `get` / `set` / `dp` + `DataProviderKey` (static paths only) |
|
|
10
|
+
| Reactive Lit template | `sub(key)` or `@subscribe` |
|
|
11
|
+
| Read component state from store | `@subscribe` + `DataProviderKey<T, U>` + `@state` |
|
|
12
|
+
| Inherit ancestor attributes | `@ancestorAttribute` |
|
|
13
|
+
| Write from component state | `@publish` |
|
|
14
|
+
| React to assignments | `@handle` |
|
|
15
|
+
| HTTP GET | `@get` + `Endpoint`, or `sonic-list` / `sonic-queue` with `fetch` |
|
|
16
|
+
| Forms | `formDataProvider` + `name` on fields |
|
|
17
|
+
| Offline doc demos | `serviceURL="/docs-mock-api"` — [Local API demos](#docs/_misc/docs-mock-api.md/docs-mock-api) |
|
|
18
|
+
|
|
19
|
+
Skill: `concorde-get-set-dp` in the package `ai/` folder.
|
|
20
|
+
|
|
21
|
+
## DataProviderKey
|
|
22
|
+
|
|
23
|
+
<sonic-code language="typescript">
|
|
24
|
+
<template>
|
|
25
|
+
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
26
|
+
import { dp, get, set } from "@supersoniks/concorde/utils";
|
|
27
|
+
|
|
28
|
+
const cartKey = new DataProviderKey<{ items: string[] }>("cart");
|
|
29
|
+
|
|
30
|
+
set(cartKey, { items: [] });
|
|
31
|
+
dp(cartKey.items).set(["a", "b"]);
|
|
32
|
+
get(cartKey);
|
|
33
|
+
</template>
|
|
34
|
+
</sonic-code>
|
|
35
|
+
|
|
36
|
+
Dynamic paths (`users.${userId}`) → decorators or `sub()` — not `get("users.${id}")` in imperative code.
|
|
37
|
+
|
|
38
|
+
[DataProviderKey](#docs/_misc/dataProviderKey.md/dataProviderKey)
|
|
39
|
+
|
|
40
|
+
## Decorators
|
|
41
|
+
|
|
42
|
+
| Decorator | Role |
|
|
43
|
+
|-----------|------|
|
|
44
|
+
| `@subscribe` | Read-only property from store — [data configuration](#docs/_getting-started/my-first-component.md/my-first-component) (type + key + scope) |
|
|
45
|
+
| `@publish` | Push property writes to store |
|
|
46
|
+
| `@handle` | Method called on assignment |
|
|
47
|
+
| `@ancestorAttribute` | Copy ancestor HTML attribute onto property |
|
|
48
|
+
| `@get` | HTTP GET into `ApiGetResult<T>` |
|
|
49
|
+
|
|
50
|
+
Walkthrough: [My first component](#docs/_getting-started/my-first-component.md/my-first-component)
|
|
51
|
+
|
|
52
|
+
## HTTP and lists
|
|
53
|
+
|
|
54
|
+
- [@get](#docs/_decorators/get.md/get) — single request on a component
|
|
55
|
+
- [List](#core/components/functional/list/list.md/list) — `fetch` + `key="data"` + `/docs-mock-api/api/users`
|
|
56
|
+
- [Queue](#core/components/functional/queue/queue.md/queue) — lazy `offset=$offset&per_page=$limit` + optional `dataFilterProvider` (form → query)
|
|
57
|
+
|
|
58
|
+
## Starter kit
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npx @supersoniks/create-concorde-ts-starter my-app
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Interactive routes mirror these patterns (`/concepts/*`, `/demo/*`).
|
|
65
|
+
|
|
66
|
+
## Legacy integration
|
|
67
|
+
|
|
68
|
+
| Topic | Page |
|
|
69
|
+
|-------|------|
|
|
70
|
+
| `Subscriber` / `Fetcher` mixins on app code | [Legacy: Subscriber mixin](#docs/_core-concept/subscriber.md/subscriber), [Legacy: My first subscriber](#docs/_getting-started/my-first-subscriber.md/my-first-subscriber) |
|
|
71
|
+
| `data-bind` HTML (plain HTML hosts) | [HTML integration](#docs/_misc/html-integration.md/html-integration) — doc demos use Lit in `src/docs/example/` |
|
|
72
|
+
| `@onAssign` | [@onAssign](#docs/_decorators/on-assign.md/on-assign) (prefer `@handle`) |
|
|
73
|
+
| `sonic-fetch` alone | [Fetch](#core/components/functional/fetch/fetch.md/fetch) |
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Legacy: Subscriber mixin
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **New app components:** [My first component](#docs/_getting-started/my-first-component.md/my-first-component) and [Data flow](#docs/_core-concept/dataFlow.md/dataFlow) — extend `LitElement` with decorators (`@subscribe`, `@ancestorAttribute`, …). This mixin remains in **core** components (`sonic-list`, `sonic-fetch`, …) and [legacy tutorials](#docs/_getting-started/my-first-subscriber.md/my-first-subscriber).
|
|
4
|
+
|
|
5
|
+
The Subscriber mixin was commonly extended by Concorde core components and older destination components. Pure UI components usually don't extend it, especially those outside of form components.
|
|
4
6
|
|
|
5
7
|
## DataProvider Attribute: Automatic Filling of Subscriber Properties
|
|
6
8
|
|
|
7
9
|
Upon being added to the DOM (connectedCallback), subscribers search for the first occurrence of the `dataProvider` attribute in their parent's HTML structure.
|
|
8
10
|
|
|
9
|
-
The value of this attribute is
|
|
11
|
+
The value of this attribute is the DataProvider path (see [Data flow](#docs/_core-concept/dataFlow.md/dataFlow) and [DataProviderKey](#docs/_misc/dataProviderKey.md/dataProviderKey); legacy API: [Sharing Data](#docs/_getting-started/pubsub.md/pubsub)).
|
|
10
12
|
|
|
11
13
|
The subscriber then subscribes to the publisher as a data template to be filled.
|
|
12
14
|
|
|
@@ -51,14 +53,11 @@ Suppose that:
|
|
|
51
53
|
</sonic-code>
|
|
52
54
|
- We want to keep the display of an image and its `title` attribute up to date, as well as a "contact" button to email the person in the photo. The content of the subscriber could be as follows:
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<a data-bind ::href="mailto:$email" ::inner-html="$email"></a>
|
|
58
|
-
</template>
|
|
59
|
-
</sonic-code>
|
|
56
|
+
In a **Lit** app, use the same data with [data configuration](#docs/_getting-started/my-first-component.md/my-first-component) (`@subscribe` + `DataProviderKey`) on a small row component — see `docs-user` in `src/docs/example/users.ts`.
|
|
57
|
+
|
|
58
|
+
For **HTML-only** embedding (no Lit), attribute binding is described in [HTML integration](#docs/_misc/html-integration.md/html-integration) and in the Legacy [Subscriber mixin](#docs/_core-concept/subscriber.md/subscriber) pages.
|
|
60
59
|
|
|
61
|
-
This
|
|
60
|
+
This pattern also illustrates:
|
|
62
61
|
|
|
63
62
|
- Binding to subproperties using dot syntax, as done for the `src` attribute of the `img` tag.
|
|
64
63
|
- Using a simple expression to include the property within a string, as in creating a `mailto` link.
|
|
@@ -25,15 +25,15 @@ The component reads `dataProvider` and `testAttribute` from its ancestor wrapper
|
|
|
25
25
|
import { html, LitElement } from "lit";
|
|
26
26
|
import { customElement } from "lit/decorators.js";
|
|
27
27
|
import { ancestorAttribute } from "@supersoniks/concorde/decorators";
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
@customElement("demo-ancestor-attribute")
|
|
30
30
|
export class DemoAncestorAttribute extends LitElement {
|
|
31
31
|
@ancestorAttribute("dataProvider")
|
|
32
32
|
dataProvider: string | null = null;
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
@ancestorAttribute("testAttribute")
|
|
35
35
|
testAttribute: string | null = null;
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
render() {
|
|
38
38
|
return html`
|
|
39
39
|
<section>
|
|
@@ -49,6 +49,7 @@ export class DemoAncestorAttribute extends LitElement {
|
|
|
49
49
|
<sonic-code>
|
|
50
50
|
<template>
|
|
51
51
|
<div dataProvider="demoDataProvider" testAttribute="test-value-123">
|
|
52
|
+
<docs-demo-sources for="demo-ancestor-attribute"></docs-demo-sources>
|
|
52
53
|
<demo-ancestor-attribute></demo-ancestor-attribute>
|
|
53
54
|
</div>
|
|
54
55
|
</template>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# @autoSubscribe
|
|
2
2
|
|
|
3
|
+
> **Legacy:** prefer [@subscribe](#docs/_decorators/subscribe.md/subscribe) + `DataProviderKey`. Examples below may still show `PublisherManager` for existing codebases.
|
|
4
|
+
|
|
3
5
|
The `@autoSubscribe` decorator automatically detects which publishers are accessed within a method and subscribes to them. When any of these publishers change, the method is automatically re-executed.
|
|
4
6
|
|
|
5
7
|
## Principle
|
|
@@ -24,10 +26,10 @@ import { autoSubscribe } from "@supersoniks/concorde/decorators";
|
|
|
24
26
|
@customElement("demo-auto-subscribe")
|
|
25
27
|
export class DemoAutoSubscribe extends LitElement {
|
|
26
28
|
static styles = [tailwind];
|
|
27
|
-
|
|
29
|
+
|
|
28
30
|
@state() displayText: string = "";
|
|
29
31
|
@state() computedValue: number = 0;
|
|
30
|
-
|
|
32
|
+
|
|
31
33
|
@autoSubscribe()
|
|
32
34
|
updateDisplay() {
|
|
33
35
|
const value1 = PublisherManager.get("autoValue1").get() || 0;
|
|
@@ -35,7 +37,7 @@ export class DemoAutoSubscribe extends LitElement {
|
|
|
35
37
|
this.computedValue = value1 + value2;
|
|
36
38
|
this.displayText = `${value1} + ${value2} = ${this.computedValue}`;
|
|
37
39
|
}
|
|
38
|
-
|
|
40
|
+
|
|
39
41
|
render() {
|
|
40
42
|
return html`
|
|
41
43
|
<p><strong>${this.displayText}</strong></p>
|
|
@@ -49,7 +51,7 @@ export class DemoAutoSubscribe extends LitElement {
|
|
|
49
51
|
</div>
|
|
50
52
|
`;
|
|
51
53
|
}
|
|
52
|
-
|
|
54
|
+
|
|
53
55
|
randomizeValue(publisherId: string) {
|
|
54
56
|
const value = PublisherManager.get(publisherId);
|
|
55
57
|
value.set(Math.floor(Math.random() * 100));
|
|
@@ -61,6 +63,7 @@ export class DemoAutoSubscribe extends LitElement {
|
|
|
61
63
|
|
|
62
64
|
<sonic-code >
|
|
63
65
|
<template>
|
|
66
|
+
<docs-demo-sources for="demo-auto-subscribe"></docs-demo-sources>
|
|
64
67
|
<demo-auto-subscribe></demo-auto-subscribe>
|
|
65
68
|
</template>
|
|
66
69
|
</sonic-code>
|
|
@@ -75,12 +78,12 @@ export class ReactiveView extends LitElement {
|
|
|
75
78
|
render() {
|
|
76
79
|
const data = PublisherManager.get("myData");
|
|
77
80
|
const config = PublisherManager.get("config");
|
|
78
|
-
|
|
81
|
+
|
|
79
82
|
// This render method will be automatically re-executed
|
|
80
83
|
// when myData or config change
|
|
81
84
|
const value = data.get()?.value || 0;
|
|
82
85
|
const multiplier = config.get()?.multiplier || 1;
|
|
83
|
-
|
|
86
|
+
|
|
84
87
|
return html`
|
|
85
88
|
<div>
|
|
86
89
|
<h1>Result: ${value * multiplier}</h1>
|
|
@@ -125,40 +128,40 @@ import { html, LitElement } from "lit";
|
|
|
125
128
|
import { customElement } from "lit/decorators.js";
|
|
126
129
|
import { autoSubscribe } from "@supersoniks/concorde/decorators";
|
|
127
130
|
import { PublisherManager } from "@supersoniks/concorde/core/utils/PublisherProxy";
|
|
128
|
-
|
|
131
|
+
|
|
129
132
|
@customElement("shopping-cart")
|
|
130
133
|
export class ShoppingCart extends LitElement {
|
|
131
134
|
items: any[] = [];
|
|
132
135
|
total: number = 0;
|
|
133
136
|
discount: number = 0;
|
|
134
|
-
|
|
137
|
+
|
|
135
138
|
@autoSubscribe()
|
|
136
139
|
calculateTotal() {
|
|
137
140
|
const cart = PublisherManager.get("cart");
|
|
138
141
|
const promo = PublisherManager.get("promo");
|
|
139
|
-
|
|
142
|
+
|
|
140
143
|
// Access cart items
|
|
141
144
|
this.items = cart.items.get() || [];
|
|
142
|
-
|
|
145
|
+
|
|
143
146
|
// Access promo code
|
|
144
147
|
const promoCode = promo.code.get() || "";
|
|
145
148
|
const discountPercent = promoCode === "SAVE10" ? 0.1 : 0;
|
|
146
|
-
|
|
149
|
+
|
|
147
150
|
// Calculate totals
|
|
148
151
|
const subtotal = this.items.reduce((sum, item) =>
|
|
149
152
|
sum + (item.price * item.quantity), 0
|
|
150
153
|
);
|
|
151
154
|
this.discount = subtotal * discountPercent;
|
|
152
155
|
this.total = subtotal - this.discount;
|
|
153
|
-
|
|
156
|
+
|
|
154
157
|
this.requestUpdate();
|
|
155
158
|
}
|
|
156
|
-
|
|
159
|
+
|
|
157
160
|
connectedCallback() {
|
|
158
161
|
super.connectedCallback();
|
|
159
162
|
this.calculateTotal();
|
|
160
163
|
}
|
|
161
|
-
|
|
164
|
+
|
|
162
165
|
render() {
|
|
163
166
|
return html`
|
|
164
167
|
<div class="cart">
|
|
@@ -175,14 +178,14 @@ export class ShoppingCart extends LitElement {
|
|
|
175
178
|
`;
|
|
176
179
|
}
|
|
177
180
|
}
|
|
178
|
-
|
|
181
|
+
|
|
179
182
|
// When you update the publishers, calculateTotal is automatically called:
|
|
180
183
|
const cart = PublisherManager.get("cart");
|
|
181
184
|
cart.items.set([
|
|
182
185
|
{ name: "Product 1", price: 10, quantity: 2 },
|
|
183
186
|
{ name: "Product 2", price: 15, quantity: 1 }
|
|
184
187
|
]);
|
|
185
|
-
|
|
188
|
+
|
|
186
189
|
const promo = PublisherManager.get("promo");
|
|
187
190
|
promo.code.set("SAVE10");
|
|
188
191
|
// calculateTotal will be automatically called and the UI will update
|
|
@@ -4,11 +4,11 @@ Binds a class property to a path in a publisher. The property updates when publi
|
|
|
4
4
|
|
|
5
5
|
For Lit re-renders, also add `@state()` on the same property.
|
|
6
6
|
|
|
7
|
-
**See also:** [@subscribe](#docs/_decorators/subscribe.md/subscribe), [@publish](#docs/_decorators/publish.md/publish), [@get](#docs/_decorators/get.md/get).
|
|
7
|
+
**See also:** [@subscribe](#docs/_decorators/subscribe.md/subscribe), [@handle](#docs/_decorators/handle.md/handle), [@publish](#docs/_decorators/publish.md/publish), [@get](#docs/_decorators/get.md/get).
|
|
8
8
|
|
|
9
9
|
## Principle
|
|
10
10
|
|
|
11
|
-
The decorator subscribes
|
|
11
|
+
The decorator subscribes to the DataProvider store using dot notation or a `DataProviderKey`. Updates flow into the decorated property ([Data flow](#docs/_core-concept/dataFlow.md/dataFlow)).
|
|
12
12
|
|
|
13
13
|
## Import
|
|
14
14
|
|
|
@@ -25,26 +25,26 @@ import { bind } from "@supersoniks/concorde/decorators";
|
|
|
25
25
|
@customElement("demo-bind")
|
|
26
26
|
export class DemoBind extends LitElement {
|
|
27
27
|
static styles = [tailwind];
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
@bind("demoData.firstName")
|
|
30
30
|
@state()
|
|
31
31
|
firstName = "";
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
@bind("demoData.lastName")
|
|
34
34
|
@state()
|
|
35
35
|
lastName: string = "";
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
@bind("demoData.count")
|
|
38
38
|
@state()
|
|
39
39
|
count: number = 0;
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
render() {
|
|
42
42
|
return //......
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
updateData() {
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
set(demoDataKey, { ...get(demoDataKey), count: get(demoDataKey).count + 1 });
|
|
47
|
+
// see demo-bind in src/docs/example/decorators-demo-bind-demos.ts
|
|
48
48
|
const randomIndex = Math.floor(Math.random() * demoUsers.get().length);
|
|
49
49
|
const randomUser = demoUsers.get()[randomIndex];
|
|
50
50
|
demoData.set({
|
|
@@ -54,12 +54,13 @@ export class DemoBind extends LitElement {
|
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
</template>
|
|
59
59
|
</sonic-code>
|
|
60
60
|
|
|
61
61
|
<sonic-code>
|
|
62
62
|
<template>
|
|
63
|
+
<docs-demo-sources for="demo-bind"></docs-demo-sources>
|
|
63
64
|
<demo-bind></demo-bind>
|
|
64
65
|
</template>
|
|
65
66
|
</sonic-code>
|
|
@@ -72,10 +73,10 @@ export class DemoBind extends LitElement {
|
|
|
72
73
|
<template>
|
|
73
74
|
import { bind } from "@supersoniks/concorde/decorators";
|
|
74
75
|
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
75
|
-
|
|
76
|
+
|
|
76
77
|
type Data = { count: number };
|
|
77
78
|
const dataKey = new DataProviderKey<Data>("data");
|
|
78
|
-
|
|
79
|
+
|
|
79
80
|
@bind(dataKey.count, { reflect: true })
|
|
80
81
|
@state()
|
|
81
82
|
count: number = 0;
|
|
@@ -99,15 +100,15 @@ avatar: string;
|
|
|
99
100
|
@customElement("demo-bind-reflect")
|
|
100
101
|
export class DemoBindReflect extends LitElement {
|
|
101
102
|
static styles = [tailwind];
|
|
102
|
-
|
|
103
|
+
|
|
103
104
|
@bind("bindReflectDemo.count", { reflect: true })
|
|
104
105
|
@state()
|
|
105
106
|
withReflect: number = 0;
|
|
106
|
-
|
|
107
|
+
|
|
107
108
|
@bind("bindReflectDemo.count")
|
|
108
109
|
@state()
|
|
109
110
|
withoutReflect: number = 0;
|
|
110
|
-
|
|
111
|
+
|
|
111
112
|
render() {
|
|
112
113
|
return html`
|
|
113
114
|
<div class="mb-3">
|
|
@@ -124,13 +125,14 @@ export class DemoBindReflect extends LitElement {
|
|
|
124
125
|
`;
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
|
-
|
|
128
|
+
|
|
128
129
|
</template>
|
|
129
130
|
</sonic-code>
|
|
130
131
|
|
|
131
132
|
<sonic-code toggleCode>
|
|
132
133
|
<template>
|
|
133
|
-
<demo-bind-reflect></demo-
|
|
134
|
+
<docs-demo-sources for="demo-bind-reflect"></docs-demo-sources>
|
|
135
|
+
<demo-bind-reflect></demo-bind-reflect>
|
|
134
136
|
</template>
|
|
135
137
|
</sonic-code>
|
|
136
138
|
|
|
@@ -148,6 +150,7 @@ Use `${prop}` or `${this.prop}` inside a **normal string literal** (not a JS tem
|
|
|
148
150
|
|
|
149
151
|
<sonic-code>
|
|
150
152
|
<template>
|
|
153
|
+
<docs-demo-sources for="demo-bind-dynamic"></docs-demo-sources>
|
|
151
154
|
<demo-bind-dynamic></demo-bind-dynamic>
|
|
152
155
|
</template>
|
|
153
156
|
</sonic-code>
|