@happyvertical/smrt-svelte 0.34.5 → 0.34.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 (39) hide show
  1. package/AGENTS.md +22 -9
  2. package/dist/browser-ai/svelte/components/STTTest.svelte +7 -42
  3. package/dist/browser-ai/svelte/components/STTTest.svelte.d.ts.map +1 -1
  4. package/dist/browser-ai/svelte/components/VoiceInput.svelte +1 -0
  5. package/dist/browser-ai/svelte/components/VoiceInput.svelte.d.ts.map +1 -1
  6. package/dist/components/forms/index.d.ts +9 -6
  7. package/dist/components/forms/index.d.ts.map +1 -1
  8. package/dist/components/forms/index.js +10 -7
  9. package/dist/components/workspace/WorkspaceShell.svelte +27 -34
  10. package/dist/components/workspace/WorkspaceShell.svelte.d.ts.map +1 -1
  11. package/dist/components/workspace/tools-dock/ToolsDock.svelte +11 -7
  12. package/dist/components/workspace/tools-dock/ToolsDock.svelte.d.ts.map +1 -1
  13. package/package.json +5 -4
  14. package/dist/components/forms/FormGroup.svelte +0 -86
  15. package/dist/components/forms/FormGroup.svelte.d.ts +0 -13
  16. package/dist/components/forms/FormGroup.svelte.d.ts.map +0 -1
  17. package/dist/components/forms/Input.svelte +0 -83
  18. package/dist/components/forms/Input.svelte.d.ts +0 -9
  19. package/dist/components/forms/Input.svelte.d.ts.map +0 -1
  20. package/dist/components/forms/Select.svelte +0 -83
  21. package/dist/components/forms/Select.svelte.d.ts +0 -11
  22. package/dist/components/forms/Select.svelte.d.ts.map +0 -1
  23. package/dist/components/forms/Textarea.svelte +0 -85
  24. package/dist/components/forms/Textarea.svelte.d.ts +0 -10
  25. package/dist/components/forms/Textarea.svelte.d.ts.map +0 -1
  26. package/dist/components/forms/Toggle.svelte +0 -217
  27. package/dist/components/forms/Toggle.svelte.d.ts +0 -37
  28. package/dist/components/forms/Toggle.svelte.d.ts.map +0 -1
  29. package/dist/components/forms/__tests__/FormGroup.test.js +0 -48
  30. package/dist/components/forms/__tests__/Input.test.js +0 -49
  31. package/dist/components/forms/__tests__/Select.test.js +0 -37
  32. package/dist/components/forms/__tests__/Textarea.test.js +0 -39
  33. package/dist/components/forms/__tests__/Toggle.test.js +0 -87
  34. package/dist/components/forms/__tests__/form-group-input.fixture.svelte +0 -16
  35. package/dist/components/forms/__tests__/form-group-input.fixture.svelte.d.ts +0 -9
  36. package/dist/components/forms/__tests__/form-group-input.fixture.svelte.d.ts.map +0 -1
  37. package/dist/state/form-group-context.d.ts +0 -13
  38. package/dist/state/form-group-context.d.ts.map +0 -1
  39. package/dist/state/form-group-context.js +0 -28
