@classic-homes/theme-svelte 0.1.4 → 0.1.6

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 (55) hide show
  1. package/dist/lib/components/CardHeader.svelte +22 -2
  2. package/dist/lib/components/CardHeader.svelte.d.ts +5 -4
  3. package/dist/lib/components/Combobox.svelte +187 -0
  4. package/dist/lib/components/Combobox.svelte.d.ts +38 -0
  5. package/dist/lib/components/DateTimePicker.svelte +415 -0
  6. package/dist/lib/components/DateTimePicker.svelte.d.ts +31 -0
  7. package/dist/lib/components/HeaderSearch.svelte +340 -0
  8. package/dist/lib/components/HeaderSearch.svelte.d.ts +37 -0
  9. package/dist/lib/components/MultiSelect.svelte +244 -0
  10. package/dist/lib/components/MultiSelect.svelte.d.ts +40 -0
  11. package/dist/lib/components/NumberInput.svelte +205 -0
  12. package/dist/lib/components/NumberInput.svelte.d.ts +33 -0
  13. package/dist/lib/components/OTPInput.svelte +213 -0
  14. package/dist/lib/components/OTPInput.svelte.d.ts +23 -0
  15. package/dist/lib/components/PageHeader.svelte +6 -0
  16. package/dist/lib/components/PageHeader.svelte.d.ts +1 -1
  17. package/dist/lib/components/RadioGroup.svelte +124 -0
  18. package/dist/lib/components/RadioGroup.svelte.d.ts +31 -0
  19. package/dist/lib/components/Signature.svelte +1070 -0
  20. package/dist/lib/components/Signature.svelte.d.ts +74 -0
  21. package/dist/lib/components/Slider.svelte +136 -0
  22. package/dist/lib/components/Slider.svelte.d.ts +30 -0
  23. package/dist/lib/components/layout/AuthLayout.svelte +133 -0
  24. package/dist/lib/components/layout/AuthLayout.svelte.d.ts +48 -0
  25. package/dist/lib/components/layout/DashboardLayout.svelte +100 -74
  26. package/dist/lib/components/layout/DashboardLayout.svelte.d.ts +17 -10
  27. package/dist/lib/components/layout/ErrorLayout.svelte +206 -0
  28. package/dist/lib/components/layout/ErrorLayout.svelte.d.ts +52 -0
  29. package/dist/lib/components/layout/FormPageLayout.svelte +2 -8
  30. package/dist/lib/components/layout/Header.svelte +232 -41
  31. package/dist/lib/components/layout/Header.svelte.d.ts +71 -5
  32. package/dist/lib/components/layout/PublicLayout.svelte +54 -80
  33. package/dist/lib/components/layout/PublicLayout.svelte.d.ts +3 -1
  34. package/dist/lib/components/layout/QuickLinks.svelte +49 -29
  35. package/dist/lib/components/layout/QuickLinks.svelte.d.ts +4 -2
  36. package/dist/lib/components/layout/Sidebar.svelte +345 -86
  37. package/dist/lib/components/layout/Sidebar.svelte.d.ts +12 -0
  38. package/dist/lib/components/layout/sidebar/SidebarFlyout.svelte +182 -0
  39. package/dist/lib/components/layout/sidebar/SidebarFlyout.svelte.d.ts +18 -0
  40. package/dist/lib/components/layout/sidebar/SidebarNavItem.svelte +378 -0
  41. package/dist/lib/components/layout/sidebar/SidebarNavItem.svelte.d.ts +25 -0
  42. package/dist/lib/components/layout/sidebar/SidebarSearch.svelte +121 -0
  43. package/dist/lib/components/layout/sidebar/SidebarSearch.svelte.d.ts +17 -0
  44. package/dist/lib/components/layout/sidebar/SidebarSection.svelte +144 -0
  45. package/dist/lib/components/layout/sidebar/SidebarSection.svelte.d.ts +25 -0
  46. package/dist/lib/components/layout/sidebar/index.d.ts +10 -0
  47. package/dist/lib/components/layout/sidebar/index.js +10 -0
  48. package/dist/lib/index.d.ts +13 -2
  49. package/dist/lib/index.js +11 -0
  50. package/dist/lib/schemas/auth.d.ts +6 -6
  51. package/dist/lib/stores/sidebar.svelte.d.ts +54 -0
  52. package/dist/lib/stores/sidebar.svelte.js +171 -1
  53. package/dist/lib/types/components.d.ts +105 -0
  54. package/dist/lib/types/layout.d.ts +203 -3
  55. package/package.json +1 -1
