@happyvertical/smrt-ui 0.53.0 → 0.53.2

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 (205) hide show
  1. package/package.json +3 -3
  2. package/dist/actions/__tests__/ripple.test.js +0 -82
  3. package/dist/actions/__tests__/swipe-dismiss.test.js +0 -69
  4. package/dist/components/calendar/__tests__/CalendarView.test.js +0 -226
  5. package/dist/components/calendar/__tests__/calendar-model.test.js +0 -138
  6. package/dist/components/chat/__tests__/chat-primitives.test.js +0 -118
  7. package/dist/components/data/__tests__/CollectionList.test.js +0 -37
  8. package/dist/components/data/__tests__/DataTable.test.js +0 -807
  9. package/dist/components/data/__tests__/DataTableConformance.test.js +0 -212
  10. package/dist/components/data/__tests__/DataTableController.test.js +0 -371
  11. package/dist/components/data/__tests__/DataTableIdentity.test.js +0 -29
  12. package/dist/components/data/__tests__/DataTableLayout.test.js +0 -195
  13. package/dist/components/data/__tests__/DataTablePerformance.test.js +0 -21
  14. package/dist/components/data/__tests__/DataTableResponsive.test.js +0 -80
  15. package/dist/components/data/__tests__/DataTableVirtualization.test.js +0 -80
  16. package/dist/components/data/__tests__/DataTableVirtualizationComponent.test.js +0 -255
  17. package/dist/components/data/__tests__/SortableHeader.test.js +0 -101
  18. package/dist/components/data/__tests__/data-surface.test.js +0 -746
  19. package/dist/components/data/__tests__/data-table-helpers.test.js +0 -36
  20. package/dist/components/data/__tests__/data-table-surface.test.js +0 -49
  21. package/dist/components/data/__tests__/link-step-surface.test.js +0 -172
  22. package/dist/components/data/__tests__/list-sort-state.svelte.test.js +0 -71
  23. package/dist/components/data/__tests__/list-sort.test.js +0 -91
  24. package/dist/components/data/__tests__/mounted-data-surface.test.js +0 -794
  25. package/dist/components/data/__tests__/responsive-table.fixture.svelte +0 -29
  26. package/dist/components/data/__tests__/responsive-table.fixture.svelte.d.ts +0 -7
  27. package/dist/components/data/__tests__/responsive-table.fixture.svelte.d.ts.map +0 -1
  28. package/dist/components/data/__tests__/surface-navigation.test.js +0 -121
  29. package/dist/components/display/__tests__/ConfidenceBadge.test.js +0 -109
  30. package/dist/components/display/__tests__/CurrencyDisplay.test.js +0 -304
  31. package/dist/components/display/__tests__/CurrencyDisplayI18nHarness.svelte +0 -20
  32. package/dist/components/display/__tests__/CurrencyDisplayI18nHarness.svelte.d.ts +0 -19
  33. package/dist/components/display/__tests__/CurrencyDisplayI18nHarness.svelte.d.ts.map +0 -1
  34. package/dist/components/display/__tests__/CurrencyDisplaySsrHarness.svelte +0 -7
  35. package/dist/components/display/__tests__/CurrencyDisplaySsrHarness.svelte.d.ts +0 -19
  36. package/dist/components/display/__tests__/CurrencyDisplaySsrHarness.svelte.d.ts.map +0 -1
  37. package/dist/components/display/__tests__/DateDisplay.test.js +0 -195
  38. package/dist/components/display/__tests__/Icon.test.js +0 -223
  39. package/dist/components/display/__tests__/StatusBadge.test.js +0 -191
  40. package/dist/components/feedback/__tests__/ConfirmDialog.test.js +0 -181
  41. package/dist/components/feedback/__tests__/LoadingOverlay.test.js +0 -113
  42. package/dist/components/feedback/__tests__/Modal.test.js +0 -72
  43. package/dist/components/feedback/__tests__/PhoneSheet.test.js +0 -101
  44. package/dist/components/feedback/__tests__/ProgressBar.test.js +0 -89
  45. package/dist/components/feedback/__tests__/WorkingStrip.test.js +0 -172
  46. package/dist/components/feedback/__tests__/confirm-message.fixture.svelte +0 -9
  47. package/dist/components/feedback/__tests__/confirm-message.fixture.svelte.d.ts +0 -19
  48. package/dist/components/feedback/__tests__/confirm-message.fixture.svelte.d.ts.map +0 -1
  49. package/dist/components/feedback/__tests__/toast.test.js +0 -190
  50. package/dist/components/forms/__tests__/CameraCapture.test.js +0 -504
  51. package/dist/components/forms/__tests__/Combobox.test.js +0 -354
  52. package/dist/components/forms/__tests__/ControlHitArea.test.js +0 -73
  53. package/dist/components/forms/__tests__/DictationButton.test.js +0 -176
  54. package/dist/components/forms/__tests__/Fieldset.test.js +0 -37
  55. package/dist/components/forms/__tests__/Form.test.js +0 -201
  56. package/dist/components/forms/__tests__/FormActionBar.test.js +0 -22
  57. package/dist/components/forms/__tests__/FormGroup.test.js +0 -48
  58. package/dist/components/forms/__tests__/Input.test.js +0 -49
  59. package/dist/components/forms/__tests__/Listbox.test.js +0 -303
  60. package/dist/components/forms/__tests__/MultiSelect.test.js +0 -281
  61. package/dist/components/forms/__tests__/SearchInput.test.js +0 -92
  62. package/dist/components/forms/__tests__/Select.test.js +0 -37
  63. package/dist/components/forms/__tests__/SignaturePad.test.js +0 -338
  64. package/dist/components/forms/__tests__/StagedControlReview.test.js +0 -702
  65. package/dist/components/forms/__tests__/Textarea.test.js +0 -39
  66. package/dist/components/forms/__tests__/Toggle.test.js +0 -87
  67. package/dist/components/forms/__tests__/camera-capture-session.test.js +0 -207
  68. package/dist/components/forms/__tests__/capture-form-retry.test.js +0 -166
  69. package/dist/components/forms/__tests__/capture-form.fixture.svelte +0 -38
  70. package/dist/components/forms/__tests__/capture-form.fixture.svelte.d.ts +0 -10
  71. package/dist/components/forms/__tests__/capture-form.fixture.svelte.d.ts.map +0 -1
  72. package/dist/components/forms/__tests__/capture-test-env.d.ts +0 -70
  73. package/dist/components/forms/__tests__/capture-test-env.d.ts.map +0 -1
  74. package/dist/components/forms/__tests__/capture-test-env.js +0 -122
  75. package/dist/components/forms/__tests__/capture-touch.fixture.svelte +0 -15
  76. package/dist/components/forms/__tests__/capture-touch.fixture.svelte.d.ts +0 -8
  77. package/dist/components/forms/__tests__/capture-touch.fixture.svelte.d.ts.map +0 -1
  78. package/dist/components/forms/__tests__/combobox-form.fixture.svelte +0 -29
  79. package/dist/components/forms/__tests__/combobox-form.fixture.svelte.d.ts +0 -14
  80. package/dist/components/forms/__tests__/combobox-form.fixture.svelte.d.ts.map +0 -1
  81. package/dist/components/forms/__tests__/combobox-labels.fixture.svelte +0 -19
  82. package/dist/components/forms/__tests__/combobox-labels.fixture.svelte.d.ts +0 -11
  83. package/dist/components/forms/__tests__/combobox-labels.fixture.svelte.d.ts.map +0 -1
  84. package/dist/components/forms/__tests__/composite-controls.fixture.svelte +0 -47
  85. package/dist/components/forms/__tests__/composite-controls.fixture.svelte.d.ts +0 -12
  86. package/dist/components/forms/__tests__/composite-controls.fixture.svelte.d.ts.map +0 -1
  87. package/dist/components/forms/__tests__/composite-controls.test.js +0 -128
  88. package/dist/components/forms/__tests__/composite-registration.fixture.svelte +0 -29
  89. package/dist/components/forms/__tests__/composite-registration.fixture.svelte.d.ts +0 -8
  90. package/dist/components/forms/__tests__/composite-registration.fixture.svelte.d.ts.map +0 -1
  91. package/dist/components/forms/__tests__/composite-user-edit.fixture.svelte +0 -41
  92. package/dist/components/forms/__tests__/composite-user-edit.fixture.svelte.d.ts +0 -13
  93. package/dist/components/forms/__tests__/composite-user-edit.fixture.svelte.d.ts.map +0 -1
  94. package/dist/components/forms/__tests__/control-interaction.test.js +0 -3421
  95. package/dist/components/forms/__tests__/control-proposals.test.js +0 -63
  96. package/dist/components/forms/__tests__/core-controls.fixture.svelte +0 -50
  97. package/dist/components/forms/__tests__/core-controls.fixture.svelte.d.ts +0 -9
  98. package/dist/components/forms/__tests__/core-controls.fixture.svelte.d.ts.map +0 -1
  99. package/dist/components/forms/__tests__/core-controls.test.js +0 -311
  100. package/dist/components/forms/__tests__/decimal-sliders.fixture.svelte +0 -25
  101. package/dist/components/forms/__tests__/decimal-sliders.fixture.svelte.d.ts +0 -8
  102. package/dist/components/forms/__tests__/decimal-sliders.fixture.svelte.d.ts.map +0 -1
  103. package/dist/components/forms/__tests__/dictation-recording.test.js +0 -582
  104. package/dist/components/forms/__tests__/dictation.test.js +0 -486
  105. package/dist/components/forms/__tests__/form-attachment.fixture.svelte +0 -28
  106. package/dist/components/forms/__tests__/form-attachment.fixture.svelte.d.ts +0 -11
  107. package/dist/components/forms/__tests__/form-attachment.fixture.svelte.d.ts.map +0 -1
  108. package/dist/components/forms/__tests__/form-group-input.fixture.svelte +0 -16
  109. package/dist/components/forms/__tests__/form-group-input.fixture.svelte.d.ts +0 -9
  110. package/dist/components/forms/__tests__/form-group-input.fixture.svelte.d.ts.map +0 -1
  111. package/dist/components/forms/__tests__/form-retry-form.fixture.svelte +0 -31
  112. package/dist/components/forms/__tests__/form-retry-form.fixture.svelte.d.ts +0 -13
  113. package/dist/components/forms/__tests__/form-retry-form.fixture.svelte.d.ts.map +0 -1
  114. package/dist/components/forms/__tests__/form-retry-form.test.js +0 -107
  115. package/dist/components/forms/__tests__/hidden-controls-form-retry.test.js +0 -69
  116. package/dist/components/forms/__tests__/hidden-controls-form.fixture.svelte +0 -29
  117. package/dist/components/forms/__tests__/hidden-controls-form.fixture.svelte.d.ts +0 -9
  118. package/dist/components/forms/__tests__/hidden-controls-form.fixture.svelte.d.ts.map +0 -1
  119. package/dist/components/forms/__tests__/listbox-form.fixture.svelte +0 -27
  120. package/dist/components/forms/__tests__/listbox-form.fixture.svelte.d.ts +0 -13
  121. package/dist/components/forms/__tests__/listbox-form.fixture.svelte.d.ts.map +0 -1
  122. package/dist/components/forms/__tests__/long-press.test.js +0 -175
  123. package/dist/components/forms/__tests__/multiselect-form.fixture.svelte +0 -27
  124. package/dist/components/forms/__tests__/multiselect-form.fixture.svelte.d.ts +0 -13
  125. package/dist/components/forms/__tests__/multiselect-form.fixture.svelte.d.ts.map +0 -1
  126. package/dist/components/forms/__tests__/native-file-field.test.js +0 -177
  127. package/dist/components/forms/__tests__/place-picker.fixture.svelte +0 -33
  128. package/dist/components/forms/__tests__/place-picker.fixture.svelte.d.ts +0 -12
  129. package/dist/components/forms/__tests__/place-picker.fixture.svelte.d.ts.map +0 -1
  130. package/dist/components/forms/__tests__/segmented-posting.fixture.svelte +0 -28
  131. package/dist/components/forms/__tests__/segmented-posting.fixture.svelte.d.ts +0 -12
  132. package/dist/components/forms/__tests__/segmented-posting.fixture.svelte.d.ts.map +0 -1
  133. package/dist/components/forms/__tests__/segmented-posting.test.js +0 -92
  134. package/dist/components/forms/__tests__/select-interaction.fixture.svelte +0 -25
  135. package/dist/components/forms/__tests__/select-interaction.fixture.svelte.d.ts +0 -9
  136. package/dist/components/forms/__tests__/select-interaction.fixture.svelte.d.ts.map +0 -1
  137. package/dist/components/forms/__tests__/signature-pad-logic.test.js +0 -54
  138. package/dist/components/forms/__tests__/staged-review-fieldset.fixture.svelte +0 -21
  139. package/dist/components/forms/__tests__/staged-review-fieldset.fixture.svelte.d.ts +0 -8
  140. package/dist/components/forms/__tests__/staged-review-fieldset.fixture.svelte.d.ts.map +0 -1
  141. package/dist/components/forms/__tests__/staged-review-outer-fieldset.fixture.svelte +0 -23
  142. package/dist/components/forms/__tests__/staged-review-outer-fieldset.fixture.svelte.d.ts +0 -8
  143. package/dist/components/forms/__tests__/staged-review-outer-fieldset.fixture.svelte.d.ts.map +0 -1
  144. package/dist/components/forms/__tests__/staged-review.fixture.svelte +0 -56
  145. package/dist/components/forms/__tests__/staged-review.fixture.svelte.d.ts +0 -12
  146. package/dist/components/forms/__tests__/staged-review.fixture.svelte.d.ts.map +0 -1
  147. package/dist/components/forms/__tests__/touch-density.fixture.svelte +0 -34
  148. package/dist/components/forms/__tests__/touch-density.fixture.svelte.d.ts +0 -8
  149. package/dist/components/forms/__tests__/touch-density.fixture.svelte.d.ts.map +0 -1
  150. package/dist/components/forms/__tests__/touch-density.test.js +0 -66
  151. package/dist/components/forms/form-retry/__tests__/boundaries.test.js +0 -23
  152. package/dist/components/forms/form-retry/__tests__/content-digest.test.js +0 -70
  153. package/dist/components/forms/form-retry/__tests__/controller.test.js +0 -802
  154. package/dist/components/forms/form-retry/__tests__/fake-kit.d.ts +0 -82
  155. package/dist/components/forms/form-retry/__tests__/fake-kit.d.ts.map +0 -1
  156. package/dist/components/forms/form-retry/__tests__/fake-kit.js +0 -180
  157. package/dist/components/forms/form-retry/__tests__/form-draft.test.js +0 -169
  158. package/dist/components/forms/form-retry/__tests__/ssr.test.js +0 -37
  159. package/dist/components/forms/form-retry/__tests__/storage.d.ts +0 -26
  160. package/dist/components/forms/form-retry/__tests__/storage.d.ts.map +0 -1
  161. package/dist/components/forms/form-retry/__tests__/storage.js +0 -63
  162. package/dist/components/forms/form-retry/__tests__/submission-key.test.js +0 -236
  163. package/dist/components/forms/form-retry/__tests__/submitted-draft.test.js +0 -334
  164. package/dist/components/layout/__tests__/Container.test.js +0 -62
  165. package/dist/components/layout/__tests__/EmptyState.test.js +0 -83
  166. package/dist/components/layout/__tests__/Footer.test.js +0 -50
  167. package/dist/components/layout/__tests__/Grid.test.js +0 -121
  168. package/dist/components/layout/__tests__/Header.test.js +0 -48
  169. package/dist/components/layout/__tests__/Masthead.test.js +0 -93
  170. package/dist/components/layout/__tests__/PageHeader.test.js +0 -166
  171. package/dist/components/layout/__tests__/SummaryCard.test.js +0 -104
  172. package/dist/components/nav/__tests__/FilterChips.test.js +0 -94
  173. package/dist/components/nav/__tests__/LinkTabs.test.js +0 -117
  174. package/dist/components/nav/__tests__/Tabs.test.js +0 -128
  175. package/dist/components/roles/__tests__/RoleSelector.test.js +0 -134
  176. package/dist/components/ui/__tests__/Badge.test.js +0 -76
  177. package/dist/components/ui/__tests__/Button.test.js +0 -166
  178. package/dist/components/ui/__tests__/Card.test.js +0 -103
  179. package/dist/components/ui/__tests__/IconToggle.test.js +0 -59
  180. package/dist/components/ui/__tests__/IconToggleGroup.test.js +0 -30
  181. package/dist/components/ui/__tests__/Pagination.test.js +0 -113
  182. package/dist/components/ui/__tests__/Popover.test.js +0 -44
  183. package/dist/components/ui/__tests__/dropdown-popover-icon.test.js +0 -125
  184. package/dist/components/ui/__tests__/gap-primitives-interactive.test.js +0 -112
  185. package/dist/components/ui/__tests__/gap-primitives.test.js +0 -84
  186. package/dist/components/ui/__tests__/interaction-primitives.fixture.svelte +0 -13
  187. package/dist/components/ui/__tests__/interaction-primitives.fixture.svelte.d.ts +0 -19
  188. package/dist/components/ui/__tests__/interaction-primitives.fixture.svelte.d.ts.map +0 -1
  189. package/dist/components/ui/__tests__/interaction-primitives.test.js +0 -31
  190. package/dist/components/ui/__tests__/phone-touch-targets.test.js +0 -39
  191. package/dist/i18n/__tests__/i18n.test.js +0 -74
  192. package/dist/i18n/__tests__/render-parity.spec.js +0 -37
  193. package/dist/svelte/__tests__/playground.test.js +0 -20
  194. package/dist/themes/__tests__/control-boundary-contrast.test.js +0 -112
  195. package/dist/themes/__tests__/create-theme.test.js +0 -79
  196. package/dist/themes/__tests__/css-generator.test.js +0 -129
  197. package/dist/themes/__tests__/happyvertical-theme.test.js +0 -231
  198. package/dist/themes/__tests__/registry.test.js +0 -43
  199. package/dist/themes/__tests__/styles-lockstep.test.js +0 -32
  200. package/dist/themes/__tests__/theme-provider.test.js +0 -147
  201. package/dist/themes/__tests__/theme-script.test.js +0 -130
  202. package/dist/themes/__tests__/token-aliases.test.js +0 -178
  203. package/dist/utils/forms/__tests__/formatters.test.js +0 -27
  204. package/dist/utils/theme/__tests__/color.test.js +0 -89
  205. package/dist/utils/theme/__tests__/typography.test.js +0 -11
