@supersoniks/concorde 5.1.2 → 5.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/concorde-docs/SKILL.md +1 -1
- package/README.md +1 -1
- package/ai/README.md +29 -41
- package/ai/skills/concorde/SKILL.md +54 -324
- package/ai/skills/concorde/rules/composition.md +32 -0
- package/ai/skills/concorde/rules/data.md +47 -0
- package/ai/skills/concorde/rules/http.md +25 -0
- package/ai/skills/concorde/rules/lists-forms.md +35 -0
- package/ai/skills/concorde/rules/styling.md +46 -0
- package/ai/skills/concorde/rules/troubleshooting.md +45 -0
- package/build-infos.json +1 -1
- package/concorde-core.bundle.js +21 -21
- package/concorde-core.es.js +977 -980
- package/custom-elements-manifest.public.config.mjs +8 -0
- package/{.tmp-cem/custom-elements.json → custom-elements.json} +11722 -8868
- package/dist/concorde-core.bundle.js +21 -21
- package/dist/concorde-core.es.js +977 -980
- package/dist/docs-mock-api-sw.js +58 -223
- package/dist/docs-mock-api-sw.js.map +4 -4
- package/dist/img/concorde/plane_01.jpg +0 -0
- package/dist/img/concorde/plane_02.jpg +0 -0
- package/dist/img/concorde/plane_03.jpg +0 -0
- package/dist/img/concorde/plane_04.jpg +0 -0
- package/dist/img/concorde/plane_05.jpg +0 -0
- package/dist/img/concorde/plane_06.jpg +0 -0
- package/dist/img/concorde/plane_07.jpg +0 -0
- package/dist/img/concorde/plane_08.jpg +0 -0
- package/dist/img/concorde/plane_09.jpg +0 -0
- package/dist/img/concorde/plane_10.jpg +0 -0
- package/dist/img/concorde/plane_11.jpg +0 -0
- package/dist/img/concorde/plane_12.jpg +0 -0
- package/dist/img/concorde/plane_13.jpg +0 -0
- package/dist/img/og-concorde.jpg +0 -0
- package/dist/robots.txt +11 -10
- package/docs/.htaccess +7 -0
- package/docs/about.html +111 -0
- package/docs/about.md +22 -0
- package/docs/assets/{index-BgG6FFPt.js → index-6sS76xWj.js} +482 -500
- package/docs/assets/{index-x89XINSG.css → index-DkdPbH0F.css} +1 -1
- package/docs/core/components/functional/date/date.md +1 -1
- package/docs/core/components/functional/list/list.html +7 -5
- package/docs/core/components/functional/list/list.md +6 -2
- package/docs/core/components/ui/card/card.html +1 -1
- package/docs/core/components/ui/card/card.md +1 -1
- package/docs/core/components/ui/image/image.html +17 -17
- package/docs/core/components/ui/image/image.md +17 -17
- package/docs/core/components/ui/modal/modal.html +2 -2
- package/docs/core/components/ui/modal/modal.md +2 -2
- package/docs/custom-elements.json +16559 -0
- package/docs/docs/decorators/bind.html +22 -21
- package/docs/docs/decorators/bind.md +23 -24
- package/docs/docs/getting-started/ai-agents.html +50 -94
- package/docs/docs/getting-started/ai-agents.md +29 -55
- package/docs/docs/getting-started/dataFlow.html +1 -1
- package/docs/docs/getting-started/dataFlow.md +1 -1
- package/docs/docs/index.html +1 -1
- package/docs/hubs/decorators.html +11 -16
- package/docs/hubs/remote-data.html +5 -9
- package/docs/img/og-concorde.jpg +0 -0
- package/docs/index.html +91 -2
- package/docs/index.md +2 -2
- package/docs/llms-full.txt +58 -74
- package/docs/llms.txt +6 -4
- package/docs/privacy.html +122 -0
- package/docs/privacy.md +32 -0
- package/docs/sitemap.xml +6 -0
- package/docs/src/core/components/functional/date/date.md +1 -1
- package/docs/src/core/components/functional/list/list.md +6 -2
- package/docs/src/core/components/functional/sdui/component-catalog.gaps.json +1 -1
- package/docs/src/core/components/functional/sdui/component-catalog.json +1 -1
- package/docs/src/core/components/ui/card/card.md +1 -1
- package/docs/src/core/components/ui/image/image.md +17 -17
- package/docs/src/core/components/ui/modal/modal.md +2 -2
- package/docs/src/docs/decorators/bind.md +23 -24
- package/docs/src/docs/getting-started/ai-agents.md +29 -55
- package/docs/src/docs/getting-started/dataFlow.md +1 -1
- package/docs/src/docs/search/docs-search.json +100 -55
- package/docs/src/tsconfig.json +11 -5
- package/index.html +89 -0
- package/package.json +8 -4
- package/public/img/og-concorde.jpg +0 -0
- package/scripts/ai-init.mjs +104 -379
- package/scripts/ai-init.test.mjs +81 -239
- package/scripts/docs-markdown-vite-plugin.ts +11 -5
- package/scripts/docs-public-url.mjs +6 -0
- package/scripts/docs.htaccess +7 -0
- package/scripts/generate-cem.mjs +244 -0
- package/scripts/generate-cem.test.mjs +122 -0
- package/scripts/generate-crawl-docs.mjs +29 -5
- package/scripts/generate-sdui-catalog.mjs +11 -10
- package/scripts/post-build-docs.js +3 -0
- package/scripts/pre-publish.mjs +2 -1
- package/scripts/site-pages.mjs +212 -0
- package/scripts/site-pages.test.mjs +116 -0
- package/site-pages/about.md +22 -0
- package/site-pages/privacy.md +32 -0
- package/src/core/components/functional/date/date.md +1 -1
- package/src/core/components/functional/list/list.md +6 -2
- package/src/core/components/functional/sdui/component-catalog.gaps.json +1 -1
- package/src/core/components/functional/sdui/component-catalog.json +1 -1
- package/src/core/components/ui/card/card.md +1 -1
- package/src/core/components/ui/image/image.md +17 -17
- package/src/core/components/ui/modal/modal.md +2 -2
- package/src/core/decorators/subscriber/bind.ts +9 -14
- package/src/docs/components/docs-demo-sources.ts +3 -3
- package/src/docs/decorators/bind.md +23 -24
- package/src/docs/docs-location.spec.ts +10 -0
- package/src/docs/docs-location.ts +10 -0
- package/src/docs/example/decorators-demo-bind-demos.ts +11 -28
- package/src/docs/example/docs-toggle-demos.ts +1 -1
- package/src/docs/getting-started/ai-agents.md +29 -55
- package/src/docs/getting-started/dataFlow.md +1 -1
- package/src/docs/home/home.ts +3 -1
- package/src/docs/navigation/navigation.ts +1 -1
- package/src/docs/search/docs-search.json +100 -55
- package/src/docs/search/markdown-renderer.ts +6 -1
- package/src/docs/tailwind/css/docs/content.css +4 -5
- package/src/tsconfig.json +11 -5
- package/src/tsconfig.tsbuildinfo +1 -1
- package/ai/AGENTS.md +0 -56
- package/ai/cursor/rules/concorde-menu.mdc +0 -15
- package/ai/cursor/rules/concorde-scope.mdc +0 -14
- package/ai/cursor/rules/concorde-theme.mdc +0 -13
- package/ai/cursor/rules/concorde.mdc +0 -66
- package/ai/jetbrains/rules/concorde.md +0 -53
- package/ai/skills/concorde-get-set-dp/SKILL.md +0 -194
- package/ai/skills/concorde-imports/SKILL.md +0 -78
- package/ai/skills/concorde-menu/SKILL.md +0 -74
- package/ai/skills/concorde-scope/SKILL.md +0 -70
- package/ai/skills/concorde-theme/SKILL.md +0 -57
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Privacy notice
|
|
2
|
+
|
|
3
|
+
This notice covers the Concorde documentation site, https://concorde.supersoniks.org, published by [Supersoniks](https://supersoniks.com/), 22 rue du Docteur Bretonneau, 37000 Tours, France.
|
|
4
|
+
|
|
5
|
+
## What this site does not do
|
|
6
|
+
|
|
7
|
+
- It has no user accounts, sign-up or login.
|
|
8
|
+
- It sets no cookies and runs no analytics, advertising or tracking scripts.
|
|
9
|
+
- It has no forms that send personal data to Supersoniks.
|
|
10
|
+
|
|
11
|
+
## What is stored in your browser
|
|
12
|
+
|
|
13
|
+
- `sonicTheme` in localStorage remembers your light or dark theme choice. It never leaves your browser.
|
|
14
|
+
- A service worker serves the mock API used by live examples (`/docs-mock-api/…`). It runs locally in your browser.
|
|
15
|
+
- Some examples demonstrate features that store values in localStorage (for example dismissed alerts or cached labels). They only run when you open those pages.
|
|
16
|
+
|
|
17
|
+
## Third-party services
|
|
18
|
+
|
|
19
|
+
To display pages, your browser loads files from these providers, which receive your IP address and browser details as part of any web request:
|
|
20
|
+
|
|
21
|
+
- Google Fonts (fonts.googleapis.com, fonts.gstatic.com) for the Schibsted Grotesk font.
|
|
22
|
+
- jsDelivr (cdn.jsdelivr.net) for the search and Markdown libraries.
|
|
23
|
+
- cdn.supersoniks.com for icons.
|
|
24
|
+
- A few live examples call public demo APIs (geo.api.gouv.fr, reqres.in, i.pravatar.cc) when you open them.
|
|
25
|
+
|
|
26
|
+
## Server logs
|
|
27
|
+
|
|
28
|
+
Like any web server, the host records technical request data (IP address, URL, date, user agent) to operate and secure the site.
|
|
29
|
+
|
|
30
|
+
## Your rights
|
|
31
|
+
|
|
32
|
+
Under the GDPR you can ask for access to, correction or deletion of data about you. Contact Supersoniks through [supersoniks.com/un-projet](https://supersoniks.com/un-projet), by phone at +33 2 47 68 93 25, or by mail at 22 rue du Docteur Bretonneau, 37000 Tours, France. See also the [Supersoniks privacy policy](https://supersoniks.com/politique-de-confidentialite) and [legal notice](https://supersoniks.com/mentions-legales).
|
|
@@ -116,7 +116,7 @@ A child `<template data-value="<part>">` wraps a part in your own markup: `weekd
|
|
|
116
116
|
<template data-value="year"><span class="block text-lg font-bold leading-tight"></span></template>
|
|
117
117
|
<template data-value="to"><span class="block my-1 text-3xl leading-none">↓</span></template>
|
|
118
118
|
</sonic-date>
|
|
119
|
-
<sonic-image src="img/concorde/plane_03.jpg" alt="Concorde specifications board" ratio="1/1" cover></sonic-image>
|
|
119
|
+
<sonic-image src="/img/concorde/plane_03.jpg" alt="Concorde specifications board" ratio="1/1" cover></sonic-image>
|
|
120
120
|
</div>
|
|
121
121
|
</template>
|
|
122
122
|
</sonic-code>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# List
|
|
2
2
|
|
|
3
|
-
**`sonic-list`** renders one row per entry of its `props` array, either set directly or loaded with `fetch`.
|
|
3
|
+
**`sonic-list`** renders one row per entry of its `props` array, either set directly or loaded with `fetch`. In TypeScript, prefer the `.items` row renderer (with `.separator` · `.noItems` · `.skeleton`); `<template>` children are for plain HTML hosts without Lit. Each row gets its own data provider at `<dataProvider>/list-item/<index>`.
|
|
4
4
|
|
|
5
5
|
## Basic example
|
|
6
6
|
|
|
@@ -16,7 +16,7 @@ Add `fetch` to load `props` from `serviceURL` + `endPoint` (or `dataProvider` wh
|
|
|
16
16
|
</template>
|
|
17
17
|
</sonic-code>
|
|
18
18
|
|
|
19
|
-
Fetch attributes (`lazyload` · `refetchEveryMs` · headers · authentication) are shared with [Fetch](/core/components/functional/fetch).
|
|
19
|
+
This example uses HTML templates; from Lit, use the [row renderer](#row-renderer) instead. Fetch attributes (`lazyload` · `refetchEveryMs` · headers · authentication) are shared with [Fetch](/core/components/functional/fetch).
|
|
20
20
|
|
|
21
21
|
## Row renderer
|
|
22
22
|
|
|
@@ -98,6 +98,8 @@ With no `loader`, nothing is shown while fetching. Set `loader` (`fixed`) or `lo
|
|
|
98
98
|
| `loader` | `fixed` (when empty) · `inline` | Loader shown while fetching. None by default |
|
|
99
99
|
| `debug` | boolean | Shows each row's data on hover |
|
|
100
100
|
|
|
101
|
+
Properties (TypeScript / Lit, preferred):
|
|
102
|
+
|
|
101
103
|
| Property | Type | Description |
|
|
102
104
|
|----------|------|-------------|
|
|
103
105
|
| `props` | array · object | Rows to render |
|
|
@@ -107,6 +109,8 @@ With no `loader`, nothing is shown while fetching. Set `loader` (`fixed`) or `lo
|
|
|
107
109
|
| `skeleton` | `() => TemplateResult` | Rendered while fetching |
|
|
108
110
|
| `itemPropertyMap` | object | `propertyMap` passed to each row subscriber |
|
|
109
111
|
|
|
112
|
+
Templates (plain HTML hosts):
|
|
113
|
+
|
|
110
114
|
| Template | Description |
|
|
111
115
|
|----------|-------------|
|
|
112
116
|
| `<template>` | Row markup; several are used in turn |
|
|
@@ -10,31 +10,31 @@ With no `rounded`, corners are square. Boolean `rounded` uses the theme token `-
|
|
|
10
10
|
<template>
|
|
11
11
|
<div class="grid gap-6 grid-cols-3 lg:grid-cols-4 items-end text-center text-xs">
|
|
12
12
|
<div>
|
|
13
|
-
<sonic-image ratio="1/1" src="img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
13
|
+
<sonic-image ratio="1/1" src="/img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
14
14
|
<p class="mt-2">default</p>
|
|
15
15
|
</div>
|
|
16
16
|
<div>
|
|
17
|
-
<sonic-image rounded="sm" ratio="1/1" src="img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
17
|
+
<sonic-image rounded="sm" ratio="1/1" src="/img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
18
18
|
<p class="mt-2">sm</p>
|
|
19
19
|
</div>
|
|
20
20
|
<div>
|
|
21
|
-
<sonic-image rounded ratio="1/1" src="img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
21
|
+
<sonic-image rounded ratio="1/1" src="/img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
22
22
|
<p class="mt-2">rounded</p>
|
|
23
23
|
</div>
|
|
24
24
|
<div>
|
|
25
|
-
<sonic-image rounded="md" ratio="1/1" src="img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
25
|
+
<sonic-image rounded="md" ratio="1/1" src="/img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
26
26
|
<p class="mt-2">md</p>
|
|
27
27
|
</div>
|
|
28
28
|
<div>
|
|
29
|
-
<sonic-image rounded="lg" ratio="1/1" src="img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
29
|
+
<sonic-image rounded="lg" ratio="1/1" src="/img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
30
30
|
<p class="mt-2">lg</p>
|
|
31
31
|
</div>
|
|
32
32
|
<div>
|
|
33
|
-
<sonic-image rounded="xl" ratio="1/1" src="img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
33
|
+
<sonic-image rounded="xl" ratio="1/1" src="/img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
34
34
|
<p class="mt-2">xl</p>
|
|
35
35
|
</div>
|
|
36
36
|
<div>
|
|
37
|
-
<sonic-image rounded="full" ratio="1/1" src="img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
37
|
+
<sonic-image rounded="full" ratio="1/1" src="/img/concorde/plane_04.jpg" alt="Concorde on the apron"></sonic-image>
|
|
38
38
|
<p class="mt-2">full</p>
|
|
39
39
|
</div>
|
|
40
40
|
</div>
|
|
@@ -48,10 +48,10 @@ With no `rounded`, corners are square. Boolean `rounded` uses the theme token `-
|
|
|
48
48
|
<sonic-code>
|
|
49
49
|
<template>
|
|
50
50
|
<div class="grid gap-8 grid-cols-2 items-center">
|
|
51
|
-
<sonic-image src="img/concorde/plane_12.jpg" alt="Concorde at the gate"></sonic-image>
|
|
52
|
-
<sonic-image ratio="16/9" src="img/concorde/plane_12.jpg" alt="Concorde at the gate"></sonic-image>
|
|
53
|
-
<sonic-image ratio="1/1" src="img/concorde/plane_12.jpg" alt="Concorde at the gate"></sonic-image>
|
|
54
|
-
<sonic-image ratio="2/3" src="img/concorde/plane_12.jpg" alt="Concorde at the gate"></sonic-image>
|
|
51
|
+
<sonic-image src="/img/concorde/plane_12.jpg" alt="Concorde at the gate"></sonic-image>
|
|
52
|
+
<sonic-image ratio="16/9" src="/img/concorde/plane_12.jpg" alt="Concorde at the gate"></sonic-image>
|
|
53
|
+
<sonic-image ratio="1/1" src="/img/concorde/plane_12.jpg" alt="Concorde at the gate"></sonic-image>
|
|
54
|
+
<sonic-image ratio="2/3" src="/img/concorde/plane_12.jpg" alt="Concorde at the gate"></sonic-image>
|
|
55
55
|
</div>
|
|
56
56
|
</template>
|
|
57
57
|
</sonic-code>
|
|
@@ -63,8 +63,8 @@ With no `rounded`, corners are square. Boolean `rounded` uses the theme token `-
|
|
|
63
63
|
<sonic-code>
|
|
64
64
|
<template>
|
|
65
65
|
<div class="grid gap-8 grid-cols-2 items-center">
|
|
66
|
-
<sonic-image ratio="11/4" src="img/concorde/plane_11.jpg" alt="Concorde flying over a field"></sonic-image>
|
|
67
|
-
<sonic-image objectPosition="center top" ratio="11/4" src="img/concorde/plane_11.jpg" alt="Concorde flying over a field"></sonic-image>
|
|
66
|
+
<sonic-image ratio="11/4" src="/img/concorde/plane_11.jpg" alt="Concorde flying over a field"></sonic-image>
|
|
67
|
+
<sonic-image objectPosition="center top" ratio="11/4" src="/img/concorde/plane_11.jpg" alt="Concorde flying over a field"></sonic-image>
|
|
68
68
|
</div>
|
|
69
69
|
</template>
|
|
70
70
|
</sonic-code>
|
|
@@ -76,7 +76,7 @@ With no `rounded`, corners are square. Boolean `rounded` uses the theme token `-
|
|
|
76
76
|
<sonic-code>
|
|
77
77
|
<template>
|
|
78
78
|
<div class="h-96 relative rounded-lg overflow-hidden">
|
|
79
|
-
<sonic-image cover src="img/concorde/plane_10.jpg" alt="Concorde fleet parked in a star"></sonic-image>
|
|
79
|
+
<sonic-image cover src="/img/concorde/plane_10.jpg" alt="Concorde fleet parked in a star"></sonic-image>
|
|
80
80
|
</div>
|
|
81
81
|
</template>
|
|
82
82
|
</sonic-code>
|
|
@@ -99,7 +99,7 @@ Set `transition` to `fade` or `fade-scale-out`. The image stays transparent unti
|
|
|
99
99
|
img.loading = 'eager';
|
|
100
100
|
img.style.width = '8rem';
|
|
101
101
|
var pics = ['01', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13'];
|
|
102
|
-
img.src = 'img/concorde/plane_' + pics[host.childElementCount % pics.length] + '.jpg';
|
|
102
|
+
img.src = '/img/concorde/plane_' + pics[host.childElementCount % pics.length] + '.jpg';
|
|
103
103
|
host.appendChild(img);
|
|
104
104
|
})()"
|
|
105
105
|
>
|
|
@@ -117,7 +117,7 @@ Set `transition` to `fade` or `fade-scale-out`. The image stays transparent unti
|
|
|
117
117
|
img.loading = 'eager';
|
|
118
118
|
img.style.width = '8rem';
|
|
119
119
|
var pics = ['01', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13'];
|
|
120
|
-
img.src = 'img/concorde/plane_' + pics[host.childElementCount % pics.length] + '.jpg';
|
|
120
|
+
img.src = '/img/concorde/plane_' + pics[host.childElementCount % pics.length] + '.jpg';
|
|
121
121
|
host.appendChild(img);
|
|
122
122
|
})()"
|
|
123
123
|
>
|
|
@@ -145,7 +145,7 @@ Always set a meaningful `alt`. Use `alt=""` only for decorative images.
|
|
|
145
145
|
rounded="md"
|
|
146
146
|
ratio="16/9"
|
|
147
147
|
alt="Crowd gathered around Concorde at night"
|
|
148
|
-
src="img/concorde/plane_07.jpg"
|
|
148
|
+
src="/img/concorde/plane_07.jpg"
|
|
149
149
|
></sonic-image>
|
|
150
150
|
</template>
|
|
151
151
|
</sonic-code>
|
|
@@ -88,7 +88,7 @@ Set **`width`** · **`height`** · **`maxWidth`** · **`maxHeight`** with CSS le
|
|
|
88
88
|
>
|
|
89
89
|
<sonic-image
|
|
90
90
|
cover
|
|
91
|
-
src="img/concorde/plane_12.jpg"
|
|
91
|
+
src="/img/concorde/plane_12.jpg"
|
|
92
92
|
alt="Concorde at the gate with boarding stairs"
|
|
93
93
|
></sonic-image>
|
|
94
94
|
</sonic-modal>
|
|
@@ -105,7 +105,7 @@ Set **`width`** · **`height`** · **`maxWidth`** · **`maxHeight`** with CSS le
|
|
|
105
105
|
<sonic-modal fullscreen id="Fullscreen">
|
|
106
106
|
<sonic-image
|
|
107
107
|
cover
|
|
108
|
-
src="img/concorde/plane_10.jpg"
|
|
108
|
+
src="/img/concorde/plane_10.jpg"
|
|
109
109
|
alt="Concorde fleet parked in a star"
|
|
110
110
|
></sonic-image>
|
|
111
111
|
</sonic-modal>
|
|
@@ -189,28 +189,23 @@ function bindImpl(
|
|
|
189
189
|
};
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
+
/** @deprecated Pass a `DataProviderKey<T>` instead of a string path (typed, refactor-safe). */
|
|
193
|
+
export function bind(
|
|
194
|
+
path: string,
|
|
195
|
+
options?: BindOptions,
|
|
196
|
+
): (target: unknown, propertyKey: string) => void;
|
|
192
197
|
/**
|
|
193
|
-
* Bidirectional binding to a publisher path
|
|
194
|
-
*
|
|
195
|
-
*
|
|
198
|
+
* Bidirectional binding to a publisher path: subscribes to changes and, with
|
|
199
|
+
* `reflect: true`, writes local assignments back. For one direction only, use
|
|
200
|
+
* `@subscribe` (read) or `@publish` (write).
|
|
201
|
+
* Supports dynamic paths: use placeholders like "users.${userIndex}" in the DataProviderKey.
|
|
196
202
|
*
|
|
197
203
|
* @example
|
|
198
|
-
* // String path (legacy):
|
|
199
|
-
* @bind("demoData.firstName")
|
|
200
|
-
* @state()
|
|
201
|
-
* firstName = "";
|
|
202
|
-
*
|
|
203
|
-
* @example
|
|
204
|
-
* // DataProviderKey with type validation:
|
|
205
204
|
* const dataKey = new DataProviderKey<Data>("data");
|
|
206
205
|
* @bind(dataKey.count, { reflect: true })
|
|
207
206
|
* @state()
|
|
208
207
|
* count: number = 0;
|
|
209
208
|
*/
|
|
210
|
-
export function bind(
|
|
211
|
-
path: string,
|
|
212
|
-
options?: BindOptions,
|
|
213
|
-
): (target: unknown, propertyKey: string) => void;
|
|
214
209
|
export function bind<T, U = any>(
|
|
215
210
|
key: DataProviderKey<T, U>,
|
|
216
211
|
options?: BindOptions,
|
|
@@ -342,12 +342,12 @@ export const DOCS_DEMO_SOURCE_REGISTRY: Record<string, DocsSource[]> = {
|
|
|
342
342
|
},
|
|
343
343
|
],
|
|
344
344
|
"demo-bind": [
|
|
345
|
-
{ path: "src/docs/example/decorators-demo-bind-demos.ts", line:
|
|
345
|
+
{ path: "src/docs/example/decorators-demo-bind-demos.ts", line: 36, label: "demo-bind" },
|
|
346
346
|
],
|
|
347
347
|
"demo-bind-reflect": [
|
|
348
348
|
{
|
|
349
349
|
path: "src/docs/example/decorators-demo-bind-demos.ts",
|
|
350
|
-
line:
|
|
350
|
+
line: 74,
|
|
351
351
|
label: "demo-bind-reflect",
|
|
352
352
|
},
|
|
353
353
|
{ path: "src/docs/example/decorators-demo-init.ts", label: "demo data" },
|
|
@@ -355,7 +355,7 @@ export const DOCS_DEMO_SOURCE_REGISTRY: Record<string, DocsSource[]> = {
|
|
|
355
355
|
"demo-bind-dynamic": [
|
|
356
356
|
{
|
|
357
357
|
path: "src/docs/example/decorators-demo-bind-demos.ts",
|
|
358
|
-
line:
|
|
358
|
+
line: 113,
|
|
359
359
|
label: "demo-bind-dynamic",
|
|
360
360
|
},
|
|
361
361
|
],
|
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
# @bind
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@bind(key)` keeps a class property and one path of the DataProvider store in sync. With `{ reflect: true }` the sync goes both ways: the property follows the store, and each assignment is written back to it. For one direction only, use the complementary decorators: [@subscribe](/docs/decorators/subscribe) to read, [@publish](/docs/decorators/publish) to write. See [Data flow](/docs/getting-started/dataFlow) for the overall model.
|
|
4
4
|
|
|
5
5
|
## Import
|
|
6
6
|
|
|
7
7
|
<sonic-code language="typescript">
|
|
8
8
|
<template>
|
|
9
9
|
import { bind } from "@supersoniks/concorde/decorators";
|
|
10
|
+
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
11
|
+
|
|
12
|
+
type Flight = { flight: string; gate: string; boarded: number };
|
|
13
|
+
const flightKey = new DataProviderKey<Flight>("flight");
|
|
10
14
|
|
|
11
|
-
@bind(
|
|
15
|
+
@bind(flightKey.boarded, { reflect: true })
|
|
12
16
|
@state()
|
|
13
|
-
|
|
17
|
+
boarded = 0;
|
|
14
18
|
</template>
|
|
15
19
|
</sonic-code>
|
|
16
20
|
|
|
17
21
|
## Basic usage
|
|
18
22
|
|
|
19
|
-
The
|
|
23
|
+
The key is a [DataProviderKey](/docs/misc/dataProviderKey): TypeScript checks that the property type matches `T` at that path. The property updates each time the store value changes. Add `@state()` so Lit re-renders.
|
|
20
24
|
|
|
21
25
|
<sonic-code>
|
|
22
26
|
<template>
|
|
@@ -25,26 +29,9 @@ The first path segment is the data provider id, the rest is dot notation (array
|
|
|
25
29
|
</template>
|
|
26
30
|
</sonic-code>
|
|
27
31
|
|
|
28
|
-
## Typed key
|
|
29
|
-
|
|
30
|
-
With a `DataProviderKey<T>`, TypeScript checks that the property type matches `T` at that path.
|
|
31
|
-
|
|
32
|
-
<sonic-code language="typescript">
|
|
33
|
-
<template>
|
|
34
|
-
import { DataProviderKey } from "@supersoniks/concorde/dataProviderKey";
|
|
35
|
-
|
|
36
|
-
type Flight = { flight: string; gate: string; boarded: number };
|
|
37
|
-
const flightKey = new DataProviderKey<Flight>("flight");
|
|
38
|
-
|
|
39
|
-
@bind(flightKey.boarded, { reflect: true })
|
|
40
|
-
@state()
|
|
41
|
-
boarded = 0;
|
|
42
|
-
</template>
|
|
43
|
-
</sonic-code>
|
|
44
|
-
|
|
45
32
|
## Reflect
|
|
46
33
|
|
|
47
|
-
|
|
34
|
+
With `reflect: true`, each assignment to the property calls `set()` at the key path, so every other subscriber sees the new value. An internal guard prevents update loops. Without `reflect` (the default), assigning the property does not touch the store, and `@bind` behaves like `@subscribe`.
|
|
48
35
|
|
|
49
36
|
<sonic-code>
|
|
50
37
|
<template>
|
|
@@ -55,7 +42,19 @@ By default (`reflect: false`) the binding is one-way: assigning the property doe
|
|
|
55
42
|
|
|
56
43
|
## Dynamic path
|
|
57
44
|
|
|
58
|
-
Placeholders such as `${index}` are resolved from properties of the same component, and `@bind` re-subscribes when they change.
|
|
45
|
+
Placeholders such as `${index}` are resolved from properties of the same component, and `@bind` re-subscribes when they change. Declare them in the key's second generic and write them in a plain string, not a backtick template literal. While a placeholder is `null` or `undefined` the binding is inactive; `{ skipEmptyPlaceholder: true }` also waits on `""`. Full rules: [Dynamic paths](/docs/misc/dynamic-path).
|
|
46
|
+
|
|
47
|
+
<sonic-code language="typescript">
|
|
48
|
+
<template>
|
|
49
|
+
const personKey = new DataProviderKey<Person, { dataProvider: string; index: number }>(
|
|
50
|
+
"${dataProvider}.${index}",
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
@bind(personKey)
|
|
54
|
+
@state()
|
|
55
|
+
person: Person | null = null;
|
|
56
|
+
</template>
|
|
57
|
+
</sonic-code>
|
|
59
58
|
|
|
60
59
|
<sonic-code>
|
|
61
60
|
<template>
|
|
@@ -72,6 +71,6 @@ The decorator subscribes in `connectedCallback` and unsubscribes in `disconnecte
|
|
|
72
71
|
|
|
73
72
|
| Argument | Type | Description |
|
|
74
73
|
|----------|------|-------------|
|
|
75
|
-
| `
|
|
74
|
+
| `key` | `DataProviderKey<T>` | Store path to bind. Supports `${prop}` placeholders |
|
|
76
75
|
| `options.reflect` | `boolean` (default `false`) | Write local assignments back to the store |
|
|
77
76
|
| `options.skipEmptyPlaceholder` | `boolean` (default `false`) | Treat a placeholder resolved to `""` as not ready |
|
|
@@ -19,6 +19,16 @@ describe("docsPagePath / docsPageHref", () => {
|
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
describe("parseDocsLocation", () => {
|
|
22
|
+
it("maps root site pages to their markdown", () => {
|
|
23
|
+
const r = parseDocsLocation("/about");
|
|
24
|
+
expect(r.url).toBe("about.md");
|
|
25
|
+
expect(r.pagePath).toBe("/about");
|
|
26
|
+
expect(parseDocsLocation("/privacy#your-rights").anchor).toBe("your-rights");
|
|
27
|
+
expect(parseDocsLocation("/about/").url).toBe("about.md");
|
|
28
|
+
expect(parseDocsLocation("/developers").url).toBe("");
|
|
29
|
+
expect(parseDocsLocation("/unknown").url).toBe("");
|
|
30
|
+
});
|
|
31
|
+
|
|
22
32
|
it("parses pretty pathname doc URLs", () => {
|
|
23
33
|
const r = parseDocsLocation("/docs/getting-started/start");
|
|
24
34
|
expect(r.url).toBe("docs/getting-started/start.md");
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
|
+
SITE_PAGE_SLUGS,
|
|
12
13
|
toPublicMdRel,
|
|
13
14
|
toPublicPath,
|
|
14
15
|
toSourceId,
|
|
@@ -107,6 +108,15 @@ export function parseDocsLocation(location: string): {
|
|
|
107
108
|
}
|
|
108
109
|
|
|
109
110
|
const rel = pathname.replace(/^\//, "");
|
|
111
|
+
if (SITE_PAGE_SLUGS.includes(rel)) {
|
|
112
|
+
return {
|
|
113
|
+
url: `${rel}.md`,
|
|
114
|
+
anchor: hash,
|
|
115
|
+
demoSubHash: hash,
|
|
116
|
+
pagePath: pathname,
|
|
117
|
+
pageHash: pathname,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
110
120
|
if (!rel || !isDocsContentPath(rel)) {
|
|
111
121
|
return empty;
|
|
112
122
|
}
|
|
@@ -14,6 +14,10 @@ type Person = { firstName: string; lastName: string; role: string };
|
|
|
14
14
|
const bindFlightKey = new DataProviderKey<Flight>("bindFlight");
|
|
15
15
|
const bindPassengersKey = new DataProviderKey<Person[]>("bindPassengers");
|
|
16
16
|
const bindCrewKey = new DataProviderKey<Person[]>("bindCrew");
|
|
17
|
+
const bindPersonKey = new DataProviderKey<
|
|
18
|
+
Person,
|
|
19
|
+
{ dataProvider: string; index: number }
|
|
20
|
+
>("${dataProvider}.${index}");
|
|
17
21
|
|
|
18
22
|
const GATES = ["B12", "B14", "C2", "D7", "E31"];
|
|
19
23
|
|
|
@@ -33,15 +37,15 @@ set(bindCrewKey, [
|
|
|
33
37
|
export class DemoBind extends LitElement {
|
|
34
38
|
static styles = [tailwind];
|
|
35
39
|
|
|
36
|
-
@bind(
|
|
40
|
+
@bind(bindFlightKey.flight)
|
|
37
41
|
@state()
|
|
38
42
|
flight = "";
|
|
39
43
|
|
|
40
|
-
@bind(
|
|
44
|
+
@bind(bindFlightKey.gate)
|
|
41
45
|
@state()
|
|
42
46
|
gate = "";
|
|
43
47
|
|
|
44
|
-
@bind(
|
|
48
|
+
@bind(bindFlightKey.updates)
|
|
45
49
|
@state()
|
|
46
50
|
updates = 0;
|
|
47
51
|
|
|
@@ -71,11 +75,11 @@ export class DemoBind extends LitElement {
|
|
|
71
75
|
export class DemoBindReflect extends LitElement {
|
|
72
76
|
static styles = [tailwind];
|
|
73
77
|
|
|
74
|
-
@bind(
|
|
78
|
+
@bind(bindReflectDemoKey.count, { reflect: true })
|
|
75
79
|
@state()
|
|
76
80
|
withReflect = 0;
|
|
77
81
|
|
|
78
|
-
@bind(
|
|
82
|
+
@bind(bindReflectDemoKey.count)
|
|
79
83
|
@state()
|
|
80
84
|
withoutReflect = 0;
|
|
81
85
|
|
|
@@ -91,7 +95,7 @@ export class DemoBindReflect extends LitElement {
|
|
|
91
95
|
render() {
|
|
92
96
|
return html`
|
|
93
97
|
<div class="mb-3">
|
|
94
|
-
Boarded passengers in the store: ${sub(
|
|
98
|
+
Boarded passengers in the store: ${sub(bindReflectDemoKey.count)}<br />
|
|
95
99
|
Property with reflect: ${this.withReflect}<br />
|
|
96
100
|
Property without reflect: ${this.withoutReflect}
|
|
97
101
|
</div>
|
|
@@ -106,27 +110,6 @@ export class DemoBindReflect extends LitElement {
|
|
|
106
110
|
}
|
|
107
111
|
}
|
|
108
112
|
|
|
109
|
-
@customElement("demo-bind-key")
|
|
110
|
-
export class DemoBindKey extends LitElement {
|
|
111
|
-
static styles = [tailwind];
|
|
112
|
-
|
|
113
|
-
@bind(bindReflectDemoKey.count, { reflect: true })
|
|
114
|
-
@state()
|
|
115
|
-
count = 0;
|
|
116
|
-
|
|
117
|
-
connectedCallback() {
|
|
118
|
-
super.connectedCallback();
|
|
119
|
-
set(bindReflectDemoKey, { count: 0 });
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
render() {
|
|
123
|
-
return html`
|
|
124
|
-
<p class="mb-3">Boarded passengers: ${this.count}</p>
|
|
125
|
-
<sonic-button @click=${() => this.count++}>Board one passenger</sonic-button>
|
|
126
|
-
`;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
113
|
@customElement("demo-bind-dynamic")
|
|
131
114
|
export class DemoBindDynamic extends LitElement {
|
|
132
115
|
static styles = [tailwind];
|
|
@@ -137,7 +120,7 @@ export class DemoBindDynamic extends LitElement {
|
|
|
137
120
|
@property({ type: Number })
|
|
138
121
|
index = 0;
|
|
139
122
|
|
|
140
|
-
@bind(
|
|
123
|
+
@bind(bindPersonKey)
|
|
141
124
|
@state()
|
|
142
125
|
person: Person | null = null;
|
|
143
126
|
|
|
@@ -36,7 +36,7 @@ export class DocsToggleIfDemo extends LitElement {
|
|
|
36
36
|
></sonic-checkbox>
|
|
37
37
|
<sonic-if .condition=${show} class="mt-4 block">
|
|
38
38
|
<sonic-image
|
|
39
|
-
src="img/concorde/plane_07.jpg"
|
|
39
|
+
src="/img/concorde/plane_07.jpg"
|
|
40
40
|
alt="Crowd gathered around Concorde at night"
|
|
41
41
|
rounded="md"
|
|
42
42
|
ratio="3/2"
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# AI agents (
|
|
1
|
+
# AI agents (skill)
|
|
2
2
|
|
|
3
|
-
Concorde ships
|
|
3
|
+
Concorde ships one [Agent Skill](https://agentskills.io), `concorde`, so coding agents follow the framework patterns. Cursor, Claude Code, JetBrains Junie and other agents load it on their own when they work on Concorde code; there is nothing to add to your `AGENTS.md`.
|
|
4
4
|
|
|
5
|
-
On a [starter](/docs/getting-started/installation) project, run `yarn ai:sync` after install. On an existing project, install Concorde first, then
|
|
5
|
+
On a [starter](/docs/getting-started/installation) project, run `yarn ai:sync` after install. On an existing project, install Concorde first, then run `ai-init`.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Commands
|
|
8
8
|
|
|
9
9
|
| Context | Command |
|
|
10
10
|
|---------|---------|
|
|
@@ -12,65 +12,39 @@ On a [starter](/docs/getting-started/installation) project, run `yarn ai:sync` a
|
|
|
12
12
|
| Any consumer app (after `yarn add @supersoniks/concorde`) | `node node_modules/@supersoniks/concorde/scripts/ai-init.mjs` |
|
|
13
13
|
| Concorde repo (contributors) | `yarn ai-init` |
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
<template>
|
|
17
|
-
# Starter (from project root)
|
|
18
|
-
yarn ai:sync
|
|
15
|
+
Re-run the same command after each Concorde upgrade to refresh the skill.
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
node node_modules/@supersoniks/concorde/scripts/ai-init.mjs
|
|
22
|
-
</template>
|
|
23
|
-
</sonic-code>
|
|
17
|
+
## The skill
|
|
24
18
|
|
|
25
|
-
|
|
19
|
+
`SKILL.md` is the entry point: where to find the truth (the project, these docs, `custom-elements.json`), the critical rules and the imports. Details live in `rules/` files that the agent reads only for the topic at hand.
|
|
26
20
|
|
|
27
|
-
|
|
|
28
|
-
|
|
29
|
-
|
|
|
30
|
-
|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
36
|
-
## `AGENTS.md` policy (non-invasive)
|
|
37
|
-
|
|
38
|
-
| Situation | Default |
|
|
39
|
-
|-----------|---------|
|
|
40
|
-
| No `AGENTS.md` | Create the Concorde guide |
|
|
41
|
-
| File with `<!-- concorde-ai -->` | Refresh the managed zone only |
|
|
42
|
-
| File **without** marker (project notes) | **Left untouched** — skills / rules are enough |
|
|
43
|
-
| `--merge-agents` / `--force-agents` / `--skip-agents` | See flags above |
|
|
44
|
-
|
|
45
|
-
```text
|
|
46
|
-
[optional project preamble — short, project-only]
|
|
47
|
-
<!-- concorde-ai -->
|
|
48
|
-
<package ai/AGENTS.md>
|
|
49
|
-
[--- + overlay AGENTS.concorde.md]
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Everything **after** `<!-- concorde-ai -->` is replaced on each `ai-init` run (idempotent). Do not paste a full copy of the Concorde guide above the marker — put project-specific notes in `AGENTS.concorde.md` (overlay). If the preamble duplicates package `AGENTS.md`, `ai-init` slims or drops it and prints a warning. Legacy filenames `AGENTS.overlay.md` / `AGENTS.starter.md` are still accepted with a deprecation warning.
|
|
21
|
+
| File | Topic |
|
|
22
|
+
|------|-------|
|
|
23
|
+
| `SKILL.md` | Sources, critical rules, component shape, imports |
|
|
24
|
+
| `rules/data.md` | Store, `DataProviderKey`, `@subscribe` / `@publish` / `@bind` / `@handle`, `sub()`, `get` / `set` / `dp` |
|
|
25
|
+
| `rules/http.md` | `Endpoint`, `@get` / `@post`, API configuration |
|
|
26
|
+
| `rules/lists-forms.md` | `sonic-list` / `sonic-queue`, form fields |
|
|
27
|
+
| `rules/styling.md` | Theme, tokens, classes, styling rules |
|
|
28
|
+
| `rules/composition.md` | Parts of compound components, built-in states |
|
|
29
|
+
| `rules/troubleshooting.md` | Symptom → cause → fix: values not updating, requests not sent, empty lists |
|
|
53
30
|
|
|
54
31
|
## What gets installed
|
|
55
32
|
|
|
56
33
|
| Path | Role |
|
|
57
34
|
|------|------|
|
|
58
|
-
|
|
|
59
|
-
| `.
|
|
60
|
-
| `.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
| `.cursor/rules/concorde.mdc` | Cursor rules (always-on patterns) |
|
|
66
|
-
| `.aiassistant/rules/concorde.md` | JetBrains AI Assistant rules |
|
|
35
|
+
| `.agents/skills/concorde/` | The skill (read directly by Cursor) |
|
|
36
|
+
| `.claude/skills/concorde` | Symlink for Claude Code |
|
|
37
|
+
| `.junie/skills/concorde` | Symlink for JetBrains Junie |
|
|
38
|
+
|
|
39
|
+
Where symlinks are not allowed (some Windows setups), the skill is copied instead. Your own skills in these folders are never touched. Commit `.agents/` and the links if your team shares agent settings.
|
|
40
|
+
|
|
41
|
+
**`AGENTS.md` stays yours:** `ai-init` never reads or writes it.
|
|
67
42
|
|
|
68
|
-
##
|
|
43
|
+
## Flags
|
|
69
44
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
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`).
|
|
45
|
+
| Flag | Effect |
|
|
46
|
+
|------|--------|
|
|
47
|
+
| `--no-links` | Install `.agents/skills` only, without the `.claude` / `.junie` links |
|
|
48
|
+
| `--overlay <dir>` | Also install the skills found in `<dir>/skills/` (project kit) |
|
|
75
49
|
|
|
76
|
-
Source files in the npm package: `node_modules/@supersoniks/concorde/ai
|
|
50
|
+
Source files in the npm package: `node_modules/@supersoniks/concorde/ai/skills/concorde/`.
|