@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
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
import { html, LitElement, nothing } from "lit";
|
|
2
|
+
import { customElement, state } from "lit/decorators.js";
|
|
3
|
+
import { subscribe } from "@supersoniks/concorde/core/decorators/Subscriber";
|
|
4
|
+
import { Endpoint } from "@supersoniks/concorde/core/utils/endpoint";
|
|
5
|
+
import {
|
|
6
|
+
DOCS_MOCK_API_BASE,
|
|
7
|
+
DOCS_MOCK_REQRES_SERVICE,
|
|
8
|
+
} from "../mock-api/urls";
|
|
9
|
+
import {
|
|
10
|
+
submitClearFormKey,
|
|
11
|
+
submitEndpointFormKey,
|
|
12
|
+
submitEndpointResultKey,
|
|
13
|
+
submitEventFormKey,
|
|
14
|
+
submitExampleFormKey,
|
|
15
|
+
submitExampleResultKey,
|
|
16
|
+
submitFormDataFormKey,
|
|
17
|
+
submitFormDataResultKey,
|
|
18
|
+
submitGetFormKey,
|
|
19
|
+
submitGetResultKey,
|
|
20
|
+
submitNativeFormKey,
|
|
21
|
+
submitNestedFormKey,
|
|
22
|
+
submitNestedResultKey,
|
|
23
|
+
} from "./docs-provider-keys";
|
|
24
|
+
import { tailwind } from "../tailwind";
|
|
25
|
+
|
|
26
|
+
import "../../core/components/functional/sonic-scope/sonic-scope";
|
|
27
|
+
import "../../core/components/functional/submit/submit";
|
|
28
|
+
import "../../core/components/ui/button/button";
|
|
29
|
+
import "../../core/components/ui/divider/divider";
|
|
30
|
+
import "../../core/components/ui/form/input/input";
|
|
31
|
+
|
|
32
|
+
type RegisterResult = {
|
|
33
|
+
id?: number;
|
|
34
|
+
token?: string;
|
|
35
|
+
email?: string;
|
|
36
|
+
error?: string;
|
|
37
|
+
messages?: { content?: string; status?: string }[];
|
|
38
|
+
method?: string;
|
|
39
|
+
query?: { email?: string; password?: string };
|
|
40
|
+
note?: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const registerEndpoint = new Endpoint<RegisterResult>("api/register");
|
|
44
|
+
const registerNestedEndpoint = new Endpoint<RegisterResult>(
|
|
45
|
+
"api/register/nested",
|
|
46
|
+
);
|
|
47
|
+
const registerEchoEndpoint = new Endpoint<RegisterResult>("api/register/echo");
|
|
48
|
+
const usersListEndpoint = new Endpoint<unknown>("api/users");
|
|
49
|
+
|
|
50
|
+
function resultLines(r: RegisterResult | null) {
|
|
51
|
+
if (!r) return nothing;
|
|
52
|
+
const messageText = r.messages
|
|
53
|
+
?.map((m) => m.content)
|
|
54
|
+
.filter(Boolean)
|
|
55
|
+
.join(" — ");
|
|
56
|
+
return html`
|
|
57
|
+
${r.id != null
|
|
58
|
+
? html`<div>Id : <span class="font-mono">${r.id}</span></div>`
|
|
59
|
+
: nothing}
|
|
60
|
+
${r.email
|
|
61
|
+
? html`<div>Email : <span class="font-mono">${r.email}</span></div>`
|
|
62
|
+
: nothing}
|
|
63
|
+
${r.token
|
|
64
|
+
? html`<div>Token : <span class="font-mono break-all">${r.token}</span></div>`
|
|
65
|
+
: nothing}
|
|
66
|
+
${r.method
|
|
67
|
+
? html`<div>Method : <span class="font-mono">${r.method}</span></div>`
|
|
68
|
+
: nothing}
|
|
69
|
+
${r.query
|
|
70
|
+
? html`<div>
|
|
71
|
+
Query :
|
|
72
|
+
<span class="font-mono"
|
|
73
|
+
>email=${r.query.email ?? ""}, password=${r.query.password ?? ""}</span
|
|
74
|
+
>
|
|
75
|
+
</div>`
|
|
76
|
+
: nothing}
|
|
77
|
+
${r.note ? html`<p class="text-neutral-500">${r.note}</p>` : nothing}
|
|
78
|
+
${r.error ? html`<div class="text-red-600">${r.error}</div>` : nothing}
|
|
79
|
+
${messageText ? html`<div class="text-red-600">${messageText}</div>` : nothing}
|
|
80
|
+
`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Form + result — `submitResultDataProvider` is filled after POST to mock `/api/register`.
|
|
85
|
+
*/
|
|
86
|
+
@customElement("docs-submit-demo")
|
|
87
|
+
export class DocsSubmitDemo extends LitElement {
|
|
88
|
+
static styles = [tailwind];
|
|
89
|
+
|
|
90
|
+
@subscribe(submitExampleResultKey)
|
|
91
|
+
@state()
|
|
92
|
+
private result: RegisterResult | null = null;
|
|
93
|
+
|
|
94
|
+
private resultBlock() {
|
|
95
|
+
const r = this.result;
|
|
96
|
+
if (!r || (!r.id && !r.token && !r.error && !r.messages?.length)) {
|
|
97
|
+
return html`
|
|
98
|
+
<p class="mt-4 text-sm text-neutral-500">
|
|
99
|
+
Submit the form to see <code>id</code> and <code>token</code> here.
|
|
100
|
+
</p>
|
|
101
|
+
`;
|
|
102
|
+
}
|
|
103
|
+
return html`
|
|
104
|
+
<sonic-divider align="left" class="mt-6">Result</sonic-divider>
|
|
105
|
+
<div class="mt-2 space-y-1 text-sm">${resultLines(r)}</div>
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
render() {
|
|
110
|
+
return html`
|
|
111
|
+
<sonic-scope
|
|
112
|
+
serviceURL=${DOCS_MOCK_REQRES_SERVICE}
|
|
113
|
+
dataProvider=${registerEndpoint.path}
|
|
114
|
+
formDataProvider=${submitExampleFormKey.path}
|
|
115
|
+
submitResultDataProvider=${submitExampleResultKey.path}
|
|
116
|
+
class="max-w-lg block"
|
|
117
|
+
>
|
|
118
|
+
<sonic-submit onEnterKey>
|
|
119
|
+
<div class="mb-4 grid grid-cols-2 gap-4">
|
|
120
|
+
<sonic-input
|
|
121
|
+
required
|
|
122
|
+
name="email"
|
|
123
|
+
type="email"
|
|
124
|
+
value="eve.holt@reqres.in"
|
|
125
|
+
></sonic-input>
|
|
126
|
+
<sonic-input
|
|
127
|
+
required
|
|
128
|
+
type="password"
|
|
129
|
+
name="password"
|
|
130
|
+
value="pistol"
|
|
131
|
+
></sonic-input>
|
|
132
|
+
</div>
|
|
133
|
+
</sonic-submit>
|
|
134
|
+
<sonic-submit onClick>
|
|
135
|
+
<sonic-button type="success" class="w-full">Submit</sonic-button>
|
|
136
|
+
</sonic-submit>
|
|
137
|
+
</sonic-scope>
|
|
138
|
+
${this.resultBlock()}
|
|
139
|
+
`;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** `clearedDataOnSuccess` resets listed publishers when the API returns a result object. */
|
|
144
|
+
@customElement("docs-submit-clear-demo")
|
|
145
|
+
export class DocsSubmitClearDemo extends LitElement {
|
|
146
|
+
static styles = [tailwind];
|
|
147
|
+
|
|
148
|
+
render() {
|
|
149
|
+
return html`
|
|
150
|
+
<sonic-scope
|
|
151
|
+
serviceURL=${DOCS_MOCK_REQRES_SERVICE}
|
|
152
|
+
dataProvider=${registerEndpoint.path}
|
|
153
|
+
formDataProvider=${submitClearFormKey.path}
|
|
154
|
+
clearedDataOnSuccess=${submitClearFormKey.path}
|
|
155
|
+
class="max-w-lg block"
|
|
156
|
+
>
|
|
157
|
+
<sonic-submit onClick>
|
|
158
|
+
<div class="mb-4 grid grid-cols-2 gap-4">
|
|
159
|
+
<sonic-input
|
|
160
|
+
required
|
|
161
|
+
name="email"
|
|
162
|
+
type="email"
|
|
163
|
+
value="eve.holt@reqres.in"
|
|
164
|
+
></sonic-input>
|
|
165
|
+
<sonic-input
|
|
166
|
+
required
|
|
167
|
+
type="password"
|
|
168
|
+
name="password"
|
|
169
|
+
value="pistol"
|
|
170
|
+
></sonic-input>
|
|
171
|
+
</div>
|
|
172
|
+
<sonic-button type="success" class="w-full">Submit and clear form</sonic-button>
|
|
173
|
+
</sonic-submit>
|
|
174
|
+
</sonic-scope>
|
|
175
|
+
<p class="mt-3 text-sm text-neutral-500">
|
|
176
|
+
After submit, <code>clearedDataOnSuccess="submit-clear-form"</code> resets
|
|
177
|
+
the publisher (inputs should empty).
|
|
178
|
+
</p>
|
|
179
|
+
`;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** `submit-result-key` keeps only a nested part of the JSON before writing the result publisher. */
|
|
184
|
+
@customElement("docs-submit-result-key-demo")
|
|
185
|
+
export class DocsSubmitResultKeyDemo extends LitElement {
|
|
186
|
+
static styles = [tailwind];
|
|
187
|
+
|
|
188
|
+
@subscribe(submitNestedResultKey)
|
|
189
|
+
@state()
|
|
190
|
+
private result: RegisterResult | null = null;
|
|
191
|
+
|
|
192
|
+
render() {
|
|
193
|
+
const r = this.result;
|
|
194
|
+
return html`
|
|
195
|
+
<sonic-scope
|
|
196
|
+
serviceURL=${DOCS_MOCK_REQRES_SERVICE}
|
|
197
|
+
dataProvider=${registerNestedEndpoint.path}
|
|
198
|
+
formDataProvider=${submitNestedFormKey.path}
|
|
199
|
+
submitResultDataProvider=${submitNestedResultKey.path}
|
|
200
|
+
class="max-w-lg block"
|
|
201
|
+
>
|
|
202
|
+
<sonic-submit onClick submit-result-key="data">
|
|
203
|
+
<div class="mb-4 grid grid-cols-2 gap-4">
|
|
204
|
+
<sonic-input
|
|
205
|
+
required
|
|
206
|
+
name="email"
|
|
207
|
+
type="email"
|
|
208
|
+
value="eve.holt@reqres.in"
|
|
209
|
+
></sonic-input>
|
|
210
|
+
<sonic-input
|
|
211
|
+
required
|
|
212
|
+
type="password"
|
|
213
|
+
name="password"
|
|
214
|
+
value="pistol"
|
|
215
|
+
></sonic-input>
|
|
216
|
+
</div>
|
|
217
|
+
<sonic-button type="primary" class="w-full">Submit (nested JSON)</sonic-button>
|
|
218
|
+
</sonic-submit>
|
|
219
|
+
</sonic-scope>
|
|
220
|
+
<sonic-divider align="left" class="mt-4">Stored in publisher</sonic-divider>
|
|
221
|
+
<div class="mt-2 text-sm">
|
|
222
|
+
${r?.id != null
|
|
223
|
+
? html`<div>id from <code>data</code> : ${r.id}</div>`
|
|
224
|
+
: html`<p class="text-neutral-500">Submit to extract <code>data.id</code> / <code>data.token</code>.</p>`}
|
|
225
|
+
</div>
|
|
226
|
+
`;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** `sendAsFormData` sends multipart <code>FormData</code> instead of JSON. */
|
|
231
|
+
@customElement("docs-submit-formdata-demo")
|
|
232
|
+
export class DocsSubmitFormDataDemo extends LitElement {
|
|
233
|
+
static styles = [tailwind];
|
|
234
|
+
|
|
235
|
+
@subscribe(submitFormDataResultKey)
|
|
236
|
+
@state()
|
|
237
|
+
private result: RegisterResult | null = null;
|
|
238
|
+
|
|
239
|
+
render() {
|
|
240
|
+
return html`
|
|
241
|
+
<sonic-scope
|
|
242
|
+
serviceURL=${DOCS_MOCK_REQRES_SERVICE}
|
|
243
|
+
dataProvider=${registerEndpoint.path}
|
|
244
|
+
formDataProvider=${submitFormDataFormKey.path}
|
|
245
|
+
submitResultDataProvider=${submitFormDataResultKey.path}
|
|
246
|
+
class="max-w-lg block"
|
|
247
|
+
>
|
|
248
|
+
<sonic-submit onClick sendAsFormData>
|
|
249
|
+
<div class="mb-4 grid grid-cols-2 gap-4">
|
|
250
|
+
<sonic-input
|
|
251
|
+
required
|
|
252
|
+
name="email"
|
|
253
|
+
type="email"
|
|
254
|
+
value="eve.holt@reqres.in"
|
|
255
|
+
></sonic-input>
|
|
256
|
+
<sonic-input
|
|
257
|
+
required
|
|
258
|
+
type="password"
|
|
259
|
+
name="password"
|
|
260
|
+
value="pistol"
|
|
261
|
+
></sonic-input>
|
|
262
|
+
</div>
|
|
263
|
+
<sonic-button type="primary" class="w-full">Submit as FormData</sonic-button>
|
|
264
|
+
</sonic-submit>
|
|
265
|
+
</sonic-scope>
|
|
266
|
+
<div class="mt-3 text-sm">
|
|
267
|
+
${this.result?.token
|
|
268
|
+
? html`Token received: <span class="font-mono">${this.result.token}</span>`
|
|
269
|
+
: html`<p class="text-neutral-500">Mock accepts JSON and multipart for <code>/api/register</code>.</p>`}
|
|
270
|
+
</div>
|
|
271
|
+
`;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/** `method="get"` appends publisher fields as query string (mock echoes them). */
|
|
276
|
+
@customElement("docs-submit-get-demo")
|
|
277
|
+
export class DocsSubmitGetDemo extends LitElement {
|
|
278
|
+
static styles = [tailwind];
|
|
279
|
+
|
|
280
|
+
@subscribe(submitGetResultKey)
|
|
281
|
+
@state()
|
|
282
|
+
private result: RegisterResult | null = null;
|
|
283
|
+
|
|
284
|
+
render() {
|
|
285
|
+
return html`
|
|
286
|
+
<sonic-scope
|
|
287
|
+
serviceURL=${DOCS_MOCK_REQRES_SERVICE}
|
|
288
|
+
dataProvider=${registerEchoEndpoint.path}
|
|
289
|
+
formDataProvider=${submitGetFormKey.path}
|
|
290
|
+
submitResultDataProvider=${submitGetResultKey.path}
|
|
291
|
+
class="max-w-lg block"
|
|
292
|
+
>
|
|
293
|
+
<sonic-submit onClick method="get">
|
|
294
|
+
<div class="mb-4 grid grid-cols-2 gap-4">
|
|
295
|
+
<sonic-input name="email" type="email" value="demo@example.com"></sonic-input>
|
|
296
|
+
<sonic-input name="password" type="password" value="secret"></sonic-input>
|
|
297
|
+
</div>
|
|
298
|
+
<sonic-button type="neutral" class="w-full">GET with query string</sonic-button>
|
|
299
|
+
</sonic-submit>
|
|
300
|
+
</sonic-scope>
|
|
301
|
+
<div class="mt-3 space-y-1 text-sm">${resultLines(this.result)}</div>
|
|
302
|
+
`;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** `native` — sync publisher to a real <form> and trigger browser submit (iframe target). */
|
|
307
|
+
@customElement("docs-submit-native-demo")
|
|
308
|
+
export class DocsSubmitNativeDemo extends LitElement {
|
|
309
|
+
static styles = [tailwind];
|
|
310
|
+
|
|
311
|
+
private formAction = `${DOCS_MOCK_API_BASE}/api/register`;
|
|
312
|
+
|
|
313
|
+
render() {
|
|
314
|
+
return html`
|
|
315
|
+
<form
|
|
316
|
+
action=${this.formAction}
|
|
317
|
+
method="post"
|
|
318
|
+
target="docs-submit-native-frame"
|
|
319
|
+
class="max-w-lg"
|
|
320
|
+
>
|
|
321
|
+
<sonic-scope formDataProvider=${submitNativeFormKey.path}>
|
|
322
|
+
<sonic-submit native onClick>
|
|
323
|
+
<div class="mb-4 grid grid-cols-2 gap-4">
|
|
324
|
+
<sonic-input
|
|
325
|
+
required
|
|
326
|
+
name="email"
|
|
327
|
+
type="email"
|
|
328
|
+
value="eve.holt@reqres.in"
|
|
329
|
+
></sonic-input>
|
|
330
|
+
<sonic-input
|
|
331
|
+
required
|
|
332
|
+
type="password"
|
|
333
|
+
name="password"
|
|
334
|
+
value="pistol"
|
|
335
|
+
></sonic-input>
|
|
336
|
+
</div>
|
|
337
|
+
<sonic-button type="success" class="w-full"
|
|
338
|
+
>Native form POST</sonic-button
|
|
339
|
+
>
|
|
340
|
+
</sonic-submit>
|
|
341
|
+
</sonic-scope>
|
|
342
|
+
</form>
|
|
343
|
+
<p class="mt-2 text-sm text-neutral-500">
|
|
344
|
+
Response loads in the iframe below (full page navigation is avoided via
|
|
345
|
+
<code>target</code>).
|
|
346
|
+
</p>
|
|
347
|
+
<iframe
|
|
348
|
+
name="docs-submit-native-frame"
|
|
349
|
+
title="Native form response"
|
|
350
|
+
class="mt-2 h-24 w-full rounded border border-neutral-200 bg-neutral-50 text-xs"
|
|
351
|
+
></iframe>
|
|
352
|
+
`;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** Bubbles <code>submit</code> custom event with API result in <code>detail</code>. */
|
|
357
|
+
@customElement("docs-submit-event-demo")
|
|
358
|
+
export class DocsSubmitEventDemo extends LitElement {
|
|
359
|
+
static styles = [tailwind];
|
|
360
|
+
|
|
361
|
+
@state()
|
|
362
|
+
private lastEvent: string | null = null;
|
|
363
|
+
|
|
364
|
+
private onSubmit = (e: CustomEvent<RegisterResult>) => {
|
|
365
|
+
const d = e.detail;
|
|
366
|
+
this.lastEvent = d?.token
|
|
367
|
+
? `token=${d.token}`
|
|
368
|
+
: d?.messages?.[0]?.content ?? JSON.stringify(d);
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
render() {
|
|
372
|
+
return html`
|
|
373
|
+
<sonic-scope
|
|
374
|
+
serviceURL=${DOCS_MOCK_REQRES_SERVICE}
|
|
375
|
+
dataProvider="api/register"
|
|
376
|
+
formDataProvider="submit-event-form"
|
|
377
|
+
class="max-w-lg block"
|
|
378
|
+
>
|
|
379
|
+
<sonic-submit onClick @submit=${this.onSubmit}>
|
|
380
|
+
<div class="mb-4 grid grid-cols-2 gap-4">
|
|
381
|
+
<sonic-input
|
|
382
|
+
required
|
|
383
|
+
name="email"
|
|
384
|
+
type="email"
|
|
385
|
+
value="eve.holt@reqres.in"
|
|
386
|
+
></sonic-input>
|
|
387
|
+
<sonic-input
|
|
388
|
+
required
|
|
389
|
+
type="password"
|
|
390
|
+
name="password"
|
|
391
|
+
value="pistol"
|
|
392
|
+
></sonic-input>
|
|
393
|
+
</div>
|
|
394
|
+
<sonic-button type="primary" class="w-full">Submit (listen event)</sonic-button>
|
|
395
|
+
</sonic-submit>
|
|
396
|
+
</sonic-scope>
|
|
397
|
+
<p class="mt-3 text-sm">
|
|
398
|
+
${this.lastEvent
|
|
399
|
+
? html`Last <code>submit</code> event: <span class="font-mono">${this.lastEvent}</span>`
|
|
400
|
+
: html`<span class="text-neutral-500">Click submit — handler reads <code>event.detail</code>.</span>`}
|
|
401
|
+
</p>
|
|
402
|
+
`;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/** <code>endPoint</code> overrides <code>dataProvider</code> for the request path. */
|
|
407
|
+
@customElement("docs-submit-endpoint-demo")
|
|
408
|
+
export class DocsSubmitEndpointDemo extends LitElement {
|
|
409
|
+
static styles = [tailwind];
|
|
410
|
+
|
|
411
|
+
@subscribe(submitEndpointResultKey)
|
|
412
|
+
@state()
|
|
413
|
+
private result: RegisterResult | null = null;
|
|
414
|
+
|
|
415
|
+
render() {
|
|
416
|
+
return html`
|
|
417
|
+
<sonic-scope
|
|
418
|
+
serviceURL=${DOCS_MOCK_REQRES_SERVICE}
|
|
419
|
+
dataProvider=${usersListEndpoint.path}
|
|
420
|
+
formDataProvider=${submitEndpointFormKey.path}
|
|
421
|
+
submitResultDataProvider=${submitEndpointResultKey.path}
|
|
422
|
+
class="max-w-lg block"
|
|
423
|
+
>
|
|
424
|
+
<sonic-submit onClick endPoint=${registerEndpoint.path}>
|
|
425
|
+
<div class="mb-4 grid grid-cols-2 gap-4">
|
|
426
|
+
<sonic-input
|
|
427
|
+
required
|
|
428
|
+
name="email"
|
|
429
|
+
type="email"
|
|
430
|
+
value="eve.holt@reqres.in"
|
|
431
|
+
></sonic-input>
|
|
432
|
+
<sonic-input
|
|
433
|
+
required
|
|
434
|
+
type="password"
|
|
435
|
+
name="password"
|
|
436
|
+
value="pistol"
|
|
437
|
+
></sonic-input>
|
|
438
|
+
</div>
|
|
439
|
+
<sonic-button type="primary" class="w-full"
|
|
440
|
+
>POST via <code>endPoint</code></sonic-button
|
|
441
|
+
>
|
|
442
|
+
</sonic-submit>
|
|
443
|
+
</sonic-scope>
|
|
444
|
+
<div class="mt-3 text-sm">
|
|
445
|
+
${this.result?.token
|
|
446
|
+
? html`Registered (scope <code>dataProvider</code> is <code>api/users</code>, request went to <code>api/register</code>).`
|
|
447
|
+
: html`<p class="text-neutral-500">
|
|
448
|
+
<code>dataProvider=${usersListEndpoint.path}</code> but
|
|
449
|
+
<code>endPoint=${registerEndpoint.path}</code> on
|
|
450
|
+
<code>sonic-submit</code>.
|
|
451
|
+
</p>`}
|
|
452
|
+
</div>
|
|
453
|
+
`;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { html, LitElement } from "lit";
|
|
2
|
+
import { customElement, property, state } from "lit/decorators.js";
|
|
3
|
+
import { subscribe } from "@supersoniks/concorde/core/decorators/Subscriber";
|
|
4
|
+
import { tailwind } from "../tailwind";
|
|
5
|
+
import {
|
|
6
|
+
docsToggleLoaderFormKey,
|
|
7
|
+
docsToggleVisibilityKey,
|
|
8
|
+
} from "./docs-provider-keys";
|
|
9
|
+
|
|
10
|
+
import "../../core/components/functional/if/if";
|
|
11
|
+
import "../../core/components/ui/form/checkbox/checkbox";
|
|
12
|
+
import "../../core/components/ui/image/image";
|
|
13
|
+
import "../../core/components/ui/loader/loader";
|
|
14
|
+
|
|
15
|
+
const isChecked = (v: unknown) =>
|
|
16
|
+
v === true || v === "true" || v === 1 || v === "1";
|
|
17
|
+
|
|
18
|
+
@customElement("docs-toggle-if-demo")
|
|
19
|
+
export class DocsToggleIfDemo extends LitElement {
|
|
20
|
+
static styles = [tailwind];
|
|
21
|
+
|
|
22
|
+
@subscribe(docsToggleVisibilityKey.togglePlan)
|
|
23
|
+
@state()
|
|
24
|
+
togglePlan = "";
|
|
25
|
+
|
|
26
|
+
render() {
|
|
27
|
+
const show = isChecked(this.togglePlan);
|
|
28
|
+
return html`
|
|
29
|
+
<div formDataProvider=${docsToggleVisibilityKey.path}>
|
|
30
|
+
<sonic-checkbox
|
|
31
|
+
label="Show evacuation plan"
|
|
32
|
+
name="togglePlan"
|
|
33
|
+
unique
|
|
34
|
+
checked
|
|
35
|
+
value="true"
|
|
36
|
+
></sonic-checkbox>
|
|
37
|
+
<sonic-if .condition=${show} class="mt-4 block">
|
|
38
|
+
<sonic-image
|
|
39
|
+
src="https://www.thebaron.info/assets/mail/concorde-evacuation.jpg"
|
|
40
|
+
rounded="md"
|
|
41
|
+
ratio="654/463"
|
|
42
|
+
></sonic-image>
|
|
43
|
+
</sonic-if>
|
|
44
|
+
</div>
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@customElement("docs-toggle-loader-demo")
|
|
50
|
+
export class DocsToggleLoaderDemo extends LitElement {
|
|
51
|
+
static styles = [tailwind];
|
|
52
|
+
|
|
53
|
+
@subscribe(docsToggleLoaderFormKey.toggleLoader)
|
|
54
|
+
@state()
|
|
55
|
+
toggleLoader = "";
|
|
56
|
+
|
|
57
|
+
render() {
|
|
58
|
+
const show = isChecked(this.toggleLoader);
|
|
59
|
+
return html`
|
|
60
|
+
<div formDataProvider=${docsToggleLoaderFormKey.path}>
|
|
61
|
+
<sonic-checkbox
|
|
62
|
+
label="Show fixed loader"
|
|
63
|
+
name="toggleLoader"
|
|
64
|
+
unique
|
|
65
|
+
value="true"
|
|
66
|
+
></sonic-checkbox>
|
|
67
|
+
<sonic-if .condition=${show}>
|
|
68
|
+
<sonic-loader></sonic-loader>
|
|
69
|
+
</sonic-if>
|
|
70
|
+
</div>
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { html, LitElement } from "lit";
|
|
2
|
+
import { customElement } from "lit/decorators.js";
|
|
3
|
+
import { docsUserScopeAKey, docsUserScopeBKey } from "./docs-provider-keys";
|
|
4
|
+
import { tailwind } from "../tailwind";
|
|
5
|
+
import "./decorators-demo-init";
|
|
6
|
+
import "./users";
|
|
7
|
+
|
|
8
|
+
import "../../core/components/ui/divider/divider";
|
|
9
|
+
|
|
10
|
+
@customElement("docs-user-two-scopes")
|
|
11
|
+
export class DocsUserTwoScopes extends LitElement {
|
|
12
|
+
static styles = [tailwind];
|
|
13
|
+
|
|
14
|
+
render() {
|
|
15
|
+
return html`
|
|
16
|
+
<div class="grid md:grid-cols-2 gap-6">
|
|
17
|
+
<section>
|
|
18
|
+
<sonic-divider align="left">Scope A — docsUserScopeA</sonic-divider>
|
|
19
|
+
<div dataProvider="docsUserScopeA">
|
|
20
|
+
<docs-user></docs-user>
|
|
21
|
+
</div>
|
|
22
|
+
</section>
|
|
23
|
+
<section>
|
|
24
|
+
<sonic-divider align="left">Scope B — ${docsUserScopeBKey.path}</sonic-divider>
|
|
25
|
+
<div dataProvider=${docsUserScopeBKey.path}>
|
|
26
|
+
<docs-user></docs-user>
|
|
27
|
+
</div>
|
|
28
|
+
</section>
|
|
29
|
+
</div>
|
|
30
|
+
<p class="mt-4 text-sm text-neutral-500">
|
|
31
|
+
Same <code>docs-user</code> component: each instance reads the nearest
|
|
32
|
+
ancestor <code>dataProvider</code> via <code>@ancestorAttribute</code>
|
|
33
|
+
and <code>docsUserRowKey</code>.
|
|
34
|
+
</p>
|
|
35
|
+
`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { html, LitElement, nothing } from "lit";
|
|
2
|
+
import { customElement } from "lit/decorators.js";
|
|
3
|
+
import { tailwind } from "../tailwind";
|
|
4
|
+
import { Endpoint } from "@supersoniks/concorde/core/utils/endpoint";
|
|
5
|
+
import { DOCS_MOCK_REQRES_SERVICE } from "../mock-api/urls";
|
|
6
|
+
|
|
7
|
+
const usersListEndpoint = new Endpoint<unknown>("api/users");
|
|
8
|
+
import type { DocsUserData } from "./users";
|
|
9
|
+
import "../../core/components/functional/list/list";
|
|
10
|
+
import "../../core/components/ui/image/image";
|
|
11
|
+
import "../../core/components/ui/button/button";
|
|
12
|
+
import "../../core/components/ui/icon/icon";
|
|
13
|
+
import "../../core/components/ui/badge/badge";
|
|
14
|
+
|
|
15
|
+
@customElement("docs-users-list")
|
|
16
|
+
export class DocsUsersList extends LitElement {
|
|
17
|
+
static styles = [tailwind];
|
|
18
|
+
|
|
19
|
+
private items = ({ id, avatar, first_name, last_name, email }: DocsUserData) =>
|
|
20
|
+
html`<div
|
|
21
|
+
class="flex items-center gap-3 rounded-md hover:bg-neutral-50 -mx-2 p-2"
|
|
22
|
+
>
|
|
23
|
+
<sonic-image
|
|
24
|
+
src=${avatar}
|
|
25
|
+
rounded="md"
|
|
26
|
+
ratio="1/1"
|
|
27
|
+
class="w-16 block"
|
|
28
|
+
></sonic-image>
|
|
29
|
+
<div>
|
|
30
|
+
<div>
|
|
31
|
+
${first_name} <span class="font-bold">${last_name}</span>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="text-sm text-neutral-400">${email}</div>
|
|
34
|
+
</div>
|
|
35
|
+
<div class="ml-auto relative">
|
|
36
|
+
${id === "2" || id === "5"
|
|
37
|
+
? html`<sonic-badge
|
|
38
|
+
type="danger"
|
|
39
|
+
size="2xs"
|
|
40
|
+
class="absolute left-0 -top-1 z-10"
|
|
41
|
+
>${id}</sonic-badge
|
|
42
|
+
>`
|
|
43
|
+
: nothing}
|
|
44
|
+
<sonic-button
|
|
45
|
+
href=${email ? `mailto:${email}` : undefined}
|
|
46
|
+
size="sm"
|
|
47
|
+
variant="outline"
|
|
48
|
+
shape="circle"
|
|
49
|
+
class="relative"
|
|
50
|
+
icon
|
|
51
|
+
>
|
|
52
|
+
<sonic-icon library="iconoir" name="chat-bubble"></sonic-icon>
|
|
53
|
+
</sonic-button>
|
|
54
|
+
</div>
|
|
55
|
+
</div>`;
|
|
56
|
+
|
|
57
|
+
render() {
|
|
58
|
+
return html`
|
|
59
|
+
<div serviceURL=${DOCS_MOCK_REQRES_SERVICE}>
|
|
60
|
+
<sonic-list
|
|
61
|
+
fetch
|
|
62
|
+
dataProvider=${usersListEndpoint.path}
|
|
63
|
+
key="data"
|
|
64
|
+
class="grid grid-cols-1 gap-2"
|
|
65
|
+
.items=${this.items}
|
|
66
|
+
debug
|
|
67
|
+
></sonic-list>
|
|
68
|
+
</div>
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
71
|
+
}
|