@@ -1,63 +0,0 @@
1
- import { render, screen } from '@testing-library/svelte';
2
- import { tick } from 'svelte';
3
- import { describe, expect, it } from 'vitest';
4
- import { createControlInteractionRegistry } from '../control-interaction.js';
5
- import { controlProposalInputSchema, controlProposalToolName, stageControlProposals, } from '../control-proposals.js';
6
- import Fixture from './composite-registration.fixture.svelte';
7
- describe('useControlRegistration (public) and control proposals', () => {
8
- it('registers a composite as one control with its declared value schema', async () => {
9
- const registry = createControlInteractionRegistry();
10
- render(Fixture, { props: { registry } });
11
- await tick();
12
- const ids = registry
13
- .list('new-site')
14
- .map((snapshot) => snapshot.identity.controlId);
15
- expect(ids).toEqual(expect.arrayContaining(['name', 'place', 'password']));
16
- const place = registry.get({ formId: 'new-site', controlId: 'place' });
17
- expect(place?.metadata.label).toBe('Town location');
18
- expect(place?.metadata.valueSchema).toMatchObject({ type: 'object' });
19
- });
20
- it('builds a proposal schema from every proposable control, never secrets', async () => {
21
- const registry = createControlInteractionRegistry();
22
- render(Fixture, { props: { registry } });
23
- await tick();
24
- const schema = controlProposalInputSchema(registry, 'new-site');
25
- expect(Object.keys(schema.properties).sort()).toEqual(['name', 'place']);
26
- expect(schema.properties.name).toEqual({
27
- type: 'string',
28
- title: 'Site name',
29
- });
30
- expect(schema.properties.place).toMatchObject({
31
- type: 'object',
32
- title: 'Town location',
33
- });
34
- expect(controlProposalInputSchema(registry, 'new-site', { exclude: ['name'] })).toMatchObject({ properties: { place: expect.any(Object) } });
35
- });
36
- it('stages proposals for review without changing values', async () => {
37
- const registry = createControlInteractionRegistry();
38
- render(Fixture, { props: { registry } });
39
- await tick();
40
- const result = await stageControlProposals(registry, 'new-site', {
41
- name: 'Lacombe',
42
- place: { name: 'Lacombe', latitude: 52.46, longitude: -113.73 },
43
- password: 'hunter2',
44
- nope: 1,
45
- }, { actorId: 'assistant' });
46
- expect(result).toEqual({
47
- ok: true,
48
- staged: 2,
49
- rejected: [],
50
- skipped: ['password', 'nope'],
51
- });
52
- expect(screen.getByTestId('place')).toHaveTextContent('none');
53
- const staged = registry.get({ formId: 'new-site', controlId: 'place' });
54
- expect(staged?.state.staged?.provenance).toMatchObject({
55
- source: 'agent',
56
- actorId: 'assistant',
57
- });
58
- });
59
- it('names the tool with tool-safe characters', () => {
60
- expect(controlProposalToolName('setup-network')).toBe('setup_network_stage_changes');
61
- expect(controlProposalToolName('--')).toBe('form_stage_changes');
62
- });
63
- });
@@ -1,50 +0,0 @@
1
- <script lang="ts">
2
- import Checkbox from '../Checkbox.svelte';
3
- import type { ControlInteractionRegistry } from '../control-interaction.js';
4
- import Form from '../Form.svelte';
5
- import Radio from '../Radio.svelte';
6
- import RadioGroup from '../RadioGroup.svelte';
7
- import RangeSlider from '../RangeSlider.svelte';
8
- import SegmentedControl from '../SegmentedControl.svelte';
9
- import Slider from '../Slider.svelte';
10
- import Switch from '../Switch.svelte';
11
- import Textarea from '../Textarea.svelte';
12
- import ToggleButton from '../ToggleButton.svelte';
13
-
14
- interface Props {
15
- registry: ControlInteractionRegistry;
16
- validInitial?: boolean;
17
- }
18
- let { registry, validInitial = false }: Props = $props();
19
- let accepted = $state(false);
20
- let notifications = $state(false);
21
- let role = $state('editor');
22
- let volume = $state(30);
23
- let range = $state({ min: 20, max: 80 });
24
- let view = $state<string | number>('grid');
25
- let notes = $state('valid notes');
26
- let pinned = $state(false);
27
- $effect(() => {
28
- accepted = validInitial;
29
- notifications = validInitial;
30
- });
31
- </script>
32
-
33
- <Form formId="settings" interactionRegistry={registry} aria-label="Settings">
34
- <Checkbox name="accepted" label="Accept terms" required bind:checked={accepted} />
35
- <Switch name="notifications" label="Notifications" required bind:checked={notifications} />
36
- <RadioGroup name="role" label="Role" bind:value={role}>
37
- <Radio value="editor" label="Editor" />
38
- <Radio value="viewer" label="Viewer" />
39
- </RadioGroup>
40
- <Slider name="volume" label="Volume" step={5} bind:value={volume} />
41
- <RangeSlider name="price" label="Price" step={5} bind:value={range} />
42
- <SegmentedControl
43
- name="view"
44
- label="View"
45
- options={[{ value: 'grid', label: 'Grid' }, { value: 'list', label: 'List' }]}
46
- bind:value={view}
47
- />
48
- <Textarea name="notes" aria-label="Notes" required minlength={3} bind:value={notes} />
49
- <ToggleButton name="pinned" aria-label="Pinned" bind:pressed={pinned}>Pinned</ToggleButton>
50
- </Form>
@@ -1,9 +0,0 @@
1
- import type { ControlInteractionRegistry } from '../control-interaction.js';
2
- interface Props {
3
- registry: ControlInteractionRegistry;
4
- validInitial?: boolean;
5
- }
6
- declare const CoreControls: import("svelte").Component<Props, {}, "">;
7
- type CoreControls = ReturnType<typeof CoreControls>;
8
- export default CoreControls;
9
- //# sourceMappingURL=core-controls.fixture.svelte.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"core-controls.fixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/__tests__/core-controls.fixture.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAY5E,UAAU,KAAK;IACb,QAAQ,EAAE,0BAA0B,CAAC;IACrC,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AA6CD,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -1,311 +0,0 @@
1
- import { render, screen } from '@testing-library/svelte';
2
- import userEvent from '@testing-library/user-event';
3
- import { describe, expect, it } from 'vitest';
4
- import { expectNoA11yViolations } from '../../../test-support/a11y';
5
- import Progress from '../../feedback/Progress.svelte';
6
- import Spinner from '../../feedback/Spinner.svelte';
7
- import { createControlInteractionRegistry } from '../control-interaction.js';
8
- import { snapSteppedNumber, validatesSteppedNumber, } from '../control-value-validation.js';
9
- import ErrorSummary from '../ErrorSummary.svelte';
10
- import Fixture from './core-controls.fixture.svelte';
11
- import DecimalSlidersFixture from './decimal-sliders.fixture.svelte';
12
- describe('core controls', () => {
13
- it('provides distinct checkbox, switch, radio, slider, range, and segmented semantics', async () => {
14
- const registry = createControlInteractionRegistry();
15
- render(Fixture, { props: { registry } });
16
- await userEvent.click(screen.getByRole('checkbox', { name: 'Accept terms' }));
17
- expect(screen.getByRole('checkbox', { name: 'Accept terms' })).toBeChecked();
18
- await userEvent.click(screen.getByRole('switch', { name: 'Notifications' }));
19
- expect(screen.getByRole('switch', { name: 'Notifications' })).toBeChecked();
20
- await userEvent.click(screen.getByRole('radio', { name: 'Viewer' }));
21
- expect(screen.getByRole('radio', { name: 'Viewer' })).toBeChecked();
22
- expect(screen.getAllByRole('slider')).toHaveLength(3);
23
- await userEvent.click(screen.getByRole('radio', { name: 'List' }));
24
- expect(screen.getByRole('radio', { name: 'List' })).toHaveAttribute('aria-checked', 'true');
25
- });
26
- it('registers all controls and keeps agent staging separate from human apply', async () => {
27
- const registry = createControlInteractionRegistry({
28
- isLocalGesture: () => true,
29
- });
30
- render(Fixture, { props: { registry } });
31
- expect(registry.list('settings').map((item) => item.identity.controlId)).toEqual(expect.arrayContaining([
32
- 'accepted',
33
- 'notifications',
34
- 'role',
35
- 'volume',
36
- 'price',
37
- 'view',
38
- ]));
39
- await registry.execute({
40
- action: 'stage',
41
- identity: { formId: 'settings', controlId: 'volume' },
42
- value: 55,
43
- }, { source: 'agent' });
44
- expect(screen.getByRole('slider', { name: 'Volume' })).toHaveValue('30');
45
- await registry.execute({
46
- action: 'apply',
47
- identity: { formId: 'settings', controlId: 'volume' },
48
- }, { source: 'agent', confirmed: true });
49
- expect(screen.getByRole('slider', { name: 'Volume' })).toHaveValue('30');
50
- await userEvent.click(screen.getByRole('button', { name: 'Apply Volume' }));
51
- expect(screen.getByRole('slider', { name: 'Volume' })).toHaveValue('55');
52
- await registry.execute({
53
- action: 'stage',
54
- identity: { formId: 'settings', controlId: 'volume' },
55
- value: '',
56
- }, { source: 'agent' });
57
- expect(registry.get({ formId: 'settings', controlId: 'volume' })?.state.staged
58
- ?.value).toBe(0);
59
- await userEvent.click(screen.getByRole('button', { name: 'Apply Volume' }));
60
- expect(screen.getByRole('slider', { name: 'Volume' })).toHaveValue('0');
61
- expect(registry.get({ formId: 'settings', controlId: 'volume' })?.state.staged).toBeUndefined();
62
- });
63
- it('canonicalizes scalar proposals before exposing them for review', async () => {
64
- const registry = createControlInteractionRegistry({
65
- isLocalGesture: () => true,
66
- });
67
- render(Fixture, { props: { registry } });
68
- for (const controlId of ['accepted', 'notes']) {
69
- expect(await registry.execute({
70
- action: 'stage',
71
- identity: { formId: 'settings', controlId },
72
- value: { malformed: true },
73
- }, { source: 'agent' })).toMatchObject({ ok: false, reason: 'staged_value_invalid' });
74
- expect(registry.get({ formId: 'settings', controlId })?.state.staged).toBeUndefined();
75
- }
76
- await registry.execute({
77
- action: 'stage',
78
- identity: { formId: 'settings', controlId: 'volume' },
79
- value: '55',
80
- }, { source: 'agent' });
81
- expect(registry.get({ formId: 'settings', controlId: 'volume' })?.state.staged
82
- ?.value).toBe(55);
83
- await userEvent.click(screen.getByRole('button', { name: 'Apply Volume' }));
84
- expect(screen.getByRole('slider', { name: 'Volume' })).toHaveValue('55');
85
- });
86
- it('applies decimal-step slider proposals without floating-point drift', async () => {
87
- const registry = createControlInteractionRegistry({
88
- isLocalGesture: () => true,
89
- });
90
- render(DecimalSlidersFixture, { props: { registry } });
91
- const valueIdentity = { formId: 'decimal', controlId: 'value' };
92
- const rangeIdentity = { formId: 'decimal', controlId: 'range' };
93
- const tinyIdentity = { formId: 'decimal', controlId: 'tiny' };
94
- const microscopicIdentity = {
95
- formId: 'decimal',
96
- controlId: 'microscopic',
97
- };
98
- const microscopicRangeIdentity = {
99
- formId: 'decimal',
100
- controlId: 'microscopic-range',
101
- };
102
- const decimalDrift = 0.1 + 0.2;
103
- const validCases = [
104
- { next: 0.3, expected: 0.3, min: 0.1, max: 1, step: 0.2 },
105
- { next: decimalDrift, expected: 0.3, min: 0.1, max: 1, step: 0.2 },
106
- {
107
- next: 3e-16,
108
- expected: 3e-16,
109
- min: 1e-16,
110
- max: 9e-16,
111
- step: 2e-16,
112
- },
113
- {
114
- next: 3e-101,
115
- expected: 3e-101,
116
- min: 1e-101,
117
- max: 9e-101,
118
- step: 2e-101,
119
- },
120
- {
121
- next: 1.12e-101,
122
- expected: 1.12e-101,
123
- min: 1e-101,
124
- max: 1.9e-101,
125
- step: 3e-103,
126
- },
127
- {
128
- next: Number.MIN_VALUE * 3,
129
- expected: Number.MIN_VALUE * 3,
130
- min: Number.MIN_VALUE,
131
- max: Number.MIN_VALUE * 5,
132
- step: Number.MIN_VALUE,
133
- },
134
- ];
135
- for (const { next, expected, min, max, step } of validCases) {
136
- expect(validatesSteppedNumber(next, min, max, step)).toBe(true);
137
- const snapped = snapSteppedNumber(next, min, max, step);
138
- expect(snapped).toBe(expected);
139
- expect(validatesSteppedNumber(snapped, min, max, step)).toBe(true);
140
- expect(snapSteppedNumber(snapped, min, max, step)).toBe(snapped);
141
- }
142
- for (const { min, max, step } of [
143
- { min: 0.1, max: 0.9, step: 0.2 },
144
- { min: 1e-16, max: 9e-16, step: 2e-16 },
145
- { min: 1e-101, max: 1.9e-101, step: 3e-103 },
146
- {
147
- min: Number.MIN_VALUE,
148
- max: Number.MIN_VALUE * 5,
149
- step: Number.MIN_VALUE,
150
- },
151
- ]) {
152
- const lastIndex = Math.round((max - min) / step);
153
- for (let index = 0; index <= lastIndex; index += 1) {
154
- const validValue = min + index * step;
155
- expect(validatesSteppedNumber(validValue, min, max, step)).toBe(true);
156
- const canonical = snapSteppedNumber(validValue, min, max, step);
157
- expect(validatesSteppedNumber(canonical, min, max, step)).toBe(true);
158
- expect(snapSteppedNumber(canonical, min, max, step)).toBe(canonical);
159
- }
160
- }
161
- await registry.execute({ action: 'stage', identity: valueIdentity, value: decimalDrift }, { source: 'agent' });
162
- await registry.execute({ action: 'stage', identity: tinyIdentity, value: 3e-16 }, { source: 'agent' });
163
- await registry.execute({ action: 'stage', identity: microscopicIdentity, value: 1.12e-101 }, { source: 'agent' });
164
- await registry.execute({
165
- action: 'stage',
166
- identity: microscopicRangeIdentity,
167
- value: { min: 1.12e-101, max: 1.9e-101 },
168
- }, { source: 'agent' });
169
- await registry.execute({
170
- action: 'stage',
171
- identity: rangeIdentity,
172
- value: { min: decimalDrift, max: 0.5 },
173
- }, { source: 'agent' });
174
- expect(registry.get(valueIdentity)?.state.staged).toMatchObject({
175
- value: 0.3,
176
- valid: true,
177
- });
178
- expect(registry.get(rangeIdentity)?.state.staged).toMatchObject({
179
- value: { min: 0.3, max: 0.5 },
180
- valid: true,
181
- });
182
- expect(registry.get(tinyIdentity)?.state.staged).toMatchObject({
183
- value: 3e-16,
184
- valid: true,
185
- });
186
- expect(registry.get(microscopicIdentity)?.state.staged).toMatchObject({
187
- value: 1.12e-101,
188
- valid: true,
189
- });
190
- expect(registry.get(microscopicRangeIdentity)?.state.staged).toMatchObject({
191
- value: { min: 1.12e-101, max: 1.9e-101 },
192
- valid: true,
193
- });
194
- await userEvent.click(screen.getByRole('button', { name: 'Apply Value' }));
195
- await userEvent.click(screen.getByRole('button', { name: 'Apply Range' }));
196
- await userEvent.click(screen.getByRole('button', { name: 'Apply Tiny value' }));
197
- await userEvent.click(screen.getByRole('button', { name: 'Apply Microscopic value' }));
198
- await userEvent.click(screen.getByRole('button', { name: 'Apply Microscopic range' }));
199
- expect(registry.get(valueIdentity)?.state).toMatchObject({ value: 0.3 });
200
- expect(registry.get(rangeIdentity)?.state).toMatchObject({
201
- value: { min: 0.3, max: 0.5 },
202
- });
203
- expect(registry.get(tinyIdentity)?.state).toMatchObject({ value: 3e-16 });
204
- expect(registry.get(microscopicIdentity)?.state).toMatchObject({
205
- value: 1.12e-101,
206
- });
207
- expect(registry.get(microscopicRangeIdentity)?.state).toMatchObject({
208
- value: { min: 1.12e-101, max: 1.9e-101 },
209
- });
210
- expect(registry.get(valueIdentity)?.state.staged).toBeUndefined();
211
- expect(registry.get(rangeIdentity)?.state.staged).toBeUndefined();
212
- expect(registry.get(tinyIdentity)?.state.staged).toBeUndefined();
213
- expect(registry.get(microscopicIdentity)?.state.staged).toBeUndefined();
214
- expect(registry.get(microscopicRangeIdentity)?.state.staged).toBeUndefined();
215
- expect(screen.getByRole('slider', { name: 'Value' })).toHaveValue('0.3');
216
- expect(screen.getByRole('spinbutton', { name: 'Value value' })).toHaveValue(0.3);
217
- expect(screen.getByRole('slider', { name: 'Minimum' })).toHaveValue('0.3');
218
- expect(screen.getByRole('slider', { name: 'Maximum' })).toHaveValue('0.5');
219
- expect(screen.getByRole('slider', { name: 'Tiny value' })).toHaveValue('3e-16');
220
- expect(screen.getByRole('slider', { name: 'Microscopic value' })).toHaveValue('1.12e-101');
221
- expect(screen.getByRole('slider', { name: 'Microscopic minimum' })).toHaveValue('1.12e-101');
222
- expect(screen.getByRole('slider', { name: 'Microscopic maximum' })).toHaveValue('1.9e-101');
223
- });
224
- it('marks constrained proposals invalid before the first valid-only batch', async () => {
225
- const registry = createControlInteractionRegistry({
226
- isLocalGesture: () => true,
227
- });
228
- render(Fixture, { props: { registry, validInitial: true } });
229
- const invalid = new Map([
230
- ['accepted', false],
231
- ['notifications', false],
232
- ['role', 'administrator'],
233
- ['price', { min: 20, max: 83 }],
234
- ['view', 'cards'],
235
- ['notes', 'x'],
236
- ['pinned', 'yes'],
237
- ]);
238
- for (const [controlId, value] of invalid) {
239
- await registry.execute({
240
- action: 'stage',
241
- identity: { formId: 'settings', controlId },
242
- value,
243
- }, { source: 'agent' });
244
- expect(registry.get({ formId: 'settings', controlId })?.state.staged?.valid).toBe(false);
245
- }
246
- await registry.execute({
247
- action: 'stage',
248
- identity: { formId: 'settings', controlId: 'volume' },
249
- value: 12,
250
- }, { source: 'agent' });
251
- expect(registry.get({ formId: 'settings', controlId: 'volume' })?.state.staged
252
- ?.valid).toBe(false);
253
- await registry.execute({
254
- action: 'stage',
255
- identity: { formId: 'settings', controlId: 'volume' },
256
- value: 55,
257
- }, { source: 'agent' });
258
- expect(registry.get({ formId: 'settings', controlId: 'volume' })?.state.staged
259
- ?.valid).toBe(true);
260
- expect(await screen.findAllByRole('alert')).toHaveLength(invalid.size);
261
- await userEvent.click(screen.getByRole('button', { name: 'Apply valid changes' }));
262
- expect(screen.getByRole('slider', { name: 'Volume' })).toHaveValue('55');
263
- expect(registry.get({ formId: 'settings', controlId: 'volume' })?.state.staged).toBeUndefined();
264
- for (const controlId of invalid.keys()) {
265
- expect(registry.get({ formId: 'settings', controlId })?.state.staged?.valid).toBe(false);
266
- }
267
- });
268
- it('is axe-clean as a composed form', async () => {
269
- const registry = createControlInteractionRegistry();
270
- const { container } = render(Fixture, { props: { registry } });
271
- await expectNoA11yViolations(container);
272
- });
273
- it('focuses the usable control inside an error-summary target', async () => {
274
- const { container } = render(ErrorSummary, {
275
- props: {
276
- errors: [
277
- {
278
- controlId: 'profile-photo',
279
- label: 'Profile photo',
280
- message: 'Choose a file',
281
- },
282
- ],
283
- },
284
- });
285
- const wrapper = document.createElement('div');
286
- wrapper.dataset.smrtControl = 'profile-photo';
287
- wrapper.scrollIntoView = () => undefined;
288
- const hidden = document.createElement('input');
289
- hidden.type = 'hidden';
290
- const file = document.createElement('input');
291
- file.type = 'file';
292
- wrapper.append(hidden, file);
293
- container.append(wrapper);
294
- await userEvent.click(screen.getByRole('button', { name: 'Profile photo: Choose a file' }));
295
- expect(file).toHaveFocus();
296
- });
297
- });
298
- describe('progress feedback', () => {
299
- it('distinguishes determinate and indeterminate progress', async () => {
300
- const { rerender } = render(Progress, {
301
- props: { label: 'Import', value: 40, showValue: true },
302
- });
303
- expect(screen.getByRole('progressbar', { name: 'Import' })).toHaveAttribute('aria-valuenow', '40');
304
- await rerender({ label: 'Import', value: undefined });
305
- expect(screen.getByRole('progressbar', { name: 'Import' })).not.toHaveAttribute('aria-valuenow');
306
- });
307
- it('announces a spinner label', () => {
308
- render(Spinner, { props: { label: 'Saving changes' } });
309
- expect(screen.getByRole('status')).toHaveTextContent('Saving changes');
310
- });
311
- });
@@ -1,25 +0,0 @@
1
- <script lang="ts">
2
- import type { ControlInteractionRegistry } from '../control-interaction.js';
3
- import Form from '../Form.svelte';
4
- import RangeSlider from '../RangeSlider.svelte';
5
- import Slider from '../Slider.svelte';
6
-
7
- interface Props {
8
- registry: ControlInteractionRegistry;
9
- }
10
-
11
- let { registry }: Props = $props();
12
- let value = $state(0.1);
13
- let range = $state({ min: 0.1, max: 0.5 });
14
- let tinyValue = $state(1e-16);
15
- let microscopicValue = $state(1e-101);
16
- let microscopicRange = $state({ min: 1e-101, max: 1.9e-101 });
17
- </script>
18
-
19
- <Form formId="decimal" interactionRegistry={registry} aria-label="Decimal controls">
20
- <Slider name="value" label="Value" min={0.1} max={1} step={0.2} bind:value />
21
- <RangeSlider name="range" label="Range" min={0.1} max={1} step={0.2} bind:value={range} />
22
- <Slider name="tiny" label="Tiny value" min={1e-16} max={9e-16} step={2e-16} bind:value={tinyValue} />
23
- <Slider name="microscopic" label="Microscopic value" min={1e-101} max={1.9e-101} step={3e-103} bind:value={microscopicValue} />
24
- <RangeSlider name="microscopic-range" label="Microscopic range" minLabel="Microscopic minimum" maxLabel="Microscopic maximum" min={1e-101} max={1.9e-101} step={3e-103} bind:value={microscopicRange} />
25
- </Form>
@@ -1,8 +0,0 @@
1
- import type { ControlInteractionRegistry } from '../control-interaction.js';
2
- interface Props {
3
- registry: ControlInteractionRegistry;
4
- }
5
- declare const DecimalSliders: import("svelte").Component<Props, {}, "">;
6
- type DecimalSliders = ReturnType<typeof DecimalSliders>;
7
- export default DecimalSliders;
8
- //# sourceMappingURL=decimal-sliders.fixture.svelte.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"decimal-sliders.fixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/__tests__/decimal-sliders.fixture.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAM5E,UAAU,KAAK;IACb,QAAQ,EAAE,0BAA0B,CAAC;CACtC;AA0BD,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}