@supersoniks/concorde 5.0.1 → 5.0.2
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/build-infos.json +1 -1
- package/concorde-core.bundle.js +519 -586
- package/concorde-core.es.js +3783 -3689
- package/dist/concorde-core.bundle.js +519 -586
- package/dist/concorde-core.es.js +3783 -3689
- package/index.html +2 -2
- package/package.json +14 -1
- package/src/core/components/ui/_css/rounded.ts +36 -0
- package/src/core/components/ui/_css/type.ts +49 -0
- package/src/core/components/ui/_i18n/ui-aria-labels.ts +104 -0
- package/src/core/components/ui/alert/alert.md +128 -72
- package/src/core/components/ui/alert/alert.spec.ts +145 -0
- package/src/core/components/ui/alert/alert.ts +86 -91
- package/src/core/components/ui/alert-messages/alert-messages.ts +1 -1
- package/src/core/components/ui/badge/badge.md +126 -78
- package/src/core/components/ui/badge/badge.ts +29 -81
- package/src/core/components/ui/button/button.md +1 -0
- package/src/core/components/ui/button/button.ts +11 -8
- package/src/core/components/ui/card/card-header.ts +7 -2
- package/src/core/components/ui/card/card.md +120 -65
- package/src/core/components/ui/divider/divider.ts +4 -9
- package/src/core/components/ui/form/fieldset/legend-description.ts +1 -1
- package/src/core/components/ui/form/fieldset/legend.ts +1 -1
- package/src/core/components/ui/form/input/input.md +1 -1
- package/src/core/components/ui/form/input/input.ts +19 -15
- package/src/core/components/ui/form/textarea/textarea.md +1 -1
- package/src/core/components/ui/image/image.md +147 -53
- package/src/core/components/ui/image/image.ts +10 -44
- package/src/core/components/ui/link/link.md +2 -2
- package/src/core/components/ui/link/link.ts +42 -37
- package/src/core/components/ui/modal/modal-close.ts +8 -12
- package/src/core/components/ui/modal/modal.ts +18 -18
- package/src/core/components/ui/pop/pop.md +7 -5
- package/src/core/components/ui/pop/pop.ts +78 -38
- package/src/core/components/ui/table/table.ts +2 -8
- package/src/core/components/ui/toast/dismissed.ts +14 -0
- package/src/core/components/ui/toast/toast-item.ts +139 -91
- package/src/core/components/ui/toast/toast.ts +4 -7
- package/src/core/components/ui/tooltip/tooltip.ts +6 -8
- package/src/core/utils/LocationHandler.ts +12 -5
- package/src/core/utils/dismissed.ts +22 -0
- package/src/core/utils/positioning.spec.ts +28 -0
- package/src/core/utils/positioning.ts +19 -0
- package/src/docs/_getting-started/concorde-outside.md +3 -3
- package/src/docs/code.ts +3 -1
- package/src/docs/search/docs-search.json +541 -1
- package/src/docs/tailwind/css/tailwind.css +6 -0
- package/src/tsconfig.json +422 -383
- package/src/tsconfig.tsbuildinfo +1 -1
- package/tailwind.config.js +50 -3
|
@@ -8,6 +8,7 @@ import { ifDefined } from "lit/directives/if-defined.js";
|
|
|
8
8
|
import { styleMap, StyleInfo } from "lit/directives/style-map.js";
|
|
9
9
|
import "@supersoniks/concorde/core/components/ui/toast/toast-item";
|
|
10
10
|
import { renderToastContent } from "@supersoniks/concorde/core/components/ui/toast/render-content";
|
|
11
|
+
import { isToastDismissed } from "@supersoniks/concorde/core/components/ui/toast/dismissed";
|
|
11
12
|
import {
|
|
12
13
|
Toast,
|
|
13
14
|
ToastContent,
|
|
@@ -66,7 +67,7 @@ export class SonicToast extends LitElement {
|
|
|
66
67
|
bottom: "1.25rem",
|
|
67
68
|
right: "1.25rem",
|
|
68
69
|
zIndex: "10000",
|
|
69
|
-
maxWidth: "
|
|
70
|
+
maxWidth: "45ch",
|
|
70
71
|
flexDirection: "column-reverse",
|
|
71
72
|
};
|
|
72
73
|
}
|
|
@@ -215,12 +216,8 @@ export class SonicToast extends LitElement {
|
|
|
215
216
|
};
|
|
216
217
|
|
|
217
218
|
// check if the toast is dismissed
|
|
218
|
-
if (conf.dismissForever && conf.id) {
|
|
219
|
-
|
|
220
|
-
const dismissedObj = JSON.parse(dismissed);
|
|
221
|
-
if (dismissedObj[conf.id]) {
|
|
222
|
-
return null;
|
|
223
|
-
}
|
|
219
|
+
if (conf.dismissForever && conf.id && isToastDismissed(conf.id)) {
|
|
220
|
+
return null;
|
|
224
221
|
}
|
|
225
222
|
|
|
226
223
|
if (toastComponent?.toasts.length) {
|
|
@@ -2,16 +2,16 @@ import { html, LitElement, css, PropertyValues } from "lit";
|
|
|
2
2
|
import { customElement, property, query } from "lit/decorators.js";
|
|
3
3
|
import {
|
|
4
4
|
computeFloatingPosition,
|
|
5
|
-
|
|
6
|
-
FloatingSide,
|
|
5
|
+
FloatingPlacement,
|
|
7
6
|
getFloatingBounds,
|
|
7
|
+
parsePlacement,
|
|
8
8
|
startFrameLoop,
|
|
9
9
|
supportsPopover,
|
|
10
10
|
} from "@supersoniks/concorde/core/utils/positioning";
|
|
11
11
|
|
|
12
12
|
const tagName = "sonic-tooltip";
|
|
13
13
|
|
|
14
|
-
type TooltipPlacement =
|
|
14
|
+
type TooltipPlacement = FloatingPlacement;
|
|
15
15
|
|
|
16
16
|
const GAP = 4;
|
|
17
17
|
|
|
@@ -102,15 +102,13 @@ export class Tooltip extends LitElement {
|
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
const
|
|
106
|
-
"-",
|
|
107
|
-
);
|
|
105
|
+
const { side, align } = parsePlacement(this.placement, "top", "center");
|
|
108
106
|
|
|
109
107
|
const { x, y } = computeFloatingPosition({
|
|
110
108
|
anchor: this.getBoundingClientRect(),
|
|
111
109
|
floating: bubble.getBoundingClientRect(),
|
|
112
|
-
side
|
|
113
|
-
align
|
|
110
|
+
side,
|
|
111
|
+
align,
|
|
114
112
|
gap: GAP,
|
|
115
113
|
bounds: getFloatingBounds(this, GAP),
|
|
116
114
|
});
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import { Route } from "./route";
|
|
2
2
|
|
|
3
|
+
export type AutoActiveMode =
|
|
4
|
+
| "strict"
|
|
5
|
+
| "partial"
|
|
6
|
+
| "disabled"
|
|
7
|
+
| "strict-path-only";
|
|
8
|
+
|
|
3
9
|
declare type Listener = {
|
|
4
10
|
location: string;
|
|
5
11
|
};
|
|
6
|
-
|
|
12
|
+
|
|
13
|
+
export type ActivableLink = HTMLElement & {
|
|
7
14
|
location?: string;
|
|
8
15
|
href?: Route | string;
|
|
9
16
|
goBack?: Route | string | null;
|
|
10
|
-
autoActive?:
|
|
17
|
+
autoActive?: AutoActiveMode;
|
|
11
18
|
setAttribute(name: string, value: string): void;
|
|
12
19
|
removeAttribute(name: string): void;
|
|
13
20
|
};
|
|
@@ -22,7 +29,7 @@ export default class LocationHandler {
|
|
|
22
29
|
static listening = false;
|
|
23
30
|
static prevURL: string = document.location?.href.replace(
|
|
24
31
|
document.location.origin,
|
|
25
|
-
""
|
|
32
|
+
"",
|
|
26
33
|
);
|
|
27
34
|
static listen() {
|
|
28
35
|
if (!LocationHandler.listening) {
|
|
@@ -30,7 +37,7 @@ export default class LocationHandler {
|
|
|
30
37
|
}
|
|
31
38
|
const newURL = document.location?.href.replace(
|
|
32
39
|
document.location.origin,
|
|
33
|
-
""
|
|
40
|
+
"",
|
|
34
41
|
);
|
|
35
42
|
if (LocationHandler.prevURL && LocationHandler.prevURL != newURL) {
|
|
36
43
|
LocationHandler.prevURL = newURL;
|
|
@@ -116,7 +123,7 @@ export default class LocationHandler {
|
|
|
116
123
|
prevSp = sp;
|
|
117
124
|
}
|
|
118
125
|
|
|
119
|
-
to = "/" + newPathName.join("/") + url.search + (url.hash ?
|
|
126
|
+
to = "/" + newPathName.join("/") + url.search + (url.hash ? url.hash : "");
|
|
120
127
|
if (component.hasAttribute("pushState")) {
|
|
121
128
|
history.pushState(null, "", to);
|
|
122
129
|
} else if (component.hasAttribute("replaceState")) {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
function readDismissed(storageKey: string): Record<string, boolean> {
|
|
2
|
+
try {
|
|
3
|
+
const parsed = JSON.parse(localStorage.getItem(storageKey) || "{}");
|
|
4
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
5
|
+
} catch {
|
|
6
|
+
return {};
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function isDismissed(storageKey: string, id: string | number): boolean {
|
|
11
|
+
return !!readDismissed(storageKey)[id];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function markDismissed(storageKey: string, id: string | number): void {
|
|
15
|
+
const dismissed = readDismissed(storageKey);
|
|
16
|
+
dismissed[id] = true;
|
|
17
|
+
try {
|
|
18
|
+
localStorage.setItem(storageKey, JSON.stringify(dismissed));
|
|
19
|
+
} catch {
|
|
20
|
+
// stockage indisponible (mode privé, quota)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
computeFloatingPosition,
|
|
4
4
|
FloatingBounds,
|
|
5
5
|
FloatingSide,
|
|
6
|
+
parsePlacement,
|
|
6
7
|
} from "./positioning";
|
|
7
8
|
|
|
8
9
|
type Rect = {
|
|
@@ -178,3 +179,30 @@ describe("computeFloatingPosition", () => {
|
|
|
178
179
|
});
|
|
179
180
|
});
|
|
180
181
|
});
|
|
182
|
+
|
|
183
|
+
describe("parsePlacement", () => {
|
|
184
|
+
it("lit côté et alignement", () => {
|
|
185
|
+
expect(parsePlacement("left-end", "bottom", "start")).toEqual({
|
|
186
|
+
side: "left",
|
|
187
|
+
align: "end",
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("applique l'alignement par défaut quand il est absent", () => {
|
|
192
|
+
expect(parsePlacement("top", "bottom", "start")).toEqual({
|
|
193
|
+
side: "top",
|
|
194
|
+
align: "start",
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it("retombe sur les défauts pour une valeur inconnue", () => {
|
|
199
|
+
expect(parsePlacement("foo-bar", "top", "center")).toEqual({
|
|
200
|
+
side: "top",
|
|
201
|
+
align: "center",
|
|
202
|
+
});
|
|
203
|
+
expect(parsePlacement(undefined, "top", "center")).toEqual({
|
|
204
|
+
side: "top",
|
|
205
|
+
align: "center",
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
});
|
|
@@ -2,6 +2,25 @@ import HTML, { SearchableDomElement } from "./HTML";
|
|
|
2
2
|
|
|
3
3
|
export type FloatingSide = "top" | "right" | "bottom" | "left";
|
|
4
4
|
export type FloatingAlign = "start" | "center" | "end";
|
|
5
|
+
export type FloatingPlacement =
|
|
6
|
+
| FloatingSide
|
|
7
|
+
| `${FloatingSide}-${FloatingAlign}`;
|
|
8
|
+
|
|
9
|
+
const SIDES: readonly string[] = ["top", "right", "bottom", "left"];
|
|
10
|
+
const ALIGNS: readonly string[] = ["start", "center", "end"];
|
|
11
|
+
|
|
12
|
+
/** Découpe `"côté-alignement"` ; une valeur inconnue retombe sur le défaut. */
|
|
13
|
+
export function parsePlacement(
|
|
14
|
+
placement: string | undefined,
|
|
15
|
+
defaultSide: FloatingSide,
|
|
16
|
+
defaultAlign: FloatingAlign,
|
|
17
|
+
): { side: FloatingSide; align: FloatingAlign } {
|
|
18
|
+
const [side, align] = (placement ?? "").split("-");
|
|
19
|
+
return {
|
|
20
|
+
side: SIDES.includes(side) ? (side as FloatingSide) : defaultSide,
|
|
21
|
+
align: ALIGNS.includes(align) ? (align as FloatingAlign) : defaultAlign,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
5
24
|
|
|
6
25
|
export type FloatingBounds = {
|
|
7
26
|
minX: number;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Installation
|
|
2
2
|
|
|
3
|
-
<sonic-alert status="
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
<sonic-alert status="info" label="Recommended — use the starter" background>
|
|
4
|
+
<p>For almost all new projects, use <a href="https://www.npmjs.com/package/@supersoniks/create-concorde-ts-starter">create-concorde-ts-starter</a></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
6
|
</sonic-alert>
|
|
7
7
|
|
|
8
8
|
## Starter
|
package/src/docs/code.ts
CHANGED
|
@@ -36,6 +36,8 @@ export class DocsCode extends LitElement {
|
|
|
36
36
|
pre {
|
|
37
37
|
font-size: 13px !important;
|
|
38
38
|
padding-right: 5rem !important;
|
|
39
|
+
border: 1px solid var(--sc-base-200);
|
|
40
|
+
border-radius: var(--sc-rounded);
|
|
39
41
|
}
|
|
40
42
|
.custom-scroll {
|
|
41
43
|
overflow: auto !important;
|
|
@@ -239,7 +241,7 @@ export class DocsCode extends LitElement {
|
|
|
239
241
|
return html`
|
|
240
242
|
<div
|
|
241
243
|
class="relative ${this.language === "markup"
|
|
242
|
-
? "border border-neutral-
|
|
244
|
+
? "rounded-md border border-neutral-200 bg-neutral-50/80 dark:border-neutral-700/80 dark:bg-neutral-900/40 p-4"
|
|
243
245
|
: ""}"
|
|
244
246
|
>
|
|
245
247
|
${this.language === "markup" && !this.noOutput
|