@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.
Files changed (124) hide show
  1. package/README.md +305 -0
  2. package/dist/lib/components/Alert.svelte +51 -0
  3. package/dist/lib/components/Alert.svelte.d.ts +9 -0
  4. package/dist/lib/components/AlertDescription.svelte +16 -0
  5. package/dist/lib/components/AlertDescription.svelte.d.ts +9 -0
  6. package/dist/lib/components/AlertDialog.svelte +136 -0
  7. package/dist/lib/components/AlertDialog.svelte.d.ts +79 -0
  8. package/dist/lib/components/AlertTitle.svelte +16 -0
  9. package/dist/lib/components/AlertTitle.svelte.d.ts +9 -0
  10. package/dist/lib/components/Avatar.svelte +56 -0
  11. package/dist/lib/components/Avatar.svelte.d.ts +26 -0
  12. package/dist/lib/components/AvatarFallback.svelte +31 -0
  13. package/dist/lib/components/AvatarFallback.svelte.d.ts +17 -0
  14. package/dist/lib/components/AvatarImage.svelte +29 -0
  15. package/dist/lib/components/AvatarImage.svelte.d.ts +12 -0
  16. package/dist/lib/components/Badge.svelte +73 -0
  17. package/dist/lib/components/Badge.svelte.d.ts +11 -0
  18. package/dist/lib/components/Button.svelte +130 -0
  19. package/dist/lib/components/Button.svelte.d.ts +17 -0
  20. package/dist/lib/components/Card.svelte +58 -0
  21. package/dist/lib/components/Card.svelte.d.ts +26 -0
  22. package/dist/lib/components/CardContent.svelte +16 -0
  23. package/dist/lib/components/CardContent.svelte.d.ts +9 -0
  24. package/dist/lib/components/CardDescription.svelte +16 -0
  25. package/dist/lib/components/CardDescription.svelte.d.ts +9 -0
  26. package/dist/lib/components/CardFooter.svelte +16 -0
  27. package/dist/lib/components/CardFooter.svelte.d.ts +9 -0
  28. package/dist/lib/components/CardHeader.svelte +16 -0
  29. package/dist/lib/components/CardHeader.svelte.d.ts +9 -0
  30. package/dist/lib/components/CardTitle.svelte +16 -0
  31. package/dist/lib/components/CardTitle.svelte.d.ts +9 -0
  32. package/dist/lib/components/Checkbox.svelte +65 -0
  33. package/dist/lib/components/Checkbox.svelte.d.ts +14 -0
  34. package/dist/lib/components/DataTable.svelte +334 -0
  35. package/dist/lib/components/DataTable.svelte.d.ts +103 -0
  36. package/dist/lib/components/Dialog.svelte +111 -0
  37. package/dist/lib/components/Dialog.svelte.d.ts +22 -0
  38. package/dist/lib/components/DropdownMenu.svelte +135 -0
  39. package/dist/lib/components/DropdownMenu.svelte.d.ts +33 -0
  40. package/dist/lib/components/FileUpload.svelte +448 -0
  41. package/dist/lib/components/FileUpload.svelte.d.ts +42 -0
  42. package/dist/lib/components/FormField.svelte +134 -0
  43. package/dist/lib/components/FormField.svelte.d.ts +37 -0
  44. package/dist/lib/components/Input.svelte +61 -0
  45. package/dist/lib/components/Input.svelte.d.ts +19 -0
  46. package/dist/lib/components/Label.svelte +33 -0
  47. package/dist/lib/components/Label.svelte.d.ts +11 -0
  48. package/dist/lib/components/LoadingLogo.svelte +124 -0
  49. package/dist/lib/components/LoadingLogo.svelte.d.ts +16 -0
  50. package/dist/lib/components/LogoMain.svelte +237 -0
  51. package/dist/lib/components/LogoMain.svelte.d.ts +20 -0
  52. package/dist/lib/components/PageHeader.svelte +90 -0
  53. package/dist/lib/components/PageHeader.svelte.d.ts +28 -0
  54. package/dist/lib/components/Section.svelte +44 -0
  55. package/dist/lib/components/Section.svelte.d.ts +28 -0
  56. package/dist/lib/components/Select.svelte +174 -0
  57. package/dist/lib/components/Select.svelte.d.ts +32 -0
  58. package/dist/lib/components/Separator.svelte +29 -0
  59. package/dist/lib/components/Separator.svelte.d.ts +9 -0
  60. package/dist/lib/components/Skeleton.svelte +35 -0
  61. package/dist/lib/components/Skeleton.svelte.d.ts +7 -0
  62. package/dist/lib/components/Spinner.svelte +50 -0
  63. package/dist/lib/components/Spinner.svelte.d.ts +8 -0
  64. package/dist/lib/components/Switch.svelte +56 -0
  65. package/dist/lib/components/Switch.svelte.d.ts +14 -0
  66. package/dist/lib/components/TabPanel.svelte +44 -0
  67. package/dist/lib/components/TabPanel.svelte.d.ts +12 -0
  68. package/dist/lib/components/Tabs.svelte +125 -0
  69. package/dist/lib/components/Tabs.svelte.d.ts +19 -0
  70. package/dist/lib/components/Textarea.svelte +54 -0
  71. package/dist/lib/components/Textarea.svelte.d.ts +16 -0
  72. package/dist/lib/components/Toast.svelte +116 -0
  73. package/dist/lib/components/Toast.svelte.d.ts +12 -0
  74. package/dist/lib/components/ToastContainer.svelte +56 -0
  75. package/dist/lib/components/ToastContainer.svelte.d.ts +8 -0
  76. package/dist/lib/components/Tooltip.svelte +55 -0
  77. package/dist/lib/components/Tooltip.svelte.d.ts +18 -0
  78. package/dist/lib/components/layout/AppShell.svelte +82 -0
  79. package/dist/lib/components/layout/AppShell.svelte.d.ts +44 -0
  80. package/dist/lib/components/layout/DashboardLayout.svelte +248 -0
  81. package/dist/lib/components/layout/DashboardLayout.svelte.d.ts +62 -0
  82. package/dist/lib/components/layout/Footer.svelte +130 -0
  83. package/dist/lib/components/layout/Footer.svelte.d.ts +32 -0
  84. package/dist/lib/components/layout/FormPageLayout.svelte +92 -0
  85. package/dist/lib/components/layout/FormPageLayout.svelte.d.ts +33 -0
  86. package/dist/lib/components/layout/Header.svelte +94 -0
  87. package/dist/lib/components/layout/Header.svelte.d.ts +30 -0
  88. package/dist/lib/components/layout/PublicLayout.svelte +180 -0
  89. package/dist/lib/components/layout/PublicLayout.svelte.d.ts +39 -0
  90. package/dist/lib/components/layout/QuickLinks.svelte +112 -0
  91. package/dist/lib/components/layout/QuickLinks.svelte.d.ts +27 -0
  92. package/dist/lib/components/layout/Sidebar.svelte +243 -0
  93. package/dist/lib/components/layout/Sidebar.svelte.d.ts +48 -0
  94. package/dist/lib/composables/index.d.ts +8 -0
  95. package/dist/lib/composables/index.js +10 -0
  96. package/dist/lib/composables/useAsync.svelte.d.ts +102 -0
  97. package/dist/lib/composables/useAsync.svelte.js +210 -0
  98. package/dist/lib/composables/useForm.svelte.d.ts +123 -0
  99. package/dist/lib/composables/useForm.svelte.js +245 -0
  100. package/dist/lib/index.d.ts +65 -0
  101. package/dist/lib/index.js +83 -0
  102. package/dist/lib/performance.d.ts +79 -0
  103. package/dist/lib/performance.js +170 -0
  104. package/dist/lib/schemas/auth.d.ts +410 -0
  105. package/dist/lib/schemas/auth.js +216 -0
  106. package/dist/lib/schemas/common.d.ts +267 -0
  107. package/dist/lib/schemas/common.js +268 -0
  108. package/dist/lib/schemas/index.d.ts +24 -0
  109. package/dist/lib/schemas/index.js +32 -0
  110. package/dist/lib/stores/sidebar.svelte.d.ts +25 -0
  111. package/dist/lib/stores/sidebar.svelte.js +38 -0
  112. package/dist/lib/stores/theme.svelte.d.ts +72 -0
  113. package/dist/lib/stores/theme.svelte.js +150 -0
  114. package/dist/lib/stores/toast.svelte.d.ts +62 -0
  115. package/dist/lib/stores/toast.svelte.js +93 -0
  116. package/dist/lib/types/components.d.ts +85 -0
  117. package/dist/lib/types/components.js +7 -0
  118. package/dist/lib/types/layout.d.ts +258 -0
  119. package/dist/lib/types/layout.js +7 -0
  120. package/dist/lib/utils.d.ts +6 -0
  121. package/dist/lib/utils.js +9 -0
  122. package/dist/lib/validation.d.ts +101 -0
  123. package/dist/lib/validation.js +170 -0
  124. package/package.json +56 -0
