@supersoniks/concorde 4.9.92 → 4.9.94
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/ai/cursor/rules/concorde.mdc +7 -0
- package/ai/jetbrains/rules/concorde.md +6 -0
- package/ai/skills/concorde/SKILL.md +48 -0
- package/build-infos.json +1 -1
- package/concorde-core.bundle.js +299 -292
- package/concorde-core.es.js +10139 -6035
- package/dist/concorde-core.bundle.js +299 -292
- package/dist/concorde-core.es.js +10139 -6035
- package/dist/docs-mock-api-sw.js +110 -0
- package/dist/docs-mock-api-sw.js.map +3 -3
- package/dist/js/core/components/functional/functional.js +1 -0
- package/dist/js/core/components/functional/functional.js.map +1 -1
- package/dist/js/core/components/functional/jsonata/jsonata.js +119 -0
- package/dist/js/core/components/functional/jsonata/jsonata.js.map +1 -0
- package/dist/js/core/components/ui/button/button.js +1 -1
- package/dist/js/core/components/ui/button/button.js.map +1 -1
- package/dist/js/core/decorators/Subscriber.js +1 -0
- package/dist/js/core/decorators/Subscriber.js.map +1 -1
- package/dist/js/core/decorators/api.js +108 -16
- package/dist/js/core/decorators/api.js.map +1 -1
- package/dist/js/core/decorators/subscriber/derive.js +60 -0
- package/dist/js/core/decorators/subscriber/derive.js.map +1 -0
- package/dist/js/core/utils/api.js +29 -8
- package/dist/js/core/utils/api.js.map +1 -1
- package/dist/js/core/utils/derive.js +246 -0
- package/dist/js/core/utils/derive.js.map +1 -0
- package/dist/js/core/utils/jsonataHelpers.js +69 -0
- package/dist/js/core/utils/jsonataHelpers.js.map +1 -0
- package/dist/js/core/utils/jsonataRuntime.js +75 -0
- package/dist/js/core/utils/jsonataRuntime.js.map +1 -0
- package/dist/js/utils.js +2 -0
- package/dist/js/utils.js.map +1 -1
- package/dist/types/core/components/functional/functional.d.ts +1 -0
- package/dist/types/core/components/functional/functional.d.ts.map +1 -1
- package/dist/types/core/components/functional/jsonata/jsonata.d.ts +29 -0
- package/dist/types/core/components/functional/jsonata/jsonata.d.ts.map +1 -0
- package/dist/types/core/components/ui/button/button.d.ts +1 -1
- package/dist/types/core/components/ui/button/button.d.ts.map +1 -1
- package/dist/types/core/components/ui/form/checkbox/checkbox.d.ts +3 -3
- package/dist/types/core/components/ui/form/input/input.d.ts +3 -3
- package/dist/types/core/components/ui/form/input-autocomplete/input-autocomplete.d.ts +3 -3
- package/dist/types/core/components/ui/form/textarea/textarea.d.ts +3 -3
- package/dist/types/core/decorators/Subscriber.d.ts +2 -0
- package/dist/types/core/decorators/Subscriber.d.ts.map +1 -1
- package/dist/types/core/decorators/api.d.ts +21 -12
- package/dist/types/core/decorators/api.d.ts.map +1 -1
- package/dist/types/core/decorators/subscriber/derive.d.ts +30 -0
- package/dist/types/core/decorators/subscriber/derive.d.ts.map +1 -0
- package/dist/types/core/utils/api.d.ts +1 -1
- package/dist/types/core/utils/api.d.ts.map +1 -1
- package/dist/types/core/utils/derive.d.ts +40 -0
- package/dist/types/core/utils/derive.d.ts.map +1 -0
- package/dist/types/core/utils/jsonataHelpers.d.ts +15 -0
- package/dist/types/core/utils/jsonataHelpers.d.ts.map +1 -0
- package/dist/types/core/utils/jsonataRuntime.d.ts +13 -0
- package/dist/types/core/utils/jsonataRuntime.d.ts.map +1 -0
- package/dist/types/mixins.d.ts +3 -3
- package/dist/types/utils.d.ts +2 -0
- package/dist/types/utils.d.ts.map +1 -1
- package/docs/assets/{index-DURr6O71.js → index-DpIkksht.js} +652 -479
- package/docs/crawl/docs/_decorators/get.html +27 -6
- package/docs/crawl/docs/_decorators/patch.html +6 -0
- package/docs/crawl/docs/_decorators/post.html +8 -0
- package/docs/crawl/docs/_decorators/put.html +6 -0
- package/docs/crawl/hubs/decorators.html +36 -31
- package/docs/crawl/hubs/remote-data.html +36 -31
- package/docs/index.html +1 -1
- package/docs/llms-full.txt +47 -3
- package/docs/src/docs/_decorators/get.md +31 -0
- package/docs/src/docs/_decorators/patch.md +9 -0
- package/docs/src/docs/_decorators/post.md +11 -0
- package/docs/src/docs/_decorators/put.md +9 -0
- package/docs/src/docs/search/docs-search.json +120 -5
- package/docs/src/tsconfig.json +268 -268
- package/package.json +28 -3
- package/public/docs-mock-api-sw.js +110 -0
- package/public/docs-mock-api-sw.js.map +3 -3
- package/src/core/components/functional/functional.ts +1 -0
- package/src/core/components/functional/jsonata/jsonata.md +56 -0
- package/src/core/components/functional/jsonata/jsonata.spec.ts +202 -0
- package/src/core/components/functional/jsonata/jsonata.ts +116 -0
- package/src/core/components/ui/button/button.ts +2 -2
- package/src/core/decorators/Subscriber.ts +2 -0
- package/src/core/decorators/api.post.spec.ts +99 -4
- package/src/core/decorators/api.spec.ts +90 -0
- package/src/core/decorators/api.ts +212 -92
- package/src/core/decorators/subscriber/derive.ts +95 -0
- package/src/core/utils/api.spec.ts +73 -0
- package/src/core/utils/api.ts +44 -11
- package/src/core/utils/derive.spec.ts +190 -0
- package/src/core/utils/derive.ts +357 -0
- package/src/core/utils/jsonataHelpers.ts +100 -0
- package/src/core/utils/jsonataRuntime.ts +88 -0
- package/src/docs/_core-concept/dataFlow.md +9 -0
- package/src/docs/_decorators/get.md +31 -0
- package/src/docs/_decorators/patch.md +9 -0
- package/src/docs/_decorators/post.md +11 -0
- package/src/docs/_decorators/put.md +9 -0
- package/src/docs/_misc/docs-mock-api.md +3 -0
- package/src/docs/components/docs-demo-sources.ts +40 -0
- package/src/docs/docs.ts +1 -0
- package/src/docs/example/decorators-demo-post.ts +70 -0
- package/src/docs/example/decorators-demo-subscribe-publish-get-demos.ts +59 -0
- package/src/docs/example/docs-jsonata-demos.ts +128 -0
- package/src/docs/mock-api/fixtures-jsonata.ts +131 -0
- package/src/docs/mock-api/router.ts +26 -0
- package/src/docs/navigation/navigation.ts +4 -0
- package/src/docs/search/docs-search.json +300 -5
- package/src/tsconfig.json +18 -0
- package/src/tsconfig.tsbuildinfo +1 -1
- package/src/utils.ts +13 -0
|
@@ -81,6 +81,24 @@ export const DOCS_LIT_DEMO_REGISTRY: Record<string, DocsLitDemoConfig> = {
|
|
|
81
81
|
{ path: "src/docs/example/docs-users-list.ts", line: 15, label: "docs-users-list" },
|
|
82
82
|
],
|
|
83
83
|
},
|
|
84
|
+
"docs-jsonata-space-cats-demo": {
|
|
85
|
+
sources: [
|
|
86
|
+
{
|
|
87
|
+
path: "src/docs/example/docs-jsonata-demos.ts",
|
|
88
|
+
line: 26,
|
|
89
|
+
label: "top-n",
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
"docs-jsonata-table-totals-demo": {
|
|
94
|
+
sources: [
|
|
95
|
+
{
|
|
96
|
+
path: "src/docs/example/docs-jsonata-demos.ts",
|
|
97
|
+
line: 69,
|
|
98
|
+
label: "totals",
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
},
|
|
84
102
|
"docs-list-alternate-demo": {
|
|
85
103
|
sources: [
|
|
86
104
|
{ path: "src/docs/example/docs-list-demos.ts", line: 51, label: "alternate" },
|
|
@@ -204,6 +222,14 @@ export const DOCS_DEMO_SOURCE_REGISTRY: Record<string, DocsSource[]> = {
|
|
|
204
222
|
"docs-joke-search-demo": [
|
|
205
223
|
{ path: "src/docs/example/docs-joke-demos.ts", label: "joke demos" },
|
|
206
224
|
],
|
|
225
|
+
"docs-jsonata-space-cats-demo": [
|
|
226
|
+
{ path: "src/docs/example/docs-jsonata-demos.ts", label: "jsonata demos" },
|
|
227
|
+
{ path: "src/docs/mock-api/fixtures-jsonata.ts", label: "fixtures" },
|
|
228
|
+
],
|
|
229
|
+
"docs-jsonata-table-totals-demo": [
|
|
230
|
+
{ path: "src/docs/example/docs-jsonata-demos.ts", label: "jsonata demos" },
|
|
231
|
+
{ path: "src/docs/mock-api/fixtures-jsonata.ts", label: "fixtures" },
|
|
232
|
+
],
|
|
207
233
|
"docs-joke-lang-demo": [
|
|
208
234
|
{ path: "src/docs/example/docs-joke-demos.ts", label: "joke demos" },
|
|
209
235
|
],
|
|
@@ -252,6 +278,13 @@ export const DOCS_DEMO_SOURCE_REGISTRY: Record<string, DocsSource[]> = {
|
|
|
252
278
|
{ path: "src/docs/example/decorators-demo-geo.ts", label: "geo API" },
|
|
253
279
|
{ path: "src/docs/mock-api/router.ts", label: "mock router" },
|
|
254
280
|
],
|
|
281
|
+
"demo-api-get-method": [
|
|
282
|
+
{
|
|
283
|
+
path: "src/docs/example/decorators-demo-subscribe-publish-get-demos.ts",
|
|
284
|
+
label: "demo-api-get-method",
|
|
285
|
+
},
|
|
286
|
+
{ path: "src/docs/example/decorators-demo-geo.ts", label: "geo API" },
|
|
287
|
+
],
|
|
255
288
|
"demo-api-get-configuration-key": [
|
|
256
289
|
{
|
|
257
290
|
path: "src/docs/example/decorators-demo-subscribe-publish-get-demos.ts",
|
|
@@ -276,6 +309,13 @@ export const DOCS_DEMO_SOURCE_REGISTRY: Record<string, DocsSource[]> = {
|
|
|
276
309
|
},
|
|
277
310
|
{ path: "src/docs/mock-api/router.ts", label: "mock router" },
|
|
278
311
|
],
|
|
312
|
+
"demo-api-post-method": [
|
|
313
|
+
{
|
|
314
|
+
path: "src/docs/example/decorators-demo-post.ts",
|
|
315
|
+
label: "demo-api-post-method",
|
|
316
|
+
},
|
|
317
|
+
{ path: "src/docs/mock-api/router.ts", label: "mock router" },
|
|
318
|
+
],
|
|
279
319
|
"demo-api-post-dynamic": [
|
|
280
320
|
{
|
|
281
321
|
path: "src/docs/example/decorators-demo-post.ts",
|
package/src/docs/docs.ts
CHANGED
|
@@ -15,6 +15,7 @@ import "./example/docs-joke-demos";
|
|
|
15
15
|
import "./example/docs-queue-demos";
|
|
16
16
|
import "./example/docs-toggle-demos";
|
|
17
17
|
import "./example/docs-list-demos";
|
|
18
|
+
import "./example/docs-jsonata-demos";
|
|
18
19
|
import "./example/docs-router-demos";
|
|
19
20
|
import "./example/docs-submit-demos";
|
|
20
21
|
import "./example/docs-api-config-demos";
|
|
@@ -65,6 +65,12 @@ export const docsDemoPostPublishRequestKey = new DataProviderKey<RegisterRequest
|
|
|
65
65
|
export const docsDemoPostTriggerKey = new DataProviderKey<number>(
|
|
66
66
|
"docsDemoPostTrigger",
|
|
67
67
|
);
|
|
68
|
+
export const docsDemoPostMethodRequestKey = new DataProviderKey<RegisterRequest>(
|
|
69
|
+
"docsDemoPostMethodRequest",
|
|
70
|
+
);
|
|
71
|
+
export const docsDemoPostMethodTriggerKey = new DataProviderKey<number>(
|
|
72
|
+
"docsDemoPostMethodTrigger",
|
|
73
|
+
);
|
|
68
74
|
export const docsDemoPostDynamicRequestKey = new DataProviderKey<SessionSyncRequest>(
|
|
69
75
|
"docsDemoPostDynamicRequest",
|
|
70
76
|
);
|
|
@@ -140,6 +146,70 @@ export class DemoApiPost extends LitElement {
|
|
|
140
146
|
}
|
|
141
147
|
}
|
|
142
148
|
|
|
149
|
+
@customElement("demo-api-post-method")
|
|
150
|
+
export class DemoApiPostMethod extends LitElement {
|
|
151
|
+
static styles = [tailwind];
|
|
152
|
+
|
|
153
|
+
@state()
|
|
154
|
+
private payload?: ApiResult<RegisterResult>;
|
|
155
|
+
|
|
156
|
+
connectedCallback() {
|
|
157
|
+
super.connectedCallback();
|
|
158
|
+
set(docsDemoPostMethodRequestKey, {
|
|
159
|
+
email: "method@concorde.local",
|
|
160
|
+
password: "method-password",
|
|
161
|
+
});
|
|
162
|
+
set(docsDemoPostMethodTriggerKey, 0);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@post(
|
|
166
|
+
registerPostEndpoint,
|
|
167
|
+
docsDemoPostMethodRequestKey,
|
|
168
|
+
docsDemoReqresApiConfigurationKey,
|
|
169
|
+
{ triggerKey: docsDemoPostMethodTriggerKey },
|
|
170
|
+
)
|
|
171
|
+
handlePayload(payload?: ApiResult<RegisterResult>) {
|
|
172
|
+
this.payload = payload;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private updateBody() {
|
|
176
|
+
set(docsDemoPostMethodRequestKey, {
|
|
177
|
+
email: `method-${Date.now()}@concorde.local`,
|
|
178
|
+
password: "method-password",
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private resend() {
|
|
183
|
+
dp(docsDemoPostMethodTriggerKey).invalidate();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
render() {
|
|
187
|
+
const result = this.payload?.result;
|
|
188
|
+
return html`
|
|
189
|
+
<div class="space-y-3">
|
|
190
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
191
|
+
<span class="text-sm font-medium">✉️ POST function mode</span>
|
|
192
|
+
<sonic-button size="sm" @click=${this.updateBody}>
|
|
193
|
+
Update body & POST
|
|
194
|
+
</sonic-button>
|
|
195
|
+
<sonic-button size="sm" variant="secondary" @click=${this.resend}>
|
|
196
|
+
Invalidate trigger
|
|
197
|
+
</sonic-button>
|
|
198
|
+
</div>
|
|
199
|
+
<p class="text-sm text-neutral-600 dark:text-neutral-400">
|
|
200
|
+
The <code>@post</code> decorator calls
|
|
201
|
+
<code>handlePayload</code> with the complete API payload.
|
|
202
|
+
</p>
|
|
203
|
+
<p class="text-xs text-neutral-500">
|
|
204
|
+
HTTP status:
|
|
205
|
+
<strong>${this.payload?.response?.status ?? "loading…"}</strong>
|
|
206
|
+
· email: <strong>${result?.email ?? "—"}</strong>
|
|
207
|
+
</p>
|
|
208
|
+
</div>
|
|
209
|
+
`;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
143
213
|
@customElement("demo-api-post-dynamic")
|
|
144
214
|
export class DemoApiPostDynamic extends LitElement {
|
|
145
215
|
static styles = [tailwind];
|
|
@@ -5,6 +5,7 @@ import type { ApiResult } from "@supersoniks/concorde/core/utils/api";
|
|
|
5
5
|
import { DataProviderKey } from "@supersoniks/concorde/core/utils/dataProviderKey";
|
|
6
6
|
import { sub } from "@supersoniks/concorde/directives";
|
|
7
7
|
import {
|
|
8
|
+
dp,
|
|
8
9
|
get as storeGet,
|
|
9
10
|
set,
|
|
10
11
|
} from "@supersoniks/concorde/core/utils/PublisherProxy";
|
|
@@ -28,6 +29,9 @@ const geoCommunesGet = get(
|
|
|
28
29
|
geoCommunesApiGetEndpoint,
|
|
29
30
|
docsDemoGeoApiConfigurationKey,
|
|
30
31
|
);
|
|
32
|
+
const geoCommunesMethodTriggerKey = new DataProviderKey<number>(
|
|
33
|
+
"docsDemoGeoCommunesMethodTrigger",
|
|
34
|
+
);
|
|
31
35
|
|
|
32
36
|
@customElement("demo-publish")
|
|
33
37
|
export class DemoPublish extends LitElement {
|
|
@@ -124,6 +128,61 @@ export class DemoApiGet extends LitElement {
|
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
130
|
|
|
131
|
+
@customElement("demo-api-get-method")
|
|
132
|
+
export class DemoApiGetMethod extends LitElement {
|
|
133
|
+
static styles = [tailwind];
|
|
134
|
+
|
|
135
|
+
@state()
|
|
136
|
+
private payload?: ApiResult<GeoCommuneRow[]>;
|
|
137
|
+
|
|
138
|
+
connectedCallback() {
|
|
139
|
+
super.connectedCallback();
|
|
140
|
+
set(geoCommunesMethodTriggerKey, 0);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@get(geoCommunesApiGetEndpoint, docsDemoGeoApiConfigurationKey, {
|
|
144
|
+
triggerKey: geoCommunesMethodTriggerKey,
|
|
145
|
+
})
|
|
146
|
+
handlePayload(payload?: ApiResult<GeoCommuneRow[]>) {
|
|
147
|
+
this.payload = payload;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private refresh() {
|
|
151
|
+
dp(geoCommunesMethodTriggerKey).invalidate();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
render() {
|
|
155
|
+
const rows = this.payload?.result ?? [];
|
|
156
|
+
return html`
|
|
157
|
+
<div class="space-y-3">
|
|
158
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
159
|
+
<span class="text-sm font-medium">🗺️ GET function mode</span>
|
|
160
|
+
<sonic-button size="sm" @click=${this.refresh}>
|
|
161
|
+
Invalidate trigger
|
|
162
|
+
</sonic-button>
|
|
163
|
+
</div>
|
|
164
|
+
<p class="text-sm text-neutral-600 dark:text-neutral-400">
|
|
165
|
+
The <code>@get</code> decorator calls <code>handlePayload</code> with
|
|
166
|
+
the complete API payload.
|
|
167
|
+
</p>
|
|
168
|
+
<p class="text-xs text-neutral-500">
|
|
169
|
+
HTTP status:
|
|
170
|
+
<strong>${this.payload?.response?.status ?? "loading…"}</strong>
|
|
171
|
+
</p>
|
|
172
|
+
<ul class="grid gap-1 sm:grid-cols-2">
|
|
173
|
+
${rows.slice(0, 6).map(
|
|
174
|
+
(commune) =>
|
|
175
|
+
html`<li class="text-sm">
|
|
176
|
+
${commune.nom}
|
|
177
|
+
<span class="text-neutral-500">(${commune.code})</span>
|
|
178
|
+
</li>`,
|
|
179
|
+
)}
|
|
180
|
+
</ul>
|
|
181
|
+
</div>
|
|
182
|
+
`;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
127
186
|
@customElement("demo-api-get-configuration-key")
|
|
128
187
|
export class DemoApiGetConfigurationKey extends LitElement {
|
|
129
188
|
static styles = [tailwind];
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { html, LitElement } from "lit";
|
|
2
|
+
import { customElement } from "lit/decorators.js";
|
|
3
|
+
import { tailwind } from "../tailwind";
|
|
4
|
+
import { DOCS_MOCK_API_BASE } from "../mock-api/urls";
|
|
5
|
+
import { Endpoint } from "@supersoniks/concorde/core/utils/endpoint";
|
|
6
|
+
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
7
|
+
import { set } from "@supersoniks/concorde/utils";
|
|
8
|
+
|
|
9
|
+
import "../../core/components/functional/fetch/fetch";
|
|
10
|
+
import "../../core/components/functional/jsonata/jsonata";
|
|
11
|
+
import "../../core/components/functional/list/list";
|
|
12
|
+
import "../../core/components/functional/value/value";
|
|
13
|
+
import "../../core/components/ui/form/input/input";
|
|
14
|
+
|
|
15
|
+
const missions = new Endpoint<unknown>("api/space-cats");
|
|
16
|
+
const topForm = new DataProviderKey<{ top: number | string }>(
|
|
17
|
+
"jsonataTopForm",
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const order = new Endpoint<unknown>("api/market-order");
|
|
21
|
+
const taxForm = new DataProviderKey<{ taxPercent: number | string }>(
|
|
22
|
+
"jsonataTaxForm",
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
/** Cas 1 — groupby + top N (recalcul via form, sans refetch). */
|
|
26
|
+
@customElement("docs-jsonata-space-cats-demo")
|
|
27
|
+
export class DocsJsonataSpaceCatsDemo extends LitElement {
|
|
28
|
+
static styles = [tailwind];
|
|
29
|
+
|
|
30
|
+
connectedCallback(): void {
|
|
31
|
+
super.connectedCallback();
|
|
32
|
+
set(topForm, { top: 3 });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
render() {
|
|
36
|
+
return html`
|
|
37
|
+
<div serviceURL=${DOCS_MOCK_API_BASE} class="flex flex-col gap-3">
|
|
38
|
+
<div formDataProvider=${topForm.path} class="max-w-xs">
|
|
39
|
+
<sonic-input name="top" type="number" label="Top N" value="3"></sonic-input>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<sonic-fetch
|
|
43
|
+
dataProvider=${missions.path}
|
|
44
|
+
endPoint=${missions.path}
|
|
45
|
+
key="data"
|
|
46
|
+
></sonic-fetch>
|
|
47
|
+
|
|
48
|
+
<sonic-jsonata
|
|
49
|
+
inputProvider=${missions.path}
|
|
50
|
+
outputProvider="spaceCatLeaderboard"
|
|
51
|
+
formDataProvider=${topForm.path}
|
|
52
|
+
expression='$input{name: $sum(points)} ~> $each(function($v,$k){{"name":$k,"points":$v}}) ^(>points)[[0..$number($top)-1]]'
|
|
53
|
+
></sonic-jsonata>
|
|
54
|
+
|
|
55
|
+
<sonic-list
|
|
56
|
+
dataProvider="spaceCatLeaderboard"
|
|
57
|
+
class="flex flex-col gap-1"
|
|
58
|
+
.items=${({ name, points }: { name: string; points: number }) =>
|
|
59
|
+
html`<div class="flex gap-3 text-sm">
|
|
60
|
+
<span class="font-medium">${name}</span>
|
|
61
|
+
<span class="ml-auto tabular-nums text-neutral-500">${points}</span>
|
|
62
|
+
</div>`}
|
|
63
|
+
></sonic-list>
|
|
64
|
+
</div>
|
|
65
|
+
`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Cas 2 — totaux d’un tableau (somme + taxe via form). */
|
|
70
|
+
@customElement("docs-jsonata-table-totals-demo")
|
|
71
|
+
export class DocsJsonataTableTotalsDemo extends LitElement {
|
|
72
|
+
static styles = [tailwind];
|
|
73
|
+
|
|
74
|
+
connectedCallback(): void {
|
|
75
|
+
super.connectedCallback();
|
|
76
|
+
set(taxForm, { taxPercent: 10 });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
render() {
|
|
80
|
+
return html`
|
|
81
|
+
<div serviceURL=${DOCS_MOCK_API_BASE} class="flex flex-col gap-3">
|
|
82
|
+
<div formDataProvider=${taxForm.path} class="max-w-xs">
|
|
83
|
+
<sonic-input
|
|
84
|
+
name="taxPercent"
|
|
85
|
+
type="number"
|
|
86
|
+
label="Tax %"
|
|
87
|
+
value="10"
|
|
88
|
+
></sonic-input>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<sonic-fetch
|
|
92
|
+
dataProvider=${order.path}
|
|
93
|
+
endPoint=${order.path}
|
|
94
|
+
key="data"
|
|
95
|
+
></sonic-fetch>
|
|
96
|
+
|
|
97
|
+
<sonic-jsonata
|
|
98
|
+
inputProvider=${order.path}
|
|
99
|
+
outputProvider="marketOrderTotals"
|
|
100
|
+
formDataProvider=${taxForm.path}
|
|
101
|
+
expression='(
|
|
102
|
+
$sub := $sum($input.(qty * unitPrice));
|
|
103
|
+
{
|
|
104
|
+
"subtotal": $round($sub, 2),
|
|
105
|
+
"tax": $round($sub * $number($taxPercent) / 100, 2),
|
|
106
|
+
"grandTotal": $round($sub * (1 + $number($taxPercent) / 100), 2)
|
|
107
|
+
}
|
|
108
|
+
)'
|
|
109
|
+
></sonic-jsonata>
|
|
110
|
+
|
|
111
|
+
<div dataProvider="marketOrderTotals" class="flex gap-6 text-sm">
|
|
112
|
+
<div>
|
|
113
|
+
<div class="text-neutral-400">Subtotal</div>
|
|
114
|
+
<sonic-value key="subtotal"></sonic-value>
|
|
115
|
+
</div>
|
|
116
|
+
<div>
|
|
117
|
+
<div class="text-neutral-400">Tax</div>
|
|
118
|
+
<sonic-value key="tax"></sonic-value>
|
|
119
|
+
</div>
|
|
120
|
+
<div>
|
|
121
|
+
<div class="text-neutral-400">Total</div>
|
|
122
|
+
<span class="font-semibold"><sonic-value key="grandTotal"></sonic-value></span>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
`;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixtures fun pour démos / tests sonic-jsonata (hors billetterie).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const avatar = (seed: string) =>
|
|
6
|
+
`https://i.pravatar.cc/150?u=${encodeURIComponent(seed)}`;
|
|
7
|
+
|
|
8
|
+
/** Missions de chats spatiaux — groupby name + top N points. */
|
|
9
|
+
export type SpaceCatMission = {
|
|
10
|
+
id: number;
|
|
11
|
+
name: string;
|
|
12
|
+
planet: string;
|
|
13
|
+
mission: string;
|
|
14
|
+
points: number;
|
|
15
|
+
avatar: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const DOCS_SPACE_CAT_MISSIONS: SpaceCatMission[] = [
|
|
19
|
+
{
|
|
20
|
+
id: 1,
|
|
21
|
+
name: "Captain Whiskers",
|
|
22
|
+
planet: "Mars",
|
|
23
|
+
mission: "Laser hunt",
|
|
24
|
+
points: 40,
|
|
25
|
+
avatar: avatar("captain-whiskers"),
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: 2,
|
|
29
|
+
name: "Captain Whiskers",
|
|
30
|
+
planet: "Mars",
|
|
31
|
+
mission: "Dust nap",
|
|
32
|
+
points: 25,
|
|
33
|
+
avatar: avatar("captain-whiskers"),
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 3,
|
|
37
|
+
name: "Nebula Paws",
|
|
38
|
+
planet: "Europa",
|
|
39
|
+
mission: "Ice fishing",
|
|
40
|
+
points: 55,
|
|
41
|
+
avatar: avatar("nebula-paws"),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: 4,
|
|
45
|
+
name: "Astro Mittens",
|
|
46
|
+
planet: "Titan",
|
|
47
|
+
mission: "Methane surf",
|
|
48
|
+
points: 33,
|
|
49
|
+
avatar: avatar("astro-mittens"),
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: 5,
|
|
53
|
+
name: "Nebula Paws",
|
|
54
|
+
planet: "Europa",
|
|
55
|
+
mission: "Comet chase",
|
|
56
|
+
points: 20,
|
|
57
|
+
avatar: avatar("nebula-paws"),
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: 6,
|
|
61
|
+
name: "Professor Meowington",
|
|
62
|
+
planet: "Venus",
|
|
63
|
+
mission: "Cloud tasting",
|
|
64
|
+
points: 48,
|
|
65
|
+
avatar: avatar("prof-meowington"),
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: 7,
|
|
69
|
+
name: "Astro Mittens",
|
|
70
|
+
planet: "Titan",
|
|
71
|
+
mission: "Antenna polish",
|
|
72
|
+
points: 12,
|
|
73
|
+
avatar: avatar("astro-mittens"),
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: 8,
|
|
77
|
+
name: "Zero-G Socks",
|
|
78
|
+
planet: "Moon",
|
|
79
|
+
mission: "Flag knitting",
|
|
80
|
+
points: 61,
|
|
81
|
+
avatar: avatar("zero-g-socks"),
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
/** Sacs de café — groupby origin + filtre roast. */
|
|
86
|
+
export type CoffeeBag = {
|
|
87
|
+
id: number;
|
|
88
|
+
origin: string;
|
|
89
|
+
roast: "light" | "medium" | "dark";
|
|
90
|
+
kg: number;
|
|
91
|
+
farm: string;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const DOCS_COFFEE_BAGS: CoffeeBag[] = [
|
|
95
|
+
{ id: 1, origin: "Ethiopia", roast: "light", kg: 12, farm: "Yirgacheffe Hills" },
|
|
96
|
+
{ id: 2, origin: "Ethiopia", roast: "medium", kg: 8, farm: "Sidamo Ridge" },
|
|
97
|
+
{ id: 3, origin: "Colombia", roast: "medium", kg: 15, farm: "Huila Valley" },
|
|
98
|
+
{ id: 4, origin: "Colombia", roast: "dark", kg: 6, farm: "Cauca Peak" },
|
|
99
|
+
{ id: 5, origin: "Brazil", roast: "dark", kg: 22, farm: "Minas Gerais" },
|
|
100
|
+
{ id: 6, origin: "Brazil", roast: "medium", kg: 10, farm: "Cerrado" },
|
|
101
|
+
{ id: 7, origin: "Guatemala", roast: "light", kg: 9, farm: "Antigua" },
|
|
102
|
+
{ id: 8, origin: "Guatemala", roast: "dark", kg: 5, farm: "Huehuetenango" },
|
|
103
|
+
{ id: 9, origin: "Ethiopia", roast: "light", kg: 4, farm: "Guji Forest" },
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
export function filterCoffeeBags(
|
|
107
|
+
bags: CoffeeBag[],
|
|
108
|
+
roast: string | null | undefined,
|
|
109
|
+
): CoffeeBag[] {
|
|
110
|
+
const r = roast?.trim().toLowerCase();
|
|
111
|
+
if (!r || r === "all") return bags;
|
|
112
|
+
return bags.filter((b) => b.roast === r);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Lignes de commande (table) — total / moyenne par ligne. */
|
|
116
|
+
export type MarketOrderLine = {
|
|
117
|
+
id: number;
|
|
118
|
+
name: string;
|
|
119
|
+
qty: number;
|
|
120
|
+
unitPrice: number;
|
|
121
|
+
category: string;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export const DOCS_MARKET_ORDER_LINES: MarketOrderLine[] = [
|
|
125
|
+
{ id: 1, name: "Heirloom tomatoes", qty: 4, unitPrice: 3.5, category: "veg" },
|
|
126
|
+
{ id: 2, name: "Sourdough loaf", qty: 2, unitPrice: 6.0, category: "bakery" },
|
|
127
|
+
{ id: 3, name: "Goat cheese", qty: 1, unitPrice: 8.5, category: "dairy" },
|
|
128
|
+
{ id: 4, name: "Honey jar", qty: 3, unitPrice: 5.2, category: "pantry" },
|
|
129
|
+
{ id: 5, name: "Sunflowers", qty: 5, unitPrice: 2.0, category: "flowers" },
|
|
130
|
+
{ id: 6, name: "Free-range eggs", qty: 2, unitPrice: 4.8, category: "dairy" },
|
|
131
|
+
];
|
|
@@ -8,6 +8,12 @@ import {
|
|
|
8
8
|
type ReqresUserResponse,
|
|
9
9
|
type ReqresUsersListResponse,
|
|
10
10
|
} from "./fixtures";
|
|
11
|
+
import {
|
|
12
|
+
DOCS_COFFEE_BAGS,
|
|
13
|
+
DOCS_MARKET_ORDER_LINES,
|
|
14
|
+
DOCS_SPACE_CAT_MISSIONS,
|
|
15
|
+
filterCoffeeBags,
|
|
16
|
+
} from "./fixtures-jsonata";
|
|
11
17
|
|
|
12
18
|
export const DOCS_MOCK_API_PREFIX = "/docs-mock-api";
|
|
13
19
|
|
|
@@ -241,6 +247,26 @@ export async function handleDocsMockApiRequest(
|
|
|
241
247
|
return json(paginateUsers(url));
|
|
242
248
|
}
|
|
243
249
|
|
|
250
|
+
if (subPath === "/api/space-cats") {
|
|
251
|
+
return json({
|
|
252
|
+
data: DOCS_SPACE_CAT_MISSIONS,
|
|
253
|
+
total: DOCS_SPACE_CAT_MISSIONS.length,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (subPath === "/api/coffee-bags") {
|
|
258
|
+
const roast = url.searchParams.get("roast");
|
|
259
|
+
const data = filterCoffeeBags(DOCS_COFFEE_BAGS, roast);
|
|
260
|
+
return json({ data, total: data.length });
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (subPath === "/api/market-order") {
|
|
264
|
+
return json({
|
|
265
|
+
data: DOCS_MARKET_ORDER_LINES,
|
|
266
|
+
total: DOCS_MARKET_ORDER_LINES.length,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
244
270
|
if (subPath === "/geo/communes" || subPath.startsWith("/geo/communes")) {
|
|
245
271
|
return json(geoCommunes(url), {
|
|
246
272
|
headers: { "X-Fetched-At": new Date().toISOString() },
|
|
@@ -40,6 +40,10 @@ export class DocsNavigation extends LitElement {
|
|
|
40
40
|
{ label: "If", href: "#core/components/functional/if/if.md/if" },
|
|
41
41
|
{ label: "List", href: "#core/components/functional/list/list.md/list" },
|
|
42
42
|
{ label: "Mix", href: "#core/components/functional/mix/mix.md/mix" },
|
|
43
|
+
{
|
|
44
|
+
label: "Jsonata",
|
|
45
|
+
href: "#core/components/functional/jsonata/jsonata.md/jsonata",
|
|
46
|
+
},
|
|
43
47
|
{
|
|
44
48
|
label: "Queue",
|
|
45
49
|
href: "#core/components/functional/queue/queue.md/queue",
|