@happyvertical/smrt-svelte 0.43.3 → 0.43.5
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/AGENTS.md +45 -0
- package/README.md +73 -0
- package/dist/Provider.svelte +83 -26
- package/dist/Provider.svelte.d.ts +4 -12
- package/dist/Provider.svelte.d.ts.map +1 -1
- package/dist/__tests__/provider-webmcp-harness.svelte +14 -0
- package/dist/__tests__/provider-webmcp-harness.svelte.d.ts +8 -0
- package/dist/__tests__/provider-webmcp-harness.svelte.d.ts.map +1 -0
- package/dist/components/forms/AddressInput.svelte +155 -42
- package/dist/components/forms/AddressInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/CheckboxInput.svelte +40 -13
- package/dist/components/forms/CheckboxInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/DateRangeInput.svelte +132 -16
- package/dist/components/forms/DateRangeInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/DateTimeInput.svelte +48 -14
- package/dist/components/forms/DateTimeInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/Form.svelte +667 -61
- package/dist/components/forms/Form.svelte.d.ts +6 -2
- package/dist/components/forms/Form.svelte.d.ts.map +1 -1
- package/dist/components/forms/MeasurementInput.svelte +137 -31
- package/dist/components/forms/MeasurementInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/MoneyInput.svelte +42 -23
- package/dist/components/forms/MoneyInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/NumberInput.svelte +59 -27
- package/dist/components/forms/NumberInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/PhoneInput.svelte +51 -22
- package/dist/components/forms/PhoneInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/SelectInput.svelte +38 -22
- package/dist/components/forms/SelectInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/TextInput.svelte +32 -18
- package/dist/components/forms/TextInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/TextareaInput.svelte +25 -18
- package/dist/components/forms/TextareaInput.svelte.d.ts.map +1 -1
- package/dist/components/forms/__tests__/AddressInput.behavior.test.js +94 -0
- package/dist/components/forms/__tests__/Form.behavior.test.js +1 -1
- package/dist/components/forms/__tests__/Form.extraction.test.js +68 -0
- package/dist/components/forms/__tests__/Form.test.js +28 -0
- package/dist/components/forms/__tests__/Form.webmcp.test.js +2120 -111
- package/dist/components/forms/__tests__/FormMicButton.test.js +0 -1
- package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte +30 -0
- package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte.d.ts +7 -0
- package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte.d.ts.map +1 -0
- package/dist/components/forms/__tests__/async-validation-form.fixture.svelte +19 -0
- package/dist/components/forms/__tests__/async-validation-form.fixture.svelte.d.ts +9 -0
- package/dist/components/forms/__tests__/async-validation-form.fixture.svelte.d.ts.map +1 -0
- package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte +21 -0
- package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte.d.ts +8 -0
- package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte.d.ts.map +1 -0
- package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte +27 -0
- package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte.d.ts +9 -0
- package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte.d.ts.map +1 -0
- package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte +48 -0
- package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte.d.ts +10 -0
- package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte.d.ts.map +1 -0
- package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte +26 -0
- package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte.d.ts +13 -0
- package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte.d.ts.map +1 -0
- package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte +52 -0
- package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte.d.ts +16 -0
- package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte.d.ts.map +1 -0
- package/dist/components/forms/__tests__/form-with-fields.fixture.svelte +108 -5
- package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts +34 -0
- package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts.map +1 -1
- package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte +24 -0
- package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte.d.ts +11 -0
- package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte.d.ts.map +1 -0
- package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte +69 -4
- package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte.d.ts +32 -0
- package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte.d.ts.map +1 -1
- package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte +44 -0
- package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte.d.ts +9 -0
- package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte.d.ts.map +1 -0
- package/dist/components/forms/__tests__/policy-field.fixture.svelte +35 -0
- package/dist/components/forms/__tests__/policy-field.fixture.svelte.d.ts +8 -0
- package/dist/components/forms/__tests__/policy-field.fixture.svelte.d.ts.map +1 -0
- package/dist/components/forms/prepare-field-value.d.ts +5 -0
- package/dist/components/forms/prepare-field-value.d.ts.map +1 -0
- package/dist/components/forms/prepare-field-value.js +15 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/provider-webmcp.test.js +244 -0
- package/dist/state/form-context.d.ts +28 -6
- package/dist/state/form-context.d.ts.map +1 -1
- package/dist/state/form-context.js +75 -7
- package/dist/web/__tests__/provider-ui-registry.fixture.svelte +43 -0
- package/dist/web/__tests__/provider-ui-registry.fixture.svelte.d.ts +13 -0
- package/dist/web/__tests__/provider-ui-registry.fixture.svelte.d.ts.map +1 -0
- package/dist/web/__tests__/provider-ui-registry.test.js +235 -0
- package/dist/web/__tests__/webmcp-composed.child.fixture.svelte +62 -0
- package/dist/web/__tests__/webmcp-composed.child.fixture.svelte.d.ts +8 -0
- package/dist/web/__tests__/webmcp-composed.child.fixture.svelte.d.ts.map +1 -0
- package/dist/web/__tests__/webmcp-composed.fixture.svelte +52 -0
- package/dist/web/__tests__/webmcp-composed.fixture.svelte.d.ts +12 -0
- package/dist/web/__tests__/webmcp-composed.fixture.svelte.d.ts.map +1 -0
- package/dist/web/__tests__/webmcp-composed.integration.svelte.test.js +247 -0
- package/dist/web/__tests__/webmcp-ssr.fixture.svelte +13 -0
- package/dist/web/__tests__/webmcp-ssr.fixture.svelte.d.ts +19 -0
- package/dist/web/__tests__/webmcp-ssr.fixture.svelte.d.ts.map +1 -0
- package/dist/web/__tests__/webmcp-ui.test.js +586 -0
- package/dist/web/__tests__/webmcp.test.js +21 -1
- package/dist/web/index.d.ts +3 -0
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +2 -0
- package/dist/web/webmcp-provider.d.ts +23 -0
- package/dist/web/webmcp-provider.d.ts.map +1 -0
- package/dist/web/webmcp-provider.js +1 -0
- package/dist/web/webmcp-ui-context.d.ts +12 -0
- package/dist/web/webmcp-ui-context.d.ts.map +1 -0
- package/dist/web/webmcp-ui-context.js +16 -0
- package/dist/web/webmcp-ui.d.ts +21 -0
- package/dist/web/webmcp-ui.d.ts.map +1 -0
- package/dist/web/webmcp-ui.js +474 -0
- package/dist/web/webmcp.d.ts +1 -1
- package/dist/web/webmcp.svelte.d.ts +4 -1
- package/dist/web/webmcp.svelte.d.ts.map +1 -1
- package/dist/web/webmcp.svelte.js +6 -1
- package/package.json +8 -6
|
@@ -1,40 +1,105 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
type ControlInteractionRegistry,
|
|
4
|
+
Input,
|
|
5
|
+
} from '@happyvertical/smrt-ui/forms';
|
|
2
6
|
import AddressInput from '../AddressInput.svelte';
|
|
3
7
|
import DateRangeInput from '../DateRangeInput.svelte';
|
|
4
8
|
import Form from '../Form.svelte';
|
|
5
9
|
import MeasurementInput from '../MeasurementInput.svelte';
|
|
10
|
+
import TextInput from '../TextInput.svelte';
|
|
6
11
|
|
|
7
12
|
let {
|
|
8
13
|
onsubmit = undefined,
|
|
9
14
|
webmcp = false,
|
|
10
15
|
addressFields = ['street', 'city', 'province', 'postalCode', 'country'],
|
|
16
|
+
addressCountries = undefined,
|
|
17
|
+
addressProvinces = undefined,
|
|
11
18
|
structuredRequired = true,
|
|
19
|
+
interactionRegistry = undefined,
|
|
20
|
+
fieldsetDisabled = false,
|
|
21
|
+
onmeasurementchange = undefined,
|
|
22
|
+
ondateschange = undefined,
|
|
23
|
+
onaddresschange = undefined,
|
|
24
|
+
measurementStep = undefined,
|
|
25
|
+
measurementUnits = undefined,
|
|
26
|
+
measurementLabel = 'Measurement',
|
|
27
|
+
measurementMin = undefined,
|
|
28
|
+
measurementMax = undefined,
|
|
29
|
+
minDate = undefined,
|
|
30
|
+
maxDate = undefined,
|
|
31
|
+
dateDisabled = false,
|
|
32
|
+
measurementName = 'measurement',
|
|
33
|
+
showCollidingSibling = false,
|
|
34
|
+
showExactNameCollisions = false,
|
|
35
|
+
showBaseControlCollision = false,
|
|
12
36
|
}: {
|
|
13
37
|
onsubmit?: (data: Record<string, unknown>) => void;
|
|
14
38
|
webmcp?: boolean;
|
|
15
39
|
addressFields?: Array<
|
|
16
40
|
'street' | 'city' | 'province' | 'postalCode' | 'country'
|
|
17
41
|
>;
|
|
42
|
+
addressCountries?: Array<{ value: string; label: string }>;
|
|
43
|
+
addressProvinces?: Array<{ value: string; label: string }>;
|
|
18
44
|
structuredRequired?: boolean;
|
|
45
|
+
interactionRegistry?: ControlInteractionRegistry;
|
|
46
|
+
fieldsetDisabled?: boolean;
|
|
47
|
+
onmeasurementchange?: (value: { value: number; unit: string } | null) => void;
|
|
48
|
+
ondateschange?: (value: { startDate: string; endDate: string }) => void;
|
|
49
|
+
onaddresschange?: (value: Partial<Record<string, string>>) => void;
|
|
50
|
+
measurementStep?: number;
|
|
51
|
+
measurementUnits?: Array<'ft' | 'in' | 'm' | 'cm' | 'mm' | 'yd'>;
|
|
52
|
+
measurementLabel?: string;
|
|
53
|
+
measurementMin?: number;
|
|
54
|
+
measurementMax?: number;
|
|
55
|
+
minDate?: string;
|
|
56
|
+
maxDate?: string;
|
|
57
|
+
dateDisabled?: boolean;
|
|
58
|
+
measurementName?: string;
|
|
59
|
+
showCollidingSibling?: boolean;
|
|
60
|
+
showExactNameCollisions?: boolean;
|
|
61
|
+
showBaseControlCollision?: boolean;
|
|
19
62
|
} = $props();
|
|
20
63
|
</script>
|
|
21
64
|
|
|
22
|
-
<Form {onsubmit} {webmcp}>
|
|
65
|
+
<Form {onsubmit} {webmcp} {interactionRegistry} formId="structured-fields">
|
|
66
|
+
<fieldset disabled={fieldsetDisabled}>
|
|
23
67
|
<MeasurementInput
|
|
24
|
-
name=
|
|
25
|
-
label=
|
|
68
|
+
name={measurementName}
|
|
69
|
+
label={measurementLabel}
|
|
26
70
|
required={structuredRequired}
|
|
71
|
+
min={measurementMin}
|
|
72
|
+
max={measurementMax}
|
|
73
|
+
step={measurementStep}
|
|
74
|
+
units={measurementUnits}
|
|
75
|
+
onchange={onmeasurementchange}
|
|
27
76
|
/>
|
|
28
77
|
<DateRangeInput
|
|
29
78
|
name="dates"
|
|
30
79
|
label="Dates"
|
|
31
80
|
required={structuredRequired}
|
|
81
|
+
{minDate}
|
|
82
|
+
{maxDate}
|
|
83
|
+
disabled={dateDisabled}
|
|
84
|
+
onchange={ondateschange}
|
|
32
85
|
/>
|
|
33
86
|
<AddressInput
|
|
34
87
|
name="address"
|
|
35
88
|
label="Address"
|
|
36
89
|
fields={addressFields}
|
|
90
|
+
countries={addressCountries}
|
|
91
|
+
provinces={addressProvinces}
|
|
37
92
|
required={structuredRequired}
|
|
38
|
-
|
|
93
|
+
onchange={onaddresschange}
|
|
94
|
+
/>
|
|
95
|
+
</fieldset>
|
|
96
|
+
{#if showExactNameCollisions}
|
|
97
|
+
<TextInput name="address[city]" label="Exact address city" />
|
|
98
|
+
<TextInput name="{measurementName}_unit" label="Exact measurement unit" />
|
|
99
|
+
{/if}
|
|
100
|
+
{#if showBaseControlCollision}
|
|
101
|
+
<Input name="address[city]" data-testid="base-address-city" />
|
|
102
|
+
{/if}
|
|
103
|
+
{#if showCollidingSibling}<input name="{measurementName}_note" />{/if}
|
|
39
104
|
<button type="submit">Submit</button>
|
|
40
105
|
</Form>
|
|
@@ -1,8 +1,40 @@
|
|
|
1
|
+
import { type ControlInteractionRegistry } from '@happyvertical/smrt-ui/forms';
|
|
1
2
|
type $$ComponentProps = {
|
|
2
3
|
onsubmit?: (data: Record<string, unknown>) => void;
|
|
3
4
|
webmcp?: boolean;
|
|
4
5
|
addressFields?: Array<'street' | 'city' | 'province' | 'postalCode' | 'country'>;
|
|
6
|
+
addressCountries?: Array<{
|
|
7
|
+
value: string;
|
|
8
|
+
label: string;
|
|
9
|
+
}>;
|
|
10
|
+
addressProvinces?: Array<{
|
|
11
|
+
value: string;
|
|
12
|
+
label: string;
|
|
13
|
+
}>;
|
|
5
14
|
structuredRequired?: boolean;
|
|
15
|
+
interactionRegistry?: ControlInteractionRegistry;
|
|
16
|
+
fieldsetDisabled?: boolean;
|
|
17
|
+
onmeasurementchange?: (value: {
|
|
18
|
+
value: number;
|
|
19
|
+
unit: string;
|
|
20
|
+
} | null) => void;
|
|
21
|
+
ondateschange?: (value: {
|
|
22
|
+
startDate: string;
|
|
23
|
+
endDate: string;
|
|
24
|
+
}) => void;
|
|
25
|
+
onaddresschange?: (value: Partial<Record<string, string>>) => void;
|
|
26
|
+
measurementStep?: number;
|
|
27
|
+
measurementUnits?: Array<'ft' | 'in' | 'm' | 'cm' | 'mm' | 'yd'>;
|
|
28
|
+
measurementLabel?: string;
|
|
29
|
+
measurementMin?: number;
|
|
30
|
+
measurementMax?: number;
|
|
31
|
+
minDate?: string;
|
|
32
|
+
maxDate?: string;
|
|
33
|
+
dateDisabled?: boolean;
|
|
34
|
+
measurementName?: string;
|
|
35
|
+
showCollidingSibling?: boolean;
|
|
36
|
+
showExactNameCollisions?: boolean;
|
|
37
|
+
showBaseControlCollision?: boolean;
|
|
6
38
|
};
|
|
7
39
|
declare const FormWithStructuredFields: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
40
|
type FormWithStructuredFields = ReturnType<typeof FormWithStructuredFields>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-with-structured-fields.fixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/__tests__/form-with-structured-fields.fixture.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"form-with-structured-fields.fixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/__tests__/form-with-structured-fields.fixture.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,0BAA0B,EAEhC,MAAM,8BAA8B,CAAC;AAOrC,KAAK,gBAAgB,GAAI;IACxB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACnD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,KAAK,CACnB,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAC1D,CAAC;IACF,gBAAgB,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,gBAAgB,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,mBAAmB,CAAC,EAAE,0BAA0B,CAAC;IACjD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,KAAK,IAAI,CAAC;IAC9E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACxE,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,IAAI,CAAC;IACnE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,KAAK,CAAC,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IACjE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC,CAAC;AAuDF,QAAA,MAAM,wBAAwB,sDAAwC,CAAC;AACvE,KAAK,wBAAwB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC5E,eAAe,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { createControlInteractionRegistry } from '@happyvertical/smrt-ui/forms';
|
|
3
|
+
import {
|
|
4
|
+
type FieldDefinition,
|
|
5
|
+
type SMRTFormContext,
|
|
6
|
+
setFormContext,
|
|
7
|
+
} from '../../../state/form-context.js';
|
|
8
|
+
import TextInput from '../TextInput.svelte';
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
showField = true,
|
|
12
|
+
onregister,
|
|
13
|
+
onunregister,
|
|
14
|
+
}: {
|
|
15
|
+
showField?: boolean;
|
|
16
|
+
onregister?: (name: string) => void;
|
|
17
|
+
onunregister?: (name: string) => void;
|
|
18
|
+
} = $props();
|
|
19
|
+
|
|
20
|
+
const fields = new Map<string, FieldDefinition>();
|
|
21
|
+
const legacyContext: SMRTFormContext = {
|
|
22
|
+
mode: 'default',
|
|
23
|
+
registerField(field) {
|
|
24
|
+
fields.set(field.name, field);
|
|
25
|
+
onregister?.(field.name);
|
|
26
|
+
},
|
|
27
|
+
unregisterField(name) {
|
|
28
|
+
fields.delete(name);
|
|
29
|
+
onunregister?.(name);
|
|
30
|
+
},
|
|
31
|
+
getFieldSchema: () => Array.from(fields.values()),
|
|
32
|
+
isFormListening: false,
|
|
33
|
+
isExtracting: false,
|
|
34
|
+
toggleListening: () => {},
|
|
35
|
+
interactionRegistry: createControlInteractionRegistry(),
|
|
36
|
+
formId: 'legacy-context',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
setFormContext(legacyContext);
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
{#if showField}
|
|
43
|
+
<TextInput name="legacy-field" label="Legacy field" />
|
|
44
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
showField?: boolean;
|
|
3
|
+
onregister?: (name: string) => void;
|
|
4
|
+
onunregister?: (name: string) => void;
|
|
5
|
+
};
|
|
6
|
+
declare const LegacyFormContext: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type LegacyFormContext = ReturnType<typeof LegacyFormContext>;
|
|
8
|
+
export default LegacyFormContext;
|
|
9
|
+
//# sourceMappingURL=legacy-form-context.fixture.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-form-context.fixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/__tests__/legacy-form-context.fixture.svelte.ts"],"names":[],"mappings":"AAWC,KAAK,gBAAgB,GAAI;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,CAAC;AAwCF,QAAA,MAAM,iBAAiB,sDAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import { tryGetFormContext } from '../../../state/form-context.js';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
sensitivity = 'public',
|
|
7
|
+
writable = true,
|
|
8
|
+
}: {
|
|
9
|
+
sensitivity?: 'public' | 'secret';
|
|
10
|
+
writable?: boolean;
|
|
11
|
+
} = $props();
|
|
12
|
+
let value = $state('Ada');
|
|
13
|
+
const policyLabel = 'Policy field';
|
|
14
|
+
const formContext = tryGetFormContext();
|
|
15
|
+
|
|
16
|
+
onMount(() => {
|
|
17
|
+
return formContext?.registerField({
|
|
18
|
+
name: 'policy',
|
|
19
|
+
type: 'text',
|
|
20
|
+
label: policyLabel,
|
|
21
|
+
get sensitivity() {
|
|
22
|
+
return sensitivity;
|
|
23
|
+
},
|
|
24
|
+
get writable() {
|
|
25
|
+
return writable;
|
|
26
|
+
},
|
|
27
|
+
setValue: (next) => {
|
|
28
|
+
value = String(next ?? '');
|
|
29
|
+
},
|
|
30
|
+
getValue: () => value,
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<input name="policy" aria-label={policyLabel} bind:value />
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
sensitivity?: 'public' | 'secret';
|
|
3
|
+
writable?: boolean;
|
|
4
|
+
};
|
|
5
|
+
declare const PolicyField: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
6
|
+
type PolicyField = ReturnType<typeof PolicyField>;
|
|
7
|
+
export default PolicyField;
|
|
8
|
+
//# sourceMappingURL=policy-field.fixture.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-field.fixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/__tests__/policy-field.fixture.svelte.ts"],"names":[],"mappings":"AAMC,KAAK,gBAAgB,GAAI;IACxB,WAAW,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAoCF,QAAA,MAAM,WAAW,sDAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Canonicalize scalar values before they enter staged rich-field review. */
|
|
2
|
+
export declare function prepareTextFieldValue(value: unknown): string;
|
|
3
|
+
/** Reject values which a rich field cannot synchronously canonicalize. */
|
|
4
|
+
export declare function invalidStagedValue(): never;
|
|
5
|
+
//# sourceMappingURL=prepare-field-value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepare-field-value.d.ts","sourceRoot":"","sources":["../../../src/components/forms/prepare-field-value.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAU5D;AAED,0EAA0E;AAC1E,wBAAgB,kBAAkB,IAAI,KAAK,CAE1C"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Canonicalize scalar values before they enter staged rich-field review. */
|
|
2
|
+
export function prepareTextFieldValue(value) {
|
|
3
|
+
if (value === null || value === undefined)
|
|
4
|
+
return '';
|
|
5
|
+
if (typeof value === 'string' ||
|
|
6
|
+
typeof value === 'number' ||
|
|
7
|
+
typeof value === 'boolean') {
|
|
8
|
+
return String(value);
|
|
9
|
+
}
|
|
10
|
+
throw new Error('staged_value_invalid');
|
|
11
|
+
}
|
|
12
|
+
/** Reject values which a rich field cannot synchronously canonicalize. */
|
|
13
|
+
export function invalidStagedValue() {
|
|
14
|
+
throw new Error('staged_value_invalid');
|
|
15
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -18,4 +18,7 @@ export * from './hooks/index.js';
|
|
|
18
18
|
export { default as Provider } from './Provider.svelte';
|
|
19
19
|
export * from './state/index.js';
|
|
20
20
|
export { useWebMcpTool, type WebMcpToolSpec } from './web/webmcp.svelte.js';
|
|
21
|
+
export type { WebMcpProviderConfig, WebMcpUiProviderConfig, } from './web/webmcp-provider.js';
|
|
22
|
+
export { type RegisterWebMcpUiToolsOptions, registerWebMcpUiTools, } from './web/webmcp-ui.js';
|
|
23
|
+
export { useWebMcpUi, type WebMcpUiContext, } from './web/webmcp-ui-context.js';
|
|
21
24
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAGH,cAAc,6BAA6B,CAAC;AAE5C,cAAc,8BAA8B,CAAC;AAE7C,cAAc,mBAAmB,CAAC;AAElC,cAAc,kBAAkB,CAAC;AAEjC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAExD,cAAc,kBAAkB,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAGH,cAAc,6BAA6B,CAAC;AAE5C,cAAc,8BAA8B,CAAC;AAE7C,cAAc,mBAAmB,CAAC;AAElC,cAAc,kBAAkB,CAAC;AAEjC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAExD,cAAc,kBAAkB,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC5E,YAAY,EACV,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,KAAK,4BAA4B,EACjC,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,KAAK,eAAe,GACrB,MAAM,4BAA4B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -26,3 +26,5 @@ export { default as Provider } from './Provider.svelte';
|
|
|
26
26
|
export * from './state/index.js';
|
|
27
27
|
// Opt-in browser WebMCP lifecycle primitive.
|
|
28
28
|
export { useWebMcpTool } from './web/webmcp.svelte.js';
|
|
29
|
+
export { registerWebMcpUiTools, } from './web/webmcp-ui.js';
|
|
30
|
+
export { useWebMcpUi, } from './web/webmcp-ui-context.js';
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { render, waitFor } from '@testing-library/svelte';
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { logger } from './internal/logger.js';
|
|
4
|
+
const { registerWebMcpTools } = vi.hoisted(() => ({
|
|
5
|
+
registerWebMcpTools: vi.fn(),
|
|
6
|
+
}));
|
|
7
|
+
vi.mock('@happyvertical/smrt-web', async (importOriginal) => {
|
|
8
|
+
const actual = await importOriginal();
|
|
9
|
+
return {
|
|
10
|
+
...actual,
|
|
11
|
+
registerWebMcpTools: (...args) => {
|
|
12
|
+
registerWebMcpTools(...args);
|
|
13
|
+
return actual.registerWebMcpTools(...args);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
import Harness from './__tests__/provider-webmcp-harness.svelte';
|
|
18
|
+
describe('Provider WebMCP policy', () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
registerWebMcpTools.mockClear();
|
|
21
|
+
document.modelContext = undefined;
|
|
22
|
+
});
|
|
23
|
+
it('passes the same exposure policy to the framework-agnostic registrar', async () => {
|
|
24
|
+
const filter = vi.fn(() => true);
|
|
25
|
+
const filterTool = vi.fn(() => true);
|
|
26
|
+
const resolveFetchers = vi.fn();
|
|
27
|
+
const resolveToolFetchers = vi.fn();
|
|
28
|
+
const definitions = [];
|
|
29
|
+
render(Harness, {
|
|
30
|
+
props: {
|
|
31
|
+
webmcp: {
|
|
32
|
+
definitions,
|
|
33
|
+
effects: ['read', 'write'],
|
|
34
|
+
namespace: 'workspace',
|
|
35
|
+
maxTools: 12,
|
|
36
|
+
basePath: '/api/v2',
|
|
37
|
+
scope: 'tenant-a',
|
|
38
|
+
filter,
|
|
39
|
+
filterTool,
|
|
40
|
+
resolveFetchers,
|
|
41
|
+
resolveToolFetchers,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
await waitFor(() => expect(registerWebMcpTools).toHaveBeenCalledOnce());
|
|
46
|
+
expect(registerWebMcpTools).toHaveBeenCalledWith(definitions, {
|
|
47
|
+
client: undefined,
|
|
48
|
+
basePath: '/api/v2',
|
|
49
|
+
fetchFn: undefined,
|
|
50
|
+
scope: 'tenant-a',
|
|
51
|
+
filter,
|
|
52
|
+
filterTool,
|
|
53
|
+
resolveFetchers,
|
|
54
|
+
resolveToolFetchers,
|
|
55
|
+
effects: ['read', 'write'],
|
|
56
|
+
namespace: 'workspace',
|
|
57
|
+
maxTools: 12,
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
it('registers the same real tool set as direct registration', async () => {
|
|
61
|
+
const definitions = [
|
|
62
|
+
{
|
|
63
|
+
name: 'reports',
|
|
64
|
+
objectRef: '@test/smrt-svelte:Report',
|
|
65
|
+
className: 'Report',
|
|
66
|
+
endpoint: '/reports',
|
|
67
|
+
idField: 'id',
|
|
68
|
+
actions: ['list', 'create'],
|
|
69
|
+
fields: {},
|
|
70
|
+
toolDescriptors: [
|
|
71
|
+
{
|
|
72
|
+
action: 'list',
|
|
73
|
+
name: 'report_list',
|
|
74
|
+
description: 'List reports',
|
|
75
|
+
inputSchema: { type: 'object' },
|
|
76
|
+
readOnly: true,
|
|
77
|
+
effect: 'read',
|
|
78
|
+
idempotent: true,
|
|
79
|
+
openWorld: false,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
action: 'create',
|
|
83
|
+
name: 'report_create',
|
|
84
|
+
description: 'Create a report',
|
|
85
|
+
inputSchema: { type: 'object' },
|
|
86
|
+
readOnly: false,
|
|
87
|
+
effect: 'write',
|
|
88
|
+
idempotent: false,
|
|
89
|
+
openWorld: false,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
collection: 'audits',
|
|
95
|
+
objectRef: '@test/smrt-svelte:Audit',
|
|
96
|
+
className: 'Audit',
|
|
97
|
+
endpoint: '/audits',
|
|
98
|
+
idField: 'id',
|
|
99
|
+
idType: 'uuid',
|
|
100
|
+
relationships: [],
|
|
101
|
+
action: 'get',
|
|
102
|
+
name: 'audit_get',
|
|
103
|
+
description: 'Get an audit record',
|
|
104
|
+
inputSchema: { type: 'object' },
|
|
105
|
+
readOnly: true,
|
|
106
|
+
effect: 'read',
|
|
107
|
+
idempotent: true,
|
|
108
|
+
openWorld: false,
|
|
109
|
+
route: { method: 'GET', scope: 'item', path: [] },
|
|
110
|
+
},
|
|
111
|
+
];
|
|
112
|
+
const resolveFetchers = (definition) => {
|
|
113
|
+
definition.actions.length = 0;
|
|
114
|
+
return {
|
|
115
|
+
list: async () => [],
|
|
116
|
+
create: async (data) => data,
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
const resolveToolFetchers = (definition) => {
|
|
120
|
+
definition.action = 'delete';
|
|
121
|
+
return { get: async () => ({ id: 'a1' }) };
|
|
122
|
+
};
|
|
123
|
+
const policy = {
|
|
124
|
+
definitions,
|
|
125
|
+
effects: ['read', 'write'],
|
|
126
|
+
namespace: 'workspace',
|
|
127
|
+
maxTools: 4,
|
|
128
|
+
filter: () => true,
|
|
129
|
+
filterTool: (tool) => tool.collection === 'audits',
|
|
130
|
+
resolveFetchers: vi.fn(resolveFetchers),
|
|
131
|
+
resolveToolFetchers: vi.fn(resolveToolFetchers),
|
|
132
|
+
};
|
|
133
|
+
const captured = [];
|
|
134
|
+
const installRegistry = () => {
|
|
135
|
+
captured.length = 0;
|
|
136
|
+
document.modelContext = {
|
|
137
|
+
async registerTool(tool) {
|
|
138
|
+
captured.push({ name: tool.name, annotations: tool.annotations });
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
installRegistry();
|
|
143
|
+
const { registerWebMcpTools: directRegister } = await vi.importActual('@happyvertical/smrt-web');
|
|
144
|
+
directRegister(definitions, policy);
|
|
145
|
+
const direct = structuredClone(captured);
|
|
146
|
+
installRegistry();
|
|
147
|
+
render(Harness, { props: { webmcp: policy } });
|
|
148
|
+
await waitFor(() => expect(registerWebMcpTools).toHaveBeenCalledOnce());
|
|
149
|
+
expect(captured).toEqual(direct);
|
|
150
|
+
expect(captured.map((tool) => tool.name)).toEqual([
|
|
151
|
+
'workspace_report_list',
|
|
152
|
+
'workspace_report_create',
|
|
153
|
+
'workspace_audit_get',
|
|
154
|
+
]);
|
|
155
|
+
expect(policy.resolveFetchers).toHaveBeenCalledTimes(2);
|
|
156
|
+
expect(policy.resolveToolFetchers).toHaveBeenCalledTimes(2);
|
|
157
|
+
});
|
|
158
|
+
it('defaults generated data tools to read-only exposure', async () => {
|
|
159
|
+
const captured = [];
|
|
160
|
+
document.modelContext = {
|
|
161
|
+
async registerTool(tool) {
|
|
162
|
+
captured.push(tool.name);
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
const definitions = [
|
|
166
|
+
{
|
|
167
|
+
name: 'reports',
|
|
168
|
+
objectRef: '@test/smrt-svelte:Report',
|
|
169
|
+
className: 'Report',
|
|
170
|
+
endpoint: '/reports',
|
|
171
|
+
idField: 'id',
|
|
172
|
+
actions: ['list', 'create'],
|
|
173
|
+
fields: {},
|
|
174
|
+
toolDescriptors: [
|
|
175
|
+
{
|
|
176
|
+
action: 'list',
|
|
177
|
+
name: 'report_list',
|
|
178
|
+
description: 'List reports',
|
|
179
|
+
inputSchema: { type: 'object' },
|
|
180
|
+
readOnly: true,
|
|
181
|
+
effect: 'read',
|
|
182
|
+
idempotent: true,
|
|
183
|
+
openWorld: false,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
action: 'create',
|
|
187
|
+
name: 'report_create',
|
|
188
|
+
description: 'Create a report',
|
|
189
|
+
inputSchema: { type: 'object' },
|
|
190
|
+
readOnly: false,
|
|
191
|
+
effect: 'write',
|
|
192
|
+
idempotent: false,
|
|
193
|
+
openWorld: false,
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
];
|
|
198
|
+
render(Harness, { props: { webmcp: { definitions } } });
|
|
199
|
+
await waitFor(() => expect(registerWebMcpTools).toHaveBeenCalledOnce());
|
|
200
|
+
expect(captured).toEqual(['report_list']);
|
|
201
|
+
});
|
|
202
|
+
it('reports rejected generated data-tool policies without an unhandled rejection', async () => {
|
|
203
|
+
const warn = vi.spyOn(logger, 'warn').mockImplementation(() => { });
|
|
204
|
+
document.modelContext = { registerTool: vi.fn() };
|
|
205
|
+
render(Harness, {
|
|
206
|
+
props: { webmcp: { definitions: [], maxTools: -1 } },
|
|
207
|
+
});
|
|
208
|
+
await waitFor(() => expect(warn).toHaveBeenCalledWith('Provider: WebMCP data tool registration rejected', {
|
|
209
|
+
error: expect.objectContaining({
|
|
210
|
+
message: 'WebMCP maxTools must be a non-negative safe integer',
|
|
211
|
+
}),
|
|
212
|
+
}));
|
|
213
|
+
});
|
|
214
|
+
it('reports asynchronous browser registration rejection', async () => {
|
|
215
|
+
const warn = vi.spyOn(logger, 'warn').mockImplementation(() => { });
|
|
216
|
+
document.modelContext = {
|
|
217
|
+
registerTool: () => Promise.reject(new Error('browser rejected tool')),
|
|
218
|
+
};
|
|
219
|
+
const definitions = [
|
|
220
|
+
{
|
|
221
|
+
collection: 'audits',
|
|
222
|
+
objectRef: '@test/smrt-svelte:Audit',
|
|
223
|
+
className: 'Audit',
|
|
224
|
+
endpoint: '/audits',
|
|
225
|
+
idField: 'id',
|
|
226
|
+
idType: 'uuid',
|
|
227
|
+
relationships: [],
|
|
228
|
+
action: 'get',
|
|
229
|
+
name: 'audit_get',
|
|
230
|
+
description: 'Get an audit record',
|
|
231
|
+
inputSchema: { type: 'object' },
|
|
232
|
+
readOnly: true,
|
|
233
|
+
effect: 'read',
|
|
234
|
+
idempotent: true,
|
|
235
|
+
openWorld: false,
|
|
236
|
+
route: { method: 'GET', scope: 'item', path: [] },
|
|
237
|
+
},
|
|
238
|
+
];
|
|
239
|
+
render(Harness, { props: { webmcp: { definitions } } });
|
|
240
|
+
await waitFor(() => expect(warn).toHaveBeenCalledWith('Provider: WebMCP data tool registration rejected', {
|
|
241
|
+
error: expect.objectContaining({ message: 'browser rejected tool' }),
|
|
242
|
+
}));
|
|
243
|
+
});
|
|
244
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SMRT Form context for field registration and coordination
|
|
3
3
|
*/
|
|
4
|
-
import type { ControlConstraints, ControlInteractionRegistry, ControlKind, ControlOption, ControlRuntimeState, ControlSensitivity } from '@happyvertical/smrt-ui/forms';
|
|
4
|
+
import type { ControlConstraints, ControlExtensionContext, ControlInteractionRegistry, ControlKind, ControlOption, ControlRuntimeState, ControlSensitivity, ControlSubject, ControlValueValidationResult } from '@happyvertical/smrt-ui/forms';
|
|
5
5
|
/**
|
|
6
6
|
* Field definition for form registration
|
|
7
7
|
*/
|
|
@@ -18,10 +18,27 @@ export interface FieldDefinition {
|
|
|
18
18
|
description?: string;
|
|
19
19
|
/** Set the field value */
|
|
20
20
|
setValue: (value: unknown) => void;
|
|
21
|
+
/** Context-aware setter for hooks that need to issue another control command. */
|
|
22
|
+
setValueWithContext?: (value: unknown, context: ControlExtensionContext) => void | Promise<void>;
|
|
21
23
|
/** Get current field value */
|
|
22
24
|
getValue: () => unknown;
|
|
25
|
+
/**
|
|
26
|
+
* Convert an incoming intent into the final value shown for review/applied.
|
|
27
|
+
* May throw when the value cannot be represented canonically by this field.
|
|
28
|
+
*/
|
|
29
|
+
prepareValue?: (value: unknown) => unknown;
|
|
30
|
+
/** Validate/canonicalize a complete value edited in staged review. */
|
|
31
|
+
prepareReviewedValue?: (value: unknown) => unknown;
|
|
32
|
+
/**
|
|
33
|
+
* Convert a value extracted from speech into the field's canonical value.
|
|
34
|
+
* May be asynchronous for controls that support natural-language parsing.
|
|
35
|
+
*/
|
|
36
|
+
prepareExtractedValue?: (value: unknown) => unknown | Promise<unknown>;
|
|
23
37
|
/** Optional richer interaction metadata and capabilities. */
|
|
24
38
|
controlId?: string;
|
|
39
|
+
/** Immutable token identifying the DOM subtree owned by this field. */
|
|
40
|
+
ownerToken?: string;
|
|
41
|
+
subject?: ControlSubject;
|
|
25
42
|
interactionKind?: ControlKind;
|
|
26
43
|
sensitivity?: ControlSensitivity;
|
|
27
44
|
readable?: boolean;
|
|
@@ -31,11 +48,13 @@ export interface FieldDefinition {
|
|
|
31
48
|
webMcpSchema?: Record<string, unknown>;
|
|
32
49
|
options?: ControlOption[];
|
|
33
50
|
unit?: string;
|
|
34
|
-
clear
|
|
51
|
+
/** Return true to affirm an accepted idempotent clear; false rejects it. */
|
|
52
|
+
clear?: ((context?: ControlExtensionContext) => void | Promise<void>) | ((context?: ControlExtensionContext) => boolean | Promise<boolean>);
|
|
35
53
|
focus?: () => void;
|
|
36
54
|
reveal?: () => void;
|
|
37
55
|
highlight?: (durationMs?: number) => void;
|
|
38
|
-
validate?: () => boolean
|
|
56
|
+
validate?: (context?: ControlExtensionContext) => boolean | Promise<boolean>;
|
|
57
|
+
validateValue?: (value: unknown, context?: ControlExtensionContext) => ControlValueValidationResult | Promise<ControlValueValidationResult>;
|
|
39
58
|
getState?: () => ControlRuntimeState;
|
|
40
59
|
}
|
|
41
60
|
/**
|
|
@@ -44,9 +63,12 @@ export interface FieldDefinition {
|
|
|
44
63
|
export interface SMRTFormContext {
|
|
45
64
|
/** Current mode */
|
|
46
65
|
readonly mode: 'smrt' | 'default';
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Register a field with the form. New contexts return an identity-bound
|
|
68
|
+
* disposer; legacy void-returning contexts remain supported.
|
|
69
|
+
*/
|
|
70
|
+
registerField: (field: FieldDefinition) => void | (() => void);
|
|
71
|
+
/** Legacy name-based cleanup. Prefer the disposer returned by registerField. */
|
|
50
72
|
unregisterField: (name: string) => void;
|
|
51
73
|
/** Get all registered fields schema (for LLM prompt) */
|
|
52
74
|
getFieldSchema: () => FieldDefinition[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-context.d.ts","sourceRoot":"","sources":["../../src/state/form-context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,0BAA0B,EAC1B,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"form-context.d.ts","sourceRoot":"","sources":["../../src/state/form-context.ts"],"names":[],"mappings":"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"}
|