@classic-homes/theme-svelte 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.
- package/README.md +305 -0
- package/dist/lib/components/Alert.svelte +51 -0
- package/dist/lib/components/Alert.svelte.d.ts +9 -0
- package/dist/lib/components/AlertDescription.svelte +16 -0
- package/dist/lib/components/AlertDescription.svelte.d.ts +9 -0
- package/dist/lib/components/AlertDialog.svelte +136 -0
- package/dist/lib/components/AlertDialog.svelte.d.ts +79 -0
- package/dist/lib/components/AlertTitle.svelte +16 -0
- package/dist/lib/components/AlertTitle.svelte.d.ts +9 -0
- package/dist/lib/components/Avatar.svelte +56 -0
- package/dist/lib/components/Avatar.svelte.d.ts +26 -0
- package/dist/lib/components/AvatarFallback.svelte +31 -0
- package/dist/lib/components/AvatarFallback.svelte.d.ts +17 -0
- package/dist/lib/components/AvatarImage.svelte +29 -0
- package/dist/lib/components/AvatarImage.svelte.d.ts +12 -0
- package/dist/lib/components/Badge.svelte +73 -0
- package/dist/lib/components/Badge.svelte.d.ts +11 -0
- package/dist/lib/components/Button.svelte +130 -0
- package/dist/lib/components/Button.svelte.d.ts +17 -0
- package/dist/lib/components/Card.svelte +58 -0
- package/dist/lib/components/Card.svelte.d.ts +26 -0
- package/dist/lib/components/CardContent.svelte +16 -0
- package/dist/lib/components/CardContent.svelte.d.ts +9 -0
- package/dist/lib/components/CardDescription.svelte +16 -0
- package/dist/lib/components/CardDescription.svelte.d.ts +9 -0
- package/dist/lib/components/CardFooter.svelte +16 -0
- package/dist/lib/components/CardFooter.svelte.d.ts +9 -0
- package/dist/lib/components/CardHeader.svelte +16 -0
- package/dist/lib/components/CardHeader.svelte.d.ts +9 -0
- package/dist/lib/components/CardTitle.svelte +16 -0
- package/dist/lib/components/CardTitle.svelte.d.ts +9 -0
- package/dist/lib/components/Checkbox.svelte +65 -0
- package/dist/lib/components/Checkbox.svelte.d.ts +14 -0
- package/dist/lib/components/DataTable.svelte +334 -0
- package/dist/lib/components/DataTable.svelte.d.ts +103 -0
- package/dist/lib/components/Dialog.svelte +111 -0
- package/dist/lib/components/Dialog.svelte.d.ts +22 -0
- package/dist/lib/components/DropdownMenu.svelte +135 -0
- package/dist/lib/components/DropdownMenu.svelte.d.ts +33 -0
- package/dist/lib/components/FileUpload.svelte +448 -0
- package/dist/lib/components/FileUpload.svelte.d.ts +42 -0
- package/dist/lib/components/FormField.svelte +134 -0
- package/dist/lib/components/FormField.svelte.d.ts +37 -0
- package/dist/lib/components/Input.svelte +61 -0
- package/dist/lib/components/Input.svelte.d.ts +19 -0
- package/dist/lib/components/Label.svelte +33 -0
- package/dist/lib/components/Label.svelte.d.ts +11 -0
- package/dist/lib/components/LoadingLogo.svelte +124 -0
- package/dist/lib/components/LoadingLogo.svelte.d.ts +16 -0
- package/dist/lib/components/LogoMain.svelte +237 -0
- package/dist/lib/components/LogoMain.svelte.d.ts +20 -0
- package/dist/lib/components/PageHeader.svelte +90 -0
- package/dist/lib/components/PageHeader.svelte.d.ts +28 -0
- package/dist/lib/components/Section.svelte +44 -0
- package/dist/lib/components/Section.svelte.d.ts +28 -0
- package/dist/lib/components/Select.svelte +174 -0
- package/dist/lib/components/Select.svelte.d.ts +32 -0
- package/dist/lib/components/Separator.svelte +29 -0
- package/dist/lib/components/Separator.svelte.d.ts +9 -0
- package/dist/lib/components/Skeleton.svelte +35 -0
- package/dist/lib/components/Skeleton.svelte.d.ts +7 -0
- package/dist/lib/components/Spinner.svelte +50 -0
- package/dist/lib/components/Spinner.svelte.d.ts +8 -0
- package/dist/lib/components/Switch.svelte +56 -0
- package/dist/lib/components/Switch.svelte.d.ts +14 -0
- package/dist/lib/components/TabPanel.svelte +44 -0
- package/dist/lib/components/TabPanel.svelte.d.ts +12 -0
- package/dist/lib/components/Tabs.svelte +125 -0
- package/dist/lib/components/Tabs.svelte.d.ts +19 -0
- package/dist/lib/components/Textarea.svelte +54 -0
- package/dist/lib/components/Textarea.svelte.d.ts +16 -0
- package/dist/lib/components/Toast.svelte +116 -0
- package/dist/lib/components/Toast.svelte.d.ts +12 -0
- package/dist/lib/components/ToastContainer.svelte +56 -0
- package/dist/lib/components/ToastContainer.svelte.d.ts +8 -0
- package/dist/lib/components/Tooltip.svelte +55 -0
- package/dist/lib/components/Tooltip.svelte.d.ts +18 -0
- package/dist/lib/components/layout/AppShell.svelte +82 -0
- package/dist/lib/components/layout/AppShell.svelte.d.ts +44 -0
- package/dist/lib/components/layout/DashboardLayout.svelte +248 -0
- package/dist/lib/components/layout/DashboardLayout.svelte.d.ts +62 -0
- package/dist/lib/components/layout/Footer.svelte +130 -0
- package/dist/lib/components/layout/Footer.svelte.d.ts +32 -0
- package/dist/lib/components/layout/FormPageLayout.svelte +92 -0
- package/dist/lib/components/layout/FormPageLayout.svelte.d.ts +33 -0
- package/dist/lib/components/layout/Header.svelte +94 -0
- package/dist/lib/components/layout/Header.svelte.d.ts +30 -0
- package/dist/lib/components/layout/PublicLayout.svelte +180 -0
- package/dist/lib/components/layout/PublicLayout.svelte.d.ts +39 -0
- package/dist/lib/components/layout/QuickLinks.svelte +112 -0
- package/dist/lib/components/layout/QuickLinks.svelte.d.ts +27 -0
- package/dist/lib/components/layout/Sidebar.svelte +243 -0
- package/dist/lib/components/layout/Sidebar.svelte.d.ts +48 -0
- package/dist/lib/composables/index.d.ts +8 -0
- package/dist/lib/composables/index.js +10 -0
- package/dist/lib/composables/useAsync.svelte.d.ts +102 -0
- package/dist/lib/composables/useAsync.svelte.js +210 -0
- package/dist/lib/composables/useForm.svelte.d.ts +123 -0
- package/dist/lib/composables/useForm.svelte.js +245 -0
- package/dist/lib/index.d.ts +65 -0
- package/dist/lib/index.js +83 -0
- package/dist/lib/performance.d.ts +79 -0
- package/dist/lib/performance.js +170 -0
- package/dist/lib/schemas/auth.d.ts +410 -0
- package/dist/lib/schemas/auth.js +216 -0
- package/dist/lib/schemas/common.d.ts +267 -0
- package/dist/lib/schemas/common.js +268 -0
- package/dist/lib/schemas/index.d.ts +24 -0
- package/dist/lib/schemas/index.js +32 -0
- package/dist/lib/stores/sidebar.svelte.d.ts +25 -0
- package/dist/lib/stores/sidebar.svelte.js +38 -0
- package/dist/lib/stores/theme.svelte.d.ts +72 -0
- package/dist/lib/stores/theme.svelte.js +150 -0
- package/dist/lib/stores/toast.svelte.d.ts +62 -0
- package/dist/lib/stores/toast.svelte.js +93 -0
- package/dist/lib/types/components.d.ts +85 -0
- package/dist/lib/types/components.js +7 -0
- package/dist/lib/types/layout.d.ts +258 -0
- package/dist/lib/types/layout.js +7 -0
- package/dist/lib/utils.d.ts +6 -0
- package/dist/lib/utils.js +9 -0
- package/dist/lib/validation.d.ts +101 -0
- package/dist/lib/validation.js +170 -0
- package/package.json +56 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Store - Svelte 5 runes-based theme management
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Light/dark/system mode support
|
|
6
|
+
* - System preference detection via matchMedia
|
|
7
|
+
* - Persistence via localStorage
|
|
8
|
+
* - SSR-safe (checks for window/document)
|
|
9
|
+
* - Reactive theme resolution
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```svelte
|
|
13
|
+
* <script>
|
|
14
|
+
* import { themeStore } from '@classic-homes/theme-svelte';
|
|
15
|
+
* </script>
|
|
16
|
+
*
|
|
17
|
+
* <button onclick={() => themeStore.toggle()}>
|
|
18
|
+
* {themeStore.resolvedTheme === 'dark' ? 'Light' : 'Dark'} Mode
|
|
19
|
+
* </button>
|
|
20
|
+
*
|
|
21
|
+
* <select value={themeStore.mode} onchange={(e) => themeStore.setMode(e.target.value)}>
|
|
22
|
+
* <option value="light">Light</option>
|
|
23
|
+
* <option value="dark">Dark</option>
|
|
24
|
+
* <option value="system">System</option>
|
|
25
|
+
* </select>
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export type ThemeMode = 'light' | 'dark' | 'system';
|
|
29
|
+
declare class ThemeStore {
|
|
30
|
+
/** Current theme mode setting (light, dark, or system) */
|
|
31
|
+
mode: ThemeMode;
|
|
32
|
+
/** Resolved theme (accounts for system preference when mode is 'system') */
|
|
33
|
+
resolvedTheme: "dark" | "light";
|
|
34
|
+
/** Whether we're on the client (not SSR) */
|
|
35
|
+
private isClient;
|
|
36
|
+
/** Media query for system dark mode preference */
|
|
37
|
+
private mediaQuery;
|
|
38
|
+
constructor();
|
|
39
|
+
private init;
|
|
40
|
+
private handleSystemChange;
|
|
41
|
+
private updateResolvedTheme;
|
|
42
|
+
private applyTheme;
|
|
43
|
+
/**
|
|
44
|
+
* Set theme mode and persist to localStorage
|
|
45
|
+
* @param mode - The theme mode to set ('light', 'dark', or 'system')
|
|
46
|
+
*/
|
|
47
|
+
setMode(mode: ThemeMode): void;
|
|
48
|
+
/**
|
|
49
|
+
* Toggle between light and dark modes
|
|
50
|
+
* If currently using system mode, switches to the opposite of system preference
|
|
51
|
+
* NOTE: No-op when DARK_MODE_ENABLED is false
|
|
52
|
+
*/
|
|
53
|
+
toggle(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Reset to follow system preference
|
|
56
|
+
*/
|
|
57
|
+
useSystem(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Check if currently following system preference
|
|
60
|
+
*/
|
|
61
|
+
get isSystem(): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Check if current resolved theme is dark
|
|
64
|
+
*/
|
|
65
|
+
get isDark(): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Check if current resolved theme is light
|
|
68
|
+
*/
|
|
69
|
+
get isLight(): boolean;
|
|
70
|
+
}
|
|
71
|
+
export declare const themeStore: ThemeStore;
|
|
72
|
+
export {};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Store - Svelte 5 runes-based theme management
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Light/dark/system mode support
|
|
6
|
+
* - System preference detection via matchMedia
|
|
7
|
+
* - Persistence via localStorage
|
|
8
|
+
* - SSR-safe (checks for window/document)
|
|
9
|
+
* - Reactive theme resolution
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```svelte
|
|
13
|
+
* <script>
|
|
14
|
+
* import { themeStore } from '@classic-homes/theme-svelte';
|
|
15
|
+
* </script>
|
|
16
|
+
*
|
|
17
|
+
* <button onclick={() => themeStore.toggle()}>
|
|
18
|
+
* {themeStore.resolvedTheme === 'dark' ? 'Light' : 'Dark'} Mode
|
|
19
|
+
* </button>
|
|
20
|
+
*
|
|
21
|
+
* <select value={themeStore.mode} onchange={(e) => themeStore.setMode(e.target.value)}>
|
|
22
|
+
* <option value="light">Light</option>
|
|
23
|
+
* <option value="dark">Dark</option>
|
|
24
|
+
* <option value="system">System</option>
|
|
25
|
+
* </select>
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* TEMPORARY: Dark mode is disabled while we focus on light mode styling.
|
|
30
|
+
* Set to true to re-enable dark mode functionality.
|
|
31
|
+
*/
|
|
32
|
+
const DARK_MODE_ENABLED = false;
|
|
33
|
+
const STORAGE_KEY = 'classic-theme-mode';
|
|
34
|
+
class ThemeStore {
|
|
35
|
+
constructor() {
|
|
36
|
+
/** Current theme mode setting (light, dark, or system) */
|
|
37
|
+
this.mode = $state('system');
|
|
38
|
+
/** Resolved theme (accounts for system preference when mode is 'system') */
|
|
39
|
+
this.resolvedTheme = $state('light');
|
|
40
|
+
/** Whether we're on the client (not SSR) */
|
|
41
|
+
this.isClient = typeof window !== 'undefined';
|
|
42
|
+
/** Media query for system dark mode preference */
|
|
43
|
+
this.mediaQuery = null;
|
|
44
|
+
if (this.isClient) {
|
|
45
|
+
this.init();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
init() {
|
|
49
|
+
// Load persisted preference
|
|
50
|
+
try {
|
|
51
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
52
|
+
if (stored && ['light', 'dark', 'system'].includes(stored)) {
|
|
53
|
+
this.mode = stored;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// localStorage may not be available (private browsing, etc.)
|
|
58
|
+
}
|
|
59
|
+
// Set up system preference listener
|
|
60
|
+
this.mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
61
|
+
this.mediaQuery.addEventListener('change', this.handleSystemChange.bind(this));
|
|
62
|
+
// Initial resolution
|
|
63
|
+
this.updateResolvedTheme();
|
|
64
|
+
}
|
|
65
|
+
handleSystemChange() {
|
|
66
|
+
if (this.mode === 'system') {
|
|
67
|
+
this.updateResolvedTheme();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
updateResolvedTheme() {
|
|
71
|
+
if (!this.isClient)
|
|
72
|
+
return;
|
|
73
|
+
let resolved;
|
|
74
|
+
// TEMPORARY: Force light mode while dark mode is disabled
|
|
75
|
+
if (!DARK_MODE_ENABLED) {
|
|
76
|
+
resolved = 'light';
|
|
77
|
+
}
|
|
78
|
+
else if (this.mode === 'system') {
|
|
79
|
+
resolved = this.mediaQuery?.matches ? 'dark' : 'light';
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
resolved = this.mode;
|
|
83
|
+
}
|
|
84
|
+
this.resolvedTheme = resolved;
|
|
85
|
+
this.applyTheme(resolved);
|
|
86
|
+
}
|
|
87
|
+
applyTheme(theme) {
|
|
88
|
+
if (!this.isClient)
|
|
89
|
+
return;
|
|
90
|
+
const root = document.documentElement;
|
|
91
|
+
root.classList.remove('light', 'dark');
|
|
92
|
+
root.classList.add(theme);
|
|
93
|
+
// Update meta theme-color for mobile browsers
|
|
94
|
+
const metaThemeColor = document.querySelector('meta[name="theme-color"]');
|
|
95
|
+
if (metaThemeColor) {
|
|
96
|
+
metaThemeColor.setAttribute('content', theme === 'dark' ? '#292424' : '#ffffff');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Set theme mode and persist to localStorage
|
|
101
|
+
* @param mode - The theme mode to set ('light', 'dark', or 'system')
|
|
102
|
+
*/
|
|
103
|
+
setMode(mode) {
|
|
104
|
+
this.mode = mode;
|
|
105
|
+
if (this.isClient) {
|
|
106
|
+
try {
|
|
107
|
+
localStorage.setItem(STORAGE_KEY, mode);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// localStorage may not be available
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
this.updateResolvedTheme();
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Toggle between light and dark modes
|
|
117
|
+
* If currently using system mode, switches to the opposite of system preference
|
|
118
|
+
* NOTE: No-op when DARK_MODE_ENABLED is false
|
|
119
|
+
*/
|
|
120
|
+
toggle() {
|
|
121
|
+
if (!DARK_MODE_ENABLED)
|
|
122
|
+
return;
|
|
123
|
+
this.setMode(this.resolvedTheme === 'light' ? 'dark' : 'light');
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Reset to follow system preference
|
|
127
|
+
*/
|
|
128
|
+
useSystem() {
|
|
129
|
+
this.setMode('system');
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if currently following system preference
|
|
133
|
+
*/
|
|
134
|
+
get isSystem() {
|
|
135
|
+
return this.mode === 'system';
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Check if current resolved theme is dark
|
|
139
|
+
*/
|
|
140
|
+
get isDark() {
|
|
141
|
+
return this.resolvedTheme === 'dark';
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Check if current resolved theme is light
|
|
145
|
+
*/
|
|
146
|
+
get isLight() {
|
|
147
|
+
return this.resolvedTheme === 'light';
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
export const themeStore = new ThemeStore();
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toast Store - Svelte 5 runes-based state management for toast notifications
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Auto-dismiss with configurable duration
|
|
6
|
+
* - Manual dismiss support
|
|
7
|
+
* - Proper timeout cleanup to prevent memory leaks
|
|
8
|
+
* - Convenience methods for common toast types
|
|
9
|
+
*/
|
|
10
|
+
export interface Toast {
|
|
11
|
+
id: string;
|
|
12
|
+
message: string;
|
|
13
|
+
type: 'success' | 'error' | 'warning' | 'info';
|
|
14
|
+
title?: string;
|
|
15
|
+
duration?: number;
|
|
16
|
+
}
|
|
17
|
+
export type ToastInput = Omit<Toast, 'id'>;
|
|
18
|
+
declare class ToastStore {
|
|
19
|
+
toasts: Toast[];
|
|
20
|
+
/** Map of toast IDs to their timeout handles for cleanup */
|
|
21
|
+
private timeouts;
|
|
22
|
+
/**
|
|
23
|
+
* Add a new toast notification
|
|
24
|
+
* @param toast - Toast configuration without id
|
|
25
|
+
* @returns The generated toast id
|
|
26
|
+
*/
|
|
27
|
+
add(toast: ToastInput): string;
|
|
28
|
+
/**
|
|
29
|
+
* Remove a toast by id
|
|
30
|
+
* Also clears any pending auto-dismiss timeout
|
|
31
|
+
*/
|
|
32
|
+
remove(id: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Remove all toasts and clear all pending timeouts
|
|
35
|
+
*/
|
|
36
|
+
clear(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Update an existing toast
|
|
39
|
+
* @param id - Toast ID to update
|
|
40
|
+
* @param updates - Partial toast properties to update
|
|
41
|
+
*/
|
|
42
|
+
update(id: string, updates: Partial<Omit<Toast, 'id'>>): void;
|
|
43
|
+
/**
|
|
44
|
+
* Convenience method for success toast
|
|
45
|
+
*/
|
|
46
|
+
success(message: string, options?: Partial<Omit<ToastInput, 'message' | 'type'>>): string;
|
|
47
|
+
/**
|
|
48
|
+
* Convenience method for error toast
|
|
49
|
+
* Note: Errors persist by default (duration: 0) since they typically require acknowledgment
|
|
50
|
+
*/
|
|
51
|
+
error(message: string, options?: Partial<Omit<ToastInput, 'message' | 'type'>>): string;
|
|
52
|
+
/**
|
|
53
|
+
* Convenience method for warning toast
|
|
54
|
+
*/
|
|
55
|
+
warning(message: string, options?: Partial<Omit<ToastInput, 'message' | 'type'>>): string;
|
|
56
|
+
/**
|
|
57
|
+
* Convenience method for info toast
|
|
58
|
+
*/
|
|
59
|
+
info(message: string, options?: Partial<Omit<ToastInput, 'message' | 'type'>>): string;
|
|
60
|
+
}
|
|
61
|
+
export declare const toastStore: ToastStore;
|
|
62
|
+
export {};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toast Store - Svelte 5 runes-based state management for toast notifications
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Auto-dismiss with configurable duration
|
|
6
|
+
* - Manual dismiss support
|
|
7
|
+
* - Proper timeout cleanup to prevent memory leaks
|
|
8
|
+
* - Convenience methods for common toast types
|
|
9
|
+
*/
|
|
10
|
+
class ToastStore {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.toasts = $state([]);
|
|
13
|
+
/** Map of toast IDs to their timeout handles for cleanup */
|
|
14
|
+
this.timeouts = new Map();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Add a new toast notification
|
|
18
|
+
* @param toast - Toast configuration without id
|
|
19
|
+
* @returns The generated toast id
|
|
20
|
+
*/
|
|
21
|
+
add(toast) {
|
|
22
|
+
const id = crypto.randomUUID();
|
|
23
|
+
const newToast = { ...toast, id };
|
|
24
|
+
this.toasts = [...this.toasts, newToast];
|
|
25
|
+
// Auto-dismiss unless duration is explicitly 0 (persistent)
|
|
26
|
+
if (toast.duration !== 0) {
|
|
27
|
+
const duration = toast.duration ?? 5000;
|
|
28
|
+
const timeoutId = setTimeout(() => {
|
|
29
|
+
this.remove(id);
|
|
30
|
+
}, duration);
|
|
31
|
+
this.timeouts.set(id, timeoutId);
|
|
32
|
+
}
|
|
33
|
+
return id;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Remove a toast by id
|
|
37
|
+
* Also clears any pending auto-dismiss timeout
|
|
38
|
+
*/
|
|
39
|
+
remove(id) {
|
|
40
|
+
// Clear timeout if exists to prevent memory leak
|
|
41
|
+
const timeoutId = this.timeouts.get(id);
|
|
42
|
+
if (timeoutId !== undefined) {
|
|
43
|
+
clearTimeout(timeoutId);
|
|
44
|
+
this.timeouts.delete(id);
|
|
45
|
+
}
|
|
46
|
+
this.toasts = this.toasts.filter((t) => t.id !== id);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Remove all toasts and clear all pending timeouts
|
|
50
|
+
*/
|
|
51
|
+
clear() {
|
|
52
|
+
// Clear all pending timeouts
|
|
53
|
+
for (const timeoutId of this.timeouts.values()) {
|
|
54
|
+
clearTimeout(timeoutId);
|
|
55
|
+
}
|
|
56
|
+
this.timeouts.clear();
|
|
57
|
+
this.toasts = [];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Update an existing toast
|
|
61
|
+
* @param id - Toast ID to update
|
|
62
|
+
* @param updates - Partial toast properties to update
|
|
63
|
+
*/
|
|
64
|
+
update(id, updates) {
|
|
65
|
+
this.toasts = this.toasts.map((t) => (t.id === id ? { ...t, ...updates } : t));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Convenience method for success toast
|
|
69
|
+
*/
|
|
70
|
+
success(message, options) {
|
|
71
|
+
return this.add({ message, type: 'success', ...options });
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Convenience method for error toast
|
|
75
|
+
* Note: Errors persist by default (duration: 0) since they typically require acknowledgment
|
|
76
|
+
*/
|
|
77
|
+
error(message, options) {
|
|
78
|
+
return this.add({ message, type: 'error', duration: 0, ...options });
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Convenience method for warning toast
|
|
82
|
+
*/
|
|
83
|
+
warning(message, options) {
|
|
84
|
+
return this.add({ message, type: 'warning', ...options });
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Convenience method for info toast
|
|
88
|
+
*/
|
|
89
|
+
info(message, options) {
|
|
90
|
+
return this.add({ message, type: 'info', ...options });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export const toastStore = new ToastStore();
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component Types for Classic Theme
|
|
3
|
+
*
|
|
4
|
+
* These types are exported from components but need to be
|
|
5
|
+
* re-exported from a TypeScript file for proper type inference.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Dropdown Menu Types
|
|
9
|
+
*/
|
|
10
|
+
import type { Snippet } from 'svelte';
|
|
11
|
+
export interface DropdownMenuItem {
|
|
12
|
+
type?: 'item' | 'checkbox' | 'radio' | 'separator' | 'label';
|
|
13
|
+
label?: string;
|
|
14
|
+
value?: string;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
checked?: boolean;
|
|
17
|
+
onSelect?: () => void;
|
|
18
|
+
destructive?: boolean;
|
|
19
|
+
icon?: Snippet;
|
|
20
|
+
shortcut?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface DropdownMenuGroup {
|
|
23
|
+
label?: string;
|
|
24
|
+
items: DropdownMenuItem[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Select Types
|
|
28
|
+
*/
|
|
29
|
+
export interface SelectOption {
|
|
30
|
+
value: string;
|
|
31
|
+
label: string;
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface SelectGroup {
|
|
35
|
+
label: string;
|
|
36
|
+
options: SelectOption[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Tabs Types
|
|
40
|
+
*/
|
|
41
|
+
export interface Tab {
|
|
42
|
+
id: string;
|
|
43
|
+
label: string;
|
|
44
|
+
disabled?: boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* FileUpload Types
|
|
48
|
+
*/
|
|
49
|
+
export interface FileMetadata {
|
|
50
|
+
/** Unique identifier for the file */
|
|
51
|
+
id: string;
|
|
52
|
+
/** Original filename */
|
|
53
|
+
filename: string;
|
|
54
|
+
/** MIME type */
|
|
55
|
+
contentType: string;
|
|
56
|
+
/** File size in bytes */
|
|
57
|
+
size: number;
|
|
58
|
+
/** URL for preview (data URL or remote URL) */
|
|
59
|
+
url?: string;
|
|
60
|
+
/** Upload progress (0-100) */
|
|
61
|
+
progress?: number;
|
|
62
|
+
/** Error message if upload failed */
|
|
63
|
+
error?: string;
|
|
64
|
+
/** Whether the file is currently uploading */
|
|
65
|
+
uploading?: boolean;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* DataTable Types
|
|
69
|
+
*/
|
|
70
|
+
export interface DataTableColumn<T = Record<string, unknown>> {
|
|
71
|
+
/** Unique column identifier */
|
|
72
|
+
id: string;
|
|
73
|
+
/** Column header text */
|
|
74
|
+
header: string;
|
|
75
|
+
/** Key in the data object, or accessor function */
|
|
76
|
+
accessor: keyof T | ((row: T) => unknown);
|
|
77
|
+
/** Whether this column is sortable */
|
|
78
|
+
sortable?: boolean;
|
|
79
|
+
/** Column width (CSS value) */
|
|
80
|
+
width?: string;
|
|
81
|
+
/** Text alignment */
|
|
82
|
+
align?: 'left' | 'center' | 'right';
|
|
83
|
+
/** Custom cell render function returning string */
|
|
84
|
+
format?: (value: unknown, row: T) => string;
|
|
85
|
+
}
|