@delightstack/components 0.1.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 (195) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +136 -0
  3. package/SKILL.md +149 -0
  4. package/bin/agents.js +63 -0
  5. package/dist/actions/Alert.svelte +202 -0
  6. package/dist/actions/Alert.svelte.d.ts +36 -0
  7. package/dist/actions/Alert.svelte.d.ts.map +1 -0
  8. package/dist/actions/Button.svelte +1450 -0
  9. package/dist/actions/Button.svelte.d.ts +56 -0
  10. package/dist/actions/Button.svelte.d.ts.map +1 -0
  11. package/dist/actions/ButtonGroup.svelte +111 -0
  12. package/dist/actions/ButtonGroup.svelte.d.ts +41 -0
  13. package/dist/actions/ButtonGroup.svelte.d.ts.map +1 -0
  14. package/dist/actions/CommandPalette.svelte +939 -0
  15. package/dist/actions/CommandPalette.svelte.d.ts +37 -0
  16. package/dist/actions/CommandPalette.svelte.d.ts.map +1 -0
  17. package/dist/actions/ContextMenu.svelte +138 -0
  18. package/dist/actions/ContextMenu.svelte.d.ts +54 -0
  19. package/dist/actions/ContextMenu.svelte.d.ts.map +1 -0
  20. package/dist/actions/Modal.svelte +474 -0
  21. package/dist/actions/Modal.svelte.d.ts +28 -0
  22. package/dist/actions/Modal.svelte.d.ts.map +1 -0
  23. package/dist/actions/Popover.svelte +1214 -0
  24. package/dist/actions/Popover.svelte.d.ts +31 -0
  25. package/dist/actions/Popover.svelte.d.ts.map +1 -0
  26. package/dist/actions/Portal.svelte +80 -0
  27. package/dist/actions/Portal.svelte.d.ts +17 -0
  28. package/dist/actions/Portal.svelte.d.ts.map +1 -0
  29. package/dist/actions/ThemeToggle.svelte +345 -0
  30. package/dist/actions/ThemeToggle.svelte.d.ts +15 -0
  31. package/dist/actions/ThemeToggle.svelte.d.ts.map +1 -0
  32. package/dist/actions/index.d.ts +13 -0
  33. package/dist/actions/index.d.ts.map +1 -0
  34. package/dist/actions/index.js +10 -0
  35. package/dist/actions/scrollbar.d.ts +48 -0
  36. package/dist/actions/scrollbar.d.ts.map +1 -0
  37. package/dist/actions/scrollbar.js +404 -0
  38. package/dist/display/Accordion.svelte +586 -0
  39. package/dist/display/Accordion.svelte.d.ts +41 -0
  40. package/dist/display/Accordion.svelte.d.ts.map +1 -0
  41. package/dist/display/Avatar.svelte +527 -0
  42. package/dist/display/Avatar.svelte.d.ts +22 -0
  43. package/dist/display/Avatar.svelte.d.ts.map +1 -0
  44. package/dist/display/AvatarGroup.svelte +298 -0
  45. package/dist/display/AvatarGroup.svelte.d.ts +31 -0
  46. package/dist/display/AvatarGroup.svelte.d.ts.map +1 -0
  47. package/dist/display/Calendar.svelte +1366 -0
  48. package/dist/display/Calendar.svelte.d.ts +58 -0
  49. package/dist/display/Calendar.svelte.d.ts.map +1 -0
  50. package/dist/display/Chart.svelte +1426 -0
  51. package/dist/display/Chart.svelte.d.ts +35 -0
  52. package/dist/display/Chart.svelte.d.ts.map +1 -0
  53. package/dist/display/Code.svelte +780 -0
  54. package/dist/display/Code.svelte.d.ts +19 -0
  55. package/dist/display/Code.svelte.d.ts.map +1 -0
  56. package/dist/display/Comparison.svelte +686 -0
  57. package/dist/display/Comparison.svelte.d.ts +22 -0
  58. package/dist/display/Comparison.svelte.d.ts.map +1 -0
  59. package/dist/display/Counter.svelte +285 -0
  60. package/dist/display/Counter.svelte.d.ts +21 -0
  61. package/dist/display/Counter.svelte.d.ts.map +1 -0
  62. package/dist/display/Expand.svelte +48 -0
  63. package/dist/display/Expand.svelte.d.ts +9 -0
  64. package/dist/display/Expand.svelte.d.ts.map +1 -0
  65. package/dist/display/List.svelte +294 -0
  66. package/dist/display/List.svelte.d.ts +40 -0
  67. package/dist/display/List.svelte.d.ts.map +1 -0
  68. package/dist/display/ListContextReset.svelte +19 -0
  69. package/dist/display/ListContextReset.svelte.d.ts +7 -0
  70. package/dist/display/ListContextReset.svelte.d.ts.map +1 -0
  71. package/dist/display/ListItem.svelte +834 -0
  72. package/dist/display/ListItem.svelte.d.ts +22 -0
  73. package/dist/display/ListItem.svelte.d.ts.map +1 -0
  74. package/dist/display/QR.svelte +1193 -0
  75. package/dist/display/QR.svelte.d.ts +23 -0
  76. package/dist/display/QR.svelte.d.ts.map +1 -0
  77. package/dist/display/SplitPane.svelte +744 -0
  78. package/dist/display/SplitPane.svelte.d.ts +25 -0
  79. package/dist/display/SplitPane.svelte.d.ts.map +1 -0
  80. package/dist/display/Stat.svelte +439 -0
  81. package/dist/display/Stat.svelte.d.ts +24 -0
  82. package/dist/display/Stat.svelte.d.ts.map +1 -0
  83. package/dist/display/Table.svelte +4654 -0
  84. package/dist/display/Table.svelte.d.ts +249 -0
  85. package/dist/display/Table.svelte.d.ts.map +1 -0
  86. package/dist/display/TableCellEditor.svelte +935 -0
  87. package/dist/display/TableCellEditor.svelte.d.ts +58 -0
  88. package/dist/display/TableCellEditor.svelte.d.ts.map +1 -0
  89. package/dist/display/Timeline.svelte +1258 -0
  90. package/dist/display/Timeline.svelte.d.ts +43 -0
  91. package/dist/display/Timeline.svelte.d.ts.map +1 -0
  92. package/dist/display/Tree.svelte +1740 -0
  93. package/dist/display/Tree.svelte.d.ts +74 -0
  94. package/dist/display/Tree.svelte.d.ts.map +1 -0
  95. package/dist/display/Typewriter.svelte +338 -0
  96. package/dist/display/Typewriter.svelte.d.ts +22 -0
  97. package/dist/display/Typewriter.svelte.d.ts.map +1 -0
  98. package/dist/display/index.d.ts +24 -0
  99. package/dist/display/index.d.ts.map +1 -0
  100. package/dist/display/index.js +18 -0
  101. package/dist/feedback/Callout.svelte +529 -0
  102. package/dist/feedback/Callout.svelte.d.ts +24 -0
  103. package/dist/feedback/Callout.svelte.d.ts.map +1 -0
  104. package/dist/feedback/Confetti.svelte +631 -0
  105. package/dist/feedback/Confetti.svelte.d.ts +90 -0
  106. package/dist/feedback/Confetti.svelte.d.ts.map +1 -0
  107. package/dist/feedback/Progress.svelte +382 -0
  108. package/dist/feedback/Progress.svelte.d.ts +25 -0
  109. package/dist/feedback/Progress.svelte.d.ts.map +1 -0
  110. package/dist/feedback/Toast.svelte +967 -0
  111. package/dist/feedback/Toast.svelte.d.ts +54 -0
  112. package/dist/feedback/Toast.svelte.d.ts.map +1 -0
  113. package/dist/feedback/index.d.ts +7 -0
  114. package/dist/feedback/index.d.ts.map +1 -0
  115. package/dist/feedback/index.js +4 -0
  116. package/dist/form/Checkbox.svelte +449 -0
  117. package/dist/form/Checkbox.svelte.d.ts +27 -0
  118. package/dist/form/Checkbox.svelte.d.ts.map +1 -0
  119. package/dist/form/Fieldset.svelte +410 -0
  120. package/dist/form/Fieldset.svelte.d.ts +22 -0
  121. package/dist/form/Fieldset.svelte.d.ts.map +1 -0
  122. package/dist/form/FileUpload.svelte +934 -0
  123. package/dist/form/FileUpload.svelte.d.ts +41 -0
  124. package/dist/form/FileUpload.svelte.d.ts.map +1 -0
  125. package/dist/form/Form.svelte +530 -0
  126. package/dist/form/Form.svelte.d.ts +120 -0
  127. package/dist/form/Form.svelte.d.ts.map +1 -0
  128. package/dist/form/Input.svelte +2858 -0
  129. package/dist/form/Input.svelte.d.ts +66 -0
  130. package/dist/form/Input.svelte.d.ts.map +1 -0
  131. package/dist/form/Radio.svelte +507 -0
  132. package/dist/form/Radio.svelte.d.ts +39 -0
  133. package/dist/form/Radio.svelte.d.ts.map +1 -0
  134. package/dist/form/Range.svelte +912 -0
  135. package/dist/form/Range.svelte.d.ts +33 -0
  136. package/dist/form/Range.svelte.d.ts.map +1 -0
  137. package/dist/form/Rating.svelte +429 -0
  138. package/dist/form/Rating.svelte.d.ts +28 -0
  139. package/dist/form/Rating.svelte.d.ts.map +1 -0
  140. package/dist/form/Select.svelte +1933 -0
  141. package/dist/form/Select.svelte.d.ts +54 -0
  142. package/dist/form/Select.svelte.d.ts.map +1 -0
  143. package/dist/form/Toggle.svelte +645 -0
  144. package/dist/form/Toggle.svelte.d.ts +50 -0
  145. package/dist/form/Toggle.svelte.d.ts.map +1 -0
  146. package/dist/form/index.d.ts +15 -0
  147. package/dist/form/index.d.ts.map +1 -0
  148. package/dist/form/index.js +10 -0
  149. package/dist/index.d.ts +7 -0
  150. package/dist/index.d.ts.map +1 -0
  151. package/dist/index.js +6 -0
  152. package/dist/layout/README.md +172 -0
  153. package/dist/media/Carousel.svelte +2424 -0
  154. package/dist/media/Carousel.svelte.d.ts +47 -0
  155. package/dist/media/Carousel.svelte.d.ts.map +1 -0
  156. package/dist/media/Gallery.svelte +2881 -0
  157. package/dist/media/Gallery.svelte.d.ts +82 -0
  158. package/dist/media/Gallery.svelte.d.ts.map +1 -0
  159. package/dist/media/Image.svelte +389 -0
  160. package/dist/media/Image.svelte.d.ts +33 -0
  161. package/dist/media/Image.svelte.d.ts.map +1 -0
  162. package/dist/media/PDF.svelte +1793 -0
  163. package/dist/media/PDF.svelte.d.ts +44 -0
  164. package/dist/media/PDF.svelte.d.ts.map +1 -0
  165. package/dist/media/Panorama.svelte +1391 -0
  166. package/dist/media/Panorama.svelte.d.ts +47 -0
  167. package/dist/media/Panorama.svelte.d.ts.map +1 -0
  168. package/dist/media/Video.svelte +2501 -0
  169. package/dist/media/Video.svelte.d.ts +58 -0
  170. package/dist/media/Video.svelte.d.ts.map +1 -0
  171. package/dist/media/carousel.d.ts +211 -0
  172. package/dist/media/carousel.d.ts.map +1 -0
  173. package/dist/media/carousel.js +408 -0
  174. package/dist/media/index.d.ts +11 -0
  175. package/dist/media/index.d.ts.map +1 -0
  176. package/dist/media/index.js +5 -0
  177. package/dist/navigation/BottomSheet.svelte +636 -0
  178. package/dist/navigation/BottomSheet.svelte.d.ts +27 -0
  179. package/dist/navigation/BottomSheet.svelte.d.ts.map +1 -0
  180. package/dist/navigation/Breadcrumbs.svelte +611 -0
  181. package/dist/navigation/Breadcrumbs.svelte.d.ts +28 -0
  182. package/dist/navigation/Breadcrumbs.svelte.d.ts.map +1 -0
  183. package/dist/navigation/Pagination.svelte +641 -0
  184. package/dist/navigation/Pagination.svelte.d.ts +27 -0
  185. package/dist/navigation/Pagination.svelte.d.ts.map +1 -0
  186. package/dist/navigation/Steps.svelte +965 -0
  187. package/dist/navigation/Steps.svelte.d.ts +43 -0
  188. package/dist/navigation/Steps.svelte.d.ts.map +1 -0
  189. package/dist/navigation/Tabs.svelte +698 -0
  190. package/dist/navigation/Tabs.svelte.d.ts +41 -0
  191. package/dist/navigation/Tabs.svelte.d.ts.map +1 -0
  192. package/dist/navigation/index.d.ts +8 -0
  193. package/dist/navigation/index.d.ts.map +1 -0
  194. package/dist/navigation/index.js +5 -0
  195. package/package.json +139 -0
