@classic-homes/theme-svelte 0.1.9 → 0.1.10

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" | "warning" | "error" | "success" | "info" | undefined;
4
+ variant?: "default" | "destructive" | "error" | "warning" | "success" | "info" | undefined;
5
5
  class?: string;
6
6
  children: Snippet;
7
7
  }, {}, "">;
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import type { Snippet } from 'svelte';
2
3
  import { Checkbox as CheckboxPrimitive } from 'bits-ui';
3
4
  import { cn } from '../utils.js';
4
5
 
@@ -10,7 +11,9 @@
10
11
  value?: string;
11
12
  id?: string;
12
13
  class?: string;
14
+ error?: string;
13
15
  onCheckedChange?: (checked: boolean) => void;
16
+ children?: Snippet;
14
17
  [key: string]: unknown;
15
18
  }
16
19
 
@@ -22,44 +25,80 @@
22
25
  value,
23
26
  id,
24
27
  class: className,
28
+ error,
25
29
  onCheckedChange,
30
+ children,
26
31
  ...restProps
27
32
  }: Props = $props();
28
33
 
34
+ // Generate a stable unique ID if none provided (for accessibility)
35
+ const generatedId = `checkbox-${Math.random().toString(36).substring(2, 11)}`;
36
+ const effectiveId = $derived(id ?? generatedId);
37
+
29
38
  function handleCheckedChange(newChecked: boolean | 'indeterminate') {
30
39
  if (typeof newChecked === 'boolean') {
31
40
  checked = newChecked;
32
41
  onCheckedChange?.(newChecked);
33
42
  }
34
43
  }
44
+
45
+ const hasError = $derived(!!error);
46
+ const errorId = $derived(`${effectiveId}-error`);
35
47
  </script>
36
48
 
37
- <CheckboxPrimitive.Root
38
- bind:checked
39
- {disabled}
40
- {required}
41
- {name}
42
- {value}
43
- {id}
44
- onCheckedChange={handleCheckedChange}
45
- class={cn(
46
- 'peer relative h-5 w-5 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground flex items-center justify-center',
47
- className
48
- )}
49
- {...restProps}
50
- >
51
- <!-- Touch target expansion (invisible, extends clickable area to 44x44px) -->
52
- <span class="absolute inset-0 -m-3" aria-hidden="true"></span>
53
- {#if checked}
54
- <svg
55
- class="h-5 w-5"
56
- fill="none"
57
- stroke="currentColor"
58
- stroke-width="2"
59
- viewBox="0 0 24 24"
60
- aria-hidden="true"
49
+ <div class="space-y-1">
50
+ <div class="flex items-start gap-3">
51
+ <CheckboxPrimitive.Root
52
+ bind:checked
53
+ {disabled}
54
+ {required}
55
+ {name}
56
+ {value}
57
+ id={effectiveId}
58
+ onCheckedChange={handleCheckedChange}
59
+ aria-invalid={hasError ? 'true' : undefined}
60
+ aria-describedby={hasError ? errorId : undefined}
61
+ class={cn(
62
+ 'peer relative h-5 w-5 shrink-0 rounded-sm border ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground flex items-center justify-center mt-0.5',
63
+ hasError ? 'border-destructive' : 'border-primary',
64
+ className
65
+ )}
66
+ {...restProps}
61
67
  >
62
- <polyline points="20 6 9 17 4 12" />
63
- </svg>
68
+ <!-- Touch target expansion (invisible, extends clickable area to 44x44px) -->
69
+ <span class="absolute inset-0 -m-3" aria-hidden="true"></span>
70
+ {#if checked}
71
+ <svg
72
+ class="h-5 w-5"
73
+ fill="none"
74
+ stroke="currentColor"
75
+ stroke-width="2"
76
+ viewBox="0 0 24 24"
77
+ aria-hidden="true"
78
+ >
79
+ <polyline points="20 6 9 17 4 12" />
80
+ </svg>
81
+ {/if}
82
+ </CheckboxPrimitive.Root>
83
+ {#if children}
84
+ <label
85
+ for={effectiveId}
86
+ class={cn(
87
+ 'text-sm leading-relaxed cursor-pointer select-none',
88
+ disabled && 'cursor-not-allowed opacity-50'
89
+ )}
90
+ >
91
+ {@render children()}
92
+ {#if required}
93
+ <span class="text-destructive ml-1" aria-hidden="true">*</span>
94
+ <span class="sr-only">(required)</span>
95
+ {/if}
96
+ </label>
97
+ {/if}
98
+ </div>
99
+ {#if error}
100
+ <p id={errorId} class="text-sm text-destructive ml-8" role="alert" aria-live="polite">
101
+ {error}
102
+ </p>
64
103
  {/if}
65
- </CheckboxPrimitive.Root>
104
+ </div>
@@ -1,3 +1,4 @@
1
+ import type { Snippet } from 'svelte';
1
2
  interface Props {
2
3
  checked?: boolean;
3
4
  disabled?: boolean;
@@ -6,7 +7,9 @@ interface Props {
6
7
  value?: string;
7
8
  id?: string;
8
9
  class?: string;
10
+ error?: string;
9
11
  onCheckedChange?: (checked: boolean) => void;
12
+ children?: Snippet;
10
13
  [key: string]: unknown;
11
14
  }
12
15
  declare const Checkbox: import("svelte").Component<Props, {}, "checked">;
@@ -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?: "warning" | "error" | "success" | "info" | undefined;
4
+ type?: "error" | "warning" | "success" | "info" | undefined;
5
5
  title?: string;
6
6
  message: string;
7
7
  class?: string;
@@ -67,7 +67,7 @@
67
67
  <div class={cn('gap-8', hasSidebar ? 'grid lg:grid-cols-[1fr,320px]' : 'mx-auto max-w-2xl')}>
68
68
  <!-- Sidebar (shows first on mobile when present) -->
69
69
  {#if hasSidebar}
70
- <aside class="order-first lg:order-last">
70
+ <aside class="order-first lg:order-last space-y-6">
71
71
  {@render sidebar!()}
72
72
  </aside>
73
73
  {/if}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classic-homes/theme-svelte",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Svelte components for the Classic theme system",
5
5
  "type": "module",
6
6
  "svelte": "./dist/lib/index.js",