@sentropic/design-system-svelte 0.6.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.
Files changed (96) hide show
  1. package/dist/Accordion.svelte +11 -3
  2. package/dist/Accordion.svelte.d.ts.map +1 -1
  3. package/dist/Alert.svelte +1 -1
  4. package/dist/AreaChart.svelte +414 -0
  5. package/dist/AreaChart.svelte.d.ts +18 -0
  6. package/dist/AreaChart.svelte.d.ts.map +1 -0
  7. package/dist/AspectRatio.svelte +44 -0
  8. package/dist/AspectRatio.svelte.d.ts +11 -0
  9. package/dist/AspectRatio.svelte.d.ts.map +1 -0
  10. package/dist/BarChart.svelte +383 -0
  11. package/dist/BarChart.svelte.d.ts +18 -0
  12. package/dist/BarChart.svelte.d.ts.map +1 -0
  13. package/dist/ChatComposer.svelte +238 -0
  14. package/dist/ChatComposer.svelte.d.ts +57 -0
  15. package/dist/ChatComposer.svelte.d.ts.map +1 -0
  16. package/dist/ChatMessage.svelte +271 -0
  17. package/dist/ChatMessage.svelte.d.ts +19 -0
  18. package/dist/ChatMessage.svelte.d.ts.map +1 -0
  19. package/dist/ChatThread.svelte +120 -0
  20. package/dist/ChatThread.svelte.d.ts +13 -0
  21. package/dist/ChatThread.svelte.d.ts.map +1 -0
  22. package/dist/CodeSnippet.svelte +91 -0
  23. package/dist/CodeSnippet.svelte.d.ts +13 -0
  24. package/dist/CodeSnippet.svelte.d.ts.map +1 -0
  25. package/dist/Combobox.svelte +16 -2
  26. package/dist/Combobox.svelte.d.ts.map +1 -1
  27. package/dist/CopyButton.svelte +3 -7
  28. package/dist/CopyButton.svelte.d.ts.map +1 -1
  29. package/dist/Drawer.svelte +23 -3
  30. package/dist/Drawer.svelte.d.ts +1 -1
  31. package/dist/Drawer.svelte.d.ts.map +1 -1
  32. package/dist/Dropdown.svelte +38 -2
  33. package/dist/Dropdown.svelte.d.ts.map +1 -1
  34. package/dist/FileUploader.svelte +119 -4
  35. package/dist/FileUploader.svelte.d.ts +1 -0
  36. package/dist/FileUploader.svelte.d.ts.map +1 -1
  37. package/dist/IconButton.svelte +103 -0
  38. package/dist/IconButton.svelte.d.ts +15 -0
  39. package/dist/IconButton.svelte.d.ts.map +1 -0
  40. package/dist/InlineLoading.svelte +22 -14
  41. package/dist/InlineLoading.svelte.d.ts.map +1 -1
  42. package/dist/LineChart.svelte +397 -0
  43. package/dist/LineChart.svelte.d.ts +19 -0
  44. package/dist/LineChart.svelte.d.ts.map +1 -0
  45. package/dist/Menu.svelte +164 -24
  46. package/dist/Menu.svelte.d.ts +26 -4
  47. package/dist/Menu.svelte.d.ts.map +1 -1
  48. package/dist/MenuPopover.svelte +180 -0
  49. package/dist/MenuPopover.svelte.d.ts +17 -0
  50. package/dist/MenuPopover.svelte.d.ts.map +1 -0
  51. package/dist/MenuTriggerButton.svelte +50 -0
  52. package/dist/MenuTriggerButton.svelte.d.ts +16 -0
  53. package/dist/MenuTriggerButton.svelte.d.ts.map +1 -0
  54. package/dist/MessageActions.svelte +89 -0
  55. package/dist/MessageActions.svelte.d.ts +22 -0
  56. package/dist/MessageActions.svelte.d.ts.map +1 -0
  57. package/dist/MessageStatusBadge.svelte +52 -0
  58. package/dist/MessageStatusBadge.svelte.d.ts +12 -0
  59. package/dist/MessageStatusBadge.svelte.d.ts.map +1 -0
  60. package/dist/Modal.svelte +83 -3
  61. package/dist/Modal.svelte.d.ts.map +1 -1
  62. package/dist/MultiSelect.svelte +17 -3
  63. package/dist/MultiSelect.svelte.d.ts.map +1 -1
  64. package/dist/OverflowMenu.svelte +111 -24
  65. package/dist/OverflowMenu.svelte.d.ts +21 -2
  66. package/dist/OverflowMenu.svelte.d.ts.map +1 -1
  67. package/dist/PaginationNav.svelte +6 -21
  68. package/dist/PaginationNav.svelte.d.ts.map +1 -1
  69. package/dist/PasswordInput.svelte +3 -9
  70. package/dist/PasswordInput.svelte.d.ts.map +1 -1
  71. package/dist/ProgressIndicator.svelte +3 -19
  72. package/dist/ProgressIndicator.svelte.d.ts.map +1 -1
  73. package/dist/Search.svelte +3 -6
  74. package/dist/Search.svelte.d.ts.map +1 -1
  75. package/dist/Sparkline.svelte +123 -0
  76. package/dist/Sparkline.svelte.d.ts +15 -0
  77. package/dist/Sparkline.svelte.d.ts.map +1 -0
  78. package/dist/StreamingMessage.svelte +292 -0
  79. package/dist/StreamingMessage.svelte.d.ts +51 -0
  80. package/dist/StreamingMessage.svelte.d.ts.map +1 -0
  81. package/dist/StructuredList.svelte +86 -0
  82. package/dist/StructuredList.svelte.d.ts +15 -0
  83. package/dist/StructuredList.svelte.d.ts.map +1 -0
  84. package/dist/Tag.svelte +2 -1
  85. package/dist/Tag.svelte.d.ts.map +1 -1
  86. package/dist/TileGroup.svelte +179 -0
  87. package/dist/TileGroup.svelte.d.ts +21 -0
  88. package/dist/TileGroup.svelte.d.ts.map +1 -0
  89. package/dist/Toast.svelte +2 -2
  90. package/dist/UnorderedList.svelte +108 -0
  91. package/dist/UnorderedList.svelte.d.ts +16 -0
  92. package/dist/UnorderedList.svelte.d.ts.map +1 -0
  93. package/dist/index.d.ts +23 -0
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +16 -0
  96. package/package.json +3 -2