@@ -1,38 +1,208 @@
1
1
  /**
2
2
  * Sidebar Store - Svelte 5 runes-based state management for sidebar
3
3
  */
4
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
5
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
6
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
7
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
8
+ };
9
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
10
+ if (kind === "m") throw new TypeError("Private method is not writable");
11
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
12
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
13
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
14
+ };
15
+ var _SidebarStore_instances, _SidebarStore_initialized, _SidebarStore_loadedFromStorage, _SidebarStore_loadedExpansionFromStorage, _SidebarStore_persist, _SidebarStore_persistExpansion;
16
+ const STORAGE_KEY = 'classic-theme-sidebar-open';
17
+ const SECTIONS_STORAGE_KEY = 'classic-theme-sidebar-sections';
18
+ const ITEMS_STORAGE_KEY = 'classic-theme-sidebar-items';
4
19
  class SidebarStore {
5
20
  constructor() {
21
+ _SidebarStore_instances.add(this);
6
22
  this.isOpen = $state(true);
7
23
  this.isMobile = $state(false);
24
+ this.expandedSections = $state(new Set());
25
+ this.expandedItems = $state(new Set());
26
+ _SidebarStore_initialized.set(this, false);
27
+ _SidebarStore_loadedFromStorage.set(this, false);
28
+ _SidebarStore_loadedExpansionFromStorage.set(this, false);
29
+ }
30
+ /**
31
+ * Whether the store has been initialized
32
+ */
33
+ get initialized() {
34
+ return __classPrivateFieldGet(this, _SidebarStore_initialized, "f");
35
+ }
36
+ /**
37
+ * Whether the sidebar open state was loaded from localStorage
38
+ */
39
+ get hasPersistedState() {
40
+ return __classPrivateFieldGet(this, _SidebarStore_loadedFromStorage, "f");
41
+ }
42
+ /**
43
+ * Whether expansion state was loaded from localStorage
44
+ */
45
+ get hasPersistedExpansionState() {
46
+ return __classPrivateFieldGet(this, _SidebarStore_loadedExpansionFromStorage, "f");
47
+ }
48
+ /**
49
+ * Initialize store with persisted state.
50
+ * Call this from a component's $effect to load saved state.
51
+ */
52
+ initialize() {
53
+ if (__classPrivateFieldGet(this, _SidebarStore_initialized, "f") || typeof window === 'undefined')
54
+ return;
55
+ __classPrivateFieldSet(this, _SidebarStore_initialized, true, "f");
56
+ try {
57
+ // Load sidebar open state
58
+ const stored = localStorage.getItem(STORAGE_KEY);
59
+ if (stored !== null) {
60
+ this.isOpen = stored === 'true';
61
+ __classPrivateFieldSet(this, _SidebarStore_loadedFromStorage, true, "f");
62
+ }
63
+ // Load expanded sections
64
+ const sections = localStorage.getItem(SECTIONS_STORAGE_KEY);
65
+ if (sections) {
66
+ this.expandedSections = new Set(JSON.parse(sections));
67
+ __classPrivateFieldSet(this, _SidebarStore_loadedExpansionFromStorage, true, "f");
68
+ }
69
+ // Load expanded items
70
+ const items = localStorage.getItem(ITEMS_STORAGE_KEY);
71
+ if (items) {
72
+ this.expandedItems = new Set(JSON.parse(items));
73
+ __classPrivateFieldSet(this, _SidebarStore_loadedExpansionFromStorage, true, "f");
74
+ }
75
+ }
76
+ catch {
77
+ // localStorage not available
78
+ }
8
79
  }
9
80
  /**
10
81
  * Toggle the sidebar open/closed state
11
82
  */
12
83
  toggle() {
13
84
  this.isOpen = !this.isOpen;
85
+ __classPrivateFieldGet(this, _SidebarStore_instances, "m", _SidebarStore_persist).call(this);
14
86
  }
15
87
  /**
16
88
  * Open the sidebar
17
89
  */
18
90
  open() {
19
91
  this.isOpen = true;
92
+ __classPrivateFieldGet(this, _SidebarStore_instances, "m", _SidebarStore_persist).call(this);
20
93
  }
21
94
  /**
22
95
  * Close the sidebar
23
96
  */
24
97
  close() {
25
98
  this.isOpen = false;
99
+ __classPrivateFieldGet(this, _SidebarStore_instances, "m", _SidebarStore_persist).call(this);
26
100
  }
27
101
  /**
28
102
  * Set mobile mode
29
103
  */
30
104
  setMobile(isMobile) {
31
105
  this.isMobile = isMobile;
32
- // Auto-close sidebar on mobile
106
+ // Auto-close sidebar on mobile (don't persist mobile state)
33
107
  if (isMobile) {
34
108
  this.isOpen = false;
35
109
  }
36
110
  }
111
+ /**
112
+ * Toggle section expansion state
113
+ */
114
+ toggleSection(sectionId) {
115
+ const newSet = new Set(this.expandedSections);
116
+ if (newSet.has(sectionId)) {
117
+ newSet.delete(sectionId);
118
+ }
119
+ else {
120
+ newSet.add(sectionId);
121
+ }
122
+ this.expandedSections = newSet;
123
+ __classPrivateFieldGet(this, _SidebarStore_instances, "m", _SidebarStore_persistExpansion).call(this);
124
+ }
125
+ /**
126
+ * Toggle item expansion state
127
+ */
128
+ toggleItem(itemId) {
129
+ const newSet = new Set(this.expandedItems);
130
+ if (newSet.has(itemId)) {
131
+ newSet.delete(itemId);
132
+ }
133
+ else {
134
+ newSet.add(itemId);
135
+ }
136
+ this.expandedItems = newSet;
137
+ __classPrivateFieldGet(this, _SidebarStore_instances, "m", _SidebarStore_persistExpansion).call(this);
138
+ }
139
+ /**
140
+ * Check if a section is expanded
141
+ */
142
+ isSectionExpanded(sectionId) {
143
+ return this.expandedSections.has(sectionId);
144
+ }
145
+ /**
146
+ * Check if an item is expanded
147
+ */
148
+ isItemExpanded(itemId) {
149
+ return this.expandedItems.has(itemId);
150
+ }
151
+ /**
152
+ * Set default expansion for sections (called during initialization)
153
+ */
154
+ setDefaultSections(sectionIds) {
155
+ if (__classPrivateFieldGet(this, _SidebarStore_loadedExpansionFromStorage, "f"))
156
+ return;
157
+ this.expandedSections = new Set(sectionIds);
158
+ }
159
+ /**
160
+ * Set default expansion for items (called during initialization)
161
+ */
162
+ setDefaultItems(itemIds) {
163
+ if (__classPrivateFieldGet(this, _SidebarStore_loadedExpansionFromStorage, "f"))
164
+ return;
165
+ this.expandedItems = new Set(itemIds);
166
+ }
167
+ /**
168
+ * Force expand specific items (used during search to show matching children)
169
+ * This bypasses the persisted state check but doesn't persist the changes
170
+ */
171
+ forceExpandItems(itemIds) {
172
+ const newSet = new Set(this.expandedItems);
173
+ itemIds.forEach((id) => newSet.add(id));
174
+ this.expandedItems = newSet;
175
+ // Don't persist - this is temporary for search
176
+ }
177
+ /**
178
+ * Force expand specific sections (used during search)
179
+ * This bypasses the persisted state check but doesn't persist the changes
180
+ */
181
+ forceExpandSections(sectionIds) {
182
+ const newSet = new Set(this.expandedSections);
183
+ sectionIds.forEach((id) => newSet.add(id));
184
+ this.expandedSections = newSet;
185
+ // Don't persist - this is temporary for search
186
+ }
37
187
  }
