@classic-homes/theme-svelte 0.1.10 → 0.1.12

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.
@@ -1,7 +1,7 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  declare const Alert: import("svelte").Component<{
3
3
  [key: string]: unknown;
4
- variant?: "default" | "destructive" | "error" | "warning" | "success" | "info" | undefined;
4
+ variant?: "default" | "destructive" | "error" | "info" | "warning" | "success" | undefined;
5
5
  class?: string;
6
6
  children: Snippet;
7
7
  }, {}, "">;
@@ -1,7 +1,7 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  declare const Badge: import("svelte").Component<{
3
3
  [key: string]: unknown;
4
- variant?: "default" | "secondary" | "destructive" | "outline" | "warning" | "success" | "info" | undefined;
4
+ variant?: "default" | "secondary" | "destructive" | "outline" | "info" | "warning" | "success" | undefined;
5
5
  size?: "default" | "sm" | "dot" | undefined;
6
6
  clickable?: boolean;
7
7
  class?: string;
@@ -29,12 +29,14 @@
29
29
  error?: string;
30
30
  /** Additional class for the trigger */
31
31
  class?: string;
32
+ /** Show only date picker without time selection */
33
+ dateOnly?: boolean;
32
34
  }
33
35
 
34
36
  let {
35
37
  value = $bindable(null),
36
38
  onValueChange,
37
- placeholder = 'Select date and time...',
39
+ placeholder,
38
40
  disabled = false,
39
41
  required = false,
40
42
  min,
@@ -45,8 +47,13 @@
45
47
  id,
46
48
  error,
47
49
  class: className,
50
+ dateOnly = false,
48
51
  }: Props = $props();
49
52
 
53
+ // Set default placeholder based on dateOnly mode
54
+ const defaultPlaceholder = $derived(dateOnly ? 'Select date...' : 'Select date and time...');
55
+ const effectivePlaceholder = $derived(placeholder ?? defaultPlaceholder);
56
+
50
57
  let open = $state(false);
51
58
 
52
59
  // Calendar state - initialize with current date
@@ -77,6 +84,9 @@
77
84
  day: 'numeric',
78
85
  year: 'numeric',
79
86
  });
