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