188
+ _SidebarStore_initialized = new WeakMap(), _SidebarStore_loadedFromStorage = new WeakMap(), _SidebarStore_loadedExpansionFromStorage = new WeakMap(), _SidebarStore_instances = new WeakSet(), _SidebarStore_persist = function _SidebarStore_persist() {
189
+ if (typeof window === 'undefined')
190
+ return;
191
+ try {
192
+ localStorage.setItem(STORAGE_KEY, String(this.isOpen));
193
+ }
194
+ catch {
195
+ // localStorage not available
196
+ }
197
+ }, _SidebarStore_persistExpansion = function _SidebarStore_persistExpansion() {
198
+ if (typeof window === 'undefined')
199
+ return;
200
+ try {
201
+ localStorage.setItem(SECTIONS_STORAGE_KEY, JSON.stringify([...this.expandedSections]));
202
+ localStorage.setItem(ITEMS_STORAGE_KEY, JSON.stringify([...this.expandedItems]));
203
+ }
204
+ catch {
205
+ // localStorage not available
206
+ }
207
+ };
38
208
  export const sidebarStore = new SidebarStore();
@@ -80,3 +80,108 @@ export interface DataTableColumn<T = object> {
80
80
  /** Custom cell render function returning string */
81
81
  format?: (value: unknown, row: T) => string;
82
82
  }
