@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,37 +0,0 @@
1
- /**
2
- * Golden test for Select (Sweep L1, #1420).
3
- *
4
- * Select forwards aria attributes (so it can be labelled / error-associated)
5
- * and inherits id / describedby / invalid from a wrapping FormGroup via context.
6
- */
7
- import { expectNoA11yViolations } from '@happyvertical/smrt-ui/test-support/a11y';
8
- import { render, screen } from '@testing-library/svelte';
9
- import { createRawSnippet } from 'svelte';
10
- import { describe, expect, it } from 'vitest';
11
- import Select from '../Select.svelte';
12
- function options() {
13
- return createRawSnippet(() => ({
14
- render: () => `<option value="a">A</option><option value="b">B</option>`,
15
- }));
16
- }
17
- describe('Select', () => {
18
- it('forwards aria-label / aria-describedby / aria-invalid', () => {
19
- render(Select, {
20
- props: {
21
- 'aria-label': 'Country',
22
- 'aria-describedby': 'country-hint',
23
- 'aria-invalid': 'true',
24
- children: options(),
25
- },
26
- });
27
- const select = screen.getByRole('combobox', { name: 'Country' });
28
- expect(select).toHaveAttribute('aria-describedby', 'country-hint');
29
- expect(select).toHaveAttribute('aria-invalid', 'true');
30
- });
31
- it('is axe-clean when labelled', async () => {
32
- const { container } = render(Select, {
33
- props: { 'aria-label': 'Country', children: options() },
34
- });
35
- await expectNoA11yViolations(container);
36
- });
37
- });
@@ -1,39 +0,0 @@
1
- /**
2
- * Golden test for Textarea (Sweep L1, #1420).
3
- *
4
- * Textarea forwards aria attributes and inherits id / describedby / invalid from
5
- * a wrapping FormGroup via context.
6
- */
7
- import { expectNoA11yViolations } from '@happyvertical/smrt-ui/test-support/a11y';
8
- import { render, screen } from '@testing-library/svelte';
9
- import userEvent from '@testing-library/user-event';
10
- import { describe, expect, it } from 'vitest';
11
- import Textarea from '../Textarea.svelte';
12
- describe('Textarea', () => {
13
- it('forwards aria-label / aria-describedby / aria-invalid', () => {
14
- render(Textarea, {
15
- props: {
16
- 'aria-label': 'Notes',
17
- 'aria-describedby': 'notes-hint',
18
- 'aria-invalid': 'true',
19
- },
20
- });
21
- const textarea = screen.getByRole('textbox', { name: 'Notes' });
22
- expect(textarea).toHaveAttribute('aria-describedby', 'notes-hint');
23
- expect(textarea).toHaveAttribute('aria-invalid', 'true');
24
- });
25
- it('accepts typed input', async () => {
26
- render(Textarea, { props: { 'aria-label': 'Notes' } });
27
- const textarea = screen.getByRole('textbox', {
28
- name: 'Notes',
29
- });
30
- await userEvent.type(textarea, 'hello');
31
- expect(textarea).toHaveValue('hello');
32
- });
33
- it('is axe-clean when labelled', async () => {
34
- const { container } = render(Textarea, {
35
- props: { 'aria-label': 'Notes' },
36
- });
37
- await expectNoA11yViolations(container);
38
- });
39
- });
@@ -1,87 +0,0 @@
1
- /**
2
- * Component test for Toggle (Sweep S11, #1416).
3
- *
4
- * Follows the golden pattern (src/components/ui/__tests__/Button.test.ts):
5
- * render → assert role/name/state → drive with user-event → prove axe-clean.
6
- * Toggle renders native checkbox semantics, so it surfaces as a `checkbox` role.
7
- */
8
- import { expectNoA11yViolations } from '@happyvertical/smrt-ui/test-support/a11y';
9
- import { render, screen } from '@testing-library/svelte';
10
- import userEvent from '@testing-library/user-event';
11
- import { describe, expect, it, vi } from 'vitest';
12
- import Toggle from '../Toggle.svelte';
13
- describe('Toggle', () => {
14
- it('renders a checkbox with its label as the accessible name', () => {
15
- render(Toggle, { props: { label: 'Email notifications' } });
16
- const toggle = screen.getByRole('checkbox', {
17
- name: 'Email notifications',
18
- });
19
- expect(toggle).toBeInTheDocument();
20
- expect(toggle).not.toBeChecked();
21
- });
22
- it('prefers ariaLabel over label for the accessible name', () => {
23
- render(Toggle, { props: { label: 'Visible', ariaLabel: 'Wifi' } });
24
- expect(screen.getByRole('checkbox', { name: 'Wifi' })).toBeInTheDocument();
25
- });
26
- it('reflects the checked prop', () => {
27
- render(Toggle, { props: { ariaLabel: 'Active', checked: true } });
28
- expect(screen.getByRole('checkbox', { name: 'Active' })).toBeChecked();
29
- });
30
- it('reflects the disabled prop', () => {
31
- render(Toggle, { props: { ariaLabel: 'Active', disabled: true } });
32
- expect(screen.getByRole('checkbox', { name: 'Active' })).toBeDisabled();
33
- });
34
- it('forwards name, value, and id to the input for form submission', () => {
35
- render(Toggle, {
36
- props: { ariaLabel: 'Sub', name: 'sub', value: 'on', id: 'sub-toggle' },
37
- });
38
- const toggle = screen.getByRole('checkbox', {
39
- name: 'Sub',
40
- });
41
- expect(toggle).toHaveAttribute('name', 'sub');
42
- expect(toggle).toHaveAttribute('id', 'sub-toggle');
43
- // Svelte binds `value` as the DOM property on checkboxes (not a reflected attribute).
44
- expect(toggle.value).toBe('on');
45
- });
46
- it('toggles checked and fires onchange when clicked', async () => {
47
- const onchange = vi.fn();
48
- render(Toggle, { props: { ariaLabel: 'Active', onchange } });
49
- const toggle = screen.getByRole('checkbox', { name: 'Active' });
50
- await userEvent.click(toggle);
51
- expect(toggle).toBeChecked();
52
- expect(onchange).toHaveBeenCalledWith(true);
53
- await userEvent.click(toggle);
54
- expect(toggle).not.toBeChecked();
55
- expect(onchange).toHaveBeenLastCalledWith(false);
56
- });
57
- it('is keyboard-activatable with Space when focused', async () => {
58
- const onchange = vi.fn();
59
- render(Toggle, { props: { ariaLabel: 'Active', onchange } });
60
- const toggle = screen.getByRole('checkbox', { name: 'Active' });
61
- toggle.focus();
62
- expect(toggle).toHaveFocus();
63
- await userEvent.keyboard(' ');
64
- expect(toggle).toBeChecked();
65
- expect(onchange).toHaveBeenCalledWith(true);
66
- });
67
- it('does not fire onchange when disabled', async () => {
68
- const onchange = vi.fn();
69
- render(Toggle, {
70
- props: { ariaLabel: 'Active', disabled: true, onchange },
71
- });
72
- await userEvent.click(screen.getByRole('checkbox', { name: 'Active' }));
73
- expect(onchange).not.toHaveBeenCalled();
74
- });
75
- it('is axe-clean with a label', async () => {
76
- const { container } = render(Toggle, {
77
- props: { label: 'Accessible toggle' },
78
- });
79
- await expectNoA11yViolations(container);
80
- });
81
- it('is axe-clean in the checked + disabled state', async () => {
82
- const { container } = render(Toggle, {
83
- props: { label: 'Locked on', checked: true, disabled: true },
84
- });
85
- await expectNoA11yViolations(container);
86
- });
87
- });
@@ -1,16 +0,0 @@
1
- <script lang="ts">
2
- /** Test fixture (L1 #1420): an Input wrapped in a FormGroup, to exercise the
3
- * FormGroup → base-input accessibility auto-wiring. */
4
- import FormGroup from '../FormGroup.svelte';
5
- import Input from '../Input.svelte';
6
-
7
- let {
8
- error = undefined,
9
- hint = undefined,
10
- required = false,
11
- }: { error?: string; hint?: string; required?: boolean } = $props();
12
- </script>
13
-
14
- <FormGroup label="Email" {error} {hint} {required}>
15
- <Input type="email" name="email" />
16
- </FormGroup>
@@ -1,9 +0,0 @@
1
- type $$ComponentProps = {
2
- error?: string;
3
- hint?: string;
4
- required?: boolean;
5
- };
6
- declare const FormGroupInput: import("svelte").Component<$$ComponentProps, {}, "">;
7
- type FormGroupInput = ReturnType<typeof FormGroupInput>;
8
- export default FormGroupInput;
9
- //# sourceMappingURL=form-group-input.fixture.svelte.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"form-group-input.fixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/__tests__/form-group-input.fixture.svelte.ts"],"names":[],"mappings":"AAQC,KAAK,gBAAgB,GAAI;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAmBhF,QAAA,MAAM,cAAc,sDAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -1,13 +0,0 @@
1
- export interface FormGroupContextValue {
2
- /** Stable id for the field control; matches the FormGroup label's `for`. */
3
- inputId: string;
4
- /** Space-joined ids of the visible hint/error text, or undefined if none. */
5
- describedBy: string | undefined;
6
- /** Whether the field is currently showing an error. */
7
- invalid: boolean;
8
- }
9
- export declare function setFormGroupContext(get: () => FormGroupContextValue): void;
10
- export declare function tryGetFormGroupContext(): (() => FormGroupContextValue) | undefined;
11
- /** Deterministic, collision-resistant id for a FormGroup that wasn't given one. */
12
- export declare function nextFieldId(): string;
13
- //# sourceMappingURL=form-group-context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"form-group-context.d.ts","sourceRoot":"","sources":["../../src/state/form-group-context.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,qBAAqB;IACpC,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,uDAAuD;IACvD,OAAO,EAAE,OAAO,CAAC;CAClB;AAID,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,qBAAqB,GAAG,IAAI,CAE1E;AAED,wBAAgB,sBAAsB,IAClC,CAAC,MAAM,qBAAqB,CAAC,GAC7B,SAAS,CAEZ;AAID,mFAAmF;AACnF,wBAAgB,WAAW,IAAI,MAAM,CAGpC"}
@@ -1,28 +0,0 @@
1
- /**
2
- * FormGroup accessibility context (Sweep L1, #1420).
3
- *
4
- * `FormGroup` publishes the wiring a wrapped input needs to be programmatically
5
- * accessible — the input's `id` (so the `<label for>` resolves), the
6
- * space-joined ids of the hint/error text (for `aria-describedby`), and whether
7
- * the field is currently in an error state (`aria-invalid`). The base form
8
- * primitives (`Input`, `Select`, `Textarea`) read this and auto-apply those
9
- * attributes when the consumer hasn't set them explicitly, so an input dropped
10
- * inside a `<FormGroup>` is accessible with no extra wiring.
11
- *
12
- * The value is a getter so the consuming input always reads the *current*
13
- * reactive state (id is stable; describedBy/invalid change as hint/error do).
14
- */
15
- import { getContext, setContext } from 'svelte';
16
- const FORM_GROUP_KEY = Symbol('smrt-form-group');
17
- export function setFormGroupContext(get) {
18
- setContext(FORM_GROUP_KEY, get);
19
- }
20
- export function tryGetFormGroupContext() {
21
- return getContext(FORM_GROUP_KEY);
22
- }
23
- let autoIdCounter = 0;
24
- /** Deterministic, collision-resistant id for a FormGroup that wasn't given one. */
25
- export function nextFieldId() {
26
- autoIdCounter += 1;
27
- return `smrt-field-${autoIdCounter}`;
28
- }