@@ -0,0 +1,529 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import Button from '../actions/Button.svelte';
4
+
5
+ const propId = $props.id();
6
+ let {
7
+ /** Success variant styling */
8
+ success = false,
9
+
10
+ /** Warning variant styling */
11
+ warning = false,
12
+
13
+ /** Error variant styling */
14
+ error = false,
15
+
16
+ /** Tip variant styling (uses accent color) */
17
+ tip = false,
18
+
19
+ /** Full-width banner mode with solid background and white text */
20
+ banner = false,
21
+
22
+ /** Optional heading text */
23
+ title = '',
24
+
25
+ /** Show a close/dismiss button */
26
+ dismissible = false,
27
+
28
+ /** Stick to top on scroll (banner mode only) */
29
+ sticky = false,
30
+
31
+ /** Compact padding */
32
+ dense = false,
33
+
34
+ /** Relaxed padding */
35
+ comfortable = false,
36
+
37
+ /** Loading skeleton state */
38
+ skeleton = false,
39
+
40
+ /** Number of body placeholder lines shown while skeleton is active */
41
+ skeleton_lines = 2,
42
+
43
+ /** Element ID */
44
+ id = propId,
45
+
46
+ /** Additional CSS classes */
47
+ class: class_name = '',
48
+
49
+ /** Called when the dismiss button is clicked */
50
+ ondismiss = undefined as (() => void) | undefined,
51
+
52
+ /** Main content */
53
+ children = undefined as undefined | Snippet,
54
+
55
+ /** Custom icon snippet (overrides default icon) */
56
+ icon = undefined as undefined | Snippet,
57
+
58
+ /** Action area snippet */
59
+ action = undefined as undefined | Snippet,
60
+ } = $props();
61
+
62
+ let dismissed = $state(false);
63
+ let visible = $state(false);
64
+
65
+ $effect(() => {
66
+ visible = true;
67
+ });
68
+
69
+ const variant = $derived(
70
+ error ? 'error' : warning ? 'warning' : success ? 'success' : tip ? 'tip' : 'info',
71
+ );
72
+
73
+ const alertRole = $derived(variant === 'error' || variant === 'warning');
74
+
75
+ function handleDismiss() {
76
+ dismissed = true;
77
+ ondismiss?.();
78
+ }
79
+ </script>
80
+
81
+ {#if !dismissed}
82
+ <svelte:element
83
+ this={banner ? 'aside' : 'div'}
84
+ {id}
85
+ class={['callout', variant, class_name].filter(Boolean).join(' ')}
86
+ class:banner
87
+ class:sticky={banner && sticky}
88
+ class:dense
89
+ class:comfortable
90
+ class:skeleton
91
+ class:visible
92
+ role={alertRole ? 'alert' : 'status'}>
93
+ <div class="inner">
94
+ <div class="icon" aria-hidden="true">
95
+ {#if icon}
96
+ {@render icon()}
97
+ {:else if variant === 'success'}
98
+ <svg
99
+ viewBox="0 0 24 24"
100
+ fill="none"
101
+ stroke="currentColor"
102
+ stroke-width="2"
103
+ stroke-linecap="round"
104
+ stroke-linejoin="round"
105
+ width="20"
106
+ height="20">
107
+ <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
108
+ <polyline points="22 4 12 14.01 9 11.01" />
109
+ </svg>
110
+ {:else if variant === 'warning'}
111
+ <svg
112
+ viewBox="0 0 24 24"
113
+ fill="none"
114
+ stroke="currentColor"
115
+ stroke-width="2"
116
+ stroke-linecap="round"
117
+ stroke-linejoin="round"
118
+ width="20"
119
+ height="20">
120
+ <path
121
+ d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" />
122
+ <line x1="12" y1="9" x2="12" y2="13" />
123
+ <line x1="12" y1="17" x2="12.01" y2="17" />
124
+ </svg>
125
+ {:else if variant === 'error'}
126
+ <svg
127
+ viewBox="0 0 24 24"
128
+ fill="none"
129
+ stroke="currentColor"
130
+ stroke-width="2"
131
+ stroke-linecap="round"
132
+ stroke-linejoin="round"
133
+ width="20"
134
+ height="20">
135
+ <circle cx="12" cy="12" r="10" />
136
+ <line x1="15" y1="9" x2="9" y2="15" />
137
+ <line x1="9" y1="9" x2="15" y2="15" />
138
+ </svg>
139
+ {:else if variant === 'tip'}
140
+ <svg
141
+ viewBox="0 0 24 24"
142
+ fill="none"
143
+ stroke="currentColor"
144
+ stroke-width="2"
145
+ stroke-linecap="round"
146
+ stroke-linejoin="round"
147
+ width="20"
148
+ height="20">
149
+ <line x1="9" y1="18" x2="15" y2="18" />
150
+ <line x1="10" y1="22" x2="14" y2="22" />
151
+ <path
152
+ d="M15.09 14c.18-.98.65-1.74 1.41-2.5A4.65 4.65 0 0 0 18 8 6 6 0 0 0 6 8c0 1 .23 2.23 1.5 3.5A4.61 4.61 0 0 1 8.91 14" />
153
+ </svg>
154
+ {:else}
155
+ <svg
156
+ viewBox="0 0 24 24"
157
+ fill="none"
158
+ stroke="currentColor"
159
+ stroke-width="2"
160
+ stroke-linecap="round"
161
+ stroke-linejoin="round"
162
+ width="20"
163
+ height="20">
164
+ <circle cx="12" cy="12" r="10" />
165
+ <line x1="12" y1="16" x2="12" y2="12" />
166
+ <line x1="12" y1="8" x2="12.01" y2="8" />
167
+ </svg>
168
+ {/if}
169
+ </div>
170
+
171
+ <div class="content">
172
+ {#if skeleton}
173
+ <!-- Mirror the real content's shape: a title bar only when a title
174
+ is coming, and one bar per expected body line — so the toggle
175
+ to loaded content causes no height change. -->
176
+ {#if title}
177
+ <div class="skeleton-line title-skeleton"></div>
178
+ {/if}
179
+ {#each { length: skeleton_lines } as _, i}
180
+ <div
181
+ class="skeleton-line"
182
+ class:short={skeleton_lines > 1 && i === skeleton_lines - 1}
183
+ style:--shimmer-delay="{(i + 1) * 120}ms">
184
+ </div>
185
+ {/each}
186
+ {:else}
187
+ {#if title}
188
+ <div class="title">{title}</div>
189
+ {/if}
190
+ {#if children}
191
+ <div class="body">
192
+ {@render children()}
193
+ </div>
194
+ {/if}
195
+ {/if}
196
+ </div>
197
+
198
+ {#if action && !skeleton}
199
+ <div class="action">
200
+ {@render action()}
201
+ </div>
202
+ {/if}
203
+
204
+ {#if dismissible && !skeleton}
205
+ <div class="dismiss">
206
+ <Button transparent icon size="0" tooltip="Dismiss" onclick={handleDismiss}>
207
+ <svg
208
+ viewBox="0 0 24 24"
209
+ fill="none"
210
+ stroke="currentColor"
211
+ stroke-width="2"
212
+ stroke-linecap="round"
213
+ stroke-linejoin="round">
214
+ <line x1="18" y1="6" x2="6" y2="18" />
215
+ <line x1="6" y1="6" x2="18" y2="18" />
216
+ </svg>
217
+ </Button>
218
+ </div>
219
+ {/if}
220
+ </div>
221
+ </svelte:element>
222
+ {/if}
223
+
224
+ <style>
225
+ .callout {
226
+ --callout-color: var(--color-action);
227
+ --callout-bg: var(--color-action-bg);
228
+ --_pad-y: 1rem;
229
+ --_pad-x: 1.25rem;
230
+ --_gap: 0.75rem;
231
+ --_accent-bar-margin: -0.25rem;
232
+ display: grid;
233
+ grid-template-rows: 0fr;
234
+ border-radius: var(--radius-lg);
235
+ @supports (corner-shape: squircle) {
236
+ corner-shape: squircle;
237
+ border-radius: calc(var(--radius-lg) * var(--squircle-ratio, 2));
238
+ }
239
+ background: var(--callout-bg);
240
+ opacity: 0;
241
+ transform: scale(0.98);
242
+ transition:
243
+ grid-template-rows 300ms ease,
244
+ opacity 300ms ease,
245
+ transform 300ms ease;
246
+
247
+ &.visible {
248
+ grid-template-rows: 1fr;
249
+ opacity: 1;
250
+ transform: scale(1);
251
+ }
252
+
253
+ &.success {
254
+ --callout-color: var(--color-success);
255
+ --callout-bg: var(--color-success-bg);
256
+ }
257
+ &.warning {
258
+ --callout-color: var(--color-warning);
259
+ --callout-bg: var(--color-warning-bg);
260
+ }
261
+ &.error {
262
+ --callout-color: var(--color-error);
263
+ --callout-bg: var(--color-error-bg);
264
+ }
265
+ &.tip {
266
+ --callout-color: var(--color-action);
267
+ --callout-bg: color-mix(in oklch, var(--color-action) 10%, transparent);
268
+ }
269
+
270
+ &.banner {
271
+ border-radius: 0;
272
+ width: 100%;
273
+ background: var(--callout-color);
274
+ color: white;
275
+ transform: none;
276
+ opacity: 0;
277
+ translate: 0 -100%;
278
+
279
+ &.visible {
280
+ opacity: 1;
281
+ translate: 0 0;
282
+ }
283
+
284
+ .inner {
285
+ justify-content: center;
286
+
287
+ /* Solid banners carry their color as the background — no accent bar. */
288
+ &::before {
289
+ content: none;
290
+ }
291
+ }
292
+
293
+ .icon {
294
+ color: white;
295
+ }
296
+
297
+ .title {
298
+ color: white;
299
+ }
300
+
301
+ .body {
302
+ color: rgba(255, 255, 255, 0.9);
303
+ }
304
+ }
305
+
306
+ &.sticky {
307
+ position: sticky;
308
+ top: 0;
309
+ z-index: var(--layer-sticky);
310
+ }
311
+
312
+ &.dense {
313
+ --_pad-y: 0.5rem;
314
+ --_pad-x: 0.75rem;
315
+ --_gap: 0.5rem;
316
+ --_accent-bar-margin: 0;
317
+ --radius-lg: var(--radius-md);
318
+ }
319
+
320
+ &.comfortable {
321
+ --_pad-y: 1.25rem;
322
+ --_pad-x: 1.75rem;
323
+ --_gap: 1rem;
324
+ --_accent-bar-margin: -0.5rem;
325
+ }
326
+
327
+ &.skeleton {
328
+ pointer-events: none;
329
+ /* Inline callouts are shrink-to-fit; the skeleton lines have no
330
+ * intrinsic width, so without a definite width here the content
331
+ * column would collapse to 0 and nothing would render. */
332
+ width: min(100%, 30rem);
333
+
334
+ /* Tint the shared skeleton tokens with the variant color so the
335
+ * placeholder lines read as part of the callout. */
336
+ --skeleton-bg: color-mix(in oklch, var(--callout-color) 25%, transparent);
337
+ --skeleton-sheen: color-mix(in oklch, var(--callout-color) 40%, transparent);
338
+
339
+ .content {
340
+ min-width: 0;
341
+ flex: 1;
342
+ /* Flex items don't collapse margins, so the bars' centering
343
+ * margins add up to exactly the real line boxes. */
344
+ display: flex;
345
+ flex-direction: column;
346
+ }
347
+ }
348
+
349
+ &.banner.skeleton {
350
+ /* Solid banners carry the variant color as background — tint the
351
+ * placeholder with white like the banner's own text. */
352
+ --skeleton-bg: rgb(255 255 255 / 0.25);
353
+ --skeleton-sheen: rgb(255 255 255 / 0.35);
354
+
355
+ .skeleton-line.title-skeleton {
356
+ --skeleton-bg: rgb(255 255 255 / 0.4);
357
+ }
358
+ }
359
+ }
360
+
361
+ .inner {
362
+ display: flex;
363
+ align-items: flex-start;
364
+ gap: var(--_gap);
365
+ padding: var(--_pad-y) var(--_pad-x);
366
+ overflow: hidden;
367
+
368
+ /* Accent bar. A border-left used to provide this emphasis, but a flush
369
+ * border fights the rounded corners (the radius curves the bar's ends
370
+ * into awkward slivers). A pill-shaped bar floating inside the padding
371
+ * keeps the emphasis and leaves the corners clean. The negative margin
372
+ * pulls it into the left padding so the space on either side of the bar
373
+ * equals the flex gap. */
374
+ &::before {
375
+ content: '';
376
+ align-self: stretch;
377
+ flex-shrink: 0;
378
+ width: 4px;
379
+ border-radius: var(--radius-full);
380
+ background: var(--callout-color);
381
+ margin-left: calc(var(--_gap) - var(--_pad-x));
382
+ margin-top: var(--_accent-bar-margin);
383
+ margin-bottom: var(--_accent-bar-margin);
384
+ }
385
+ }
386
+
387
+ /* Icon vertical alignment:
388
+ * - Single-line / short body: optically center on the first line of text.
389
+ * We achieve this by aligning the icon to the top and matching the
390
+ * text's first cap-height row via line-height math.
391
+ * - With a title: center on the title text specifically.
392
+ * - Long paragraphs naturally look balanced because the icon sits on the
393
+ * first line of body text. */
394
+ .icon {
395
+ flex-shrink: 0;
396
+ color: var(--callout-color);
397
+ display: flex;
398
+ align-items: center;
399
+ /* The icon is 20px and the body line-height ≈ 1.5em * 0.9375rem ≈ 22.5px,
400
+ * the title is 1em with line-height 1.4 ≈ 22.4px. Center the 20px icon
401
+ * inside a 22px line box. */
402
+ height: 1.4em;
403
+ line-height: 1.4em;
404
+
405
+ .visible & {
406
+ animation: icon-bounce 400ms ease 150ms both;
407
+ }
408
+ }
409
+
410
+ .content {
411
+ flex: 1;
412
+ min-width: 0;
413
+ }
414
+
415
+ .title {
416
+ font-weight: 600;
417
+ color: var(--callout-color);
418
+ margin-bottom: 0.25rem;
419
+ line-height: 1.4;
420
+ }
421
+
422
+ .body {
423
+ color: var(--color-text);
424
+ line-height: 1.5;
425
+ font-size: 0.9375rem;
426
+ }
427
+
428
+ .action {
429
+ display: flex;
430
+ align-items: center;
431
+ flex-shrink: 0;
432
+ margin-left: auto;
433
+ }
434
+
435
+ .dismiss {
436
+ display: flex;
437
+ align-items: center;
438
+ justify-content: center;
439
+ flex-shrink: 0;
440
+ color: var(--callout-color);
441
+ }
442
+ .dismiss :global(.button) {
443
+ --color-text: var(--callout-color);
444
+ }
445
+
446
+ /* Skeleton — each bar is centered inside the line box of the text it
447
+ * stands in for (body: 0.9375rem × 1.5 = 1.40625rem; title: 1em × 1.4
448
+ * plus its 0.25rem margin), so a title + two-line body resolves with no
449
+ * layout shift. */
450
+ .skeleton-line {
451
+ position: relative;
452
+ overflow: hidden;
453
+ background: var(--skeleton-bg, rgb(from var(--color-text, #888) r g b / 0.1));
454
+ border-radius: var(--radius-full, 1e5px);
455
+ height: 0.65625rem; /* 0.7 × body font size */
456
+ margin: 0.375rem 0; /* (1.40625rem - 0.65625rem) / 2 */
457
+
458
+ &::after {
459
+ content: '';
460
+ position: absolute;
461
+ inset: 0;
462
+ transform: translateX(-100%);
463
+ background-image: linear-gradient(
464
+ 105deg,
465
+ transparent 25%,
466
+ var(--skeleton-sheen, rgb(from var(--color-text, #888) r g b / 0.12)) 50%,
467
+ transparent 75%
468
+ );
469
+ animation: delight-skeleton-shimmer var(--skeleton-duration, 2.4s) ease-in-out
470
+ infinite;
471
+ animation-delay: var(--shimmer-delay, 0s);
472
+ }
473
+
474
+ &.title-skeleton {
475
+ width: 35%;
476
+ height: 0.7em;
477
+ margin: 0.35em 0 calc(0.35em + 0.25rem);
478
+ --skeleton-bg: color-mix(in oklch, var(--callout-color) 35%, transparent);
479
+ }
480
+ &.short {
481
+ width: 55%;
482
+ }
483
+ }
484
+
485
+ @keyframes icon-bounce {
486
+ 0% {
487
+ transform: scale(0);
488
+ opacity: 0;
489
+ }
490
+ 60% {
491
+ transform: scale(1.2);
492
+ opacity: 1;
493
+ }
494
+ 100% {
495
+ transform: scale(1);
496
+ opacity: 1;
497
+ }
498
+ }
499
+
500
+ @keyframes -global-delight-skeleton-shimmer {
501
+ 0% {
502
+ transform: translateX(-100%);
503
+ }
504
+ 55%,
505
+ 100% {
506
+ transform: translateX(100%);
507
+ }
508
+ }
509
+
510
+ @media (prefers-reduced-motion: reduce) {
511
+ .callout {
512
+ transition: none;
513
+
514
+ &.banner {
515
+ translate: none;
516
+ }
517
+ }
518
+
519
+ .icon {
520
+ .visible & {
521
+ animation: none;
522
+ }
523
+ }
524
+
525
+ .skeleton-line::after {
526
+ animation: none;
527
+ }
528
+ }
529
+ </style>
@@ -0,0 +1,24 @@
1
+ import type { Snippet } from 'svelte';
2
+ declare const Callout: import("svelte").Component<{
3
+ success?: boolean;
4
+ warning?: boolean;
5
+ error?: boolean;
6
+ tip?: boolean;
7
+ banner?: boolean;
8
+ title?: string;
9
+ dismissible?: boolean;
10
+ sticky?: boolean;
11
+ dense?: boolean;
12
+ comfortable?: boolean;
13
+ skeleton?: boolean;
14
+ skeleton_lines?: number;
15
+ id?: string;
16
+ class?: string;
17
+ ondismiss?: (() => void) | undefined;
18
+ children?: undefined | Snippet;
19
+ icon?: undefined | Snippet;
20
+ action?: undefined | Snippet;
21
+ }, {}, "">;
22
+ type Callout = ReturnType<typeof Callout>;
23
+ export default Callout;
24
+ //# sourceMappingURL=Callout.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Callout.svelte.d.ts","sourceRoot":"","sources":["../../src/feedback/Callout.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAuKtC,QAAA,MAAM,OAAO;cAhKsE,OAAO;cAAY,OAAO;YAAU,OAAO;UAAQ,OAAO;aAAW,OAAO;YAAU,MAAM;kBAAgB,OAAO;aAAW,OAAO;YAAU,OAAO;kBAAgB,OAAO;eAAa,OAAO;qBAAmB,MAAM;;YAA8B,MAAM;gBAAc,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS;eAAa,SAAS,GAAG,OAAO;WAAS,SAAS,GAAG,OAAO;aAAW,SAAS,GAAG,OAAO;UAgK5Z,CAAC;AACtD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAe,OAAO,CAAC"}