@happyvertical/smrt-ui 0.53.1 → 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.
- package/package.json +3 -3
- package/dist/actions/__tests__/ripple.test.js +0 -82
- package/dist/actions/__tests__/swipe-dismiss.test.js +0 -69
- package/dist/components/calendar/__tests__/CalendarView.test.js +0 -226
- package/dist/components/calendar/__tests__/calendar-model.test.js +0 -138
- package/dist/components/chat/__tests__/chat-primitives.test.js +0 -118
- package/dist/components/data/__tests__/CollectionList.test.js +0 -37
- package/dist/components/data/__tests__/DataTable.test.js +0 -807
- package/dist/components/data/__tests__/DataTableConformance.test.js +0 -212
- package/dist/components/data/__tests__/DataTableController.test.js +0 -371
- package/dist/components/data/__tests__/DataTableIdentity.test.js +0 -29
- package/dist/components/data/__tests__/DataTableLayout.test.js +0 -195
- package/dist/components/data/__tests__/DataTablePerformance.test.js +0 -21
- package/dist/components/data/__tests__/DataTableResponsive.test.js +0 -80
- package/dist/components/data/__tests__/DataTableVirtualization.test.js +0 -80
- package/dist/components/data/__tests__/DataTableVirtualizationComponent.test.js +0 -255
- package/dist/components/data/__tests__/SortableHeader.test.js +0 -101
- package/dist/components/data/__tests__/data-surface.test.js +0 -746
- package/dist/components/data/__tests__/data-table-helpers.test.js +0 -36
- package/dist/components/data/__tests__/data-table-surface.test.js +0 -49
- package/dist/components/data/__tests__/link-step-surface.test.js +0 -172
- package/dist/components/data/__tests__/list-sort-state.svelte.test.js +0 -71
- package/dist/components/data/__tests__/list-sort.test.js +0 -91
- package/dist/components/data/__tests__/mounted-data-surface.test.js +0 -794
- package/dist/components/data/__tests__/responsive-table.fixture.svelte +0 -29
- package/dist/components/data/__tests__/responsive-table.fixture.svelte.d.ts +0 -7
- package/dist/components/data/__tests__/responsive-table.fixture.svelte.d.ts.map +0 -1
- package/dist/components/data/__tests__/surface-navigation.test.js +0 -121
- package/dist/components/display/__tests__/ConfidenceBadge.test.js +0 -109
- package/dist/components/display/__tests__/CurrencyDisplay.test.js +0 -304
- package/dist/components/display/__tests__/CurrencyDisplayI18nHarness.svelte +0 -20
- package/dist/components/display/__tests__/CurrencyDisplayI18nHarness.svelte.d.ts +0 -19
- package/dist/components/display/__tests__/CurrencyDisplayI18nHarness.svelte.d.ts.map +0 -1
- package/dist/components/display/__tests__/CurrencyDisplaySsrHarness.svelte +0 -7
- package/dist/components/display/__tests__/CurrencyDisplaySsrHarness.svelte.d.ts +0 -19
- package/dist/components/display/__tests__/CurrencyDisplaySsrHarness.svelte.d.ts.map +0 -1
- package/dist/components/display/__tests__/DateDisplay.test.js +0 -195
- package/dist/components/display/__tests__/Icon.test.js +0 -223
- package/dist/components/display/__tests__/StatusBadge.test.js +0 -191
- package/dist/components/feedback/__tests__/ConfirmDialog.test.js +0 -181
- package/dist/components/feedback/__tests__/LoadingOverlay.test.js +0 -113
- package/dist/components/feedback/__tests__/Modal.test.js +0 -72
- package/dist/components/feedback/__tests__/PhoneSheet.test.js +0 -101
- package/dist/components/feedback/__tests__/ProgressBar.test.js +0 -89
- package/dist/components/feedback/__tests__/WorkingStrip.test.js +0 -172
- package/dist/components/feedback/__tests__/confirm-message.fixture.svelte +0 -9
- package/dist/components/feedback/__tests__/confirm-message.fixture.svelte.d.ts +0 -19
- package/dist/components/feedback/__tests__/confirm-message.fixture.svelte.d.ts.map +0 -1
- package/dist/components/feedback/__tests__/toast.test.js +0 -190
- package/dist/components/forms/__tests__/CameraCapture.test.js +0 -504
- package/dist/components/forms/__tests__/Combobox.test.js +0 -354
- package/dist/components/forms/__tests__/ControlHitArea.test.js +0 -73
- package/dist/components/forms/__tests__/DictationButton.test.js +0 -176
- package/dist/components/forms/__tests__/Fieldset.test.js +0 -37
- package/dist/components/forms/__tests__/Form.test.js +0 -201
- package/dist/components/forms/__tests__/FormActionBar.test.js +0 -22
- package/dist/components/forms/__tests__/FormGroup.test.js +0 -48
- package/dist/components/forms/__tests__/Input.test.js +0 -49
- package/dist/components/forms/__tests__/Listbox.test.js +0 -303
- package/dist/components/forms/__tests__/MultiSelect.test.js +0 -281
- package/dist/components/forms/__tests__/SearchInput.test.js +0 -92
- package/dist/components/forms/__tests__/Select.test.js +0 -37
- package/dist/components/forms/__tests__/SignaturePad.test.js +0 -338
- package/dist/components/forms/__tests__/StagedControlReview.test.js +0 -702
- package/dist/components/forms/__tests__/Textarea.test.js +0 -39
- package/dist/components/forms/__tests__/Toggle.test.js +0 -87
- package/dist/components/forms/__tests__/camera-capture-session.test.js +0 -207
- package/dist/components/forms/__tests__/capture-form-retry.test.js +0 -166
- package/dist/components/forms/__tests__/capture-form.fixture.svelte +0 -38
- package/dist/components/forms/__tests__/capture-form.fixture.svelte.d.ts +0 -10
- package/dist/components/forms/__tests__/capture-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/capture-test-env.d.ts +0 -70
- package/dist/components/forms/__tests__/capture-test-env.d.ts.map +0 -1
- package/dist/components/forms/__tests__/capture-test-env.js +0 -122
- package/dist/components/forms/__tests__/capture-touch.fixture.svelte +0 -15
- package/dist/components/forms/__tests__/capture-touch.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/capture-touch.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/combobox-form.fixture.svelte +0 -29
- package/dist/components/forms/__tests__/combobox-form.fixture.svelte.d.ts +0 -14
- package/dist/components/forms/__tests__/combobox-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/combobox-labels.fixture.svelte +0 -19
- package/dist/components/forms/__tests__/combobox-labels.fixture.svelte.d.ts +0 -11
- package/dist/components/forms/__tests__/combobox-labels.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/composite-controls.fixture.svelte +0 -47
- package/dist/components/forms/__tests__/composite-controls.fixture.svelte.d.ts +0 -12
- package/dist/components/forms/__tests__/composite-controls.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/composite-controls.test.js +0 -128
- package/dist/components/forms/__tests__/composite-registration.fixture.svelte +0 -29
- package/dist/components/forms/__tests__/composite-registration.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/composite-registration.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/composite-user-edit.fixture.svelte +0 -41
- package/dist/components/forms/__tests__/composite-user-edit.fixture.svelte.d.ts +0 -13
- package/dist/components/forms/__tests__/composite-user-edit.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/control-interaction.test.js +0 -3421
- package/dist/components/forms/__tests__/control-proposals.test.js +0 -63
- package/dist/components/forms/__tests__/core-controls.fixture.svelte +0 -50
- package/dist/components/forms/__tests__/core-controls.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/core-controls.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/core-controls.test.js +0 -311
- package/dist/components/forms/__tests__/decimal-sliders.fixture.svelte +0 -25
- package/dist/components/forms/__tests__/decimal-sliders.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/decimal-sliders.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/dictation-recording.test.js +0 -582
- package/dist/components/forms/__tests__/dictation.test.js +0 -486
- package/dist/components/forms/__tests__/form-attachment.fixture.svelte +0 -28
- package/dist/components/forms/__tests__/form-attachment.fixture.svelte.d.ts +0 -11
- package/dist/components/forms/__tests__/form-attachment.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-group-input.fixture.svelte +0 -16
- package/dist/components/forms/__tests__/form-group-input.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/form-group-input.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-retry-form.fixture.svelte +0 -31
- package/dist/components/forms/__tests__/form-retry-form.fixture.svelte.d.ts +0 -13
- package/dist/components/forms/__tests__/form-retry-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-retry-form.test.js +0 -107
- package/dist/components/forms/__tests__/hidden-controls-form-retry.test.js +0 -69
- package/dist/components/forms/__tests__/hidden-controls-form.fixture.svelte +0 -29
- package/dist/components/forms/__tests__/hidden-controls-form.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/hidden-controls-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/listbox-form.fixture.svelte +0 -27
- package/dist/components/forms/__tests__/listbox-form.fixture.svelte.d.ts +0 -13
- package/dist/components/forms/__tests__/listbox-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/long-press.test.js +0 -175
- package/dist/components/forms/__tests__/multiselect-form.fixture.svelte +0 -27
- package/dist/components/forms/__tests__/multiselect-form.fixture.svelte.d.ts +0 -13
- package/dist/components/forms/__tests__/multiselect-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/native-file-field.test.js +0 -177
- package/dist/components/forms/__tests__/place-picker.fixture.svelte +0 -33
- package/dist/components/forms/__tests__/place-picker.fixture.svelte.d.ts +0 -12
- package/dist/components/forms/__tests__/place-picker.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/segmented-posting.fixture.svelte +0 -28
- package/dist/components/forms/__tests__/segmented-posting.fixture.svelte.d.ts +0 -12
- package/dist/components/forms/__tests__/segmented-posting.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/segmented-posting.test.js +0 -92
- package/dist/components/forms/__tests__/select-interaction.fixture.svelte +0 -25
- package/dist/components/forms/__tests__/select-interaction.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/select-interaction.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/signature-pad-logic.test.js +0 -54
- package/dist/components/forms/__tests__/staged-review-fieldset.fixture.svelte +0 -21
- package/dist/components/forms/__tests__/staged-review-fieldset.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/staged-review-fieldset.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/staged-review-outer-fieldset.fixture.svelte +0 -23
- package/dist/components/forms/__tests__/staged-review-outer-fieldset.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/staged-review-outer-fieldset.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/staged-review.fixture.svelte +0 -56
- package/dist/components/forms/__tests__/staged-review.fixture.svelte.d.ts +0 -12
- package/dist/components/forms/__tests__/staged-review.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/touch-density.fixture.svelte +0 -34
- package/dist/components/forms/__tests__/touch-density.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/touch-density.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/touch-density.test.js +0 -66
- package/dist/components/forms/form-retry/__tests__/boundaries.test.js +0 -23
- package/dist/components/forms/form-retry/__tests__/content-digest.test.js +0 -70
- package/dist/components/forms/form-retry/__tests__/controller.test.js +0 -802
- package/dist/components/forms/form-retry/__tests__/fake-kit.d.ts +0 -82
- package/dist/components/forms/form-retry/__tests__/fake-kit.d.ts.map +0 -1
- package/dist/components/forms/form-retry/__tests__/fake-kit.js +0 -180
- package/dist/components/forms/form-retry/__tests__/form-draft.test.js +0 -169
- package/dist/components/forms/form-retry/__tests__/ssr.test.js +0 -37
- package/dist/components/forms/form-retry/__tests__/storage.d.ts +0 -26
- package/dist/components/forms/form-retry/__tests__/storage.d.ts.map +0 -1
- package/dist/components/forms/form-retry/__tests__/storage.js +0 -63
- package/dist/components/forms/form-retry/__tests__/submission-key.test.js +0 -236
- package/dist/components/forms/form-retry/__tests__/submitted-draft.test.js +0 -334
- package/dist/components/layout/__tests__/Container.test.js +0 -62
- package/dist/components/layout/__tests__/EmptyState.test.js +0 -83
- package/dist/components/layout/__tests__/Footer.test.js +0 -50
- package/dist/components/layout/__tests__/Grid.test.js +0 -121
- package/dist/components/layout/__tests__/Header.test.js +0 -48
- package/dist/components/layout/__tests__/Masthead.test.js +0 -93
- package/dist/components/layout/__tests__/PageHeader.test.js +0 -166
- package/dist/components/layout/__tests__/SummaryCard.test.js +0 -104
- package/dist/components/nav/__tests__/FilterChips.test.js +0 -94
- package/dist/components/nav/__tests__/LinkTabs.test.js +0 -117
- package/dist/components/nav/__tests__/Tabs.test.js +0 -128
- package/dist/components/roles/__tests__/RoleSelector.test.js +0 -134
- package/dist/components/ui/__tests__/Badge.test.js +0 -76
- package/dist/components/ui/__tests__/Button.test.js +0 -166
- package/dist/components/ui/__tests__/Card.test.js +0 -103
- package/dist/components/ui/__tests__/IconToggle.test.js +0 -59
- package/dist/components/ui/__tests__/IconToggleGroup.test.js +0 -30
- package/dist/components/ui/__tests__/Pagination.test.js +0 -113
- package/dist/components/ui/__tests__/Popover.test.js +0 -44
- package/dist/components/ui/__tests__/dropdown-popover-icon.test.js +0 -125
- package/dist/components/ui/__tests__/gap-primitives-interactive.test.js +0 -112
- package/dist/components/ui/__tests__/gap-primitives.test.js +0 -84
- package/dist/components/ui/__tests__/interaction-primitives.fixture.svelte +0 -13
- package/dist/components/ui/__tests__/interaction-primitives.fixture.svelte.d.ts +0 -19
- package/dist/components/ui/__tests__/interaction-primitives.fixture.svelte.d.ts.map +0 -1
- package/dist/components/ui/__tests__/interaction-primitives.test.js +0 -31
- package/dist/components/ui/__tests__/phone-touch-targets.test.js +0 -39
- package/dist/i18n/__tests__/i18n.test.js +0 -74
- package/dist/i18n/__tests__/render-parity.spec.js +0 -37
- package/dist/svelte/__tests__/playground.test.js +0 -20
- package/dist/themes/__tests__/control-boundary-contrast.test.js +0 -112
- package/dist/themes/__tests__/create-theme.test.js +0 -79
- package/dist/themes/__tests__/css-generator.test.js +0 -129
- package/dist/themes/__tests__/happyvertical-theme.test.js +0 -231
- package/dist/themes/__tests__/registry.test.js +0 -43
- package/dist/themes/__tests__/styles-lockstep.test.js +0 -32
- package/dist/themes/__tests__/theme-provider.test.js +0 -147
- package/dist/themes/__tests__/theme-script.test.js +0 -130
- package/dist/themes/__tests__/token-aliases.test.js +0 -178
- package/dist/utils/forms/__tests__/formatters.test.js +0 -27
- package/dist/utils/theme/__tests__/color.test.js +0 -89
- package/dist/utils/theme/__tests__/typography.test.js +0 -11
|
@@ -1,486 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dictation state machine over a fake speech source (no real microphone:
|
|
3
|
-
* speech recognition cannot run headless). Covers start → listening (with the
|
|
4
|
-
* ready beep) → final text → stop, errors in plain kinds, and "stopped
|
|
5
|
-
* before the microphone opened".
|
|
6
|
-
*/
|
|
7
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
8
|
-
import { classifyDictationError, Dictation, dictationErrorCode, } from '../dictation.svelte.js';
|
|
9
|
-
import { insertTextAtCursor } from '../insert-text.js';
|
|
10
|
-
import { createLongPress } from '../long-press.js';
|
|
11
|
-
function fakeSource(options = {}) {
|
|
12
|
-
const results = new Set();
|
|
13
|
-
const errors = new Set();
|
|
14
|
-
const ends = new Set();
|
|
15
|
-
const starts = new Set();
|
|
16
|
-
const source = {
|
|
17
|
-
start: vi.fn(async () => {
|
|
18
|
-
if (options.startError)
|
|
19
|
-
throw options.startError;
|
|
20
|
-
}),
|
|
21
|
-
stop: vi.fn(async () => {
|
|
22
|
-
for (const cb of ends)
|
|
23
|
-
cb();
|
|
24
|
-
}),
|
|
25
|
-
onResult: (cb) => (results.add(cb), () => results.delete(cb)),
|
|
26
|
-
onError: (cb) => (errors.add(cb), () => errors.delete(cb)),
|
|
27
|
-
onEnd: (cb) => (ends.add(cb), () => ends.delete(cb)),
|
|
28
|
-
...(options.emitStart
|
|
29
|
-
? {
|
|
30
|
-
onStart: (cb) => (starts.add(cb), () => starts.delete(cb)),
|
|
31
|
-
}
|
|
32
|
-
: {}),
|
|
33
|
-
emitResult: (text, isFinal) => {
|
|
34
|
-
for (const cb of results)
|
|
35
|
-
cb({ text, isFinal });
|
|
36
|
-
},
|
|
37
|
-
emitError: (error) => {
|
|
38
|
-
for (const cb of errors)
|
|
39
|
-
cb(error);
|
|
40
|
-
},
|
|
41
|
-
emitEnd: () => {
|
|
42
|
-
for (const cb of ends)
|
|
43
|
-
cb();
|
|
44
|
-
},
|
|
45
|
-
emitStart: () => {
|
|
46
|
-
for (const cb of starts)
|
|
47
|
-
cb();
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
return source;
|
|
51
|
-
}
|
|
52
|
-
describe('Dictation', () => {
|
|
53
|
-
it('listens, beeps once ready, hands over final phrases, and stops', async () => {
|
|
54
|
-
const source = fakeSource();
|
|
55
|
-
const beep = vi.fn(async () => true);
|
|
56
|
-
const onText = vi.fn();
|
|
57
|
-
const dictation = new Dictation({
|
|
58
|
-
source: () => source,
|
|
59
|
-
onText,
|
|
60
|
-
beep,
|
|
61
|
-
language: 'en-CA',
|
|
62
|
-
});
|
|
63
|
-
expect(dictation.state).toBe('idle');
|
|
64
|
-
const started = dictation.start();
|
|
65
|
-
expect(dictation.state).toBe('starting');
|
|
66
|
-
await started;
|
|
67
|
-
expect(dictation.state).toBe('listening');
|
|
68
|
-
expect(source.start).toHaveBeenCalledWith({
|
|
69
|
-
language: 'en-CA',
|
|
70
|
-
continuous: true,
|
|
71
|
-
interimResults: true,
|
|
72
|
-
});
|
|
73
|
-
await vi.waitFor(() => expect(beep).toHaveBeenCalledTimes(1));
|
|
74
|
-
source.emitResult('make it', false);
|
|
75
|
-
expect(dictation.interim).toBe('make it');
|
|
76
|
-
source.emitResult('make it brighter ', true);
|
|
77
|
-
expect(onText).toHaveBeenCalledWith('make it brighter');
|
|
78
|
-
expect(dictation.interim).toBe('');
|
|
79
|
-
await dictation.stop();
|
|
80
|
-
expect(source.stop).toHaveBeenCalled();
|
|
81
|
-
expect(dictation.state).toBe('idle');
|
|
82
|
-
});
|
|
83
|
-
it('waits for the source to say it is listening before beeping', async () => {
|
|
84
|
-
const source = fakeSource({ emitStart: true });
|
|
85
|
-
const beep = vi.fn(async () => true);
|
|
86
|
-
const dictation = new Dictation({
|
|
87
|
-
source: () => source,
|
|
88
|
-
onText: () => { },
|
|
89
|
-
beep,
|
|
90
|
-
});
|
|
91
|
-
await dictation.start();
|
|
92
|
-
expect(dictation.state).toBe('starting');
|
|
93
|
-
expect(beep).not.toHaveBeenCalled();
|
|
94
|
-
source.emitStart();
|
|
95
|
-
expect(dictation.state).toBe('listening');
|
|
96
|
-
await vi.waitFor(() => expect(beep).toHaveBeenCalled());
|
|
97
|
-
});
|
|
98
|
-
it('closes the microphone if it opens after the person already stopped', async () => {
|
|
99
|
-
const source = fakeSource({ emitStart: true });
|
|
100
|
-
const dictation = new Dictation({
|
|
101
|
-
source: () => source,
|
|
102
|
-
onText: () => { },
|
|
103
|
-
beep: false,
|
|
104
|
-
stopTimeoutMs: 10,
|
|
105
|
-
});
|
|
106
|
-
await dictation.start();
|
|
107
|
-
await dictation.stop();
|
|
108
|
-
source.stop.mockClear();
|
|
109
|
-
source.emitStart();
|
|
110
|
-
expect(source.stop).toHaveBeenCalledTimes(1);
|
|
111
|
-
expect(dictation.state).not.toBe('listening');
|
|
112
|
-
});
|
|
113
|
-
it('toggle starts and stops', async () => {
|
|
114
|
-
const source = fakeSource();
|
|
115
|
-
const dictation = new Dictation({
|
|
116
|
-
source: () => source,
|
|
117
|
-
onText: () => { },
|
|
118
|
-
beep: false,
|
|
119
|
-
});
|
|
120
|
-
await dictation.toggle();
|
|
121
|
-
expect(dictation.state).toBe('listening');
|
|
122
|
-
await dictation.toggle();
|
|
123
|
-
expect(dictation.state).toBe('idle');
|
|
124
|
-
});
|
|
125
|
-
it('reports unsupported without a source, or when the source cannot load', async () => {
|
|
126
|
-
const none = new Dictation({ source: null, onText: () => { } });
|
|
127
|
-
await none.start();
|
|
128
|
-
expect(none.state).toBe('error');
|
|
129
|
-
expect(none.errorKind).toBe('unsupported');
|
|
130
|
-
const missing = Object.assign(new Error('Required capability not available: Web Speech API'), {
|
|
131
|
-
name: 'CapabilityNotAvailableError',
|
|
132
|
-
code: 'CAPABILITY_NOT_AVAILABLE',
|
|
133
|
-
});
|
|
134
|
-
const broken = new Dictation({
|
|
135
|
-
source: () => {
|
|
136
|
-
throw missing;
|
|
137
|
-
},
|
|
138
|
-
onText: () => { },
|
|
139
|
-
});
|
|
140
|
-
await broken.start();
|
|
141
|
-
expect(broken.errorKind).toBe('unsupported');
|
|
142
|
-
});
|
|
143
|
-
it('reports a blocked microphone as denied, from start or later', async () => {
|
|
144
|
-
const denied = Object.assign(new Error('Permission denied: microphone'), {
|
|
145
|
-
name: 'PermissionDeniedError',
|
|
146
|
-
code: 'PERMISSION_DENIED',
|
|
147
|
-
});
|
|
148
|
-
const atStart = new Dictation({
|
|
149
|
-
source: () => fakeSource({ startError: denied }),
|
|
150
|
-
onText: () => { },
|
|
151
|
-
});
|
|
152
|
-
await atStart.start();
|
|
153
|
-
expect(atStart.errorKind).toBe('denied');
|
|
154
|
-
const source = fakeSource();
|
|
155
|
-
const later = new Dictation({
|
|
156
|
-
source: () => source,
|
|
157
|
-
onText: () => { },
|
|
158
|
-
beep: false,
|
|
159
|
-
});
|
|
160
|
-
await later.start();
|
|
161
|
-
source.emitError(denied);
|
|
162
|
-
source.emitEnd();
|
|
163
|
-
expect(later.state).toBe('error');
|
|
164
|
-
expect(later.errorKind).toBe('denied');
|
|
165
|
-
later.clearError();
|
|
166
|
-
expect(later.state).toBe('idle');
|
|
167
|
-
});
|
|
168
|
-
it('keeps the beep for a later gesture when audio is not allowed yet', async () => {
|
|
169
|
-
const source = fakeSource();
|
|
170
|
-
const beep = vi
|
|
171
|
-
.fn()
|
|
172
|
-
.mockResolvedValueOnce(false)
|
|
173
|
-
.mockResolvedValueOnce(true);
|
|
174
|
-
const dictation = new Dictation({
|
|
175
|
-
source: () => source,
|
|
176
|
-
onText: () => { },
|
|
177
|
-
beep,
|
|
178
|
-
});
|
|
179
|
-
await dictation.start();
|
|
180
|
-
await vi.waitFor(() => expect(dictation.beepPending).toBe(true));
|
|
181
|
-
await dictation.unlock();
|
|
182
|
-
expect(beep).toHaveBeenCalledTimes(2);
|
|
183
|
-
expect(dictation.beepPending).toBe(false);
|
|
184
|
-
});
|
|
185
|
-
it('ignores results after dispose', async () => {
|
|
186
|
-
const source = fakeSource();
|
|
187
|
-
const onText = vi.fn();
|
|
188
|
-
const dictation = new Dictation({
|
|
189
|
-
source: () => source,
|
|
190
|
-
onText,
|
|
191
|
-
beep: false,
|
|
192
|
-
});
|
|
193
|
-
await dictation.start();
|
|
194
|
-
dictation.dispose();
|
|
195
|
-
source.emitResult('late words', true);
|
|
196
|
-
expect(onText).not.toHaveBeenCalled();
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
describe('classifyDictationError', () => {
|
|
200
|
-
it('sorts errors into plain kinds', () => {
|
|
201
|
-
expect(classifyDictationError(new Error('No speech detected'))).toBe('no-speech');
|
|
202
|
-
expect(classifyDictationError({ name: 'NotAllowedError' })).toBe('denied');
|
|
203
|
-
expect(classifyDictationError(new Error('Speech recognition error: network'))).toBe('unsupported');
|
|
204
|
-
});
|
|
205
|
-
it('reads the Web Speech code first', () => {
|
|
206
|
-
const coded = (code, message = 'x') => Object.assign(new Error(message), { speechError: code });
|
|
207
|
-
expect(classifyDictationError(coded('network'))).toBe('unsupported');
|
|
208
|
-
// Brave: the browser has no speech service, not a blocked microphone.
|
|
209
|
-
expect(classifyDictationError(Object.assign(coded('service-not-allowed', 'Permission denied'), {
|
|
210
|
-
code: 'PERMISSION_DENIED',
|
|
211
|
-
}))).toBe('unsupported');
|
|
212
|
-
expect(classifyDictationError(coded('not-allowed'))).toBe('denied');
|
|
213
|
-
expect(classifyDictationError(coded('no-speech'))).toBe('no-speech');
|
|
214
|
-
expect(classifyDictationError(coded('audio-capture'))).toBe('microphone');
|
|
215
|
-
expect(classifyDictationError(coded('aborted'))).toBe('interrupted');
|
|
216
|
-
// A raw SpeechRecognitionErrorEvent.
|
|
217
|
-
expect(classifyDictationError({ error: 'network' })).toBe('unsupported');
|
|
218
|
-
expect(dictationErrorCode(coded('network'))).toBe('network');
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
describe('Dictation errors are never silent', () => {
|
|
222
|
-
const codes = [
|
|
223
|
-
['network', 'unsupported'],
|
|
224
|
-
['service-not-allowed', 'unsupported'],
|
|
225
|
-
['not-allowed', 'denied'],
|
|
226
|
-
['no-speech', 'no-speech'],
|
|
227
|
-
['audio-capture', 'microphone'],
|
|
228
|
-
['aborted', 'interrupted'],
|
|
229
|
-
];
|
|
230
|
-
it.each(codes)('%s after the beep becomes %s, with the code, and is logged', async (code, kind) => {
|
|
231
|
-
const source = fakeSource({ emitStart: true });
|
|
232
|
-
const log = vi.fn();
|
|
233
|
-
const dictation = new Dictation({
|
|
234
|
-
source: () => source,
|
|
235
|
-
onText: () => { },
|
|
236
|
-
beep: false,
|
|
237
|
-
log,
|
|
238
|
-
});
|
|
239
|
-
await dictation.start();
|
|
240
|
-
source.emitStart();
|
|
241
|
-
expect(dictation.state).toBe('listening');
|
|
242
|
-
// What Chrome and Brave do: the error, then the end.
|
|
243
|
-
source.emitError(Object.assign(new Error(`Speech recognition error: ${code}`), {
|
|
244
|
-
speechError: code,
|
|
245
|
-
}));
|
|
246
|
-
source.emitEnd();
|
|
247
|
-
expect(dictation.state).toBe('error');
|
|
248
|
-
expect(dictation.errorKind).toBe(kind);
|
|
249
|
-
expect(dictation.errorCode).toBe(code);
|
|
250
|
-
expect(log).toHaveBeenCalledTimes(1);
|
|
251
|
-
expect(log.mock.calls[0][0]).toMatchObject({ kind, code, stage: 'error' });
|
|
252
|
-
});
|
|
253
|
-
it('logs to the console by default', async () => {
|
|
254
|
-
const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
255
|
-
const source = fakeSource();
|
|
256
|
-
const dictation = new Dictation({
|
|
257
|
-
source: () => source,
|
|
258
|
-
onText: () => { },
|
|
259
|
-
beep: false,
|
|
260
|
-
});
|
|
261
|
-
await dictation.start();
|
|
262
|
-
source.emitError(Object.assign(new Error('Network error'), { speechError: 'network' }));
|
|
263
|
-
expect(warn).toHaveBeenCalledWith(expect.stringContaining('[network]'));
|
|
264
|
-
warn.mockRestore();
|
|
265
|
-
});
|
|
266
|
-
it('an end right after the beep, with nothing heard and no stop, is a failure', async () => {
|
|
267
|
-
const source = fakeSource({ emitStart: true });
|
|
268
|
-
const dictation = new Dictation({
|
|
269
|
-
source: () => source,
|
|
270
|
-
onText: () => { },
|
|
271
|
-
beep: false,
|
|
272
|
-
log: () => { },
|
|
273
|
-
});
|
|
274
|
-
await dictation.start();
|
|
275
|
-
source.emitStart();
|
|
276
|
-
source.emitEnd();
|
|
277
|
-
expect(dictation.state).toBe('error');
|
|
278
|
-
expect(dictation.errorKind).toBe('interrupted');
|
|
279
|
-
});
|
|
280
|
-
it('an end before it ever listened is a failure', async () => {
|
|
281
|
-
const source = fakeSource({ emitStart: true });
|
|
282
|
-
const dictation = new Dictation({
|
|
283
|
-
source: () => source,
|
|
284
|
-
onText: () => { },
|
|
285
|
-
beep: false,
|
|
286
|
-
log: () => { },
|
|
287
|
-
});
|
|
288
|
-
await dictation.start();
|
|
289
|
-
expect(dictation.state).toBe('starting');
|
|
290
|
-
source.emitEnd();
|
|
291
|
-
expect(dictation.state).toBe('error');
|
|
292
|
-
expect(dictation.errorKind).toBe('interrupted');
|
|
293
|
-
});
|
|
294
|
-
it('a pause after talking, or a late end, just stops', async () => {
|
|
295
|
-
vi.useFakeTimers();
|
|
296
|
-
try {
|
|
297
|
-
const source = fakeSource({ emitStart: true });
|
|
298
|
-
const dictation = new Dictation({
|
|
299
|
-
source: () => source,
|
|
300
|
-
onText: () => { },
|
|
301
|
-
beep: false,
|
|
302
|
-
log: () => { },
|
|
303
|
-
});
|
|
304
|
-
await dictation.start();
|
|
305
|
-
source.emitStart();
|
|
306
|
-
source.emitResult('make it square', true);
|
|
307
|
-
source.emitEnd();
|
|
308
|
-
expect(dictation.state).toBe('idle');
|
|
309
|
-
await dictation.start();
|
|
310
|
-
source.emitStart();
|
|
311
|
-
vi.advanceTimersByTime(1500);
|
|
312
|
-
source.emitEnd();
|
|
313
|
-
expect(dictation.state).toBe('idle');
|
|
314
|
-
}
|
|
315
|
-
finally {
|
|
316
|
-
vi.useRealTimers();
|
|
317
|
-
}
|
|
318
|
-
});
|
|
319
|
-
it('being cut off after the person stopped is just the stop', async () => {
|
|
320
|
-
const source = fakeSource({ emitStart: true });
|
|
321
|
-
source.stop.mockImplementation(async () => { });
|
|
322
|
-
const log = vi.fn();
|
|
323
|
-
const dictation = new Dictation({
|
|
324
|
-
source: () => source,
|
|
325
|
-
onText: () => { },
|
|
326
|
-
beep: false,
|
|
327
|
-
log,
|
|
328
|
-
});
|
|
329
|
-
await dictation.start();
|
|
330
|
-
source.emitStart();
|
|
331
|
-
await dictation.stop();
|
|
332
|
-
source.emitError(Object.assign(new Error('aborted'), { speechError: 'aborted' }));
|
|
333
|
-
source.emitEnd();
|
|
334
|
-
expect(dictation.state).toBe('idle');
|
|
335
|
-
expect(log).not.toHaveBeenCalled();
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
describe('Dictation asks for the microphone first', () => {
|
|
339
|
-
const original = Object.getOwnPropertyDescriptor(navigator, 'mediaDevices');
|
|
340
|
-
afterEach(() => {
|
|
341
|
-
if (original)
|
|
342
|
-
Object.defineProperty(navigator, 'mediaDevices', original);
|
|
343
|
-
else
|
|
344
|
-
delete navigator.mediaDevices;
|
|
345
|
-
});
|
|
346
|
-
function stubMedia(getUserMedia) {
|
|
347
|
-
Object.defineProperty(navigator, 'mediaDevices', {
|
|
348
|
-
configurable: true,
|
|
349
|
-
value: { getUserMedia: vi.fn(getUserMedia) },
|
|
350
|
-
});
|
|
351
|
-
return navigator.mediaDevices;
|
|
352
|
-
}
|
|
353
|
-
it('waits for the grant, closes the probe stream, then starts; only once', async () => {
|
|
354
|
-
const track = { stop: vi.fn() };
|
|
355
|
-
let grant;
|
|
356
|
-
const media = stubMedia(() => new Promise((resolve) => {
|
|
357
|
-
grant = () => resolve({ getTracks: () => [track] });
|
|
358
|
-
}));
|
|
359
|
-
const source = fakeSource();
|
|
360
|
-
const dictation = new Dictation({
|
|
361
|
-
source: () => source,
|
|
362
|
-
onText: () => { },
|
|
363
|
-
beep: false,
|
|
364
|
-
});
|
|
365
|
-
const started = dictation.start();
|
|
366
|
-
await vi.waitFor(() => expect(media.getUserMedia).toHaveBeenCalled());
|
|
367
|
-
expect(media.getUserMedia).toHaveBeenCalledWith({ audio: true });
|
|
368
|
-
expect(dictation.state).toBe('starting');
|
|
369
|
-
expect(source.start).not.toHaveBeenCalled();
|
|
370
|
-
grant();
|
|
371
|
-
await started;
|
|
372
|
-
expect(track.stop).toHaveBeenCalled();
|
|
373
|
-
expect(source.start).toHaveBeenCalledTimes(1);
|
|
374
|
-
expect(dictation.state).toBe('listening');
|
|
375
|
-
await dictation.stop();
|
|
376
|
-
await dictation.start();
|
|
377
|
-
expect(media.getUserMedia).toHaveBeenCalledTimes(1);
|
|
378
|
-
});
|
|
379
|
-
it('a refused prompt is "blocked", a missing microphone says so, and recognition never starts', async () => {
|
|
380
|
-
stubMedia(async () => {
|
|
381
|
-
throw new DOMException('Permission denied', 'NotAllowedError');
|
|
382
|
-
});
|
|
383
|
-
const source = fakeSource();
|
|
384
|
-
const denied = new Dictation({
|
|
385
|
-
source: () => source,
|
|
386
|
-
onText: () => { },
|
|
387
|
-
log: () => { },
|
|
388
|
-
});
|
|
389
|
-
await denied.start();
|
|
390
|
-
expect(denied.errorKind).toBe('denied');
|
|
391
|
-
expect(denied.errorCode).toBe('NotAllowedError');
|
|
392
|
-
expect(source.start).not.toHaveBeenCalled();
|
|
393
|
-
stubMedia(async () => {
|
|
394
|
-
throw new DOMException('Requested device not found', 'NotFoundError');
|
|
395
|
-
});
|
|
396
|
-
const none = new Dictation({
|
|
397
|
-
source: () => fakeSource(),
|
|
398
|
-
onText: () => { },
|
|
399
|
-
log: () => { },
|
|
400
|
-
});
|
|
401
|
-
await none.start();
|
|
402
|
-
expect(none.errorKind).toBe('microphone');
|
|
403
|
-
});
|
|
404
|
-
it('can be turned off', async () => {
|
|
405
|
-
const media = stubMedia(async () => ({ getTracks: () => [] }));
|
|
406
|
-
const dictation = new Dictation({
|
|
407
|
-
source: () => fakeSource(),
|
|
408
|
-
onText: () => { },
|
|
409
|
-
beep: false,
|
|
410
|
-
requestMicrophone: false,
|
|
411
|
-
});
|
|
412
|
-
await dictation.start();
|
|
413
|
-
expect(media.getUserMedia).not.toHaveBeenCalled();
|
|
414
|
-
expect(dictation.state).toBe('listening');
|
|
415
|
-
});
|
|
416
|
-
});
|
|
417
|
-
describe('insertTextAtCursor', () => {
|
|
418
|
-
it('inserts at the cursor with spacing and fires input', () => {
|
|
419
|
-
const field = document.createElement('textarea');
|
|
420
|
-
document.body.append(field);
|
|
421
|
-
field.value = 'Make it brighter';
|
|
422
|
-
field.focus();
|
|
423
|
-
field.setSelectionRange(7, 7);
|
|
424
|
-
const onInput = vi.fn();
|
|
425
|
-
field.addEventListener('input', onInput);
|
|
426
|
-
insertTextAtCursor(field, 'a bit');
|
|
427
|
-
expect(field.value).toBe('Make it a bit brighter');
|
|
428
|
-
expect(field.selectionStart).toBe('Make it a bit'.length);
|
|
429
|
-
expect(onInput).toHaveBeenCalledTimes(1);
|
|
430
|
-
field.remove();
|
|
431
|
-
});
|
|
432
|
-
it('appends to a field the cursor has not been in', () => {
|
|
433
|
-
const field = document.createElement('textarea');
|
|
434
|
-
field.value = 'Crop it';
|
|
435
|
-
field.setSelectionRange(0, 0);
|
|
436
|
-
insertTextAtCursor(field, 'square');
|
|
437
|
-
expect(field.value).toBe('Crop it square');
|
|
438
|
-
});
|
|
439
|
-
});
|
|
440
|
-
describe('Dictation with a long press', () => {
|
|
441
|
-
it('letting go after the press keeps listening', async () => {
|
|
442
|
-
vi.useFakeTimers();
|
|
443
|
-
try {
|
|
444
|
-
const source = fakeSource({ emitStart: true });
|
|
445
|
-
const dictation = new Dictation({
|
|
446
|
-
source: () => source,
|
|
447
|
-
onText: () => { },
|
|
448
|
-
beep: false,
|
|
449
|
-
log: () => { },
|
|
450
|
-
});
|
|
451
|
-
const press = createLongPress({
|
|
452
|
-
onLongPress: () => void dictation.start(),
|
|
453
|
-
onRelease: () => void dictation.unlock(),
|
|
454
|
-
});
|
|
455
|
-
const at = {
|
|
456
|
-
isPrimary: true,
|
|
457
|
-
pointerId: 1,
|
|
458
|
-
pointerType: 'touch',
|
|
459
|
-
button: 0,
|
|
460
|
-
clientX: 10,
|
|
461
|
-
clientY: 10,
|
|
462
|
-
target: document.body,
|
|
463
|
-
};
|
|
464
|
-
press.handlePointerDown({
|
|
465
|
-
...at,
|
|
466
|
-
type: 'pointerdown',
|
|
467
|
-
});
|
|
468
|
-
vi.advanceTimersByTime(600);
|
|
469
|
-
await vi.waitFor(() => expect(source.start).toHaveBeenCalled());
|
|
470
|
-
source.emitStart();
|
|
471
|
-
expect(dictation.state).toBe('listening');
|
|
472
|
-
press.handlePointerUp({
|
|
473
|
-
...at,
|
|
474
|
-
type: 'pointerup',
|
|
475
|
-
});
|
|
476
|
-
const click = new Event('click', { cancelable: true });
|
|
477
|
-
press.handleClick(click);
|
|
478
|
-
vi.advanceTimersByTime(300);
|
|
479
|
-
expect(dictation.state).toBe('listening');
|
|
480
|
-
expect(source.stop).not.toHaveBeenCalled();
|
|
481
|
-
}
|
|
482
|
-
finally {
|
|
483
|
-
vi.useRealTimers();
|
|
484
|
-
}
|
|
485
|
-
});
|
|
486
|
-
});
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Action } from 'svelte/action';
|
|
3
|
-
import { fromAction } from 'svelte/attachments';
|
|
4
|
-
import type { ControlInteractionRegistry } from '../control-interaction.js';
|
|
5
|
-
import Form from '../Form.svelte';
|
|
6
|
-
import Input from '../Input.svelte';
|
|
7
|
-
|
|
8
|
-
interface Props {
|
|
9
|
-
enhance: Action<HTMLFormElement, void>;
|
|
10
|
-
registry: ControlInteractionRegistry;
|
|
11
|
-
onsubmit?: (event: SubmitEvent) => void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
let { enhance, registry, onsubmit }: Props = $props();
|
|
15
|
-
</script>
|
|
16
|
-
|
|
17
|
-
<Form
|
|
18
|
-
method="POST"
|
|
19
|
-
action="/profile"
|
|
20
|
-
preventDefault={false}
|
|
21
|
-
formId="profile"
|
|
22
|
-
interactionRegistry={registry}
|
|
23
|
-
{onsubmit}
|
|
24
|
-
{@attach fromAction(enhance)}
|
|
25
|
-
>
|
|
26
|
-
<Input name="displayName" value="Dana" />
|
|
27
|
-
<button type="submit">Save</button>
|
|
28
|
-
</Form>
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { Action } from 'svelte/action';
|
|
2
|
-
import type { ControlInteractionRegistry } from '../control-interaction.js';
|
|
3
|
-
interface Props {
|
|
4
|
-
enhance: Action<HTMLFormElement, void>;
|
|
5
|
-
registry: ControlInteractionRegistry;
|
|
6
|
-
onsubmit?: (event: SubmitEvent) => void;
|
|
7
|
-
}
|
|
8
|
-
declare const FormAttachment: import("svelte").Component<Props, {}, "">;
|
|
9
|
-
type FormAttachment = ReturnType<typeof FormAttachment>;
|
|
10
|
-
export default FormAttachment;
|
|
11
|
-
//# sourceMappingURL=form-attachment.fixture.svelte.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"form-attachment.fixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/__tests__/form-attachment.fixture.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAK5E,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IACvC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CACzC;AAmBD,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -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,31 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { fromAction } from 'svelte/attachments';
|
|
3
|
-
import Form from '../Form.svelte';
|
|
4
|
-
import type { FormRetry } from '../form-retry/controller.js';
|
|
5
|
-
import type { FormRetrySubmitFunction } from '../form-retry/types.js';
|
|
6
|
-
import Input from '../Input.svelte';
|
|
7
|
-
|
|
8
|
-
interface Props {
|
|
9
|
-
/** SvelteKit's `enhance` action (here: the structural fake). */
|
|
10
|
-
enhance: (
|
|
11
|
-
form: HTMLFormElement,
|
|
12
|
-
submit?: FormRetrySubmitFunction,
|
|
13
|
-
) => { destroy(): void };
|
|
14
|
-
retry: FormRetry;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
let { enhance, retry }: Props = $props();
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<!-- The pairing the guide documents: kit's enhance with the retry submit
|
|
21
|
-
function, plus the retry attachment for the hidden key field. -->
|
|
22
|
-
<Form
|
|
23
|
-
method="POST"
|
|
24
|
-
action="?/create"
|
|
25
|
-
preventDefault={false}
|
|
26
|
-
{@attach fromAction(enhance, () => retry.enhance())}
|
|
27
|
-
{@attach retry.attach}
|
|
28
|
-
>
|
|
29
|
-
<Input name="title" aria-label="Title" />
|
|
30
|
-
<button type="submit">Send</button>
|
|
31
|
-
</Form>
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { FormRetry } from '../form-retry/controller.js';
|
|
2
|
-
import type { FormRetrySubmitFunction } from '../form-retry/types.js';
|
|
3
|
-
interface Props {
|
|
4
|
-
/** SvelteKit's `enhance` action (here: the structural fake). */
|
|
5
|
-
enhance: (form: HTMLFormElement, submit?: FormRetrySubmitFunction) => {
|
|
6
|
-
destroy(): void;
|
|
7
|
-
};
|
|
8
|
-
retry: FormRetry;
|
|
9
|
-
}
|
|
10
|
-
declare const FormRetryForm: import("svelte").Component<Props, {}, "">;
|
|
11
|
-
type FormRetryForm = ReturnType<typeof FormRetryForm>;
|
|
12
|
-
export default FormRetryForm;
|
|
13
|
-
//# sourceMappingURL=form-retry-form.fixture.svelte.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"form-retry-form.fixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/__tests__/form-retry-form.fixture.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAItE,UAAU,KAAK;IACb,gEAAgE;IAChE,OAAO,EAAE,CACP,IAAI,EAAE,eAAe,EACrB,MAAM,CAAC,EAAE,uBAAuB,KAC7B;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,CAAC;IACzB,KAAK,EAAE,SAAS,CAAC;CAClB;AAoBD,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|