87
+ if (dateOnly) {
88
+ return dateStr;
89
+ }
80
90
  const timeStr = value.toLocaleTimeString('en-US', {
81
91
  hour: 'numeric',
82
92
  minute: '2-digit',
@@ -139,12 +149,17 @@
139
149
 
140
150
  const newDate = new Date(viewYear, viewMonth, day);
141
151
 
142
- // Preserve or set time
143
- let h = hour;
144
- if (timeFormat === '12h') {
145
- h = period === 'PM' ? (hour === 12 ? 12 : hour + 12) : hour === 12 ? 0 : hour;
152
+ if (dateOnly) {
153
+ // Set to midnight for date-only mode
154
+ newDate.setHours(0, 0, 0, 0);
155
+ } else {
156
+ // Preserve or set time
157
+ let h = hour;
158
+ if (timeFormat === '12h') {
159
+ h = period === 'PM' ? (hour === 12 ? 12 : hour + 12) : hour === 12 ? 0 : hour;
160
+ }
161
+ newDate.setHours(h, minute, 0, 0);
146
162
  }
147
- newDate.setHours(h, minute, 0, 0);
148
163
 
149
164
  value = newDate;
150
165
  onValueChange?.(newDate);
@@ -227,7 +242,7 @@
227
242
  aria-invalid={error ? 'true' : undefined}
228
243
  >
229
244
  <span class="truncate">
230
- {displayValue || placeholder}
245
+ {displayValue || effectivePlaceholder}
231
246
  </span>
232
247
  <svg
233
248
  xmlns="http://www.w3.org/2000/svg"
@@ -344,43 +359,45 @@
344
359
  {/each}
345
360
  </div>
346
361
 
347
- <!-- Time selector -->
348
- <div class="border-t mt-3 pt-3">
349
- <div class="flex items-center gap-2">
350
- <span class="text-sm text-muted-foreground">Time:</span>
351
- <select
352
- bind:value={hour}
353
- onchange={updateTime}
354
- class="h-8 rounded-md border border-input bg-background px-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
355
- >
356
- {#each hourOptions as h}
357
- <option value={timeFormat === '12h' ? h : h}>
358
- {String(h).padStart(2, '0')}
359
- </option>
360
- {/each}
361
- </select>
362
- <span class="text-muted-foreground">:</span>
363
- <select
364
- bind:value={minute}
365
- onchange={updateTime}
366
- class="h-8 rounded-md border border-input bg-background px-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
367
- >
368
- {#each minuteOptions as m}
369
- <option value={m}>{String(m).padStart(2, '0')}</option>
370
- {/each}
371
- </select>
372
- {#if timeFormat === '12h'}
362
+ <!-- Time selector (hidden in dateOnly mode) -->
363
+ {#if !dateOnly}
364
+ <div class="border-t mt-3 pt-3">
365
+ <div class="flex items-center gap-2">
366
+ <span class="text-sm text-muted-foreground">Time:</span>
373
367
  <select
374
- bind:value={period}
368
+ bind:value={hour}
375
369
  onchange={updateTime}
376
370
  class="h-8 rounded-md border border-input bg-background px-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
377
371
  >
378
- <option value="AM">AM</option>
379
- <option value="PM">PM</option>
372
+ {#each hourOptions as h}
373
+ <option value={timeFormat === '12h' ? h : h}>
374
+ {String(h).padStart(2, '0')}
375
+ </option>
376
+ {/each}
380
377
  </select>
381
- {/if}
378
+ <span class="text-muted-foreground">:</span>
379
+ <select
380
+ bind:value={minute}
381
+ onchange={updateTime}
382
+ class="h-8 rounded-md border border-input bg-background px-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
383
+ >
384
+ {#each minuteOptions as m}
385
+ <option value={m}>{String(m).padStart(2, '0')}</option>
386
+ {/each}
387
+ </select>
388
+ {#if timeFormat === '12h'}
389
+ <select
390
+ bind:value={period}
391
+ onchange={updateTime}
392
+ class="h-8 rounded-md border border-input bg-background px-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
393
+ >
394
+ <option value="AM">AM</option>
395
+ <option value="PM">PM</option>
396
+ </select>
397
+ {/if}
398
+ </div>
382
399
  </div>
383
- </div>
400
+ {/if}
384
401
 
385
402
  <!-- Actions -->
386
403
  <div class="border-t mt-3 pt-3 flex justify-between">
@@ -25,6 +25,8 @@ interface Props {
25
25
  error?: string;
26
26
  /** Additional class for the trigger */
27
27
  class?: string;
28
+ /** Show only date picker without time selection */
29
+ dateOnly?: boolean;
28
30
  }
29
31
  declare const DateTimePicker: import("svelte").Component<Props, {}, "value">;
30
32
  type DateTimePicker = ReturnType<typeof DateTimePicker>;
@@ -0,0 +1,370 @@
1
+ <script lang="ts">
2
+ import { cn } from '../utils.js';
3
+
4
+ /**
5
+ * Available icon names for the Icon component.
6
+ * These are common icons useful across applications.
7
+ */
8
+ export type IconName =
9
+ | 'close'
10
+ | 'check'
11
+ | 'plus'
12
+ | 'minus'
13
+ | 'edit'
14
+ | 'trash'
15
+ | 'info'
16
+ | 'alert-circle'
17
+ | 'alert-triangle'
18
+ | 'chevron-down'
19
+ | 'chevron-up'
20
+ | 'chevron-left'
21
+ | 'chevron-right'
22
+ | 'search'
23
+ | 'settings'
24
+ | 'user'
25
+ | 'home'
26
+ | 'external-link'
27
+ | 'loading'
28
+ | 'send'
29
+ | 'more'
30
+ | 'more-horizontal'
31
+ | 'grip'
32
+ | 'history'
33
+ | 'message'
34
+ | 'chat'
35
+ | 'eye'
36
+ | 'eye-off'
37
+ | 'copy'
38
+ | 'download'
39
+ | 'upload'
40
+ | 'refresh'
41
+ | 'arrow-left'
42
+ | 'arrow-right'
43
+ | 'menu'
44
+ | 'filter'
45
+ | 'sort'
46
+ | 'calendar'
47
+ | 'clock'
48
+ | 'mail'
49
+ | 'phone'
50
+ | 'link'
51
+ | 'image'
52
+ | 'file'
53
+ | 'folder'
54
+ | 'star'
55
+ | 'heart'
56
+ | 'bookmark'
57
+ | 'lock'
58
+ | 'unlock';
59
+
60
+ interface Props {
61
+ /** The name of the icon to display */
62
+ name: IconName;
63
+ /** Size of the icon in pixels (default: 24) */
64
+ size?: number;
65
+ /** Additional CSS classes */
66
+ class?: string;
67
+ /** Stroke width for stroke-based icons (default: 2) */
68
+ strokeWidth?: number;
69
+ /** Accessible label for the icon (renders as visually hidden text) */
70
+ label?: string;
71
+ /** Additional attributes to spread onto the SVG element */
72
+ [key: string]: unknown;
73
+ }
74
+
75
+ let { name, size = 24, class: className, strokeWidth = 2, label, ...restProps }: Props = $props();
76
+
77
+ // SVG path definitions for each icon
78
+ // All icons use a 24x24 viewBox
79
+ const icons: Record<IconName, { path: string; fill?: boolean }> = {
80
+ // Close (X)
81
+ close: {
82
+ path: 'M18 6L6 18M6 6l12 12',
83
+ },
84
+ // Check mark
85
+ check: {
86
+ path: 'M20 6L9 17l-5-5',
87
+ },
88
+ // Plus
89
+ plus: {
90
+ path: 'M12 5v14M5 12h14',
91
+ },
92
+ // Minus
93
+ minus: {
94
+ path: 'M5 12h14',
95
+ },
96
+ // Edit (pencil)
97
+ edit: {
98
+ path: 'M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5ZM15 5l4 4',
99
+ },
100
+ // Trash
101
+ trash: {
102
+ path: 'M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M10 11v6M14 11v6',
103
+ },
104
+ // Info
105
+ info: {
106
+ path: 'M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zM12 16v-4M12 8h.01',
107
+ },
108
+ // Alert circle
109
+ 'alert-circle': {
110
+ path: 'M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zM12 8v4M12 16h.01',
111
+ },
112
+ // Alert triangle
113
+ 'alert-triangle': {
114
+ path: '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 0zM12 9v4M12 17h.01',
115
+ },
116
+ // Chevrons
117
+ 'chevron-down': {
118
+ path: 'M6 9l6 6 6-6',
119
+ },
120
+ 'chevron-up': {
121
+ path: 'M18 15l-6-6-6 6',
122
+ },
123
+ 'chevron-left': {
124
+ path: 'M15 18l-6-6 6-6',
125
+ },
126
+ 'chevron-right': {
127
+ path: 'M9 18l6-6-6-6',
128
+ },
129
+ // Search
130
+ search: {
131
+ path: 'M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM21 21l-4.35-4.35',
132
+ },
133
+ // Settings (gear)
134
+ settings: {
135
+ path: 'M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2zM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z',
136
+ },
137
+ // User
138
+ user: {
139
+ path: 'M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z',
140
+ },
141
+ // Home
142
+ home: {
143
+ path: 'M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V9zM9 22V12h6v10',
144
+ },
145
+ // External link
146
+ 'external-link': {
147
+ path: 'M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14L21 3',
148
+ },
149
+ // Loading spinner (animated)
150
+ loading: {
151
+ path: '', // Special case - handled separately
152
+ },
153
+ // Send
154
+ send: {
155
+ path: 'M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z',
156
+ },
157
+ // More (vertical dots)
158
+ more: {
159
+ path: '', // Special case - uses filled circles
160
+ fill: true,
161
+ },
162
+ // More horizontal (horizontal dots)
163
+ 'more-horizontal': {
164
+ path: '', // Special case - uses filled circles
165
+ fill: true,
166
+ },
167
+ // Grip (drag handle)
168
+ grip: {
169
+ path: '', // Special case - uses filled circles
170
+ fill: true,
171
+ },
172
+ // History (clock)
173
+ history: {
174
+ path: 'M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zM12 6v6l4 2',
175
+ },
176
+ // Message bubble
177
+ message: {
178
+ path: 'M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z',
179
+ },
180
+ // Chat bubble (simpler)
181
+ chat: {
182
+ path: 'M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z',
183
+ },
184
+ // Eye
185
+ eye: {
186
+ path: 'M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8zM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z',
187
+ },
188
+ // Eye off
189
+ 'eye-off': {
190
+ path: 'M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24M1 1l22 22',
191
+ },
192
+ // Copy
193
+ copy: {
194
+ path: 'M20 9h-9a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2zM5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1',
195
+ },
196
+ // Download
197
+ download: {
198
+ path: 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3',
199
+ },
200
+ // Upload
201
+ upload: {
202
+ path: 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12',
203
+ },
204
+ // Refresh
205
+ refresh: {
206
+ path: 'M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15',
207
+ },
208
+ // Arrow left
209
+ 'arrow-left': {
210
+ path: 'M19 12H5M12 19l-7-7 7-7',
211
+ },
212
+ // Arrow right
213
+ 'arrow-right': {
214
+ path: 'M5 12h14M12 5l7 7-7 7',
215
+ },
216
+ // Menu (hamburger)
217
+ menu: {
218
+ path: 'M3 12h18M3 6h18M3 18h18',
219
+ },
220
+ // Filter
221
+ filter: {
222
+ path: 'M22 3H2l8 9.46V19l4 2v-8.54L22 3z',
223
+ },
224
+ // Sort
225
+ sort: {
226
+ path: 'M11 5h10M11 9h7M11 13h4M3 17l3 3 3-3M6 18V4',
227
+ },
228
+ // Calendar
229
+ calendar: {
230
+ path: 'M19 4H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zM16 2v4M8 2v4M3 10h18',
231
+ },
232
+ // Clock
233
+ clock: {
234
+ path: 'M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zM12 6v6l4 2',
235
+ },
236
+ // Mail
237
+ mail: {
238
+ path: 'M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2zM22 6l-10 7L2 6',
239
+ },
240
+ // Phone
241
+ phone: {
242
+ path: 'M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z',
243
+ },
244
+ // Link
245
+ link: {
246
+ path: 'M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71',
247
+ },
248
+ // Image
249
+ image: {
250
+ path: 'M19 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2zM8.5 10a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM21 15l-5-5L5 21',
251
+ },
252
+ // File
253
+ file: {
254
+ path: 'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8zM14 2v6h6M16 13H8M16 17H8M10 9H8',
255
+ },
256
+ // Folder
257
+ folder: {
258
+ path: 'M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z',
259
+ },
260
+ // Star
261
+ star: {
262
+ path: 'M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z',
263
+ },
264
+ // Heart
265
+ heart: {
266
+ path: 'M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z',
267
+ },
268
+ // Bookmark
269
+ bookmark: {
270
+ path: 'M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z',
271
+ },
272
+ // Lock
273
+ lock: {
274
+ path: 'M19 11H5a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7a2 2 0 0 0-2-2zM7 11V7a5 5 0 0 1 10 0v4',
275
+ },
276
+ // Unlock
277
+ unlock: {
278
+ path: 'M19 11H5a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7a2 2 0 0 0-2-2zM7 11V7a5 5 0 0 1 9.9-1',
279
+ },
280
+ };
281
+
282
+ const iconDef = $derived(icons[name]);
283
+ </script>
284
+
285
+ {#if name === 'loading'}
286
+ <!-- Loading spinner with animation -->
287
+ <svg
288
+ aria-hidden={!label}
289
+ width={size}
290
+ height={size}
291
+ viewBox="0 0 24 24"
292
+ fill="none"
293
+ stroke="currentColor"
294
+ stroke-width={strokeWidth}
295
+ class={cn('animate-spin', className)}
296
+ {...restProps}
297
+ >
298
+ <circle cx="12" cy="12" r="10" stroke-opacity="0.25"></circle>
299
+ <path d="M12 2a10 10 0 0 1 10 10" stroke-linecap="round"></path>
300
+ </svg>
301
+ {:else if name === 'more'}
302
+ <!-- Vertical dots -->
303
+ <svg
304
+ aria-hidden={!label}
305
+ width={size}
306
+ height={size}
307
+ viewBox="0 0 24 24"
308
+ fill="currentColor"
309
+ class={className}
310
+ {...restProps}
311
+ >
312
+ <circle cx="12" cy="5" r="1.5"></circle>
313
+ <circle cx="12" cy="12" r="1.5"></circle>
314
+ <circle cx="12" cy="19" r="1.5"></circle>
315
+ </svg>
316
+ {:else if name === 'more-horizontal'}
317
+ <!-- Horizontal dots -->
318
+ <svg
319
+ aria-hidden={!label}
320
+ width={size}
321
+ height={size}
322
+ viewBox="0 0 24 24"
323
+ fill="currentColor"
324
+ class={className}
325
+ {...restProps}
326
+ >
327
+ <circle cx="5" cy="12" r="1.5"></circle>
328
+ <circle cx="12" cy="12" r="1.5"></circle>
329
+ <circle cx="19" cy="12" r="1.5"></circle>
330
+ </svg>
331
+ {:else if name === 'grip'}
332
+ <!-- Grip handle (6 dots for drag) -->
333
+ <svg
334
+ aria-hidden={!label}
335
+ width={size}
336
+ height={size}
337
+ viewBox="0 0 24 24"
338
+ fill="currentColor"
339
+ class={className}
340
+ {...restProps}
341
+ >
342
+ <circle cx="8" cy="6" r="2"></circle>
343
+ <circle cx="16" cy="6" r="2"></circle>
344
+ <circle cx="8" cy="12" r="2"></circle>
345
+ <circle cx="16" cy="12" r="2"></circle>
346
+ <circle cx="8" cy="18" r="2"></circle>
347
+ <circle cx="16" cy="18" r="2"></circle>
348
+ </svg>
349
+ {:else if iconDef}
350
+ <!-- Standard path-based icons -->
351
+ <svg
352
+ aria-hidden={!label}
353
+ width={size}
354
+ height={size}
355
+ viewBox="0 0 24 24"
356
+ fill={iconDef.fill ? 'currentColor' : 'none'}
357
+ stroke={iconDef.fill ? 'none' : 'currentColor'}
358
+ stroke-width={iconDef.fill ? 0 : strokeWidth}
359
+ stroke-linecap="round"
360
+ stroke-linejoin="round"
361
+ class={className}
362
+ {...restProps}
363
+ >
364
+ <path d={iconDef.path}></path>
365
+ </svg>
366
+ {/if}
367
+
368
+ {#if label}
369
+ <span class="sr-only">{label}</span>
370
+ {/if}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Available icon names for the Icon component.
3
+ * These are common icons useful across applications.
4
+ */
5
+ export type IconName = 'close' | 'check' | 'plus' | 'minus' | 'edit' | 'trash' | 'info' | 'alert-circle' | 'alert-triangle' | 'chevron-down' | 'chevron-up' | 'chevron-left' | 'chevron-right' | 'search' | 'settings' | 'user' | 'home' | 'external-link' | 'loading' | 'send' | 'more' | 'more-horizontal' | 'grip' | 'history' | 'message' | 'chat' | 'eye' | 'eye-off' | 'copy' | 'download' | 'upload' | 'refresh' | 'arrow-left' | 'arrow-right' | 'menu' | 'filter' | 'sort' | 'calendar' | 'clock' | 'mail' | 'phone' | 'link' | 'image' | 'file' | 'folder' | 'star' | 'heart' | 'bookmark' | 'lock' | 'unlock';
6
+ interface Props {
7
+ /** The name of the icon to display */
8
+ name: IconName;
9
+ /** Size of the icon in pixels (default: 24) */
10
+ size?: number;
11
+ /** Additional CSS classes */
12
+ class?: string;
13
+ /** Stroke width for stroke-based icons (default: 2) */
14
+ strokeWidth?: number;
15
+ /** Accessible label for the icon (renders as visually hidden text) */
16
+ label?: string;
17
+ /** Additional attributes to spread onto the SVG element */
18
+ [key: string]: unknown;
19
+ }
20
+ declare const Icon: import("svelte").Component<Props, {}, "">;
21
+ type Icon = ReturnType<typeof Icon>;
22
+ export default Icon;
@@ -1,7 +1,7 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  declare const Toast: import("svelte").Component<{
3
3
  [key: string]: unknown;
4
- type?: "error" | "warning" | "success" | "info" | undefined;
4
+ type?: "error" | "info" | "warning" | "success" | undefined;
5
5
  title?: string;
6
6
  message: string;
7
7
  class?: string;
@@ -13,6 +13,7 @@ export { default as Textarea } from './components/Textarea.svelte';
13
13
  export { default as Checkbox } from './components/Checkbox.svelte';
14
14
  export { default as Switch } from './components/Switch.svelte';
15
15
  export { default as Separator } from './components/Separator.svelte';
16
+ export { default as Icon, type IconName } from './components/Icon.svelte';
16
17
  export { default as Card } from './components/Card.svelte';
17
18
  export { default as CardHeader } from './components/CardHeader.svelte';
18
19
  export { default as CardTitle } from './components/CardTitle.svelte';
@@ -74,3 +75,4 @@ export { validateNonEmptyArray, validateRequired, validateOneOf, validateRange,
74
75
  export { perfStart, perfEnd, measure, measureAsync, getPerformanceEntries, clearPerformanceEntries, createPerfMonitor, type PerformanceMark, } from './performance.js';
75
76
  export { useForm, useAsync, runAsync, usePersistedForm, type UseFormOptions, type UseFormReturn, type FieldError, type FormState, type InferFormData, type UseAsyncOptions, type UseAsyncReturn, type UsePersistedFormOptions, type UsePersistedFormReturn, type InferPersistedFormData, } from './composables/index.js';
76
77
  export * from './schemas/index.js';
78
+ export { type Notice, type NoticeConfig, type NoticeLocation, type NoticeVariant, type NoticePage, type ActiveNotice, NoticeSchema, NoticeLinkSchema, validateNotice, validateNotices, initializeNotices, setCurrentPath, dismissNotice, clearDismissedNotices, isNoticeDismissed, activeNotices, bannerNotices, cardNotices, getNoticesForPage, refreshNotices, cleanupDismissedNotices, isNoticeActive, isNoticeForPage, isNoticeForLocation, sanitizeHtml, initSanitizer, NoticeBanner, NoticeCard, } from './notices/index.js';
package/dist/lib/index.js CHANGED
@@ -14,6 +14,7 @@ export { default as Textarea } from './components/Textarea.svelte';
14
14
  export { default as Checkbox } from './components/Checkbox.svelte';
15
15
  export { default as Switch } from './components/Switch.svelte';
16
16
  export { default as Separator } from './components/Separator.svelte';
17
+ export { default as Icon } from './components/Icon.svelte';
17
18
  // Card Components
18
19
  export { default as Card } from './components/Card.svelte';
19
20
  export { default as CardHeader } from './components/CardHeader.svelte';
@@ -92,3 +93,13 @@ export { perfStart, perfEnd, measure, measureAsync, getPerformanceEntries, clear
92
93
  export { useForm, useAsync, runAsync, usePersistedForm, } from './composables/index.js';
93
94
  // Validation schemas - Zod schemas for forms and data validation
94
95
  export * from './schemas/index.js';
96
+ // Notice System - Scheduled, page-specific, dismissible announcements
97
+ export {
98
+ // Schemas
99
+ NoticeSchema, NoticeLinkSchema, validateNotice, validateNotices,
100
+ // Store
101
+ initializeNotices, setCurrentPath, dismissNotice, clearDismissedNotices, isNoticeDismissed, activeNotices, bannerNotices, cardNotices, getNoticesForPage, refreshNotices, cleanupDismissedNotices, isNoticeActive, isNoticeForPage, isNoticeForLocation,
102
+ // Sanitization
103
+ sanitizeHtml, initSanitizer,
104
+ // Components
105
+ NoticeBanner, NoticeCard, } from './notices/index.js';