@supersoniks/concorde 4.6.0 → 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 +127 -127
- package/concorde-core.es.js +1435 -1364
- package/dist/altcha-widget.js +2662 -0
- package/dist/concorde-core.bundle.js +127 -127
- package/dist/concorde-core.es.js +1435 -1364
- 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/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/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
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
# @subscribe
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Keeps a **Lit property** in sync with a **read-only** slice of the DataProvider store. You pass a [`DataProviderKey`](#docs/_misc/dataProviderKey.md/dataProviderKey); when that path changes, the property updates and the component re-renders.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Typical setup (same idea as [My first component](#docs/_getting-started/my-first-component.md/my-first-component)):
|
|
6
|
+
|
|
7
|
+
| Piece | Role |
|
|
8
|
+
|-------|------|
|
|
9
|
+
| **Type** `T` | Shape of the object at that path (`DocsUserData`, `{ count: number }`, …) |
|
|
10
|
+
| **Key** | `DataProviderKey<T, U>` — static path (`"cart"`) or dynamic (`"users.${userIndex}"`, `"${dataProvider}"`) |
|
|
11
|
+
| **Scope on the host** | Properties listed in `U` (e.g. `dataProvider`, `userIndex`) — often filled via [`@ancestorAttribute`](#docs/_decorators/ancestor-attribute.md/ancestor-attribute) |
|
|
12
|
+
| **`@subscribe(key)`** | Mirrors the store into `@state()` (or another property); read-only from the component side |
|
|
13
|
+
|
|
14
|
+
For **writing** back to the store from component state, use [@publish](#docs/_decorators/publish.md/publish). In templates, the same paths work with [sub()](#docs/_directives/sub.md/sub).
|
|
6
15
|
|
|
7
16
|
## Import
|
|
8
17
|
|
|
@@ -10,27 +19,79 @@ For bidirectional binding or string paths, use [@bind](#docs/_decorators/bind.md
|
|
|
10
19
|
<template>
|
|
11
20
|
import { subscribe } from "@supersoniks/concorde/decorators";
|
|
12
21
|
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
13
|
-
|
|
22
|
+
|
|
14
23
|
type Data = { count: number };
|
|
15
|
-
const dataKey = new DataProviderKey
|
|
16
|
-
|
|
24
|
+
const dataKey = new DataProviderKey<Data>("data");
|
|
25
|
+
|
|
17
26
|
@subscribe(dataKey.count)
|
|
18
27
|
@state()
|
|
19
28
|
count = 0;
|
|
20
29
|
</template>
|
|
21
30
|
</sonic-code>
|
|
22
31
|
|
|
23
|
-
##
|
|
32
|
+
## Static path
|
|
24
33
|
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
The key path is fixed. The property type must match `T` at that segment.
|
|
35
|
+
|
|
36
|
+
<sonic-code language="typescript">
|
|
37
|
+
<template>
|
|
38
|
+
const cartKey = new DataProviderKey<{ items: string[] }>("cart");
|
|
39
|
+
|
|
40
|
+
@subscribe(cartKey)
|
|
41
|
+
@state()
|
|
42
|
+
cart: { items: string[] } | null = null;
|
|
43
|
+
</template>
|
|
44
|
+
</sonic-code>
|
|
45
|
+
|
|
46
|
+
## Dynamic path and scope
|
|
47
|
+
|
|
48
|
+
Placeholders `${prop}` in the key string are resolved from **properties on the same component**. Declare them in the key’s second generic so TypeScript expects them on the host:
|
|
49
|
+
|
|
50
|
+
<sonic-code language="typescript">
|
|
51
|
+
<template>
|
|
52
|
+
type User = { firstName: string; lastName: string; email: string };
|
|
53
|
+
|
|
54
|
+
@subscribe(new DataProviderKey<User, { userIndex: number }>("demoUsers.${userIndex}"))
|
|
55
|
+
@state()
|
|
56
|
+
user: User | null = null;
|
|
57
|
+
|
|
58
|
+
@property({ type: Number }) userIndex = 0;
|
|
59
|
+
</template>
|
|
60
|
+
</sonic-code>
|
|
61
|
+
|
|
62
|
+
When `userIndex` changes, `@subscribe` re-resolves the path and refreshes `user`.
|
|
63
|
+
|
|
64
|
+
## Row / ancestor scope
|
|
65
|
+
|
|
66
|
+
List items (and wrappers like `<div dataProvider="…">`) set which branch the child reads. Pattern from the tutorial:
|
|
67
|
+
|
|
68
|
+
<sonic-code language="typescript">
|
|
69
|
+
<template>
|
|
70
|
+
export const rowKey = new DataProviderKey<
|
|
71
|
+
User,
|
|
72
|
+
{ dataProvider: string | null }
|
|
73
|
+
>("${dataProvider}");
|
|
74
|
+
|
|
75
|
+
@ancestorAttribute("dataProvider")
|
|
76
|
+
dataProvider: string | null = null;
|
|
77
|
+
|
|
78
|
+
@subscribe(rowKey)
|
|
79
|
+
@state()
|
|
80
|
+
user: User | null = null;
|
|
81
|
+
</template>
|
|
82
|
+
</sonic-code>
|
|
27
83
|
|
|
28
84
|
## Demo
|
|
29
85
|
|
|
30
86
|
<sonic-code>
|
|
31
87
|
<template>
|
|
88
|
+
<docs-demo-sources for="demo-subscribe-dynamic"></docs-demo-sources>
|
|
32
89
|
<demo-subscribe-dynamic></demo-subscribe-dynamic>
|
|
33
90
|
</template>
|
|
34
91
|
</sonic-code>
|
|
35
92
|
|
|
36
|
-
See also
|
|
93
|
+
## See also
|
|
94
|
+
|
|
95
|
+
- [Data flow](#docs/_core-concept/dataFlow.md/dataFlow) — overview
|
|
96
|
+
- [DataProviderKey](#docs/_misc/dataProviderKey.md/dataProviderKey) — paths and host generics
|
|
97
|
+
- [sub()](#docs/_directives/sub.md/sub) — same paths inside `html` templates
|
|
@@ -30,7 +30,7 @@ The parent is registered via `customElements.define()` (vanilla JS) rather than
|
|
|
30
30
|
<template>
|
|
31
31
|
import { html, LitElement } from "lit";
|
|
32
32
|
import { customElement, state } from "lit/decorators.js";
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
// Parent: registered later via customElements.define(), not @customElement
|
|
35
35
|
@dispatchConnectedEvent()
|
|
36
36
|
export class DemoWaitAncestorContainer extends LitElement {
|
|
@@ -38,21 +38,21 @@ export class DemoWaitAncestorContainer extends LitElement {
|
|
|
38
38
|
return html`<slot></slot>`;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
// Child: waits for parent before initializing
|
|
43
43
|
@customElement("demo-wait-ancestor-value")
|
|
44
44
|
@awaitConnectedAncestors("demo-wait-ancestor-container[dataProvider]")
|
|
45
45
|
export class DemoWaitAncestorValue extends LitElement {
|
|
46
46
|
@ancestorAttribute("dataProvider")
|
|
47
47
|
dataProvider: string | null = null;
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
@state() initializedAt: string = "";
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
connectedCallback() {
|
|
52
52
|
super.connectedCallback();
|
|
53
53
|
this.initializedAt = new Date().toISOString();
|
|
54
54
|
}
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
render() {
|
|
57
57
|
return html`
|
|
58
58
|
<p>DataProvider from ancestor: <strong>${this.dataProvider || "—"}</strong></p>
|
|
@@ -60,7 +60,7 @@ export class DemoWaitAncestorValue extends LitElement {
|
|
|
60
60
|
`;
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
// Demo section: register parent via customElements.define() when user clicks
|
|
65
65
|
@customElement("demo-wait-ancestors-section")
|
|
66
66
|
export class DemoWaitAncestorsSection extends LitElement {
|
|
@@ -83,7 +83,8 @@ export class DemoWaitAncestorsSection extends LitElement {
|
|
|
83
83
|
|
|
84
84
|
<sonic-code>
|
|
85
85
|
<template>
|
|
86
|
-
<demo-wait-ancestors-section></demo-
|
|
86
|
+
<docs-demo-sources for="demo-wait-ancestors-section"></docs-demo-sources>
|
|
87
|
+
<demo-wait-ancestors-section></demo-wait-ancestors-section>
|
|
87
88
|
</template>
|
|
88
89
|
</sonic-code>
|
|
89
90
|
|
|
@@ -105,7 +106,8 @@ When the parent is defined at load and already in the DOM, the child initializes
|
|
|
105
106
|
|
|
106
107
|
<sonic-code>
|
|
107
108
|
<template>
|
|
108
|
-
<demo-wait-ancestors-static-section></demo-
|
|
109
|
+
<docs-demo-sources for="demo-wait-ancestors-static-section"></docs-demo-sources>
|
|
110
|
+
<demo-wait-ancestors-static-section></demo-wait-ancestors-static-section>
|
|
109
111
|
</template>
|
|
110
112
|
</sonic-code>
|
|
111
113
|
|
|
@@ -113,7 +115,8 @@ When the parent is defined at load and already in the DOM, the child initializes
|
|
|
113
115
|
|
|
114
116
|
<sonic-code>
|
|
115
117
|
<template>
|
|
116
|
-
<demo-wait-ancestors-ready-section></demo-
|
|
118
|
+
<docs-demo-sources for="demo-wait-ancestors-ready-section"></docs-demo-sources>
|
|
119
|
+
<demo-wait-ancestors-ready-section></demo-wait-ancestors-ready-section>
|
|
117
120
|
</template>
|
|
118
121
|
</sonic-code>
|
|
119
122
|
|
|
@@ -145,7 +148,7 @@ The `sonic-connected` event bubbles, so you can listen to it from anywhere:
|
|
|
145
148
|
<sonic-code language="typescript">
|
|
146
149
|
<template>
|
|
147
150
|
import { CONNECTED } from "@supersoniks/concorde/decorators";
|
|
148
|
-
|
|
151
|
+
|
|
149
152
|
someConnectable.addEventListener(CONNECTED, (e) => {
|
|
150
153
|
console.log("Component connected:", e.target);
|
|
151
154
|
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# sub()
|
|
2
|
+
|
|
3
|
+
Read-only Lit directive: displays the current **DataProvider** value and updates whenever it is assigned.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
<sonic-code language="typescript">
|
|
8
|
+
<template>
|
|
9
|
+
import { sub } from "@supersoniks/concorde/directives";
|
|
10
|
+
</template>
|
|
11
|
+
</sonic-code>
|
|
12
|
+
|
|
13
|
+
## String path
|
|
14
|
+
|
|
15
|
+
<sonic-code language="typescript">
|
|
16
|
+
<template>
|
|
17
|
+
render() {
|
|
18
|
+
return html`<p>Count: ${sub("myCounter.count")}</p>`;
|
|
19
|
+
}
|
|
20
|
+
</template>
|
|
21
|
+
</sonic-code>
|
|
22
|
+
|
|
23
|
+
## DataProviderKey (static)
|
|
24
|
+
|
|
25
|
+
<sonic-code language="typescript">
|
|
26
|
+
<template>
|
|
27
|
+
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
28
|
+
import { sub } from "@supersoniks/concorde/directives";
|
|
29
|
+
|
|
30
|
+
const counterKey = new DataProviderKey<{ count: number }>("myCounter");
|
|
31
|
+
|
|
32
|
+
render() {
|
|
33
|
+
return html`<p>${sub(counterKey.count)}</p>`;
|
|
34
|
+
}
|
|
35
|
+
</template>
|
|
36
|
+
</sonic-code>
|
|
37
|
+
|
|
38
|
+
## Dynamic DataProviderKey (`${prop}`)
|
|
39
|
+
|
|
40
|
+
Like `@subscribe`: the path is resolved on the template **host component**; the directive re-subscribes when observed props change.
|
|
41
|
+
|
|
42
|
+
<sonic-code language="typescript">
|
|
43
|
+
<template>
|
|
44
|
+
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
45
|
+
import { sub } from "@supersoniks/concorde/directives";
|
|
46
|
+
|
|
47
|
+
type User = { firstName: string; lastName: string; email: string };
|
|
48
|
+
const userKey = new DataProviderKey<User, { userIndex: number }>(
|
|
49
|
+
"demoUsers.${userIndex}",
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
@customElement("demo-sub-dynamic")
|
|
53
|
+
export class DemoSubDynamic extends LitElement {
|
|
54
|
+
@property({ type: Number }) userIndex = 0;
|
|
55
|
+
|
|
56
|
+
render() {
|
|
57
|
+
return html`
|
|
58
|
+
<p>${sub(userKey.email)}</p>
|
|
59
|
+
`;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
</template>
|
|
63
|
+
</sonic-code>
|
|
64
|
+
|
|
65
|
+
## Demo
|
|
66
|
+
|
|
67
|
+
<sonic-code toggleCode>
|
|
68
|
+
<template>
|
|
69
|
+
<docs-demo-sources for="demo-sub-template"></docs-demo-sources>
|
|
70
|
+
<demo-sub-template></demo-sub-template>
|
|
71
|
+
</template>
|
|
72
|
+
</sonic-code>
|
|
73
|
+
|
|
74
|
+
## Concatenation (forms)
|
|
75
|
+
|
|
76
|
+
<sonic-code language="typescript">
|
|
77
|
+
<template>
|
|
78
|
+
html`<span>${sub(this.formDataProvider + ".email")}</span>`
|
|
79
|
+
</template>
|
|
80
|
+
</sonic-code>
|
|
81
|
+
|
|
82
|
+
## sub() vs get() / set() / dp()
|
|
83
|
+
|
|
84
|
+
| API | Context | Dynamic `${…}` |
|
|
85
|
+
|-----|----------|------------------|
|
|
86
|
+
| `sub()` | Lit template, reactive | Yes |
|
|
87
|
+
| `get` / `set` / `dp` | Imperative code | No |
|
|
88
|
+
|
|
89
|
+
Do not replace `sub(path)` with `get(path)` in a template: `get` returns a one-time snapshot.
|
|
90
|
+
|
|
91
|
+
See [DataProviderKey](#docs/_misc/dataProviderKey.md/dataProviderKey), [@subscribe](#docs/_decorators/subscribe.md/subscribe), and the `concorde-get-set-dp` migration skill.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# AI agents (skills & AGENTS.md)
|
|
2
|
+
|
|
3
|
+
Concorde ships **skills**, **rules**, and a root **`AGENTS.md`** so Cursor, JetBrains AI Assistant, and other coding agents follow framework patterns (DataProvider, decorators, short imports, scope, theme, migrations).
|
|
4
|
+
|
|
5
|
+
On a [starter](#docs/_getting-started/concorde-outside.md/concorde-outside) project, run `yarn ai:sync` after install. On a [manual / brownfield](#docs/_getting-started/concorde-manual-install.md/concorde-manual-install) project, install Concorde first, then use `ai-init` below.
|
|
6
|
+
|
|
7
|
+
## Dedicated commands
|
|
8
|
+
|
|
9
|
+
| Context | Command |
|
|
10
|
+
|---------|---------|
|
|
11
|
+
| [create-concorde-ts-starter](https://www.npmjs.com/package/@supersoniks/create-concorde-ts-starter) project | `yarn ai:sync` |
|
|
12
|
+
| Any consumer app (after `yarn add @supersoniks/concorde`) | `node node_modules/@supersoniks/concorde/scripts/ai-init.mjs` |
|
|
13
|
+
| Concorde repo (contributors) | `yarn ai-init` |
|
|
14
|
+
|
|
15
|
+
<sonic-code language="shell">
|
|
16
|
+
<template>
|
|
17
|
+
# Starter (from project root)
|
|
18
|
+
yarn ai:sync
|
|
19
|
+
|
|
20
|
+
# Manual / existing project
|
|
21
|
+
node node_modules/@supersoniks/concorde/scripts/ai-init.mjs
|
|
22
|
+
</template>
|
|
23
|
+
</sonic-code>
|
|
24
|
+
|
|
25
|
+
## Useful flags
|
|
26
|
+
|
|
27
|
+
| Flag | Effect |
|
|
28
|
+
|------|--------|
|
|
29
|
+
| `--merge-agents` | Append to an existing `AGENTS.md` instead of replacing it |
|
|
30
|
+
| `--overlay <dir>` | Copy extra rules/skills from another layer (e.g. starter kit) |
|
|
31
|
+
| `--cursor-only` | Install only `.cursor/skills` and `.cursor/rules` |
|
|
32
|
+
| `--jetbrains-only` | Install only `.aiassistant/rules/` |
|
|
33
|
+
|
|
34
|
+
## What gets installed
|
|
35
|
+
|
|
36
|
+
| Path | Role |
|
|
37
|
+
|------|------|
|
|
38
|
+
| `AGENTS.md` | Project-level guide for agents (Concorde conventions) |
|
|
39
|
+
| `.cursor/skills/concorde/` | Core Lit + DataProvider patterns |
|
|
40
|
+
| `.cursor/skills/concorde-imports/` | Short `@supersoniks/concorde/…` import paths |
|
|
41
|
+
| `.cursor/skills/concorde-scope/` | `serviceURL`, `formDataProvider`, API configuration |
|
|
42
|
+
| `.cursor/skills/concorde-theme/` | `sonic-theme` and `--sc-*` tokens |
|
|
43
|
+
| `.cursor/skills/concorde-menu/` | `sonic-menu` navigation |
|
|
44
|
+
| `.cursor/skills/concorde-get-set-dp/` | `get` / `set` / `dp` and `DataProviderKey` migration |
|
|
45
|
+
| `.cursor/rules/concorde.mdc` | Cursor rules (always-on patterns) |
|
|
46
|
+
| `.aiassistant/rules/concorde.md` | JetBrains AI Assistant rules |
|
|
47
|
+
|
|
48
|
+
## Workflow
|
|
49
|
+
|
|
50
|
+
1. **Starter project:** [Installation](#docs/_getting-started/concorde-outside.md/concorde-outside) — `yarn ai:sync` is wired in the kit.
|
|
51
|
+
2. **Existing / manual Vite project:** [Manual installation](#docs/_getting-started/concorde-manual-install.md/concorde-manual-install), then **`ai-init`** after `yarn add @supersoniks/concorde`.
|
|
52
|
+
3. Commit `AGENTS.md`, `.cursor/`, and `.aiassistant/` if your team shares agent settings.
|
|
53
|
+
4. Re-run the same command when you bump `@supersoniks/concorde` to refresh skills from `node_modules/@supersoniks/concorde/ai/`.
|
|
54
|
+
5. In Cursor, skills under `.cursor/skills/` are picked up automatically; mention a skill in chat for focused tasks (e.g. migration → `concorde-get-set-dp`).
|
|
55
|
+
|
|
56
|
+
Source files in the npm package: `node_modules/@supersoniks/concorde/ai/` (see also `ai/README.md` in the [Concorde repository](https://github.com/supersoniks/concorde)).
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Manual installation (Vite)
|
|
2
|
+
|
|
3
|
+
> **Legacy** — for brownfield apps or custom stacks. New projects should use the [starter](#docs/_getting-started/concorde-outside.md/concorde-outside).
|
|
4
|
+
|
|
5
|
+
## Brand New Vite Project
|
|
6
|
+
|
|
7
|
+
Tailwind configuration is not covered here yet.
|
|
8
|
+
|
|
9
|
+
### Creating the Project
|
|
10
|
+
|
|
11
|
+
<sonic-code language="shell">
|
|
12
|
+
<template>
|
|
13
|
+
# Pure JavaScript project
|
|
14
|
+
yarn create vite --template vanilla-js
|
|
15
|
+
# TypeScript project
|
|
16
|
+
# (it is recommended to use this approach, which installs Lit separately if needed, via "yarn add lit")
|
|
17
|
+
yarn create vite --template vanilla-ts
|
|
18
|
+
# TypeScript + Lit project
|
|
19
|
+
# (creating new web components, for example, to extend the fetch or subscriber mixins)
|
|
20
|
+
yarn create vite --template lit-ts
|
|
21
|
+
</template>
|
|
22
|
+
</sonic-code>
|
|
23
|
+
|
|
24
|
+
Using Lit with TypeScript requires the following configuration in the "compilerOptions" section of the `tsconfig.json` file:
|
|
25
|
+
|
|
26
|
+
<sonic-code language="json">
|
|
27
|
+
<template>
|
|
28
|
+
"experimentalDecorators": true,
|
|
29
|
+
"useDefineForClassFields": false
|
|
30
|
+
</template>
|
|
31
|
+
</sonic-code>
|
|
32
|
+
|
|
33
|
+
### Installing Concorde
|
|
34
|
+
|
|
35
|
+
Navigate to the project folder created and perform the installation:
|
|
36
|
+
|
|
37
|
+
<sonic-code language="shell">
|
|
38
|
+
<template>
|
|
39
|
+
yarn add @supersoniks/concorde
|
|
40
|
+
</template>
|
|
41
|
+
</sonic-code>
|
|
42
|
+
|
|
43
|
+
Agent skills (`AGENTS.md`, Cursor / JetBrains): see [AI agents](#docs/_getting-started/ai-agents.md/ai-agents) — run `node node_modules/@supersoniks/concorde/scripts/ai-init.mjs` after install.
|
|
44
|
+
|
|
45
|
+
### Development / Build
|
|
46
|
+
|
|
47
|
+
<sonic-code language="shell">
|
|
48
|
+
<template>
|
|
49
|
+
# Development (you can add `--host` after the command chain in package.json's dev script instead of typing it each time as shown below)
|
|
50
|
+
yarn dev --host
|
|
51
|
+
# Build
|
|
52
|
+
yarn build
|
|
53
|
+
</template>
|
|
54
|
+
</sonic-code>
|
|
55
|
+
|
|
56
|
+
## Shortcut Imports
|
|
57
|
+
|
|
58
|
+
Shortcut imports work by default in JavaScript, but in TypeScript, they are activated by choice as they inject data into *tsconfig.json*. Here is the command:
|
|
59
|
+
|
|
60
|
+
<sonic-code language="shell">
|
|
61
|
+
<template>
|
|
62
|
+
npx concorde enable-short-paths
|
|
63
|
+
</template>
|
|
64
|
+
</sonic-code>
|
|
65
|
+
|
|
66
|
+
Shortcut imports replace the actual paths with aliases as follows:
|
|
67
|
+
|
|
68
|
+
* `@supersoniks/concorde/core/components/functional_or_ui/component/component` becomes `@supersoniks/concorde/functional_or_ui/component`
|
|
69
|
+
* `@supersoniks/concorde/core/mixins_or_utils/class_name` becomes `@supersoniks/concorde/mixins_or_utils/class_name`
|
|
70
|
+
|
|
71
|
+
The original paths remain accessible. Shortcut imports are used for the examples later in this documentation.
|
|
72
|
+
|
|
73
|
+
## Usage
|
|
74
|
+
|
|
75
|
+
### Simple Integration in HTML
|
|
76
|
+
|
|
77
|
+
Import needed component in `main.ts` or wherever you want to use it:
|
|
78
|
+
|
|
79
|
+
<sonic-code language="typescript">
|
|
80
|
+
<template>
|
|
81
|
+
import "@supersoniks/concorde/ui/button";
|
|
82
|
+
</template>
|
|
83
|
+
</sonic-code>
|
|
84
|
+
|
|
85
|
+
Then in the render function ofyour component or in the HTML of the web page that includes the compiled JS, use the component as follows:
|
|
86
|
+
|
|
87
|
+
<sonic-code>
|
|
88
|
+
<template>
|
|
89
|
+
<sonic-button variant="outline">My button</sonic-button>
|
|
90
|
+
</template>
|
|
91
|
+
</sonic-code>
|
|
92
|
+
|
|
93
|
+
### Using a Mixin to Create a New Lit Component
|
|
94
|
+
|
|
95
|
+
For example, create a file `my-element.ts` at the root:
|
|
96
|
+
|
|
97
|
+
<sonic-code language="typescript">
|
|
98
|
+
<template>
|
|
99
|
+
import { html, LitElement } from "lit";
|
|
100
|
+
import { customElement, property } from "lit/decorators.js";
|
|
101
|
+
import Fetcher from "@supersoniks/concorde/mixins/Fetcher";
|
|
102
|
+
import Subscriber from "@supersoniks/concorde/mixins/Subscriber";
|
|
103
|
+
|
|
104
|
+
@customElement("my-element")
|
|
105
|
+
export class SonicComponent extends Fetcher(Subscriber(LitElement)) {
|
|
106
|
+
@property() email = "";
|
|
107
|
+
@property() first_name = "";
|
|
108
|
+
@property() last_name = "";
|
|
109
|
+
|
|
110
|
+
render() {
|
|
111
|
+
return html`<div>
|
|
112
|
+
${this.first_name} ${this.last_name} : ${this.email}
|
|
113
|
+
</div>`;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
</template>
|
|
117
|
+
</sonic-code>
|
|
118
|
+
|
|
119
|
+
Import component `main.ts` or `main.js` or any other component that uses it to be compiled
|
|
120
|
+
|
|
121
|
+
<sonic-code language="typescript">
|
|
122
|
+
<template>
|
|
123
|
+
import "./my-element";
|
|
124
|
+
</template>
|
|
125
|
+
</sonic-code>
|
|
126
|
+
|
|
127
|
+
In the HTML of a JS or TS component or in the HTML of the web page containing the compiled JS:
|
|
128
|
+
|
|
129
|
+
<sonic-code language="html">
|
|
130
|
+
<template>
|
|
131
|
+
<my-element serviceURL="/docs-mock-api" dataProvider="api/users/2" key="data"></my-element>
|
|
132
|
+
</template>
|
|
133
|
+
</sonic-code>
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# Installation
|
|
2
2
|
|
|
3
|
+
<sonic-alert status="success" label="Recommended — use the starter" size="xl" background>
|
|
4
|
+
<p><strong>For almost all new projects, use <a href="https://www.npmjs.com/package/@supersoniks/create-concorde-ts-starter">create-concorde-ts-starter</a>.</strong></p>
|
|
5
|
+
<p>You get Vite + TypeScript + Lit + Tailwind, an example component, <code>npx concorde enable-short-paths</code> ready to run, and <code>yarn ai:sync</code> for <a href="#docs/_getting-started/ai-agents.md/ai-agents">AI agent skills</a> (<code>AGENTS.md</code>, Cursor / JetBrains rules) without extra setup.</p>
|
|
6
|
+
</sonic-alert>
|
|
7
|
+
|
|
3
8
|
## Starter
|
|
4
9
|
|
|
5
|
-
The easiest way to use Concorde is by using the Concorde starter.
|
|
6
10
|
The following command creates a new Vite project in TypeScript mode with Tailwind and an example component to get started.
|
|
7
11
|
|
|
8
12
|
<sonic-code language="shell">
|
|
@@ -11,133 +15,19 @@ npx @supersoniks/create-concorde-ts-starter "project_name"
|
|
|
11
15
|
</template>
|
|
12
16
|
</sonic-code>
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
For a more manual configuration, you can refer to the following sections. <br/>
|
|
18
|
-
However, the Tailwind configuration is not mentioned at the moment.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
### Creating the Project
|
|
18
|
+
Then, from the project folder:
|
|
22
19
|
|
|
23
20
|
<sonic-code language="shell">
|
|
24
21
|
<template>
|
|
25
|
-
|
|
26
|
-
yarn create vite --template vanilla-js
|
|
27
|
-
# TypeScript project
|
|
28
|
-
# (it is recommended to use this approach, which installs Lit separately if needed, via "yarn add lit")
|
|
29
|
-
yarn create vite --template vanilla-ts
|
|
30
|
-
# TypeScript + Lit project
|
|
31
|
-
# (creating new web components, for example, to extend the fetch or subscriber mixins)
|
|
32
|
-
yarn create vite --template lit-ts
|
|
33
|
-
</template>
|
|
34
|
-
</sonic-code>
|
|
35
|
-
|
|
36
|
-
Using Lit with TypeScript requires the following configuration in the "compilerOptions" section of the `tsconfig.json` file:
|
|
37
|
-
|
|
38
|
-
<sonic-code language="json">
|
|
39
|
-
<template>
|
|
40
|
-
"experimentalDecorators": true,
|
|
41
|
-
"useDefineForClassFields": false
|
|
42
|
-
</template>
|
|
43
|
-
</sonic-code>
|
|
44
|
-
|
|
45
|
-
### Installing Concorde
|
|
46
|
-
|
|
47
|
-
Navigate to the project folder created and perform the installation:
|
|
48
|
-
|
|
49
|
-
<sonic-code language="shell">
|
|
50
|
-
<template>
|
|
51
|
-
yarn add @supersoniks/concorde
|
|
52
|
-
</template>
|
|
53
|
-
</sonic-code>
|
|
54
|
-
|
|
55
|
-
### Development / Build
|
|
56
|
-
|
|
57
|
-
<sonic-code language="shell">
|
|
58
|
-
<template>
|
|
59
|
-
# Development (you can add `--host` after the command chain in package.json's dev script instead of typing it each time as shown below)
|
|
22
|
+
yarn install
|
|
60
23
|
yarn dev --host
|
|
61
|
-
# Build
|
|
62
|
-
yarn build
|
|
63
24
|
</template>
|
|
64
25
|
</sonic-code>
|
|
65
26
|
|
|
66
|
-
##
|
|
67
|
-
|
|
68
|
-
Shortcut imports work by default in JavaScript, but in TypeScript, they are activated by choice as they inject data into *tsconfig.json*. Here is the command:
|
|
69
|
-
|
|
70
|
-
<sonic-code language="shell">
|
|
71
|
-
<template>
|
|
72
|
-
npx concorde enable-short-paths
|
|
73
|
-
</template>
|
|
74
|
-
</sonic-code>
|
|
75
|
-
|
|
76
|
-
Shortcut imports replace the actual paths with aliases as follows:
|
|
77
|
-
|
|
78
|
-
* `@supersoniks/concorde/core/components/functional_or_ui/component/component` becomes `@supersoniks/concorde/functional_or_ui/component`
|
|
79
|
-
* `@supersoniks/concorde/core/mixins_or_utils/class_name` becomes `@supersoniks/concorde/mixins_or_utils/class_name`
|
|
27
|
+
## Next steps
|
|
80
28
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
Import needed component in `main.ts` or wherever you want to use it:
|
|
88
|
-
|
|
89
|
-
<sonic-code language="typescript">
|
|
90
|
-
<template>
|
|
91
|
-
import "@supersoniks/concorde/ui/button";
|
|
92
|
-
</template>
|
|
93
|
-
</sonic-code>
|
|
94
|
-
|
|
95
|
-
Then in the render function ofyour component or in the HTML of the web page that includes the compiled JS, use the component as follows:
|
|
96
|
-
|
|
97
|
-
<sonic-code>
|
|
98
|
-
<template>
|
|
99
|
-
<sonic-button variant="outline">My button</sonic-button>
|
|
100
|
-
</template>
|
|
101
|
-
</sonic-code>
|
|
102
|
-
|
|
103
|
-
### Using a Mixin to Create a New Lit Component
|
|
104
|
-
|
|
105
|
-
For example, create a file `my-element.ts` at the root:
|
|
106
|
-
|
|
107
|
-
<sonic-code language="typescript">
|
|
108
|
-
<template>
|
|
109
|
-
import { html, LitElement } from "lit";
|
|
110
|
-
import { customElement, property } from "lit/decorators.js";
|
|
111
|
-
import Fetcher from "@supersoniks/concorde/mixins/Fetcher";
|
|
112
|
-
import Subscriber from "@supersoniks/concorde/mixins/Subscriber";
|
|
113
|
-
|
|
114
|
-
@customElement("my-element")
|
|
115
|
-
export class SonicComponent extends Fetcher(Subscriber(LitElement)) {
|
|
116
|
-
@property() email = "";
|
|
117
|
-
@property() first_name = "";
|
|
118
|
-
@property() last_name = "";
|
|
119
|
-
|
|
120
|
-
render() {
|
|
121
|
-
return html`<div>
|
|
122
|
-
${this.first_name} ${this.last_name} : ${this.email}
|
|
123
|
-
</div>`;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
</template>
|
|
127
|
-
</sonic-code>
|
|
128
|
-
|
|
129
|
-
Import component `main.ts` or `main.js` or any other component that uses it to be compiled
|
|
130
|
-
|
|
131
|
-
<sonic-code language="typescript">
|
|
132
|
-
<template>
|
|
133
|
-
import "./my-element";
|
|
134
|
-
</template>
|
|
135
|
-
</sonic-code>
|
|
136
|
-
|
|
137
|
-
In the HTML of a JS or TS component or in the HTML of the web page containing the compiled JS:
|
|
138
|
-
|
|
139
|
-
<sonic-code language="html">
|
|
140
|
-
<template>
|
|
141
|
-
<my-element serviceURL="https://reqres.in" dataProvider="api/users/2" key="data"></my-element>
|
|
142
|
-
</template>
|
|
143
|
-
</sonic-code>
|
|
29
|
+
| Step | Page |
|
|
30
|
+
|------|------|
|
|
31
|
+
| Learn patterns | [My first component](#docs/_getting-started/my-first-component.md/my-first-component) |
|
|
32
|
+
| Agent skills | [AI agents (skills)](#docs/_getting-started/ai-agents.md/ai-agents) — `yarn ai:sync` on the starter |
|
|
33
|
+
| Brownfield / manual Vite | [Legacy: Manual installation](#docs/_getting-started/concorde-manual-install.md/concorde-manual-install) |
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Creating components
|
|
2
2
|
|
|
3
|
+
> **New app components:** start with [My first component](#docs/_getting-started/my-first-component.md/my-first-component) and [Data flow](#docs/_core-concept/dataFlow.md/dataFlow). The `Subscriber` mixin below is [legacy](#docs/_core-concept/subscriber.md/subscriber).
|
|
4
|
+
|
|
3
5
|
## Where to put it?
|
|
4
6
|
|
|
5
7
|
In this document, we consider the src directory of the project as the root.<br>
|