@sentropic/design-system-svelte 0.7.0 → 0.8.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/dist/Accordion.svelte +11 -3
- package/dist/Accordion.svelte.d.ts.map +1 -1
- package/dist/Alert.svelte +1 -1
- package/dist/AreaChart.svelte +414 -0
- package/dist/AreaChart.svelte.d.ts +18 -0
- package/dist/AreaChart.svelte.d.ts.map +1 -0
- package/dist/BarChart.svelte +383 -0
- package/dist/BarChart.svelte.d.ts +18 -0
- package/dist/BarChart.svelte.d.ts.map +1 -0
- package/dist/ChatComposer.svelte +238 -0
- package/dist/ChatComposer.svelte.d.ts +57 -0
- package/dist/ChatComposer.svelte.d.ts.map +1 -0
- package/dist/ChatMessage.svelte +271 -0
- package/dist/ChatMessage.svelte.d.ts +19 -0
- package/dist/ChatMessage.svelte.d.ts.map +1 -0
- package/dist/ChatThread.svelte +120 -0
- package/dist/ChatThread.svelte.d.ts +13 -0
- package/dist/ChatThread.svelte.d.ts.map +1 -0
- package/dist/Combobox.svelte +16 -2
- package/dist/Combobox.svelte.d.ts.map +1 -1
- package/dist/CopyButton.svelte +3 -7
- package/dist/CopyButton.svelte.d.ts.map +1 -1
- package/dist/Drawer.svelte +23 -3
- package/dist/Drawer.svelte.d.ts +1 -1
- package/dist/Drawer.svelte.d.ts.map +1 -1
- package/dist/Dropdown.svelte +38 -2
- package/dist/Dropdown.svelte.d.ts.map +1 -1
- package/dist/FileUploader.svelte +119 -4
- package/dist/FileUploader.svelte.d.ts +1 -0
- package/dist/FileUploader.svelte.d.ts.map +1 -1
- package/dist/IconButton.svelte +103 -0
- package/dist/IconButton.svelte.d.ts +15 -0
- package/dist/IconButton.svelte.d.ts.map +1 -0
- package/dist/InlineLoading.svelte +22 -14
- package/dist/InlineLoading.svelte.d.ts.map +1 -1
- package/dist/LineChart.svelte +397 -0
- package/dist/LineChart.svelte.d.ts +19 -0
- package/dist/LineChart.svelte.d.ts.map +1 -0
- package/dist/Menu.svelte +164 -24
- package/dist/Menu.svelte.d.ts +26 -4
- package/dist/Menu.svelte.d.ts.map +1 -1
- package/dist/MenuPopover.svelte +180 -0
- package/dist/MenuPopover.svelte.d.ts +17 -0
- package/dist/MenuPopover.svelte.d.ts.map +1 -0
- package/dist/MenuTriggerButton.svelte +50 -0
- package/dist/MenuTriggerButton.svelte.d.ts +16 -0
- package/dist/MenuTriggerButton.svelte.d.ts.map +1 -0
- package/dist/MessageActions.svelte +89 -0
- package/dist/MessageActions.svelte.d.ts +22 -0
- package/dist/MessageActions.svelte.d.ts.map +1 -0
- package/dist/MessageStatusBadge.svelte +52 -0
- package/dist/MessageStatusBadge.svelte.d.ts +12 -0
- package/dist/MessageStatusBadge.svelte.d.ts.map +1 -0
- package/dist/Modal.svelte +83 -3
- package/dist/Modal.svelte.d.ts.map +1 -1
- package/dist/MultiSelect.svelte +17 -3
- package/dist/MultiSelect.svelte.d.ts.map +1 -1
- package/dist/OverflowMenu.svelte +111 -24
- package/dist/OverflowMenu.svelte.d.ts +21 -2
- package/dist/OverflowMenu.svelte.d.ts.map +1 -1
- package/dist/PaginationNav.svelte +6 -21
- package/dist/PaginationNav.svelte.d.ts.map +1 -1
- package/dist/PasswordInput.svelte +3 -9
- package/dist/PasswordInput.svelte.d.ts.map +1 -1
- package/dist/ProgressIndicator.svelte +3 -19
- package/dist/ProgressIndicator.svelte.d.ts.map +1 -1
- package/dist/Search.svelte +3 -6
- package/dist/Search.svelte.d.ts.map +1 -1
- package/dist/Sparkline.svelte +123 -0
- package/dist/Sparkline.svelte.d.ts +15 -0
- package/dist/Sparkline.svelte.d.ts.map +1 -0
- package/dist/StreamingMessage.svelte +292 -0
- package/dist/StreamingMessage.svelte.d.ts +51 -0
- package/dist/StreamingMessage.svelte.d.ts.map +1 -0
- package/dist/Tag.svelte +2 -1
- package/dist/Tag.svelte.d.ts.map +1 -1
- package/dist/Toast.svelte +2 -2
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -0
- package/package.json +3 -2
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
|
|
5
|
+
type MenuPopoverProps = Omit<HTMLAttributes<HTMLDivElement>, "class"> & {
|
|
6
|
+
open?: boolean;
|
|
7
|
+
trigger: HTMLElement | null;
|
|
8
|
+
placement?: "bottom-start" | "bottom-end" | "top-start" | "top-end";
|
|
9
|
+
align?: "start" | "end" | "center";
|
|
10
|
+
label: string;
|
|
11
|
+
class?: string;
|
|
12
|
+
closeOnOutside?: boolean;
|
|
13
|
+
closeOnEscape?: boolean;
|
|
14
|
+
children?: Snippet;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
open = $bindable(false),
|
|
19
|
+
trigger,
|
|
20
|
+
placement = "bottom-start",
|
|
21
|
+
align,
|
|
22
|
+
label,
|
|
23
|
+
class: className,
|
|
24
|
+
closeOnOutside = true,
|
|
25
|
+
closeOnEscape = true,
|
|
26
|
+
children,
|
|
27
|
+
...rest
|
|
28
|
+
}: MenuPopoverProps = $props();
|
|
29
|
+
|
|
30
|
+
let panel: HTMLDivElement | undefined = $state();
|
|
31
|
+
let top = $state(0);
|
|
32
|
+
let left = $state(0);
|
|
33
|
+
let alignmentRight = $state(false);
|
|
34
|
+
let alignmentCenter = $state(false);
|
|
35
|
+
|
|
36
|
+
const GAP = 4;
|
|
37
|
+
|
|
38
|
+
function computePosition() {
|
|
39
|
+
if (!trigger) return;
|
|
40
|
+
const rect = trigger.getBoundingClientRect();
|
|
41
|
+
const verticalUp = placement === "top-start" || placement === "top-end";
|
|
42
|
+
const horizontalEnd = placement === "bottom-end" || placement === "top-end";
|
|
43
|
+
|
|
44
|
+
// Resolve secondary alignment override (align prop overrides the placement's horizontal cue).
|
|
45
|
+
const resolvedAlign: "start" | "end" | "center" = align
|
|
46
|
+
?? (horizontalEnd ? "end" : "start");
|
|
47
|
+
|
|
48
|
+
alignmentRight = resolvedAlign === "end";
|
|
49
|
+
alignmentCenter = resolvedAlign === "center";
|
|
50
|
+
|
|
51
|
+
if (verticalUp) {
|
|
52
|
+
// We don't know the panel height yet on first frame; position the panel's
|
|
53
|
+
// bottom edge above the trigger using transform.
|
|
54
|
+
top = rect.top + window.scrollY - GAP;
|
|
55
|
+
} else {
|
|
56
|
+
top = rect.bottom + window.scrollY + GAP;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (resolvedAlign === "end") {
|
|
60
|
+
left = rect.right + window.scrollX;
|
|
61
|
+
} else if (resolvedAlign === "center") {
|
|
62
|
+
left = rect.left + window.scrollX + rect.width / 2;
|
|
63
|
+
} else {
|
|
64
|
+
left = rect.left + window.scrollX;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
$effect(() => {
|
|
69
|
+
if (!open) return;
|
|
70
|
+
computePosition();
|
|
71
|
+
const onScroll = () => computePosition();
|
|
72
|
+
const onResize = () => computePosition();
|
|
73
|
+
window.addEventListener("scroll", onScroll, true);
|
|
74
|
+
window.addEventListener("resize", onResize);
|
|
75
|
+
return () => {
|
|
76
|
+
window.removeEventListener("scroll", onScroll, true);
|
|
77
|
+
window.removeEventListener("resize", onResize);
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
function isWithin(event: Event, node: HTMLElement | null | undefined): boolean {
|
|
82
|
+
if (!node) return false;
|
|
83
|
+
const path = typeof (event as Event & { composedPath?: () => EventTarget[] }).composedPath === "function"
|
|
84
|
+
? (event as Event & { composedPath: () => EventTarget[] }).composedPath()
|
|
85
|
+
: [];
|
|
86
|
+
if (path.includes(node)) return true;
|
|
87
|
+
const target = event.target as Node | null;
|
|
88
|
+
return Boolean(target && node.contains(target));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function onWindowPointerDown(event: PointerEvent) {
|
|
92
|
+
if (!open || !closeOnOutside) return;
|
|
93
|
+
if (isWithin(event, panel)) return;
|
|
94
|
+
if (isWithin(event, trigger)) return;
|
|
95
|
+
open = false;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function onWindowKeyDown(event: KeyboardEvent) {
|
|
99
|
+
if (!open || !closeOnEscape) return;
|
|
100
|
+
if (event.key === "Escape") {
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
open = false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const classes = () =>
|
|
107
|
+
[
|
|
108
|
+
"st-menuPopover",
|
|
109
|
+
`st-menuPopover--${placement}`,
|
|
110
|
+
alignmentRight ? "st-menuPopover--alignEnd" : null,
|
|
111
|
+
alignmentCenter ? "st-menuPopover--alignCenter" : null,
|
|
112
|
+
className
|
|
113
|
+
]
|
|
114
|
+
.filter(Boolean)
|
|
115
|
+
.join(" ");
|
|
116
|
+
</script>
|
|
117
|
+
|
|
118
|
+
<svelte:window onpointerdown={onWindowPointerDown} onkeydown={onWindowKeyDown} />
|
|
119
|
+
|
|
120
|
+
{#if open}
|
|
121
|
+
<div
|
|
122
|
+
{...rest}
|
|
123
|
+
bind:this={panel}
|
|
124
|
+
class={classes()}
|
|
125
|
+
role="dialog"
|
|
126
|
+
aria-label={label}
|
|
127
|
+
style={`top: ${top}px; left: ${left}px;`}
|
|
128
|
+
>
|
|
129
|
+
{@render children?.()}
|
|
130
|
+
</div>
|
|
131
|
+
{/if}
|
|
132
|
+
|
|
133
|
+
<style>
|
|
134
|
+
.st-menuPopover {
|
|
135
|
+
background: var(--st-component-menu-background, var(--st-semantic-surface-raised, #ffffff));
|
|
136
|
+
border: 1px solid var(--st-component-menu-border, var(--st-semantic-border-subtle));
|
|
137
|
+
border-radius: var(--st-component-menu-radius, 0.375rem);
|
|
138
|
+
box-shadow: var(--st-component-menu-shadow, 0 8px 24px rgb(15 23 42 / 0.14));
|
|
139
|
+
color: var(--st-component-menu-text, var(--st-semantic-text-primary));
|
|
140
|
+
min-width: var(--st-component-menu-minWidth, 12rem);
|
|
141
|
+
max-width: var(--st-component-menu-maxWidth, 18rem);
|
|
142
|
+
max-height: calc(100vh - 2rem);
|
|
143
|
+
overflow: auto;
|
|
144
|
+
padding: 0;
|
|
145
|
+
position: absolute;
|
|
146
|
+
z-index: var(--st-component-popover-zIndex, 80);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* Default origin: left edge aligned to trigger left. */
|
|
150
|
+
.st-menuPopover--alignEnd {
|
|
151
|
+
/* Move the panel left by 100% of its width so its right edge aligns to `left`. */
|
|
152
|
+
transform: translateX(-100%);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.st-menuPopover--alignCenter {
|
|
156
|
+
transform: translateX(-50%);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* For top placements, the `top` value is the trigger's top edge; shift the
|
|
160
|
+
panel up by 100% of its height so its bottom edge sits above the trigger. */
|
|
161
|
+
.st-menuPopover--top-start {
|
|
162
|
+
transform: translateY(-100%);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.st-menuPopover--top-end {
|
|
166
|
+
transform: translate(-100%, -100%);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.st-menuPopover--top-start.st-menuPopover--alignEnd {
|
|
170
|
+
transform: translate(-100%, -100%);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.st-menuPopover--top-start.st-menuPopover--alignCenter {
|
|
174
|
+
transform: translate(-50%, -100%);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.st-menuPopover--top-end.st-menuPopover--alignCenter {
|
|
178
|
+
transform: translate(-50%, -100%);
|
|
179
|
+
}
|
|
180
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
type MenuPopoverProps = Omit<HTMLAttributes<HTMLDivElement>, "class"> & {
|
|
4
|
+
open?: boolean;
|
|
5
|
+
trigger: HTMLElement | null;
|
|
6
|
+
placement?: "bottom-start" | "bottom-end" | "top-start" | "top-end";
|
|
7
|
+
align?: "start" | "end" | "center";
|
|
8
|
+
label: string;
|
|
9
|
+
class?: string;
|
|
10
|
+
closeOnOutside?: boolean;
|
|
11
|
+
closeOnEscape?: boolean;
|
|
12
|
+
children?: Snippet;
|
|
13
|
+
};
|
|
14
|
+
declare const MenuPopover: import("svelte").Component<MenuPopoverProps, {}, "open">;
|
|
15
|
+
type MenuPopover = ReturnType<typeof MenuPopover>;
|
|
16
|
+
export default MenuPopover;
|
|
17
|
+
//# sourceMappingURL=MenuPopover.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MenuPopover.svelte.d.ts","sourceRoot":"","sources":["../src/lib/MenuPopover.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,GAAG;IACtE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;IACpE,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAuHJ,QAAA,MAAM,WAAW,0DAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
4
|
+
import { ChevronDownCircle } from "@lucide/svelte";
|
|
5
|
+
import IconButton from "./IconButton.svelte";
|
|
6
|
+
|
|
7
|
+
type MenuTriggerButtonProps = Omit<
|
|
8
|
+
HTMLButtonAttributes,
|
|
9
|
+
"class" | "type" | "aria-label" | "aria-haspopup" | "aria-expanded" | "aria-controls"
|
|
10
|
+
> & {
|
|
11
|
+
"aria-label": string;
|
|
12
|
+
"aria-controls"?: string;
|
|
13
|
+
expanded?: boolean;
|
|
14
|
+
size?: "sm" | "md" | "lg";
|
|
15
|
+
variant?: "ghost" | "secondary";
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
class?: string;
|
|
18
|
+
children?: Snippet;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
"aria-label": ariaLabel,
|
|
23
|
+
"aria-controls": ariaControls,
|
|
24
|
+
expanded = false,
|
|
25
|
+
size = "md",
|
|
26
|
+
variant = "ghost",
|
|
27
|
+
disabled = false,
|
|
28
|
+
class: className,
|
|
29
|
+
children,
|
|
30
|
+
...rest
|
|
31
|
+
}: MenuTriggerButtonProps = $props();
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<IconButton
|
|
35
|
+
{...rest}
|
|
36
|
+
aria-label={ariaLabel}
|
|
37
|
+
aria-haspopup="menu"
|
|
38
|
+
aria-expanded={expanded}
|
|
39
|
+
aria-controls={ariaControls}
|
|
40
|
+
{size}
|
|
41
|
+
{variant}
|
|
42
|
+
{disabled}
|
|
43
|
+
class={className}
|
|
44
|
+
>
|
|
45
|
+
{#if children}
|
|
46
|
+
{@render children()}
|
|
47
|
+
{:else}
|
|
48
|
+
<ChevronDownCircle size={18} strokeWidth={2} aria-hidden="true" />
|
|
49
|
+
{/if}
|
|
50
|
+
</IconButton>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
3
|
+
type MenuTriggerButtonProps = Omit<HTMLButtonAttributes, "class" | "type" | "aria-label" | "aria-haspopup" | "aria-expanded" | "aria-controls"> & {
|
|
4
|
+
"aria-label": string;
|
|
5
|
+
"aria-controls"?: string;
|
|
6
|
+
expanded?: boolean;
|
|
7
|
+
size?: "sm" | "md" | "lg";
|
|
8
|
+
variant?: "ghost" | "secondary";
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
class?: string;
|
|
11
|
+
children?: Snippet;
|
|
12
|
+
};
|
|
13
|
+
declare const MenuTriggerButton: import("svelte").Component<MenuTriggerButtonProps, {}, "">;
|
|
14
|
+
type MenuTriggerButton = ReturnType<typeof MenuTriggerButton>;
|
|
15
|
+
export default MenuTriggerButton;
|
|
16
|
+
//# sourceMappingURL=MenuTriggerButton.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MenuTriggerButton.svelte.d.ts","sourceRoot":"","sources":["../src/lib/MenuTriggerButton.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAK1D,KAAK,sBAAsB,GAAG,IAAI,CAChC,oBAAoB,EACpB,OAAO,GAAG,MAAM,GAAG,YAAY,GAAG,eAAe,GAAG,eAAe,GAAG,eAAe,CACtF,GAAG;IACF,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AA+BJ,QAAA,MAAM,iBAAiB,4DAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import IconButton from "./IconButton.svelte";
|
|
4
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
5
|
+
|
|
6
|
+
export type MessageActionVariant = "default" | "danger";
|
|
7
|
+
|
|
8
|
+
export type MessageAction = {
|
|
9
|
+
id: string;
|
|
10
|
+
label: string;
|
|
11
|
+
icon: Snippet;
|
|
12
|
+
onClick?: () => void;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
variant?: MessageActionVariant;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type MessageActionsVisibility = "always" | "hover";
|
|
18
|
+
|
|
19
|
+
type MessageActionsProps = Omit<HTMLAttributes<HTMLElement>, "children" | "class"> & {
|
|
20
|
+
actions: MessageAction[];
|
|
21
|
+
visibility?: MessageActionsVisibility;
|
|
22
|
+
overflow?: Snippet;
|
|
23
|
+
class?: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
let {
|
|
27
|
+
actions = [],
|
|
28
|
+
visibility = "hover",
|
|
29
|
+
overflow,
|
|
30
|
+
class: className,
|
|
31
|
+
...rest
|
|
32
|
+
}: MessageActionsProps = $props();
|
|
33
|
+
|
|
34
|
+
const classes = () =>
|
|
35
|
+
["st-messageActions", visibility === "hover" && "st-messageActions--hoverOnly", className]
|
|
36
|
+
.filter(Boolean)
|
|
37
|
+
.join(" ");
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<div class={classes()} {...rest} role="group" aria-label="Actions du message">
|
|
41
|
+
{#if actions.length > 0}
|
|
42
|
+
{#each actions as action (action.id)}
|
|
43
|
+
<IconButton
|
|
44
|
+
size="sm"
|
|
45
|
+
variant={action.variant === "danger" ? "danger" : "ghost"}
|
|
46
|
+
aria-label={action.label}
|
|
47
|
+
disabled={action.disabled}
|
|
48
|
+
onclick={action.onClick}
|
|
49
|
+
>
|
|
50
|
+
{@render action.icon()}
|
|
51
|
+
</IconButton>
|
|
52
|
+
{/each}
|
|
53
|
+
{/if}
|
|
54
|
+
{#if overflow}
|
|
55
|
+
<div class="st-messageActions__overflow">{@render overflow()}</div>
|
|
56
|
+
{/if}
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<style>
|
|
60
|
+
.st-messageActions {
|
|
61
|
+
align-items: center;
|
|
62
|
+
display: inline-flex;
|
|
63
|
+
gap: 0.25rem;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.st-messageActions--hoverOnly {
|
|
67
|
+
opacity: 0;
|
|
68
|
+
pointer-events: none;
|
|
69
|
+
transition:
|
|
70
|
+
opacity var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.st-messageActions--hoverOnly:focus-within,
|
|
74
|
+
.st-messageActions--hoverOnly:hover {
|
|
75
|
+
opacity: 1;
|
|
76
|
+
pointer-events: auto;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@media (prefers-reduced-motion: reduce) {
|
|
80
|
+
.st-messageActions--hoverOnly {
|
|
81
|
+
transition: none;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.st-messageActions__overflow {
|
|
86
|
+
align-items: center;
|
|
87
|
+
display: inline-flex;
|
|
88
|
+
}
|
|
89
|
+
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
export type MessageActionVariant = "default" | "danger";
|
|
4
|
+
export type MessageAction = {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
icon: Snippet;
|
|
8
|
+
onClick?: () => void;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
variant?: MessageActionVariant;
|
|
11
|
+
};
|
|
12
|
+
type MessageActionsVisibility = "always" | "hover";
|
|
13
|
+
type MessageActionsProps = Omit<HTMLAttributes<HTMLElement>, "children" | "class"> & {
|
|
14
|
+
actions: MessageAction[];
|
|
15
|
+
visibility?: MessageActionsVisibility;
|
|
16
|
+
overflow?: Snippet;
|
|
17
|
+
class?: string;
|
|
18
|
+
};
|
|
19
|
+
declare const MessageActions: import("svelte").Component<MessageActionsProps, {}, "">;
|
|
20
|
+
type MessageActions = ReturnType<typeof MessageActions>;
|
|
21
|
+
export default MessageActions;
|
|
22
|
+
//# sourceMappingURL=MessageActions.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageActions.svelte.d.ts","sourceRoot":"","sources":["../src/lib/MessageActions.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAExD,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC,CAAC;AAEF,KAAK,wBAAwB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEnD,KAAK,mBAAmB,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,GAAG;IACnF,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,wBAAwB,CAAC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAyCJ,QAAA,MAAM,cAAc,yDAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Tag from "./Tag.svelte";
|
|
3
|
+
import type { ChatMessageStatus } from "./ChatMessage.svelte";
|
|
4
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
5
|
+
|
|
6
|
+
type StatusTone = "neutral" | "success" | "warning" | "error" | "info";
|
|
7
|
+
|
|
8
|
+
type MessageStatusBadgeProps = Omit<HTMLAttributes<HTMLSpanElement>, "children"> & {
|
|
9
|
+
status: ChatMessageStatus;
|
|
10
|
+
tone?: StatusTone;
|
|
11
|
+
class?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
let { status, tone, class: className, ...rest }: MessageStatusBadgeProps = $props();
|
|
15
|
+
|
|
16
|
+
const mappedTone = () => {
|
|
17
|
+
if (tone) return tone;
|
|
18
|
+
if (status === "processing") return "info";
|
|
19
|
+
if (status === "failed") return "error";
|
|
20
|
+
if (status === "completed") return "success";
|
|
21
|
+
return "warning";
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const label = () => {
|
|
25
|
+
if (status === "pending") return "En attente";
|
|
26
|
+
if (status === "processing") return "En cours";
|
|
27
|
+
if (status === "completed") return "Terminé";
|
|
28
|
+
return "Échec";
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const classes = () => ["st-messageStatusBadge", className].filter(Boolean).join(" ");
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<Tag tone={mappedTone()} size="sm" class={classes()} {...rest} aria-label={`Statut: ${label()}`}>
|
|
35
|
+
<span class="st-messageStatusBadge__dot" aria-hidden="true"></span>
|
|
36
|
+
{label()}
|
|
37
|
+
</Tag>
|
|
38
|
+
|
|
39
|
+
<style>
|
|
40
|
+
.st-messageStatusBadge {
|
|
41
|
+
align-items: center;
|
|
42
|
+
text-transform: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.st-messageStatusBadge__dot {
|
|
46
|
+
background: currentColor;
|
|
47
|
+
border-radius: 999px;
|
|
48
|
+
display: inline-block;
|
|
49
|
+
height: 0.38rem;
|
|
50
|
+
width: 0.38rem;
|
|
51
|
+
}
|
|
52
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ChatMessageStatus } from "./ChatMessage.svelte";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
type StatusTone = "neutral" | "success" | "warning" | "error" | "info";
|
|
4
|
+
type MessageStatusBadgeProps = Omit<HTMLAttributes<HTMLSpanElement>, "children"> & {
|
|
5
|
+
status: ChatMessageStatus;
|
|
6
|
+
tone?: StatusTone;
|
|
7
|
+
class?: string;
|
|
8
|
+
};
|
|
9
|
+
declare const MessageStatusBadge: import("svelte").Component<MessageStatusBadgeProps, {}, "">;
|
|
10
|
+
type MessageStatusBadge = ReturnType<typeof MessageStatusBadge>;
|
|
11
|
+
export default MessageStatusBadge;
|
|
12
|
+
//# sourceMappingURL=MessageStatusBadge.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageStatusBadge.svelte.d.ts","sourceRoot":"","sources":["../src/lib/MessageStatusBadge.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAEvE,KAAK,uBAAuB,GAAG,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE,UAAU,CAAC,GAAG;IACjF,MAAM,EAAE,iBAAiB,CAAC;IAC1B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAqCJ,QAAA,MAAM,kBAAkB,6DAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|
package/dist/Modal.svelte
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { X } from "@lucide/svelte";
|
|
3
|
+
import { tick } from "svelte";
|
|
2
4
|
import type { Snippet } from "svelte";
|
|
3
5
|
import type { HTMLAttributes } from "svelte/elements";
|
|
4
6
|
|
|
@@ -25,19 +27,97 @@
|
|
|
25
27
|
...rest
|
|
26
28
|
}: ModalProps = $props();
|
|
27
29
|
|
|
30
|
+
let dialog: HTMLElement | undefined = $state();
|
|
31
|
+
let closeButton: HTMLButtonElement | undefined = $state();
|
|
32
|
+
let previousFocus: HTMLElement | null = null;
|
|
28
33
|
const classes = () => ["st-modal", className].filter(Boolean).join(" ");
|
|
34
|
+
|
|
35
|
+
const focusableSelector = [
|
|
36
|
+
"a[href]",
|
|
37
|
+
"button:not([disabled])",
|
|
38
|
+
"input:not([disabled])",
|
|
39
|
+
"select:not([disabled])",
|
|
40
|
+
"textarea:not([disabled])",
|
|
41
|
+
"[tabindex]:not([tabindex='-1'])"
|
|
42
|
+
].join(",");
|
|
43
|
+
|
|
44
|
+
$effect(() => {
|
|
45
|
+
if (!open) return;
|
|
46
|
+
previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
47
|
+
tick().then(() => closeButton?.focus());
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
function requestClose() {
|
|
51
|
+
onclose?.();
|
|
52
|
+
tick().then(() => previousFocus?.focus());
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function trapFocus(event: KeyboardEvent) {
|
|
56
|
+
if (!dialog || event.key !== "Tab") return;
|
|
57
|
+
const focusable = Array.from(dialog.querySelectorAll<HTMLElement>(focusableSelector));
|
|
58
|
+
|
|
59
|
+
if (focusable.length === 0) {
|
|
60
|
+
event.preventDefault();
|
|
61
|
+
dialog.focus();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const first = focusable[0];
|
|
66
|
+
const last = focusable.at(-1);
|
|
67
|
+
const active = document.activeElement;
|
|
68
|
+
|
|
69
|
+
if (!dialog.contains(active)) {
|
|
70
|
+
event.preventDefault();
|
|
71
|
+
first.focus();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (event.shiftKey && active === first) {
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
last?.focus();
|
|
78
|
+
} else if (!event.shiftKey && active === last) {
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
first.focus();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function onWindowKeydown(event: KeyboardEvent) {
|
|
85
|
+
if (!open) return;
|
|
86
|
+
if (event.key === "Escape") {
|
|
87
|
+
event.preventDefault();
|
|
88
|
+
requestClose();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
trapFocus(event);
|
|
92
|
+
}
|
|
29
93
|
</script>
|
|
30
94
|
|
|
95
|
+
<svelte:window onkeydown={onWindowKeydown} />
|
|
96
|
+
|
|
31
97
|
{#if open}
|
|
32
98
|
<div class="st-modal__backdrop">
|
|
33
|
-
<section
|
|
99
|
+
<section
|
|
100
|
+
{...rest}
|
|
101
|
+
bind:this={dialog}
|
|
102
|
+
class={classes()}
|
|
103
|
+
role="dialog"
|
|
104
|
+
aria-modal="true"
|
|
105
|
+
aria-label={title}
|
|
106
|
+
tabindex="-1"
|
|
107
|
+
>
|
|
34
108
|
<header class="st-modal__header">
|
|
35
109
|
<div>
|
|
36
110
|
<h2 class="st-modal__title">{title}</h2>
|
|
37
111
|
{#if description}<p class="st-modal__description">{description}</p>{/if}
|
|
38
112
|
</div>
|
|
39
|
-
<button
|
|
40
|
-
|
|
113
|
+
<button
|
|
114
|
+
bind:this={closeButton}
|
|
115
|
+
class="st-modal__close"
|
|
116
|
+
type="button"
|
|
117
|
+
aria-label={closeLabel}
|
|
118
|
+
onclick={requestClose}
|
|
119
|
+
>
|
|
120
|
+
<X size={18} strokeWidth={2.25} aria-hidden="true" />
|
|
41
121
|
</button>
|
|
42
122
|
</header>
|
|
43
123
|
<div class="st-modal__body">
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Modal.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Modal.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Modal.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,GAAG;IAC7D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAmHJ,QAAA,MAAM,KAAK,gDAAwC,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
|
package/dist/MultiSelect.svelte
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
9
|
<script lang="ts">
|
|
10
|
+
import { ChevronDown, X } from "@lucide/svelte";
|
|
10
11
|
import type { HTMLAttributes } from "svelte/elements";
|
|
11
12
|
|
|
12
13
|
type MultiSelectProps = Omit<HTMLAttributes<HTMLDivElement>, "class" | "onchange"> & {
|
|
@@ -115,7 +116,7 @@
|
|
|
115
116
|
{disabled}
|
|
116
117
|
onclick={() => removeOption(option.value)}
|
|
117
118
|
>
|
|
118
|
-
<
|
|
119
|
+
<X size={14} strokeWidth={2.25} aria-hidden="true" />
|
|
119
120
|
</button>
|
|
120
121
|
</span>
|
|
121
122
|
{/each}
|
|
@@ -135,7 +136,13 @@
|
|
|
135
136
|
{:else}
|
|
136
137
|
<span class="st-multiSelect__count">{selectedOptions.length} selected</span>
|
|
137
138
|
{/if}
|
|
138
|
-
<span class="st-multiSelect__caret" aria-hidden="true"
|
|
139
|
+
<span class="st-multiSelect__caret" aria-hidden="true">
|
|
140
|
+
<ChevronDown
|
|
141
|
+
class={`st-multiSelect__caretIcon ${expanded ? "st-multiSelect__caretIcon--open" : ""}`}
|
|
142
|
+
size={18}
|
|
143
|
+
strokeWidth={2.25}
|
|
144
|
+
/>
|
|
145
|
+
</span>
|
|
139
146
|
<span class="st-visually-hidden">{toggleLabel}</span>
|
|
140
147
|
</button>
|
|
141
148
|
</span>
|
|
@@ -342,11 +349,18 @@
|
|
|
342
349
|
color: var(--st-semantic-text-secondary);
|
|
343
350
|
display: inline-flex;
|
|
344
351
|
flex: 0 0 auto;
|
|
345
|
-
font-size: 0.875rem;
|
|
346
352
|
margin-inline-start: auto;
|
|
347
353
|
padding-inline-start: 0.25rem;
|
|
348
354
|
}
|
|
349
355
|
|
|
356
|
+
.st-multiSelect__caretIcon {
|
|
357
|
+
transition: transform var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.st-multiSelect__caretIcon--open {
|
|
361
|
+
transform: rotate(180deg);
|
|
362
|
+
}
|
|
363
|
+
|
|
350
364
|
.st-multiSelect__panel {
|
|
351
365
|
background: var(--st-component-dropdown-background, var(--st-semantic-surface-default));
|
|
352
366
|
border: 1px solid var(--st-component-dropdown-border, var(--st-semantic-border-subtle));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSelect.svelte.d.ts","sourceRoot":"","sources":["../src/lib/MultiSelect.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"MultiSelect.svelte.d.ts","sourceRoot":"","sources":["../src/lib/MultiSelect.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACzC,CAAC;AAqIJ,QAAA,MAAM,WAAW,8DAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|