83
+ /**
84
+ * RadioGroup Types
85
+ */
86
+ export interface RadioOption {
87
+ value: string;
88
+ label: string;
89
+ disabled?: boolean;
90
+ description?: string;
91
+ }
92
+ /**
93
+ * Combobox Types
94
+ */
95
+ export interface ComboboxOption {
96
+ value: string;
97
+ label: string;
98
+ disabled?: boolean;
99
+ }
100
+ /**
101
+ * MultiSelect Types
102
+ */
103
+ export interface MultiSelectOption {
104
+ value: string;
105
+ label: string;
106
+ disabled?: boolean;
107
+ }
108
+ /**
109
+ * Signature Types
110
+ */
111
+ /** Signature output data */
112
+ export interface SignatureData {
113
+ /** Unique identifier for this signature instance */
114
+ id: string;
115
+ /** The signature mode used */
116
+ mode: 'draw' | 'type';
117
+ /** Data URL of the signature image (PNG base64) */
118
+ dataUrl: string;
119
+ /** PNG blob (if requested) */
120
+ png?: Blob;
121
+ /** SVG string (if requested or mode is draw) */
122
+ svg?: string;
123
+ /** Typed name (if mode is type) */
124
+ typedName?: string;
125
+ /** Font used for typed signature */
126
+ font?: string;
127
+ /** Stroke data for reconstruction (draw mode) */
128
+ strokes?: SignatureStroke[];
129
+ /** Metadata for legal/audit purposes */
130
+ metadata: SignatureMetadata;
131
+ }
132
+ /** Individual stroke in draw mode */
133
+ export interface SignatureStroke {
134
+ /** Stroke points */
135
+ points: SignaturePoint[];
136
+ /** Stroke color */
137
+ color: string;
138
+ /** Stroke width */
139
+ width: number;
140
+ /** Timestamp when stroke started */
141
+ startTime: number;
142
+ /** Timestamp when stroke ended */
143
+ endTime: number;
144
+ }
145
+ /** Point in a stroke */
146
+ export interface SignaturePoint {
147
+ x: number;
148
+ y: number;
149
+ /** Pressure (0-1) if available */
150
+ pressure?: number;
151
+ /** Timestamp */
152
+ time: number;
153
+ }
154
+ /** Metadata captured with signature */
155
+ export interface SignatureMetadata {
156
+ /** ISO timestamp when signature was created */
157
+ timestamp: string;
158
+ /** User agent string */
159
+ userAgent: string;
160
+ /** Canvas dimensions used */
161
+ dimensions: {
162
+ width: number;
163
+ height: number;
164
+ };
165
+ /** Whether consent was given */
166
+ consented: boolean;
167
+ /** Consent text shown (for audit trail) */
168
+ consentText?: string;
169
+ /** Hash of signature data for tamper detection */
170
+ hash?: string;
171
+ }
172
+ /** Font configuration for typed signatures */
173
+ export interface SignatureFont {
174
+ /** Font family name */
175
+ family: string;
176
+ /** Display name for font picker */
177
+ label: string;
178
+ /** CSS src URL or Google Fonts name */
179
+ src?: string;
180
+ /** Whether font is loaded from Google Fonts */
181
+ googleFont?: boolean;
182
+ }
183
+ /** Validation result */
184
+ export interface SignatureValidationResult {
185
+ valid: boolean;
186
+ error?: string;
187
+ }
@@ -5,6 +5,65 @@
5
5
  * navigation, user data, and layout props.
6
6
  */