@@ -0,0 +1,271 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import type { HTMLAttributes } from "svelte/elements";
4
+
5
+ export type ChatMessageRole = "user" | "assistant" | "system" | "tool";
6
+ export type ChatMessageStatus = "pending" | "processing" | "completed" | "failed";
7
+ type ChatMessageLegacyStatus = "idle" | "streaming" | "error";
8
+
9
+ type ChatMessageProps = Omit<HTMLAttributes<HTMLElement>, "class" | "role"> & {
10
+ role: ChatMessageRole;
11
+ status?: ChatMessageStatus | ChatMessageLegacyStatus;
12
+ timestamp?: string;
13
+ class?: string;
14
+ avatar?: Snippet;
15
+ children: Snippet;
16
+ footer?: Snippet;
17
+ actions?: Snippet;
18
+ };
19
+
20
+ let {
21
+ role,
22
+ status = "completed",
23
+ timestamp,
24
+ class: className,
25
+ avatar,
26
+ children,
27
+ footer,
28
+ actions,
29
+ ...rest
30
+ }: ChatMessageProps = $props();
31
+
32
+ const normalizedStatus = () => {
33
+ if (status === "idle" || status === "streaming") return "processing";
34
+ if (status === "error") return "failed";
35
+ return status;
36
+ };
37
+
38
+ const isStreaming = () => normalizedStatus() === "processing";
39
+
40
+ const classes = () =>
41
+ [
42
+ "st-chatMessage",
43
+ `st-chatMessage--${role}`,
44
+ `st-chatMessage--${normalizedStatus()}`,
45
+ className
46
+ ]
47
+ .filter(Boolean)
48
+ .join(" ");
49
+
50
+ const alignment = $derived(role === "user" ? "end" : "start");
51
+ </script>
52
+
53
+ <article
54
+ {...rest}
55
+ class={classes()}
56
+ data-role={role}
57
+ data-status={normalizedStatus()}
58
+ data-align={alignment}
59
+ aria-live={isStreaming() ? "polite" : undefined}
60
+ >
61
+ {#if avatar}
62
+ <div class="st-chatMessage__avatar" aria-hidden="true">
63
+ {@render avatar()}
64
+ </div>
65
+ {/if}
66
+ <div class="st-chatMessage__body">
67
+ <div class="st-chatMessage__bubble">
68
+ <div class="st-chatMessage__content">
69
+ {@render children()}
70
+ </div>
71
+ {#if isStreaming()}
72
+ <span class="st-chatMessage__pulse" aria-hidden="true"></span>
73
+ {/if}
74
+ </div>
75
+ {#if footer || timestamp}
76
+ <div class="st-chatMessage__footer">
77
+ {#if footer}{@render footer()}{:else if timestamp}<span class="st-chatMessage__timestamp">{timestamp}</span>{/if}
78
+ </div>
79
+ {/if}
80
+ {#if actions}
81
+ <div class="st-chatMessage__actions">
82
+ {@render actions()}
83
+ </div>
84
+ {/if}
85
+ </div>
86
+ </article>
87
+
88
+ <style>
89
+ .st-chatMessage {
90
+ align-items: flex-start;
91
+ color: var(--st-semantic-text-primary);
92
+ display: flex;
93
+ gap: var(--st-component-chatMessage-gap, 0.5rem);
94
+ width: 100%;
95
+ }
96
+
97
+ .st-chatMessage[data-align="end"] {
98
+ flex-direction: row-reverse;
99
+ }
100
+
101
+ .st-chatMessage__avatar {
102
+ align-items: center;
103
+ background: var(--st-component-chatMessage-avatarBackground, var(--st-semantic-surface-subtle));
104
+ border-radius: 999px;
105
+ color: var(--st-semantic-text-secondary);
106
+ display: inline-flex;
107
+ flex: 0 0 auto;
108
+ font-size: 0.75rem;
109
+ height: var(--st-component-chatMessage-avatarSize, 1.75rem);
110
+ justify-content: center;
111
+ overflow: hidden;
112
+ width: var(--st-component-chatMessage-avatarSize, 1.75rem);
113
+ }
114
+
115
+ .st-chatMessage__body {
116
+ display: flex;
117
+ flex-direction: column;
118
+ gap: 0.25rem;
119
+ min-width: 0;
120
+ max-width: var(--st-component-chatMessage-maxWidth, min(42rem, 100%));
121
+ }
122
+
123
+ .st-chatMessage[data-align="end"] .st-chatMessage__body {
124
+ align-items: flex-end;
125
+ }
126
+
127
+ .st-chatMessage__bubble {
128
+ border: 1px solid transparent;
129
+ border-radius: var(--st-component-chatMessage-radius, 0.75rem);
130
+ line-height: 1.5;
131
+ padding: var(--st-component-chatMessage-padding, 0.625rem 0.875rem);
132
+ position: relative;
133
+ word-break: break-word;
134
+ }
135
+
136
+ .st-chatMessage__content :global(p) {
137
+ margin: 0;
138
+ }
139
+ .st-chatMessage__content :global(p + p),
140
+ .st-chatMessage__content :global(* + p),
141
+ .st-chatMessage__content :global(* + ul),
142
+ .st-chatMessage__content :global(* + ol),
143
+ .st-chatMessage__content :global(* + pre) {
144
+ margin-top: 0.5rem;
145
+ }
146
+
147
+ .st-chatMessage--user .st-chatMessage__bubble {
148
+ background: var(
149
+ --st-component-chatMessage-userBackground,
150
+ var(--st-component-chat-userBubbleBackground, var(--st-semantic-action-primary, #2563eb))
151
+ );
152
+ color: var(
153
+ --st-component-chatMessage-userText,
154
+ var(--st-component-chat-userBubbleText, #ffffff)
155
+ );
156
+ }
157
+
158
+ .st-chatMessage--assistant .st-chatMessage__bubble {
159
+ background: var(
160
+ --st-component-chatMessage-assistantBackground,
161
+ var(--st-component-chat-assistantBubbleBackground, var(--st-semantic-surface-subtle, #f8fafc))
162
+ );
163
+ color: var(
164
+ --st-component-chatMessage-assistantText,
165
+ var(--st-component-chat-assistantBubbleText, var(--st-semantic-text-primary))
166
+ );
167
+ }
168
+
169
+ .st-chatMessage--system .st-chatMessage__bubble {
170
+ background: var(
171
+ --st-component-chatMessage-systemBackground,
172
+ var(--st-semantic-surface-default, #ffffff)
173
+ );
174
+ border-color: var(
175
+ --st-component-chatMessage-systemBorder,
176
+ var(--st-semantic-border-subtle)
177
+ );
178
+ color: var(
179
+ --st-component-chatMessage-systemText,
180
+ var(--st-semantic-text-secondary)
181
+ );
182
+ font-size: 0.875rem;
183
+ }
184
+
185
+ .st-chatMessage--tool .st-chatMessage__bubble {
186
+ background: var(
187
+ --st-component-chatMessage-toolBackground,
188
+ var(--st-component-chatMessage-assistantBackground, var(--st-component-chat-assistantBubbleBackground, var(--st-semantic-surface-subtle, #f8fafc)))
189
+ );
190
+ color: var(
191
+ --st-component-chatMessage-toolText,
192
+ var(--st-component-chatMessage-assistantText, var(--st-component-chat-assistantBubbleText, var(--st-semantic-text-primary)))
193
+ );
194
+ border-color: var(
195
+ --st-component-chatMessage-toolBorder,
196
+ var(--st-semantic-border-subtle)
197
+ );
198
+ font-style: italic;
199
+ }
200
+
201
+ .st-chatMessage--pending .st-chatMessage__bubble {
202
+ border-color: var(
203
+ --st-component-chatMessage-pendingBorder,
204
+ var(--st-semantic-status-pending, #d97706)
205
+ );
206
+ }
207
+
208
+ .st-chatMessage--processing .st-chatMessage__bubble {
209
+ border-color: var(
210
+ --st-component-chatMessage-processingBorder,
211
+ var(--st-semantic-status-processing, #2563eb)
212
+ );
213
+ }
214
+
215
+ .st-chatMessage--failed .st-chatMessage__bubble {
216
+ border-color: var(
217
+ --st-component-chatMessage-errorBorder,
218
+ var(--st-semantic-feedback-danger, #b91c1c)
219
+ );
220
+ }
221
+
222
+ .st-chatMessage__pulse {
223
+ background: currentColor;
224
+ border-radius: 999px;
225
+ display: inline-block;
226
+ height: 0.5rem;
227
+ margin-left: 0.5rem;
228
+ opacity: 0.65;
229
+ vertical-align: middle;
230
+ width: 0.5rem;
231
+ animation: st-chatMessage-pulse 1.1s ease-in-out infinite;
232
+ }
233
+
234
+ @keyframes st-chatMessage-pulse {
235
+ 0%,
236
+ 100% {
237
+ opacity: 0.25;
238
+ transform: scale(0.85);
239
+ }
240
+ 50% {
241
+ opacity: 0.9;
242
+ transform: scale(1.05);
243
+ }
244
+ }
245
+
246
+ @media (prefers-reduced-motion: reduce) {
247
+ .st-chatMessage__pulse {
248
+ animation: none;
249
+ opacity: 0.6;
250
+ }
251
+ }
252
+
253
+ .st-chatMessage__footer {
254
+ color: var(--st-semantic-text-secondary);
255
+ font-size: 0.75rem;
256
+ line-height: 1.3;
257
+ }
258
+
259
+ .st-chatMessage__timestamp {
260
+ font-variant-numeric: tabular-nums;
261
+ }
262
+
263
+ .st-chatMessage__actions {
264
+ display: flex;
265
+ gap: 0.25rem;
266
+ }
267
+
268
+ .st-chatMessage[data-align="end"] .st-chatMessage__actions {
269
+ justify-content: flex-end;
270
+ }
271
+ </style>
@@ -0,0 +1,19 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+ export type ChatMessageRole = "user" | "assistant" | "system" | "tool";
4
+ export type ChatMessageStatus = "pending" | "processing" | "completed" | "failed";
5
+ type ChatMessageLegacyStatus = "idle" | "streaming" | "error";
6
+ type ChatMessageProps = Omit<HTMLAttributes<HTMLElement>, "class" | "role"> & {
7
+ role: ChatMessageRole;
8
+ status?: ChatMessageStatus | ChatMessageLegacyStatus;
9
+ timestamp?: string;
10
+ class?: string;
11
+ avatar?: Snippet;
12
+ children: Snippet;
13
+ footer?: Snippet;
14
+ actions?: Snippet;
15
+ };
16
+ declare const ChatMessage: import("svelte").Component<ChatMessageProps, {}, "">;
17
+ type ChatMessage = ReturnType<typeof ChatMessage>;
18
+ export default ChatMessage;
19
+ //# sourceMappingURL=ChatMessage.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatMessage.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ChatMessage.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;AACvE,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;AAClF,KAAK,uBAAuB,GAAG,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC;AAE9D,KAAK,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;IAC5E,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,CAAC,EAAE,iBAAiB,GAAG,uBAAuB,CAAC;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AA0EJ,QAAA,MAAM,WAAW,sDAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -0,0 +1,120 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import type { HTMLAttributes } from "svelte/elements";
4
+
5
+ type ChatThreadProps = Omit<HTMLAttributes<HTMLElement>, "class" | "aria-label"> & {
6
+ label: string;
7
+ autoScroll?: boolean;
8
+ class?: string;
9
+ children?: Snippet;
10
+ emptyState?: Snippet;
11
+ };
12
+
13
+ let {
14
+ label,
15
+ autoScroll = true,
16
+ class: className,
17
+ children,
18
+ emptyState,
19
+ ...rest
20
+ }: ChatThreadProps = $props();
21
+
22
+ let scrollEl: HTMLElement | undefined = $state();
23
+ let listEl: HTMLElement | undefined = $state();
24
+ let hasChildren = $state(true);
25
+
26
+ const classes = () => ["st-chatThread", className].filter(Boolean).join(" ");
27
+
28
+ function scrollToBottom() {
29
+ const node = scrollEl;
30
+ if (!node) return;
31
+ node.scrollTop = node.scrollHeight;
32
+ }
33
+
34
+ $effect(() => {
35
+ if (!autoScroll) return;
36
+ const node = listEl;
37
+ if (!node) return;
38
+ // Initial scroll on mount and on children change.
39
+ scrollToBottom();
40
+ const observer = new MutationObserver(() => {
41
+ scrollToBottom();
42
+ });
43
+ observer.observe(node, { childList: true, subtree: true, characterData: true });
44
+ return () => observer.disconnect();
45
+ });
46
+
47
+ $effect(() => {
48
+ const node = listEl;
49
+ if (!node) {
50
+ hasChildren = false;
51
+ return;
52
+ }
53
+ const update = () => {
54
+ hasChildren = node.childElementCount > 0;
55
+ };
56
+ update();
57
+ const observer = new MutationObserver(update);
58
+ observer.observe(node, { childList: true });
59
+ return () => observer.disconnect();
60
+ });
61
+ </script>
62
+
63
+ <section
64
+ {...rest}
65
+ bind:this={scrollEl}
66
+ class={classes()}
67
+ role="log"
68
+ aria-label={label}
69
+ aria-live="polite"
70
+ aria-relevant="additions text"
71
+ >
72
+ <div bind:this={listEl} class="st-chatThread__list">
73
+ {@render children?.()}
74
+ </div>
75
+ {#if emptyState && !hasChildren}
76
+ <div class="st-chatThread__empty">
77
+ {@render emptyState()}
78
+ </div>
79
+ {/if}
80
+ </section>
81
+
82
+ <style>
83
+ .st-chatThread {
84
+ background: var(--st-component-chatThread-background, transparent);
85
+ border-radius: var(--st-component-chatThread-radius, 0.75rem);
86
+ color: var(--st-semantic-text-primary);
87
+ display: flex;
88
+ flex-direction: column;
89
+ gap: var(--st-component-chatThread-gap, 0.75rem);
90
+ max-height: var(--st-component-chatThread-maxHeight, 32rem);
91
+ min-height: var(--st-component-chatThread-minHeight, 12rem);
92
+ overflow-y: auto;
93
+ padding: var(--st-component-chatThread-padding, 0.75rem);
94
+ position: relative;
95
+ scroll-behavior: smooth;
96
+ }
97
+
98
+ @media (prefers-reduced-motion: reduce) {
99
+ .st-chatThread {
100
+ scroll-behavior: auto;
101
+ }
102
+ }
103
+
104
+ .st-chatThread__list {
105
+ display: flex;
106
+ flex-direction: column;
107
+ gap: var(--st-component-chatThread-gap, 0.75rem);
108
+ min-height: 0;
109
+ }
110
+
111
+ .st-chatThread__empty {
112
+ align-items: center;
113
+ color: var(--st-semantic-text-secondary);
114
+ display: flex;
115
+ flex: 1;
116
+ justify-content: center;
117
+ padding: var(--st-spacing-4, 1rem);
118
+ text-align: center;
119
+ }
120
+ </style>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+ type ChatThreadProps = Omit<HTMLAttributes<HTMLElement>, "class" | "aria-label"> & {
4
+ label: string;
5
+ autoScroll?: boolean;
6
+ class?: string;
7
+ children?: Snippet;
8
+ emptyState?: Snippet;
9
+ };
10
+ declare const ChatThread: import("svelte").Component<ChatThreadProps, {}, "">;
11
+ type ChatThread = ReturnType<typeof ChatThread>;
12
+ export default ChatThread;
13
+ //# sourceMappingURL=ChatThread.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatThread.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ChatThread.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,eAAe,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,OAAO,GAAG,YAAY,CAAC,GAAG;IACjF,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAuEJ,QAAA,MAAM,UAAU,qDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -0,0 +1,91 @@
1
+ <script lang="ts">
2
+ import CopyButton from "./CopyButton.svelte";
3
+
4
+ type CodeSnippetProps = {
5
+ code: string;
6
+ language?: string;
7
+ inline?: boolean;
8
+ copyable?: boolean;
9
+ copyLabel?: string;
10
+ copiedLabel?: string;
11
+ class?: string;
12
+ };
13
+
14
+ let {
15
+ code,
16
+ language,
17
+ inline = false,
18
+ copyable = true,
19
+ copyLabel = "Copy",
20
+ copiedLabel = "Copied",
21
+ class: className
22
+ }: CodeSnippetProps = $props();
23
+
24
+ const inlineClasses = () =>
25
+ ["st-codeSnippet--inline", className].filter(Boolean).join(" ");
26
+ const blockClasses = () => ["st-codeSnippet", className].filter(Boolean).join(" ");
27
+ </script>
28
+
29
+ {#if inline}
30
+ <code class={inlineClasses()} data-language={language}>{code}</code>
31
+ {:else}
32
+ <div class="st-codeSnippet__wrapper">
33
+ <pre class={blockClasses()} data-language={language}><code
34
+ class="st-codeSnippet__code">{code}</code></pre>
35
+ {#if copyable}
36
+ <span class="st-codeSnippet__copy">
37
+ <CopyButton value={code} size="sm" label={copyLabel} copiedLabel={copiedLabel} />
38
+ </span>
39
+ {/if}
40
+ </div>
41
+ {/if}
42
+
43
+ <style>
44
+ .st-codeSnippet__wrapper {
45
+ position: relative;
46
+ }
47
+
48
+ .st-codeSnippet {
49
+ background: var(
50
+ --st-component-codeSnippet-background,
51
+ var(--st-semantic-surface-subtle)
52
+ );
53
+ border: 1px solid
54
+ var(--st-component-codeSnippet-border, var(--st-semantic-border-subtle));
55
+ border-radius: var(--st-component-codeSnippet-radius, 0.375rem);
56
+ color: var(--st-component-codeSnippet-text, var(--st-semantic-text-primary));
57
+ font-family: var(--st-font-mono, ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace);
58
+ font-size: 0.8125rem;
59
+ line-height: 1.5;
60
+ margin: 0;
61
+ max-height: var(--st-component-codeSnippet-maxHeight, 16rem);
62
+ overflow: auto;
63
+ padding: 0.75rem 0.875rem;
64
+ padding-inline-end: 4rem;
65
+ }
66
+
67
+ .st-codeSnippet__code {
68
+ font: inherit;
69
+ white-space: pre;
70
+ }
71
+
72
+ .st-codeSnippet__copy {
73
+ position: absolute;
74
+ inset-block-start: 0.375rem;
75
+ inset-inline-end: 0.375rem;
76
+ }
77
+
78
+ .st-codeSnippet--inline {
79
+ background: var(
80
+ --st-component-codeSnippet-background,
81
+ var(--st-semantic-surface-subtle)
82
+ );
83
+ border: 1px solid
84
+ var(--st-component-codeSnippet-border, var(--st-semantic-border-subtle));
85
+ border-radius: var(--st-radius-sm, 0.25rem);
86
+ color: var(--st-component-codeSnippet-text, var(--st-semantic-text-primary));
87
+ font-family: var(--st-font-mono, ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace);
88
+ font-size: 0.8125rem;
89
+ padding: 0.0625rem 0.375rem;
90
+ }
91
+ </style>
@@ -0,0 +1,13 @@
1
+ type CodeSnippetProps = {
2
+ code: string;
3
+ language?: string;
4
+ inline?: boolean;
5
+ copyable?: boolean;
6
+ copyLabel?: string;
7
+ copiedLabel?: string;
8
+ class?: string;
9
+ };
10
+ declare const CodeSnippet: import("svelte").Component<CodeSnippetProps, {}, "">;
11
+ type CodeSnippet = ReturnType<typeof CodeSnippet>;
12
+ export default CodeSnippet;
13
+ //# sourceMappingURL=CodeSnippet.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeSnippet.svelte.d.ts","sourceRoot":"","sources":["../src/lib/CodeSnippet.svelte.ts"],"names":[],"mappings":"AAME,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAqCJ,QAAA,MAAM,WAAW,sDAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -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 { HTMLInputAttributes } from "svelte/elements";
11
12
 
12
13
  type ComboboxProps = Omit<
@@ -158,7 +159,7 @@
158
159
  {disabled}
159
160
  onclick={clear}
160
161
  >
161
- <span aria-hidden="true">×</span>
162
+ <X size={16} strokeWidth={2.25} aria-hidden="true" />
162
163
  </button>
163
164
  {/if}
164
165
  <button
@@ -169,7 +170,12 @@
169
170
  {disabled}
170
171
  onclick={() => (expanded = !expanded)}
171
172
  >
172
- <span aria-hidden="true">▾</span>
173
+ <ChevronDown
174
+ class={`st-combobox__toggleIcon ${expanded ? "st-combobox__toggleIcon--open" : ""}`}
175
+ size={18}
176
+ strokeWidth={2.25}
177
+ aria-hidden="true"
178
+ />
173
179
  </button>
174
180
  </span>
175
181
  </label>
@@ -339,6 +345,14 @@
339
345
  cursor: not-allowed;
340
346
  }
341
347
 
348
+ .st-combobox__toggleIcon {
349
+ transition: transform var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
350
+ }
351
+
352
+ .st-combobox__toggleIcon--open {
353
+ transform: rotate(180deg);
354
+ }
355
+
342
356
  .st-combobox__list {
343
357
  background: var(--st-component-dropdown-background, var(--st-semantic-surface-default));
344
358
  border: 1px solid var(--st-component-dropdown-border, var(--st-semantic-border-subtle));
@@ -1 +1 @@
1
- {"version":3,"file":"Combobox.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Combobox.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAGzD,KAAK,aAAa,GAAG,IAAI,CACvB,mBAAmB,EACnB,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CACjD,GAAG;IACF,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,cAAc,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AAqJJ,QAAA,MAAM,QAAQ,wDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"Combobox.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Combobox.svelte.ts"],"names":[],"mappings":"AAGE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAGzD,KAAK,aAAa,GAAG,IAAI,CACvB,mBAAmB,EACnB,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CACjD,GAAG;IACF,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,cAAc,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AAsJJ,QAAA,MAAM,QAAQ,wDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import type { HTMLButtonAttributes } from "svelte/elements";
3
+ import { Check, Copy } from "@lucide/svelte";
3
4
 
4
5
  type CopyButtonProps = Omit<HTMLButtonAttributes, "class" | "type"> & {
5
6
  value: string;
@@ -59,14 +60,9 @@
59
60
  >
60
61
  <span class="st-copyButton__icon" aria-hidden="true">
61
62
  {#if copied}
62
- <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" width="14" height="14">
63
- <path d="m3 8 3.5 3.5L13 5" stroke-linecap="round" stroke-linejoin="round" />
64
- </svg>
63
+ <Check size={14} strokeWidth={2} aria-hidden="true" />
65
64
  {:else}
66
- <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="14" height="14">
67
- <rect x="4" y="4" width="9" height="10" rx="1.5" />
68
- <path d="M3 11V3a1 1 0 0 1 1-1h7" />
69
- </svg>
65
+ <Copy size={14} strokeWidth={2} aria-hidden="true" />
70
66
  {/if}
71
67
  </span>
72
68
  <span class="st-copyButton__label">{copied ? copiedLabel : label}</span>
@@ -1 +1 @@
1
- {"version":3,"file":"CopyButton.svelte.d.ts","sourceRoot":"","sources":["../src/lib/CopyButton.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAG1D,KAAK,eAAe,GAAG,IAAI,CAAC,oBAAoB,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AA8DJ,QAAA,MAAM,UAAU,qDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"CopyButton.svelte.d.ts","sourceRoot":"","sources":["../src/lib/CopyButton.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAI1D,KAAK,eAAe,GAAG,IAAI,CAAC,oBAAoB,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AA0DJ,QAAA,MAAM,UAAU,qDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -15,7 +15,7 @@
15
15
  };
16
16
 
17
17
  let {
18
- open = false,
18
+ open = $bindable(false),
19
19
  title,
20
20
  description,
21
21
  side = "right",
@@ -28,17 +28,37 @@
28
28
  }: DrawerProps = $props();
29
29
 
30
30
  const classes = () => ["st-drawer", `st-drawer--${side}`, className].filter(Boolean).join(" ");
31
+
32
+ function close() {
33
+ open = false;
34
+ onclose?.();
35
+ }
36
+
37
+ function onBackdropClick(event: MouseEvent) {
38
+ if (event.target === event.currentTarget) {
39
+ close();
40
+ }
41
+ }
42
+
43
+ function onWindowKeydown(event: KeyboardEvent) {
44
+ if (event.key === "Escape" && open) {
45
+ event.preventDefault();
46
+ close();
47
+ }
48
+ }
31
49
  </script>
32
50
 
51
+ <svelte:window onkeydown={onWindowKeydown} />
52
+
33
53
  {#if open}
34
- <div class="st-drawer__backdrop">
54
+ <div class="st-drawer__backdrop" onclick={onBackdropClick} role="presentation">
35
55
  <aside {...rest} class={classes()} role="dialog" aria-modal="true" aria-label={title}>
36
56
  <header class="st-drawer__header">
37
57
  <div>
38
58
  <h2 class="st-drawer__title">{title}</h2>
39
59
  {#if description}<p class="st-drawer__description">{description}</p>{/if}
40
60
  </div>
41
- <button class="st-drawer__close" type="button" aria-label={closeLabel} onclick={onclose}>
61
+ <button class="st-drawer__close" type="button" aria-label={closeLabel} onclick={close}>
42
62
  <span aria-hidden="true">x</span>
43
63
  </button>
44
64
  </header>
@@ -11,7 +11,7 @@ type DrawerProps = Omit<HTMLAttributes<HTMLElement>, "class"> & {
11
11
  footer?: Snippet;
12
12
  onclose?: () => void;
13
13
  };
14
- declare const Drawer: import("svelte").Component<DrawerProps, {}, "">;
14
+ declare const Drawer: import("svelte").Component<DrawerProps, {}, "open">;
15
15
  type Drawer = ReturnType<typeof Drawer>;
16
16
  export default Drawer;
17
17
  //# sourceMappingURL=Drawer.svelte.d.ts.map