@@ -1 +0,0 @@
1
- {"version":3,"file":"FormGroup.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/FormGroup.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAQtC,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAiDD,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -1,83 +0,0 @@
1
- <script lang="ts">
2
- import type { HTMLInputAttributes } from 'svelte/elements';
3
- import { tryGetFormGroupContext } from '../../state/form-group-context.js';
4
-
5
- export interface Props extends Omit<HTMLInputAttributes, 'class' | 'value'> {
6
- value?: string | number;
7
- class?: string;
8
- }
9
-
10
- let {
11
- id,
12
- type = 'text',
13
- value = $bindable(''),
14
- placeholder,
15
- disabled = false,
16
- readonly = false,
17
- required = false,
18
- name,
19
- class: className = '',
20
- 'aria-describedby': ariaDescribedby,
21
- 'aria-invalid': ariaInvalid,
22
- ...rest
23
- }: Props = $props();
24
-
25
- // When wrapped in a <FormGroup>, inherit the id (so its <label for> resolves),
26
- // the hint/error association, and the error state — unless set explicitly.
27
- const formGroup = tryGetFormGroupContext();
28
- const resolvedId = $derived(id ?? formGroup?.().inputId);
29
- const resolvedDescribedBy = $derived(
30
- ariaDescribedby ?? formGroup?.().describedBy,
31
- );
32
- const resolvedInvalid = $derived(
33
- ariaInvalid ?? (formGroup?.().invalid ? 'true' : undefined),
34
- );
35
- </script>
36
-
37
- <input
38
- id={resolvedId}
39
- {type}
40
- bind:value
41
- {placeholder}
42
- {disabled}
43
- {readonly}
44
- {required}
45
- {name}
46
- aria-describedby={resolvedDescribedBy}
47
- aria-invalid={resolvedInvalid}
48
- class="input {className}"
49
- {...rest}
50
- />
51
-
52
- <style>
53
- .input {
54
- display: block;
55
- width: 100%;
56
- padding: 0.5rem 0.75rem;
57
- font-size: var(--smrt-typography-body-medium-size, 0.875rem);
58
- line-height: var(--smrt-typography-body-medium-line-height, 1.5);
59
- color: var(--smrt-color-on-surface, #1f2937);
60
- background-color: var(--smrt-color-surface, #fff);
61
- border: 1px solid var(--smrt-color-outline-variant, #d1d5db);
62
- border-radius: var(--smrt-radius-small, 0.375rem);
63
- transition:
64
- border-color var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease-in-out),
65
- box-shadow var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease-in-out);
66
- }
67
-
68
- .input:focus {
69
- outline: none;
70
- border-color: var(--smrt-color-primary, #005ac1);
71
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--smrt-color-primary, #005ac1) 10%, transparent);
72
- }
73
-
74
- .input:disabled {
75
- background-color: var(--smrt-color-surface-container-high, #f3f4f6);
76
- cursor: not-allowed;
77
- opacity: 0.7;
78
- }
79
-
80
- .input::placeholder {
81
- color: var(--smrt-color-on-surface-variant, #9ca3af);
82
- }
83
- </style>
@@ -1,9 +0,0 @@
1
- import type { HTMLInputAttributes } from 'svelte/elements';
2
- export interface Props extends Omit<HTMLInputAttributes, 'class' | 'value'> {
3
- value?: string | number;
4
- class?: string;
5
- }
6
- declare const Input: import("svelte").Component<Props, {}, "value">;
7
- type Input = ReturnType<typeof Input>;
8
- export default Input;
9
- //# sourceMappingURL=Input.svelte.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Input.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/Input.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAI3D,MAAM,WAAW,KAAM,SAAQ,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,OAAO,CAAC;IACzE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAuCD,QAAA,MAAM,KAAK,gDAAwC,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
@@ -1,83 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from 'svelte';
3
- import type { HTMLSelectAttributes } from 'svelte/elements';
4
- import { tryGetFormGroupContext } from '../../state/form-group-context.js';
5
-
6
- export interface Props extends Omit<HTMLSelectAttributes, 'class' | 'value'> {
7
- value?: string;
8
- class?: string;
9
- children: Snippet;
10
- }
11
-
12
- let {
13
- id,
14
- value = $bindable(''),
15
- disabled = false,
16
- required = false,
17
- name,
18
- class: className = '',
19
- children,
20
- 'aria-describedby': ariaDescribedby,
21
- 'aria-invalid': ariaInvalid,
22
- ...rest
23
- }: Props = $props();
24
-
25
- // Inherit id / hint+error association / error state from a wrapping FormGroup.
26
- const formGroup = tryGetFormGroupContext();
27
- const resolvedId = $derived(id ?? formGroup?.().inputId);
28
- const resolvedDescribedBy = $derived(
29
- ariaDescribedby ?? formGroup?.().describedBy,
30
- );
31
- const resolvedInvalid = $derived(
32
- ariaInvalid ?? (formGroup?.().invalid ? 'true' : undefined),
33
- );
34
- </script>
35
-
36
- <select
37
- id={resolvedId}
38
- bind:value
39
- {disabled}
40
- {required}
41
- {name}
42
- aria-describedby={resolvedDescribedBy}
43
- aria-invalid={resolvedInvalid}
44
- class="select {className}"
45
- {...rest}
46
- >
47
- {@render children()}
48
- </select>
49
-
50
- <style>
51
- .select {
52
- display: block;
53
- width: 100%;
54
- padding: 0.5rem 2rem 0.5rem 0.75rem;
55
- font-size: var(--smrt-typography-body-medium-size, 0.875rem);
56
- line-height: var(--smrt-typography-body-medium-line-height, 1.5);
57
- color: var(--smrt-color-on-surface, #1f2937);
58
- background-color: var(--smrt-color-surface, #fff);
59
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%2379747e' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
60
- background-position: right 0.5rem center;
61
- background-repeat: no-repeat;
62
- background-size: 1.5em 1.5em;
63
- border: 1px solid var(--smrt-color-outline-variant, #d1d5db);
64
- border-radius: 0.375rem;
65
- appearance: none;
66
- cursor: pointer;
67
- transition:
68
- border-color 0.15s ease-in-out,
69
- box-shadow 0.15s ease-in-out;
70
- }
71
-
72
- .select:focus {
73
- outline: none;
74
- border-color: var(--smrt-color-primary, #005ac1);
75
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--smrt-color-primary, #005ac1) 10%, transparent);
76
- }
77
-
78
- .select:disabled {
79
- background-color: var(--smrt-color-surface-container-high, #f3f4f6);
80
- cursor: not-allowed;
81
- opacity: 0.7;
82
- }
83
- </style>
@@ -1,11 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- import type { HTMLSelectAttributes } from 'svelte/elements';
3
- export interface Props extends Omit<HTMLSelectAttributes, 'class' | 'value'> {
4
- value?: string;
5
- class?: string;
6
- children: Snippet;
7
- }
8
- declare const Select: import("svelte").Component<Props, {}, "value">;
9
- type Select = ReturnType<typeof Select>;
10
- export default Select;
11
- //# sourceMappingURL=Select.svelte.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Select.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/Select.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAI5D,MAAM,WAAW,KAAM,SAAQ,IAAI,CAAC,oBAAoB,EAAE,OAAO,GAAG,OAAO,CAAC;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB;AAuCD,QAAA,MAAM,MAAM,gDAAwC,CAAC;AACrD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;AACxC,eAAe,MAAM,CAAC"}
@@ -1,85 +0,0 @@
1
- <script lang="ts">
2
- import type { HTMLTextareaAttributes } from 'svelte/elements';
3
- import { tryGetFormGroupContext } from '../../state/form-group-context.js';
4
-
5
- export interface Props extends Omit<HTMLTextareaAttributes, 'class' | 'value'> {
6
- value?: string;
7
- rows?: number;
8
- class?: string;
9
- }
10
-
11
- let {
12
- id,
13
- value = $bindable(''),
14
- placeholder,
15
- disabled = false,
16
- readonly = false,
17
- required = false,
18
- name,
19
- rows = 4,
20
- class: className = '',
21
- 'aria-describedby': ariaDescribedby,
22
- 'aria-invalid': ariaInvalid,
23
- ...rest
24
- }: Props = $props();
25
-
26
- // Inherit id / hint+error association / error state from a wrapping FormGroup.
27
- const formGroup = tryGetFormGroupContext();
28
- const resolvedId = $derived(id ?? formGroup?.().inputId);
29
- const resolvedDescribedBy = $derived(
30
- ariaDescribedby ?? formGroup?.().describedBy,
31
- );
32
- const resolvedInvalid = $derived(
33
- ariaInvalid ?? (formGroup?.().invalid ? 'true' : undefined),
34
- );
35
- </script>
36
-
37
- <textarea
38
- id={resolvedId}
39
- bind:value
40
- {placeholder}
41
- {disabled}
42
- {readonly}
43
- {required}
44
- {name}
45
- {rows}
46
- aria-describedby={resolvedDescribedBy}
47
- aria-invalid={resolvedInvalid}
48
- class="textarea {className}"
49
- {...rest}
50
- ></textarea>
51
-
52
- <style>
53
- .textarea {
54
- display: block;
55
- width: 100%;
56
- padding: 0.5rem 0.75rem;
57
- font-size: var(--smrt-typography-body-medium-size, 0.875rem);
58
- line-height: var(--smrt-typography-body-medium-line-height, 1.5);
59
- color: var(--smrt-color-on-surface, #1f2937);
60
- background-color: var(--smrt-color-surface, #fff);
61
- border: 1px solid var(--smrt-color-outline-variant, #d1d5db);
62
- border-radius: 0.375rem;
63
- resize: vertical;
64
- min-height: 80px;
65
- transition:
66
- border-color 0.15s ease-in-out,
67
- box-shadow 0.15s ease-in-out;
68
- }
69
-
70
- .textarea:focus {
71
- outline: none;
72
- border-color: var(--smrt-color-primary, #005ac1);
73
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--smrt-color-primary, #005ac1) 10%, transparent);
74
- }
75
-
76
- .textarea:disabled {
77
- background-color: var(--smrt-color-surface-container-high, #f3f4f6);
78
- cursor: not-allowed;
79
- opacity: 0.7;
80
- }
81
-
82
- .textarea::placeholder {
83
- color: var(--smrt-color-on-surface-variant, #9ca3af);
84
- }
85
- </style>
@@ -1,10 +0,0 @@
1
- import type { HTMLTextareaAttributes } from 'svelte/elements';
2
- export interface Props extends Omit<HTMLTextareaAttributes, 'class' | 'value'> {
3
- value?: string;
4
- rows?: number;
5
- class?: string;
6
- }
7
- declare const Textarea: import("svelte").Component<Props, {}, "value">;
8
- type Textarea = ReturnType<typeof Textarea>;
9
- export default Textarea;
10
- //# sourceMappingURL=Textarea.svelte.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Textarea.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/Textarea.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAI9D,MAAM,WAAW,KAAM,SAAQ,IAAI,CAAC,sBAAsB,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAsCD,QAAA,MAAM,QAAQ,gDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
@@ -1,217 +0,0 @@
1
- <script lang="ts">
2
- /**
3
- * SMRTToggle - An accessible toggle/switch component
4
- *
5
- * Features:
6
- * - Native checkbox semantics for accessibility
7
- * - Bindable checked state
8
- * - Disabled state
9
- * - Labels on either side
10
- * - Size variants
11
- * - Material 3 styling
12
- */
13
-
14
- export interface Props {
15
- /** Whether the toggle is checked */
16
- checked?: boolean;
17
- /** Whether the toggle is disabled */
18
- disabled?: boolean;
19
- /** Name attribute for form submission */
20
- name?: string;
21
- /** Value attribute for form submission */
22
- value?: string;
23
- /** Label text */
24
- label?: string;
25
- /** Position of the label */
26
- labelPosition?: 'left' | 'right';
27
- /** Size variant */
28
- size?: 'sm' | 'md' | 'lg';
29
- /** ID for the input element */
30
- id?: string;
31
- /** ARIA label for accessibility */
32
- ariaLabel?: string;
33
- /** Change callback */
34
- onchange?: (checked: boolean) => void;
35
- }
36
-
37
- let {
38
- checked = $bindable(false),
39
- disabled = false,
40
- name,
41
- value,
42
- label,
43
- labelPosition = 'right',
44
- size = 'md',
45
- id,
46
- ariaLabel,
47
- onchange,
48
- }: Props = $props();
49
-
50
- function handleChange(event: Event) {
51
- const target = event.target as HTMLInputElement;
52
- checked = target.checked;
53
- onchange?.(checked);
54
- }
55
-
56
- const sizeClasses = {
57
- sm: 'toggle--sm',
58
- md: 'toggle--md',
59
- lg: 'toggle--lg',
60
- };
61
- </script>
62
-
63
- <label class="toggle {sizeClasses[size]}" class:toggle--disabled={disabled}>
64
- {#if label && labelPosition === 'left'}
65
- <span class="toggle__label toggle__label--left">{label}</span>
66
- {/if}
67
-
68
- <span class="toggle__track">
69
- <input
70
- type="checkbox"
71
- class="toggle__input"
72
- {id}
73
- {name}
74
- {value}
75
- {disabled}
76
- {checked}
77
- onchange={handleChange}
78
- aria-label={ariaLabel ?? label ?? ''}
79
- />
80
- <span class="toggle__thumb"></span>
81
- </span>
82
-
83
- {#if label && labelPosition === 'right'}
84
- <span class="toggle__label toggle__label--right">{label}</span>
85
- {/if}
86
- </label>
87
-
88
- <style>
89
- .toggle {
90
- display: inline-flex;
91
- align-items: center;
92
- gap: var(--smrt-spacing-2, 0.5rem);
93
- cursor: pointer;
94
- user-select: none;
95
- }
96
-
97
- .toggle--disabled {
98
- cursor: not-allowed;
99
- opacity: 0.5;
100
- }
101
-
102
- .toggle__label {
103
- font-size: var(--smrt-typography-body-medium-size, 0.875rem);
104
- color: var(--smrt-color-on-surface, #111827);
105
- line-height: 1.5;
106
- }
107
-
108
- .toggle__track {
109
- position: relative;
110
- display: inline-flex;
111
- align-items: center;
112
- flex-shrink: 0;
113
- }
114
-
115
- .toggle__input {
116
- position: absolute;
117
- width: 1px;
118
- height: 1px;
119
- padding: 0;
120
- margin: -1px;
121
- overflow: hidden;
122
- clip: rect(0, 0, 0, 0);
123
- white-space: nowrap;
124
- border: 0;
125
- }
126
-
127
- .toggle__thumb {
128
- position: relative;
129
- background: var(--smrt-color-surface-container-highest, #e5e7eb);
130
- border-radius: var(--smrt-radius-full, 9999px);
131
- transition: background-color var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease);
132
- }
133
-
134
- .toggle__thumb::after {
135
- content: '';
136
- position: absolute;
137
- background: var(--smrt-color-surface, #ffffff);
138
- border-radius: var(--smrt-radius-full, 9999px);
139
- box-shadow: var(--smrt-elevation-1, 0 1px 3px color-mix(in srgb, var(--smrt-color-shadow) 20%, transparent));
140
- transition: transform var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease);
141
- }
142
-
143
- /* Checked state */
144
- .toggle__input:checked + .toggle__thumb {
145
- background: var(--smrt-color-primary, #005ac1);
146
- }
147
-
148
- /* Focus state */
149
- .toggle__input:focus-visible + .toggle__thumb {
150
- outline: 2px solid var(--smrt-color-primary, #005ac1);
151
- outline-offset: 2px;
152
- }
153
-
154
- /* Hover state */
155
- .toggle:not(.toggle--disabled):hover .toggle__thumb {
156
- background: var(--smrt-color-surface-container-high, #d1d5db);
157
- }
158
-
159
- .toggle:not(.toggle--disabled):hover .toggle__input:checked + .toggle__thumb {
160
- background: var(--smrt-color-primary, #2563eb);
161
- }
162
-
163
- /* Size: Small */
164
- .toggle--sm .toggle__thumb {
165
- width: 32px;
166
- height: 18px;
167
- }
168
-
169
- .toggle--sm .toggle__thumb::after {
170
- width: 14px;
171
- height: 14px;
172
- top: 2px;
173
- left: 2px;
174
- }
175
-
176
- .toggle--sm .toggle__input:checked + .toggle__thumb::after {
177
- transform: translateX(14px);
178
- }
179
-
180
- /* Size: Medium (default) */
181
- .toggle--md .toggle__thumb {
182
- width: 44px;
183
- height: 24px;
184
- }
185
-
186
- .toggle--md .toggle__thumb::after {
187
- width: 20px;
188
- height: 20px;
189
- top: 2px;
190
- left: 2px;
191
- }
192
-
193
- .toggle--md .toggle__input:checked + .toggle__thumb::after {
194
- transform: translateX(20px);
195
- }
196
-
197
- /* Size: Large */
198
- .toggle--lg .toggle__thumb {
199
- width: 56px;
200
- height: 30px;
201
- }
202
-
203
- .toggle--lg .toggle__thumb::after {
204
- width: 26px;
205
- height: 26px;
206
- top: 2px;
207
- left: 2px;
208
- }
209
-
210
- .toggle--lg .toggle__input:checked + .toggle__thumb::after {
211
- transform: translateX(26px);
212
- }
213
-
214
- .toggle--lg .toggle__label {
215
- font-size: var(--smrt-typography-body-large-size, 1rem);
216
- }
217
- </style>
@@ -1,37 +0,0 @@
1
- /**
2
- * SMRTToggle - An accessible toggle/switch component
3
- *
4
- * Features:
5
- * - Native checkbox semantics for accessibility
6
- * - Bindable checked state
7
- * - Disabled state
8
- * - Labels on either side
9
- * - Size variants
10
- * - Material 3 styling
11
- */
12
- export interface Props {
13
- /** Whether the toggle is checked */
14
- checked?: boolean;
15
- /** Whether the toggle is disabled */
16
- disabled?: boolean;
17
- /** Name attribute for form submission */
18
- name?: string;
19
- /** Value attribute for form submission */
20
- value?: string;
21
- /** Label text */
22
- label?: string;
23
- /** Position of the label */
24
- labelPosition?: 'left' | 'right';
25
- /** Size variant */
26
- size?: 'sm' | 'md' | 'lg';
27
- /** ID for the input element */
28
- id?: string;
29
- /** ARIA label for accessibility */
30
- ariaLabel?: string;
31
- /** Change callback */
32
- onchange?: (checked: boolean) => void;
33
- }
34
- declare const Toggle: import("svelte").Component<Props, {}, "checked">;
35
- type Toggle = ReturnType<typeof Toggle>;
36
- export default Toggle;
37
- //# sourceMappingURL=Toggle.svelte.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Toggle.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/Toggle.svelte.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,KAAK;IACpB,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,mBAAmB;IACnB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,+BAA+B;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC;AAiDD,QAAA,MAAM,MAAM,kDAAwC,CAAC;AACrD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;AACxC,eAAe,MAAM,CAAC"}
@@ -1,48 +0,0 @@
1
- /**
2
- * Golden test for FormGroup accessibility wiring (Sweep L1, #1420).
3
- *
4
- * FormGroup must make a wrapped base input programmatically accessible with no
5
- * extra wiring: a real <label> association, hint/error linked via
6
- * aria-describedby, and aria-invalid in the error state.
7
- */
8
- import { expectNoA11yViolations } from '@happyvertical/smrt-ui/test-support/a11y';
9
- import { render, screen } from '@testing-library/svelte';
10
- import { describe, expect, it } from 'vitest';
11
- import Fixture from './form-group-input.fixture.svelte';
12
- describe('FormGroup a11y wiring', () => {
13
- it('associates its label with the wrapped input', () => {
14
- render(Fixture, {});
15
- // getByLabelText only resolves if the label is programmatically associated.
16
- expect(screen.getByLabelText('Email')).toBeInTheDocument();
17
- });
18
- it('links a hint via aria-describedby', () => {
19
- render(Fixture, { props: { hint: 'Work address preferred' } });
20
- const input = screen.getByLabelText('Email');
21
- const describedBy = input.getAttribute('aria-describedby');
22
- expect(describedBy).toBeTruthy();
23
- const hint = document.getElementById(describedBy);
24
- expect(hint).toHaveTextContent('Work address preferred');
25
- });
26
- it('sets aria-invalid and links the error in the error state', () => {
27
- render(Fixture, { props: { error: 'Email is required' } });
28
- const input = screen.getByLabelText('Email');
29
- expect(input).toHaveAttribute('aria-invalid', 'true');
30
- const describedBy = input.getAttribute('aria-describedby');
31
- const error = document.getElementById(describedBy);
32
- expect(error).toHaveTextContent('Email is required');
33
- // error is announced
34
- expect(error).toHaveAttribute('role', 'alert');
35
- });
36
- it('is axe-clean (labelled control, associated hint)', async () => {
37
- const { container } = render(Fixture, {
38
- props: { hint: 'Work address preferred' },
39
- });
40
- await expectNoA11yViolations(container);
41
- });
42
- it('is axe-clean in the error state', async () => {
43
- const { container } = render(Fixture, {
44
- props: { error: 'Email is required' },
45
- });
46
- await expectNoA11yViolations(container);
47
- });
48
- });
@@ -1,49 +0,0 @@
1
- /**
2
- * Golden test for Input (Sweep L4, #1423).
3
- *
4
- * Input is the low-level form primitive: a bare <input> whose accessible name
5
- * comes from a wrapping label/FormGroup, not from itself. Programmatic-label +
6
- * axe-clean coverage for the form primitives is L1's deliverable (#1420, "with
7
- * L4"); here we cover render + interaction + state behavior.
8
- */
9
- import { render, screen } from '@testing-library/svelte';
10
- import userEvent from '@testing-library/user-event';
11
- import { describe, expect, it } from 'vitest';
12
- import Input from '../Input.svelte';
13
- describe('Input', () => {
14
- it('renders an <input> with the given id/name/type', () => {
15
- render(Input, { props: { id: 'first', name: 'first', type: 'text' } });
16
- const input = screen.getByRole('textbox');
17
- expect(input).toHaveAttribute('id', 'first');
18
- expect(input).toHaveAttribute('name', 'first');
19
- expect(input).toHaveAttribute('type', 'text');
20
- });
21
- it('accepts typed input', async () => {
22
- render(Input, { props: { id: 'q', name: 'q' } });
23
- const input = screen.getByRole('textbox');
24
- await userEvent.type(input, 'hello');
25
- expect(input).toHaveValue('hello');
26
- });
27
- it('renders the placeholder', () => {
28
- render(Input, { props: { id: 'q', placeholder: 'Search…' } });
29
- expect(screen.getByPlaceholderText('Search…')).toBeInTheDocument();
30
- });
31
- it('does not accept input when disabled', async () => {
32
- render(Input, { props: { id: 'q', disabled: true } });
33
- const input = screen.getByRole('textbox');
34
- expect(input).toBeDisabled();
35
- await userEvent.type(input, 'nope');
36
- expect(input).toHaveValue('');
37
- });
38
- it('is read-only when readonly is set', async () => {
39
- render(Input, { props: { id: 'q', readonly: true, value: 'fixed' } });
40
- const input = screen.getByRole('textbox');
41
- expect(input).toHaveAttribute('readonly');
42
- await userEvent.type(input, 'x');
43
- expect(input).toHaveValue('fixed');
44
- });
45
- it('marks required inputs', () => {
46
- render(Input, { props: { id: 'q', required: true } });
47
- expect(screen.getByRole('textbox')).toBeRequired();
48
- });
49
- });