7
7
  import type { Snippet } from 'svelte';
8
+ /**
9
+ * Generic search result item for header search
10
+ * Consumers can extend this interface for custom result types
11
+ */
12
+ export interface SearchResultItem {
13
+ /** Unique identifier */
14
+ id: string;
15
+ /** Display title */
16
+ title: string;
17
+ /** Optional description/excerpt */
18
+ description?: string;
19
+ /** Navigation URL */
20
+ href?: string;
21
+ /** Optional category/section for grouping */
22
+ category?: string;
23
+ /** Optional icon name */
24
+ icon?: string;
25
+ }
26
+ /**
27
+ * Search result group for categorized results
28
+ */
29
+ export interface SearchResultGroup<T = SearchResultItem> {
30
+ /** Group title (e.g., "Pages", "Documentation") */
31
+ title: string;
32
+ /** Items in this group */
33
+ items: T[];
34
+ }
35
+ /**
36
+ * Search configuration for Header component
37
+ * Backend-agnostic - works with any search provider (Algolia, Fuse.js, custom API, etc.)
38
+ */
39
+ export interface HeaderSearchConfig<T = SearchResultItem> {
40
+ /** Whether search is enabled/visible */
41
+ enabled?: boolean;
42
+ /** Placeholder text for search input */
43
+ placeholder?: string;
44
+ /** Called when user types (debounced). App should update results prop. */
45
+ onSearch?: (query: string) => void;
46
+ /** Called when user selects a result */
47
+ onSelect?: (item: T) => void;
48
+ /** Called when search dialog opens/closes */
49
+ onOpenChange?: (open: boolean) => void;
50
+ /** Search results to display (flat list or grouped) */
51
+ results?: T[] | SearchResultGroup<T>[];
52
+ /** Whether results are currently loading */
53
+ loading?: boolean;
54
+ /** Message when no results found */
55
+ emptyMessage?: string;
56
+ /** Enable Cmd/Ctrl+K shortcut (default: true) */
57
+ enableShortcut?: boolean;
58
+ /** Custom shortcut key (default: 'k') */
59
+ shortcutKey?: string;
60
+ /** Trigger button variant: 'default' shows full search box, 'icon' shows icon-only button */
61
+ variant?: 'default' | 'icon';
62
+ /** Custom result item renderer */
63
+ renderResult?: Snippet<[T, boolean]>;
64
+ /** Custom empty state renderer */
65
+ renderEmpty?: Snippet;
66
+ }
8
67
  /**
9
68
  * Navigation item for sidebar and header navigation
10
69
  */
@@ -13,8 +72,8 @@ export interface NavItem {
13
72
  id: string;
14
73
  /** Display name */
15
74
  name: string;
16
- /** URL to navigate to */
17
- href: string;
75
+ /** URL to navigate to (optional if item has children) */
76
+ href?: string;
18
77
  /** Icon name (app renders via snippet) */
19
78
  icon?: string;
20
79
  /** Optional badge (notification count, etc.) */
@@ -25,6 +84,14 @@ export interface NavItem {
25
84
  external?: boolean;
26
85
  /** Whether this item is currently active */
27
86
  active?: boolean;
87
+ /** Nested child items for submenus */
88
+ children?: NavItem[];
89
+ /** Whether submenu is expanded (for items with children) */
90
+ expanded?: boolean;
91
+ /** Whether the item is disabled */
92
+ disabled?: boolean;
93
+ /** Whether the item is in a loading state */
94
+ loading?: boolean;
28
95
  }
29
96
  /**
30
97
  * Navigation section for grouping nav items
@@ -85,6 +152,8 @@ export interface QuickLink {
85
152
  external?: boolean;
86
153
  /** Accessible label for screen readers (used in icon-only mode) */
87
154
  ariaLabel?: string;
155
+ /** Optional badge (notification count, etc.) */
156
+ badge?: string | number;
88
157
  }
89
158
  /**
90
159
  * Props for QuickLinks component
@@ -98,6 +167,8 @@ export interface QuickLinksProps {
98
167
  variant?: 'light' | 'dark';
99
168
  /** Custom icon renderer */
100
169
  icon?: Snippet<[QuickLink]>;
170
+ /** Accessible label for the navigation region */
171
+ ariaLabel?: string;
101
172
  /** Additional classes */