@@ -0,0 +1,90 @@
1
+ <script lang="ts">
2
+ /**
3
+ * PageHeader - Comprehensive hero/page header component
4
+ *
5
+ * A flexible page header component for hero sections and page titles.
6
+ * Supports multiple layout variants and optional action buttons.
7
+ *
8
+ * Features:
9
+ * - Multiple variants: default, hero, centered
10
+ * - Optional subtitle with branded styling
11
+ * - Optional actions slot for CTA buttons
12
+ * - Consistent typography using design tokens
13
+ */
14
+ import type { Snippet } from 'svelte';
15
+ import { cn } from '../utils.js';
16
+ import { tv, type VariantProps } from 'tailwind-variants';
17
+
18
+ const pageHeaderVariants = tv({
19
+ slots: {
20
+ container: '',
21
+ title: 'text-foreground',
22
+ subtitle: 'text-muted-foreground',
23
+ actionsWrapper: 'flex gap-4',
24
+ },
25
+ variants: {
26
+ variant: {
27
+ default: {
28
+ container: '',
29
+ title: 'text-3xl font-bold mb-2',
30
+ subtitle: 'text-lg',
31
+ actionsWrapper: 'mt-4',
32
+ },
33
+ hero: {
34
+ container: '',
35
+ title: 'text-5xl font-black uppercase tracking-tight mb-2',
36
+ subtitle: 'text-lg font-serif italic',
37
+ actionsWrapper: 'mt-6',
38
+ },
39
+ centered: {
40
+ container: 'text-center',
41
+ title: 'text-4xl font-bold mb-3',
42
+ subtitle: 'text-xl max-w-2xl mx-auto',
43
+ actionsWrapper: 'mt-6 justify-center',
44
+ },
45
+ },
46
+ },
47
+ defaultVariants: {
48
+ variant: 'default',
49
+ },
50
+ });
51
+
52
+ type PageHeaderVariants = VariantProps<typeof pageHeaderVariants>;
53
+
54
+ interface Props {
55
+ /** Main title text */
56
+ title: string;
57
+ /** Optional subtitle text */
58
+ subtitle?: string;
59
+ /** Visual variant */
60
+ variant?: PageHeaderVariants['variant'];
61
+ /** Additional classes for the container */
62
+ class?: string;
63
+ /** Optional action buttons/content */
64
+ actions?: Snippet;
65
+ [key: string]: unknown;
66
+ }
67
+
68
+ let {
69
+ title,
70
+ subtitle,
71
+ variant = 'default',
72
+ class: className,
73
+ actions,
74
+ ...restProps
75
+ }: Props = $props();
76
+
77
+ const styles = $derived(pageHeaderVariants({ variant }));
78
+ </script>
79
+
80
+ <header class={cn(styles.container(), className)} {...restProps}>
81
+ <h1 class={styles.title()}>{title}</h1>
82
+ {#if subtitle}
83
+ <p class={styles.subtitle()}>{subtitle}</p>
84
+ {/if}
85
+ {#if actions}
86
+ <div class={styles.actionsWrapper()}>
87
+ {@render actions()}
88
+ </div>
89
+ {/if}
90
+ </header>
@@ -0,0 +1,28 @@
1
+ /**
2
+ * PageHeader - Comprehensive hero/page header component
3
+ *
4
+ * A flexible page header component for hero sections and page titles.
5
+ * Supports multiple layout variants and optional action buttons.
6
+ *
7
+ * Features:
8
+ * - Multiple variants: default, hero, centered
9
+ * - Optional subtitle with branded styling
10
+ * - Optional actions slot for CTA buttons
11
+ * - Consistent typography using design tokens
12
+ */
13
+ import type { Snippet } from 'svelte';
14
+ declare const PageHeader: import("svelte").Component<{
15
+ [key: string]: unknown;
16
+ /** Main title text */
17
+ title: string;
18
+ /** Optional subtitle text */
19
+ subtitle?: string;
20
+ /** Visual variant */
21
+ variant?: "default" | "hero" | "centered" | undefined;
22
+ /** Additional classes for the container */
23
+ class?: string;
24
+ /** Optional action buttons/content */
25
+ actions?: Snippet;
26
+ }, {}, "">;
27
+ type PageHeader = ReturnType<typeof PageHeader>;
28
+ export default PageHeader;
@@ -0,0 +1,44 @@
1
+ <script lang="ts">
2
+ /**
3
+ * Section - Content section container component
4
+ *
5
+ * A full-width content container with optional title and description.
6
+ * Different from Card in that Sections are meant for page-level content
7
+ * organization, while Cards are for individual content panels.
8
+ *
9
+ * Features:
10
+ * - Optional title (renders as h2)
11
+ * - Optional description
12
+ * - Consistent styling with shadow and border
13
+ * - Flexible content area via children snippet
14
+ */
15
+ import type { Snippet } from 'svelte';
16
+ import { cn } from '../utils.js';
17
+
18
+ interface Props {
19
+ /** Section title (rendered as h2) */
20
+ title?: string;
21
+ /** Optional description text below the title */
22
+ description?: string;
23
+ /** Additional classes for the section container */
24
+ class?: string;
25
+ /** Section content */
26
+ children: Snippet;
27
+ [key: string]: unknown;
28
+ }
29
+
30
+ let { title, description, class: className, children, ...restProps }: Props = $props();
31
+ </script>
32
+
33
+ <section
34
+ class={cn('bg-card rounded-lg shadow-md p-6 border border-border', className)}
35
+ {...restProps}
36
+ >
37
+ {#if title}
38
+ <h2 class="text-2xl font-bold text-card-foreground mb-4">{title}</h2>
39
+ {/if}
40
+ {#if description}
41
+ <p class="text-sm text-muted-foreground mb-4">{description}</p>
42
+ {/if}
43
+ {@render children()}
44
+ </section>
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Section - Content section container component
3
+ *
4
+ * A full-width content container with optional title and description.
5
+ * Different from Card in that Sections are meant for page-level content
6
+ * organization, while Cards are for individual content panels.
7
+ *
8
+ * Features:
9
+ * - Optional title (renders as h2)
10
+ * - Optional description
11
+ * - Consistent styling with shadow and border
12
+ * - Flexible content area via children snippet
13
+ */
14
+ import type { Snippet } from 'svelte';
15
+ interface Props {
16
+ /** Section title (rendered as h2) */
17
+ title?: string;
18
+ /** Optional description text below the title */
19
+ description?: string;
20
+ /** Additional classes for the section container */
21
+ class?: string;
22
+ /** Section content */
23
+ children: Snippet;
24
+ [key: string]: unknown;
25
+ }
26
+ declare const Section: import("svelte").Component<Props, {}, "">;
27
+ type Section = ReturnType<typeof Section>;
28
+ export default Section;
@@ -0,0 +1,174 @@
1
+ <script lang="ts">
2
+ import { Select as SelectPrimitive } from 'bits-ui';
3
+ import { cn } from '../utils.js';
4
+ import { validateNonEmptyArray } from '../validation.js';
5
+
6
+ export interface SelectOption {
7
+ value: string;
8
+ label: string;
9
+ disabled?: boolean;
10
+ }
11
+
12
+ export interface SelectGroup {
13
+ label: string;
14
+ options: SelectOption[];
15
+ }
16
+
17
+ interface Props {
18
+ /** Current value */
19
+ value?: string;
20
+ /** Callback when value changes */
21
+ onValueChange?: (value: string) => void;
22
+ /** Placeholder text when no value selected */
23
+ placeholder?: string;
24
+ /** Array of options or grouped options */
25
+ options: (SelectOption | SelectGroup)[];
26
+ /** Whether the select is disabled */
27
+ disabled?: boolean;
28
+ /** Name attribute for form submission */
29
+ name?: string;
30
+ /** Whether this field is required */
31
+ required?: boolean;
32
+ /** Additional class for the trigger */
33
+ class?: string;
34
+ /** Optional label */
35
+ label?: string;
36
+ }
37
+
38
+ let {
39
+ value = $bindable(''),
40
+ onValueChange,
41
+ placeholder = 'Select an option...',
42
+ options,
43
+ disabled = false,
44
+ name,
45
+ required = false,
46
+ class: className,
47
+ label,
48
+ }: Props = $props();
49
+
50
+ // Validate props in development
51
+ $effect(() => {
52
+ validateNonEmptyArray(options, 'options', 'Select');
53
+ });
54
+
55
+ function isGroup(item: SelectOption | SelectGroup): item is SelectGroup {
56
+ return 'options' in item;
57
+ }
58
+
59
+ // Find the label for the current value
60
+ const selectedLabel = $derived.by(() => {
61
+ for (const item of options) {
62
+ if (isGroup(item)) {
63
+ const found = item.options.find((opt) => opt.value === value);
64
+ if (found) return found.label;
65
+ } else if (item.value === value) {
66
+ return item.label;
67
+ }
68
+ }
69
+ return undefined;
70
+ });
71
+
72
+ // Build items array for typeahead support
73
+ const flatItems = $derived.by(() => {
74
+ const items: { value: string; label: string; disabled?: boolean }[] = [];
75
+ for (const item of options) {
76
+ if (isGroup(item)) {
77
+ for (const opt of item.options) {
78
+ items.push(opt);
79
+ }
80
+ } else {
81
+ items.push(item);
82
+ }
83
+ }
84
+ return items;
85
+ });
86
+
87
+ function handleValueChange(newValue: string) {
88
+ value = newValue;
89
+ onValueChange?.(newValue);
90
+ }
91
+ </script>
92
+
93
+ {#if label}
94
+ <span
95
+ class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 mb-1.5 block"
96
+ >
97
+ {label}
98
+ {#if required}
99
+ <span class="text-destructive">*</span>
100
+ {/if}
101
+ </span>
102
+ {/if}
103
+
104
+ <SelectPrimitive.Root
105
+ type="single"
106
+ {name}
107
+ {disabled}
108
+ {required}
109
+ {value}
110
+ items={flatItems}
111
+ onValueChange={handleValueChange}
112
+ >
113
+ <SelectPrimitive.Trigger
114
+ class={cn(
115
+ 'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
116
+ className
117
+ )}
118
+ aria-label={label || placeholder}
119
+ >
120
+ <span class={value ? '' : 'text-muted-foreground'}>
121
+ {selectedLabel || placeholder}
122
+ </span>
123
+ <svg
124
+ xmlns="http://www.w3.org/2000/svg"
125
+ width="24"
126
+ height="24"
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
+ class="h-4 w-4 opacity-50"
134
+ >
135
+ <path d="m6 9 6 6 6-6" />
136
+ </svg>
137
+ </SelectPrimitive.Trigger>
138
+
139
+ <SelectPrimitive.Content
140
+ class="relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
141
+ sideOffset={4}
142
+ >
143
+ <div class="p-1">
144
+ {#each options as item}
145
+ {#if isGroup(item)}
146
+ <SelectPrimitive.Group>
147
+ <div class="py-1.5 pl-8 pr-2 text-sm font-semibold">
148
+ {item.label}
149
+ </div>
150
+ {#each item.options as option}
151
+ <SelectPrimitive.Item
152
+ value={option.value}
153
+ label={option.label}
154
+ disabled={option.disabled}
155
+ class="relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50"
156
+ >
157
+ {option.label}
158
+ </SelectPrimitive.Item>
159
+ {/each}
160
+ </SelectPrimitive.Group>
161
+ {:else}
162
+ <SelectPrimitive.Item
163
+ value={item.value}
164
+ label={item.label}
165
+ disabled={item.disabled}
166
+ class="relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50"
167
+ >
168
+ {item.label}
169
+ </SelectPrimitive.Item>
170
+ {/if}
171
+ {/each}
172
+ </div>
173
+ </SelectPrimitive.Content>
174
+ </SelectPrimitive.Root>
@@ -0,0 +1,32 @@
1
+ export interface SelectOption {
2
+ value: string;
3
+ label: string;
4
+ disabled?: boolean;
5
+ }
6
+ export interface SelectGroup {
7
+ label: string;
8
+ options: SelectOption[];
9
+ }
10
+ interface Props {
11
+ /** Current value */
12
+ value?: string;
13
+ /** Callback when value changes */
14
+ onValueChange?: (value: string) => void;
15
+ /** Placeholder text when no value selected */
16
+ placeholder?: string;
17
+ /** Array of options or grouped options */
18
+ options: (SelectOption | SelectGroup)[];
19
+ /** Whether the select is disabled */
20
+ disabled?: boolean;
21
+ /** Name attribute for form submission */
22
+ name?: string;
23
+ /** Whether this field is required */
24
+ required?: boolean;
25
+ /** Additional class for the trigger */
26
+ class?: string;
27
+ /** Optional label */
28
+ label?: string;
29
+ }
30
+ declare const Select: import("svelte").Component<Props, {}, "value">;
31
+ type Select = ReturnType<typeof Select>;
32
+ export default Select;
@@ -0,0 +1,29 @@
1
+ <script lang="ts">
2
+ import { Separator as SeparatorPrimitive } from 'bits-ui';
3
+ import { cn } from '../utils.js';
4
+
5
+ interface Props {
6
+ orientation?: 'horizontal' | 'vertical';
7
+ decorative?: boolean;
8
+ class?: string;
9
+ [key: string]: unknown;
10
+ }
11
+
12
+ let {
13
+ orientation = 'horizontal',
14
+ decorative = true,
15
+ class: className,
16
+ ...restProps
17
+ }: Props = $props();
18
+ </script>
19
+
20
+ <SeparatorPrimitive.Root
21
+ {orientation}
22
+ {decorative}
23
+ class={cn(
24
+ 'shrink-0 bg-black',
25
+ orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
26
+ className
27
+ )}
28
+ {...restProps}
29
+ />
@@ -0,0 +1,9 @@
1
+ interface Props {
2
+ orientation?: 'horizontal' | 'vertical';
3
+ decorative?: boolean;
4
+ class?: string;
5
+ [key: string]: unknown;
6
+ }
7
+ declare const Separator: import("svelte").Component<Props, {}, "">;
8
+ type Separator = ReturnType<typeof Separator>;
9
+ export default Separator;
@@ -0,0 +1,35 @@
1
+ <script lang="ts">
2
+ import { cn } from '../utils.js';
3
+ import { tv, type VariantProps } from 'tailwind-variants';
4
+ import type { HTMLAttributes } from 'svelte/elements';
5
+
6
+ const skeletonVariants = tv({
7
+ base: 'animate-pulse rounded-md bg-muted',
8
+ variants: {
9
+ variant: {
10
+ default: '',
11
+ text: 'h-4 w-full',
12
+ avatar: 'h-12 w-12 rounded-full',
13
+ card: 'h-32 w-full',
14
+ button: 'h-10 w-24',
15
+ title: 'h-6 w-3/4',
16
+ },
17
+ },
18
+ defaultVariants: {
19
+ variant: 'default',
20
+ },
21
+ });
22
+
23
+ type SkeletonVariants = VariantProps<typeof skeletonVariants>;
24
+
25
+ interface Props extends HTMLAttributes<HTMLDivElement> {
26
+ variant?: SkeletonVariants['variant'];
27
+ class?: string;
28
+ }
29
+
30
+ let { variant = 'default', class: className, ...restProps }: Props = $props();
31
+
32
+ const classes = $derived(cn(skeletonVariants({ variant }), className));
33
+ </script>
34
+
35
+ <div class={classes} {...restProps}></div>
@@ -0,0 +1,7 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ declare const Skeleton: import("svelte").Component<HTMLAttributes<HTMLDivElement> & {
3
+ variant?: "default" | "button" | "text" | "title" | "avatar" | "card" | undefined;
4
+ class?: string;
5
+ }, {}, "">;
6
+ type Skeleton = ReturnType<typeof Skeleton>;
7
+ export default Skeleton;
@@ -0,0 +1,50 @@
1
+ <script lang="ts">
2
+ import { cn } from '../utils.js';
3
+ import { tv, type VariantProps } from 'tailwind-variants';
4
+
5
+ const spinnerVariants = tv({
6
+ base: 'animate-spin text-current',
7
+ variants: {
8
+ size: {
9
+ sm: 'h-4 w-4',
10
+ md: 'h-6 w-6',
11
+ lg: 'h-8 w-8',
12
+ xl: 'h-12 w-12',
13
+ },
14
+ },
15
+ defaultVariants: {
16
+ size: 'md',
17
+ },
18
+ });
19
+
20
+ type SpinnerVariants = VariantProps<typeof spinnerVariants>;
21
+
22
+ interface Props {
23
+ size?: SpinnerVariants['size'];
24
+ class?: string;
25
+ label?: string;
26
+ [key: string]: unknown;
27
+ }
28
+
29
+ let { size = 'md', class: className, label = 'Loading...', ...restProps }: Props = $props();
30
+
31
+ const classes = $derived(cn(spinnerVariants({ size }), className));
32
+ </script>
33
+
34
+ <svg
35
+ class={classes}
36
+ xmlns="http://www.w3.org/2000/svg"
37
+ fill="none"
38
+ viewBox="0 0 24 24"
39
+ aria-label={label}
40
+ role="status"
41
+ {...restProps}
42
+ >
43
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
44
+ <path
45
+ class="opacity-75"
46
+ fill="currentColor"
47
+ d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
48
+ ></path>
49
+ <title>{label}</title>
50
+ </svg>
@@ -0,0 +1,8 @@
1
+ declare const Spinner: import("svelte").Component<{
2
+ [key: string]: unknown;
3
+ size?: "sm" | "md" | "lg" | "xl" | undefined;
4
+ class?: string;
5
+ label?: string;
6
+ }, {}, "">;
7
+ type Spinner = ReturnType<typeof Spinner>;
8
+ export default Spinner;
@@ -0,0 +1,56 @@
1
+ <script lang="ts">
2
+ import { Switch as SwitchPrimitive } from 'bits-ui';
3
+ import { cn } from '../utils.js';
4
+
5
+ interface Props {
6
+ checked?: boolean;
7
+ disabled?: boolean;
8
+ required?: boolean;
9
+ name?: string;
10
+ value?: string;
11
+ id?: string;
12
+ class?: string;
13
+ onchange?: (checked: boolean) => void;
14
+ [key: string]: unknown;
15
+ }
16
+
17
+ let {
18
+ checked = $bindable(false),
19
+ disabled = false,
20
+ required = false,
21
+ name,
22
+ value,
23
+ id,
24
+ class: className,
25
+ onchange,
26
+ ...restProps
27
+ }: Props = $props();
28
+
29
+ function handleCheckedChange(newChecked: boolean) {
30
+ checked = newChecked;
31
+ onchange?.(newChecked);
32
+ }
33
+ </script>
34
+
35
+ <SwitchPrimitive.Root
36
+ bind:checked
37
+ {disabled}
38
+ {required}
39
+ {name}
40
+ {value}
41
+ {id}
42
+ onCheckedChange={handleCheckedChange}
43
+ class={cn(
44
+ 'peer relative inline-flex h-7 w-12 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
45
+ className
46
+ )}
47
+ {...restProps}
48
+ >
49
+ <!-- Touch target expansion (invisible, extends clickable area) -->
50
+ <span class="absolute inset-0 -m-2" aria-hidden="true"></span>
51
+ <SwitchPrimitive.Thumb
52
+ class={cn(
53
+ 'pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-0.5'
54
+ )}
55
+ />
56
+ </SwitchPrimitive.Root>
@@ -0,0 +1,14 @@
1
+ interface Props {
2
+ checked?: boolean;
3
+ disabled?: boolean;
4
+ required?: boolean;
5
+ name?: string;
6
+ value?: string;
7
+ id?: string;
8
+ class?: string;
9
+ onchange?: (checked: boolean) => void;
10
+ [key: string]: unknown;
11
+ }
12
+ declare const Switch: import("svelte").Component<Props, {}, "checked">;
13
+ type Switch = ReturnType<typeof Switch>;
14
+ export default Switch;
@@ -0,0 +1,44 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { getContext } from 'svelte';
4
+ import { cn } from '../utils.js';
5
+
6
+ interface TabsContext {
7
+ activeTab: string;
8
+ tabsId: string;
9
+ }
10
+
11
+ interface Props {
12
+ /** Tab ID this panel belongs to */
13
+ value: string;
14
+ /** Additional classes */
15
+ class?: string;
16
+ /** Panel content */
17
+ children?: Snippet;
18
+ }
19
+
20
+ let { value, class: className, children }: Props = $props();
21
+
22
+ // Get context from parent Tabs
23
+ const context = getContext<TabsContext>('tabs');
24
+ const isActive = $derived(context?.activeTab === value);
25
+ const panelId = $derived(context ? `${context.tabsId}-panel-${value}` : `panel-${value}`);
26
+ const tabId = $derived(context ? `${context.tabsId}-tab-${value}` : `tab-${value}`);
27
+ </script>
28
+
29
+ {#if isActive}
30
+ <div
31
+ id={panelId}
32
+ role="tabpanel"
33
+ aria-labelledby={tabId}
34
+ tabindex="0"
35
+ class={cn(
36
+ 'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
37
+ className
38
+ )}
39
+ >
40
+ {#if children}
41
+ {@render children()}
42
+ {/if}
43
+ </div>
44
+ {/if}
@@ -0,0 +1,12 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ /** Tab ID this panel belongs to */
4
+ value: string;
5
+ /** Additional classes */
6
+ class?: string;
7
+ /** Panel content */
8
+ children?: Snippet;
9
+ }
10
+ declare const TabPanel: import("svelte").Component<Props, {}, "">;
11
+ type TabPanel = ReturnType<typeof TabPanel>;
12
+ export default TabPanel;