102
173
  class?: string;
103
174
  }
@@ -131,6 +202,8 @@ export interface DashboardLayoutProps {
131
202
  quickLinksDisplay?: 'list' | 'icons';
132
203
  /** Custom icon renderer for quick links */
133
204
  quickLinkIcon?: Snippet<[QuickLink]>;
205
+ /** Callback when a navigation item is clicked */
206
+ onNavigate?: (item: NavItem) => void;
134
207
  /** Custom content at start of header */
135
208
  headerStart?: Snippet;
136
209
  /** Custom content at end of header */
@@ -139,6 +212,12 @@ export interface DashboardLayoutProps {
139
212
  userMenu?: Snippet<[User]>;
140
213
  /** Sidebar footer content */
141
214
  sidebarFooter?: Snippet;
215
+ /** Sidebar width when expanded in pixels (default: 256) */
216
+ expandedWidth?: number;
217
+ /** Sidebar width when collapsed in pixels (default: 64) */
218
+ collapsedWidth?: number;
219
+ /** Header search configuration */
220
+ headerSearch?: HeaderSearchConfig;
142
221
  /** Main content */
143
222
  children: Snippet;
144
223
  }
@@ -158,6 +237,8 @@ export interface PublicLayoutProps {
158
237
  logo?: Snippet;
159
238
  /** Custom header end content */
160
239
  headerEnd?: Snippet;
240
+ /** Header search configuration */
241
+ headerSearch?: HeaderSearchConfig;
161
242
  /** Main content */
162
243
  children: Snippet;
163
244
  }
@@ -167,6 +248,8 @@ export interface PublicLayoutProps {
167
248
  export interface SidebarProps {
168
249
  /** Navigation sections */
169
250
  navigation: NavSection[];
251
+ /** User roles for filtering navigation items */
252
+ userRoles?: string[];
170
253
  /** Visual variant - light (default) or dark */
171
254
  variant?: 'light' | 'dark';
172
255
  /** Whether sidebar is collapsed */
@@ -177,6 +260,8 @@ export interface SidebarProps {
177
260
  mobileOpen?: boolean;
178
261
  /** Callback when mobile sidebar should close */
179
262
  onClose?: () => void;
263
+ /** Callback when a navigation item is clicked */
264
+ onNavigate?: (item: NavItem) => void;
180
265
  /** Custom logo snippet */
181
266
  logo?: Snippet;
182
267
  /** Custom icon renderer for nav items */
@@ -191,21 +276,59 @@ export interface SidebarProps {
191
276
  footer?: Snippet;
192
277
  /** Use stronger/thicker border */
193
278
  strongBorder?: boolean;
279
+ /** Sidebar width when expanded in pixels (default: 256) */
280
+ expandedWidth?: number;
281
+ /** Sidebar width when collapsed in pixels (default: 64) */
282
+ collapsedWidth?: number;
283
+ /** Enable search/filter input for navigation */
284
+ searchable?: boolean;
285
+ /** Placeholder text for search input */
286
+ searchPlaceholder?: string;
194
287
  /** Additional classes */
195
288
  class?: string;
196
289
  }
197
290
  /**
198
291
  * Props for Header component
292
+ *
293
+ * A unified header component that supports both dashboard and public layouts.
294
+ * Use mobileBreakpoint to control responsive behavior and mobileNav for
295
+ * inline mobile navigation drawers.
199
296
  */
200
297
  export interface HeaderProps {
201
298
  /** Whether to show hamburger menu button (mobile) */
202
299
  showMenuButton?: boolean;
300
+ /** Whether the mobile menu is currently open (for aria-expanded) */
301
+ menuOpen?: boolean;
203
302
  /** Callback when menu button is clicked */
204
303
  onMenuClick?: () => void;
205
- /** Custom start content (left side) */
304
+ /** Whether to show collapse/expand button (desktop sidebar toggle) */
305
+ showCollapseButton?: boolean;
306
+ /** Whether the sidebar is collapsed (for aria-expanded and icon direction) */
307
+ sidebarCollapsed?: boolean;
308
+ /** Callback when collapse button is clicked */
309
+ onCollapseClick?: () => void;
310
+ /** Page title displayed in header */
311
+ title?: string;
312
+ /** Custom start content (left side, after menu/collapse buttons) */
206
313
  start?: Snippet;
314
+ /** Navigation content (center/right on desktop, hidden on mobile) */
315
+ nav?: Snippet;
207
316
  /** Custom end content (right side) */
208
317
  end?: Snippet;
318
+ /** Mobile navigation drawer content (appears below header bar when menu is open) */
319
+ mobileNav?: Snippet;
320
+ /** Breakpoint at which to switch between mobile and desktop layouts */
321
+ mobileBreakpoint?: 'sm' | 'md' | 'lg';
322
+ /** Use stronger/thicker border */
323
+ strongBorder?: boolean;
324
+ /** Enable backdrop blur effect */
325
+ backdropBlur?: boolean;
326
+ /** Use elevated z-index (z-50 instead of z-30) */
327
+ elevated?: boolean;
328
+ /** Constrain content to max-width container */
329
+ maxWidth?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | '7xl';
330
+ /** Search configuration */
331
+ search?: HeaderSearchConfig;
209
332
  /** Additional classes */
210
333
  class?: string;
211
334
  }
@@ -256,3 +379,80 @@ export interface FormPageLayoutProps {
256
379
  /** Additional classes for the container */
257
380
  class?: string;
258
381
  }
382
+ /**
383
+ * Footer link for AuthLayout
384
+ */
385
+ export interface AuthFooterLink {
386
+ /** Link label */
387
+ label: string;
388
+ /** Link URL */
389
+ href: string;
390
+ /** Opens in new tab */
391
+ external?: boolean;
392
+ }
393
+ /**
394
+ * Props for AuthLayout component
395
+ *
396
+ * A centered layout for authentication pages (login, signup, password reset, etc.)
397
+ * Composes AppShell for consistent base structure.
398
+ */
399
+ export interface AuthLayoutProps {
400
+ /** Custom logo snippet */
401
+ logo?: Snippet;
402
+ /** Logo subtitle for default logo (e.g., "Sign in to your account") */
403
+ logoSubtitle?: string;
404
+ /** Logo environment indicator for default logo */
405
+ logoEnvironment?: 'local' | 'dev' | 'demo';
406
+ /** Footer links (privacy policy, terms, etc.) */
407
+ footerLinks?: AuthFooterLink[];
408
+ /** Custom footer content (replaces footer links) */
409
+ footer?: Snippet;
410
+ /** Show decorative background */
411
+ showBackground?: boolean;
412
+ /** Background variant */
413
+ backgroundVariant?: 'default' | 'gradient' | 'pattern';
414
+ /** Maximum width of content card */
415
+ maxWidth?: 'sm' | 'md' | 'lg';
416
+ /** Additional classes for the container */
417
+ class?: string;
418
+ /** Main content (auth form) */
419
+ children: Snippet;
420
+ }
421
+ /**
422
+ * Props for ErrorLayout component
423
+ *
424
+ * A centered layout for error pages (404, 500, etc.)
425
+ * Composes AppShell for consistent base structure.
426
+ */
427
+ export interface ErrorLayoutProps {
428
+ /** HTTP status code (404, 500, etc.) */
429
+ statusCode?: number;
430
+ /** Custom title (overrides default for status code) */
431
+ title?: string;
432
+ /** Error description/message */
433
+ description?: string;
434
+ /** Show logo at top */
435
+ showLogo?: boolean;
436
+ /** Custom logo snippet */
437
+ logo?: Snippet;
438
+ /** Show "Go Home" button */
439
+ showHomeButton?: boolean;
440
+ /** Home button URL */
441
+ homeUrl?: string;
442
+ /** Home button text */
443
+ homeText?: string;
444
+ /** Show "Go Back" button */
445
+ showBackButton?: boolean;
446
+ /** Go back button text */
447
+ backText?: string;
448
+ /** Custom illustration/icon snippet (replaces status code display) */
449
+ illustration?: Snippet;
450
+ /** Additional action buttons or content */
451
+ actions?: Snippet;
452
+ /** Footer content */
453
+ footer?: Snippet;
454
+ /** Additional classes for the container */
455
+ class?: string;
456
+ /** Main content (custom error content, replaces default display) */
457
+ children?: Snippet;
458
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classic-homes/theme-svelte",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Svelte components for the Classic theme system",
5
5
  "type": "module",
6
6
  "svelte": "./dist/lib/index.js",