@happyvertical/smrt-svelte 0.43.4 → 0.43.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/AGENTS.md +23 -0
  2. package/README.md +23 -1
  3. package/dist/components/forms/AddressInput.svelte +155 -42
  4. package/dist/components/forms/AddressInput.svelte.d.ts.map +1 -1
  5. package/dist/components/forms/CheckboxInput.svelte +40 -13
  6. package/dist/components/forms/CheckboxInput.svelte.d.ts.map +1 -1
  7. package/dist/components/forms/DateRangeInput.svelte +132 -16
  8. package/dist/components/forms/DateRangeInput.svelte.d.ts.map +1 -1
  9. package/dist/components/forms/DateTimeInput.svelte +48 -14
  10. package/dist/components/forms/DateTimeInput.svelte.d.ts.map +1 -1
  11. package/dist/components/forms/Form.svelte +599 -70
  12. package/dist/components/forms/Form.svelte.d.ts +6 -2
  13. package/dist/components/forms/Form.svelte.d.ts.map +1 -1
  14. package/dist/components/forms/MeasurementInput.svelte +137 -31
  15. package/dist/components/forms/MeasurementInput.svelte.d.ts.map +1 -1
  16. package/dist/components/forms/MoneyInput.svelte +42 -23
  17. package/dist/components/forms/MoneyInput.svelte.d.ts.map +1 -1
  18. package/dist/components/forms/NumberInput.svelte +59 -27
  19. package/dist/components/forms/NumberInput.svelte.d.ts.map +1 -1
  20. package/dist/components/forms/PhoneInput.svelte +51 -22
  21. package/dist/components/forms/PhoneInput.svelte.d.ts.map +1 -1
  22. package/dist/components/forms/SelectInput.svelte +38 -22
  23. package/dist/components/forms/SelectInput.svelte.d.ts.map +1 -1
  24. package/dist/components/forms/TextInput.svelte +32 -18
  25. package/dist/components/forms/TextInput.svelte.d.ts.map +1 -1
  26. package/dist/components/forms/TextareaInput.svelte +25 -18
  27. package/dist/components/forms/TextareaInput.svelte.d.ts.map +1 -1
  28. package/dist/components/forms/__tests__/AddressInput.behavior.test.js +94 -0
  29. package/dist/components/forms/__tests__/Form.behavior.test.js +1 -1
  30. package/dist/components/forms/__tests__/Form.extraction.test.js +68 -0
  31. package/dist/components/forms/__tests__/Form.test.js +28 -0
  32. package/dist/components/forms/__tests__/Form.webmcp.test.js +2123 -114
  33. package/dist/components/forms/__tests__/FormMicButton.test.js +0 -1
  34. package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte +30 -0
  35. package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte.d.ts +7 -0
  36. package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte.d.ts.map +1 -0
  37. package/dist/components/forms/__tests__/async-validation-form.fixture.svelte +19 -0
  38. package/dist/components/forms/__tests__/async-validation-form.fixture.svelte.d.ts +9 -0
  39. package/dist/components/forms/__tests__/async-validation-form.fixture.svelte.d.ts.map +1 -0
  40. package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte +21 -0
  41. package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte.d.ts +8 -0
  42. package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte.d.ts.map +1 -0
  43. package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte +27 -0
  44. package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte.d.ts +9 -0
  45. package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte.d.ts.map +1 -0
  46. package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte +48 -0
  47. package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte.d.ts +10 -0
  48. package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte.d.ts.map +1 -0
  49. package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte +26 -0
  50. package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte.d.ts +13 -0
  51. package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte.d.ts.map +1 -0
  52. package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte +52 -0
  53. package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte.d.ts +16 -0
  54. package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte.d.ts.map +1 -0
  55. package/dist/components/forms/__tests__/form-with-fields.fixture.svelte +108 -5
  56. package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts +34 -0
  57. package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts.map +1 -1
  58. package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte +24 -0
  59. package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte.d.ts +11 -0
  60. package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte.d.ts.map +1 -0
  61. package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte +69 -4
  62. package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte.d.ts +32 -0
  63. package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte.d.ts.map +1 -1
  64. package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte +44 -0
  65. package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte.d.ts +9 -0
  66. package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte.d.ts.map +1 -0
  67. package/dist/components/forms/__tests__/policy-field.fixture.svelte +35 -0
  68. package/dist/components/forms/__tests__/policy-field.fixture.svelte.d.ts +8 -0
  69. package/dist/components/forms/__tests__/policy-field.fixture.svelte.d.ts.map +1 -0
  70. package/dist/components/forms/prepare-field-value.d.ts +5 -0
  71. package/dist/components/forms/prepare-field-value.d.ts.map +1 -0
  72. package/dist/components/forms/prepare-field-value.js +15 -0
  73. package/dist/state/form-context.d.ts +28 -6
  74. package/dist/state/form-context.d.ts.map +1 -1
  75. package/dist/state/form-context.js +75 -7
  76. package/dist/web/__tests__/webmcp-composed.child.fixture.svelte +62 -0
  77. package/dist/web/__tests__/webmcp-composed.child.fixture.svelte.d.ts +8 -0
  78. package/dist/web/__tests__/webmcp-composed.child.fixture.svelte.d.ts.map +1 -0
  79. package/dist/web/__tests__/webmcp-composed.fixture.svelte +52 -0
  80. package/dist/web/__tests__/webmcp-composed.fixture.svelte.d.ts +12 -0
  81. package/dist/web/__tests__/webmcp-composed.fixture.svelte.d.ts.map +1 -0
  82. package/dist/web/__tests__/webmcp-composed.integration.svelte.test.js +247 -0
  83. package/dist/web/__tests__/webmcp-ssr.fixture.svelte +13 -0
  84. package/dist/web/__tests__/webmcp-ssr.fixture.svelte.d.ts +19 -0
  85. package/dist/web/__tests__/webmcp-ssr.fixture.svelte.d.ts.map +1 -0
  86. package/dist/web/__tests__/webmcp-ui.test.js +209 -33
  87. package/dist/web/__tests__/webmcp.test.js +20 -0
  88. package/dist/web/webmcp-ui.d.ts.map +1 -1
  89. package/dist/web/webmcp-ui.js +50 -31
  90. package/dist/web/webmcp.svelte.d.ts.map +1 -1
  91. package/dist/web/webmcp.svelte.js +6 -1
  92. 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="measurement"
25
- label="Measurement"
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":"AAQC,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,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAwBF,QAAA,MAAM,wBAAwB,sDAAwC,CAAC;AACvE,KAAK,wBAAwB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC5E,eAAe,wBAAwB,CAAC"}
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
+ }
@@ -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?: () => void;
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
- /** Register a field with the form */
48
- registerField: (field: FieldDefinition) => void;
49
- /** Unregister a field */
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,EACnB,MAAM,8BAA8B,CAAC;AAGtC;;GAEG;AACH,qCAAqC;AACrC,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,OAAO,GACP,UAAU,GACV,QAAQ,GACR,SAAS,GACT,UAAU,GACV,WAAW,GACX,aAAa,GACb,OAAO,GACP,OAAO,GACP,QAAQ,GACR,UAAU,CAAC;AAEf,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB;IACjB,IAAI,EAAE,aAAa,CAAC;IACpB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,WAAW,CAAC;IAC9B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,mBAAmB,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,mBAAmB;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,qCAAqC;IACrC,aAAa,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAChD,yBAAyB;IACzB,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,wDAAwD;IACxD,cAAc,EAAE,MAAM,eAAe,EAAE,CAAC;IACxC,6CAA6C;IAC7C,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,+CAA+C;IAC/C,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,yCAAyC;IACzC,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,mBAAmB,EAAE,0BAA0B,CAAC;IACzD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,eAAsB,CAAC;AAEjD;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,CAEzD;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,eAAe,CAUhD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,eAAe,GAAG,IAAI,CAE1D"}
1
+ {"version":3,"file":"form-context.d.ts","sourceRoot":"","sources":["../../src/state/form-context.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,83 @@
1
1
  /**
2
2
  * SMRT Form context for field registration and coordination
3
3
  */
4
- import { getContext, setContext } from 'svelte';
4
+ import { getAllContexts, getContext, setContext } from 'svelte';
5
5
  /**
6
6
  * Context key for SMRT form
7
7
  */
8
8
  export const SMRT_FORM_KEY = Symbol('smrt-form');
9
+ // Svelte gives every component its own context map, copying inherited values
10
+ // into that map. Cache a facade by this map rather than by the inherited
11
+ // context value: repeated calls from one component share ownership, while
12
+ // descendants that inherit a facade receive their own ownership boundary.
13
+ const callerFormContextFacades = new WeakMap();
14
+ function createFormContextFacade(ctx) {
15
+ const registrations = new Map();
16
+ const facade = {
17
+ get mode() {
18
+ return ctx.mode;
19
+ },
20
+ registerField(field) {
21
+ const registeredName = field.name;
22
+ const registeredDisposer = ctx.registerField(field);
23
+ const disposeField = typeof registeredDisposer === 'function'
24
+ ? registeredDisposer
25
+ : () => ctx.unregisterField(registeredName);
26
+ let active = true;
27
+ const dispose = () => {
28
+ if (!active)
29
+ return;
30
+ active = false;
31
+ const ownedRegistrations = registrations.get(registeredName);
32
+ ownedRegistrations?.delete(dispose);
33
+ if (ownedRegistrations?.size === 0) {
34
+ registrations.delete(registeredName);
35
+ }
36
+ disposeField();
37
+ };
38
+ const ownedRegistrations = registrations.get(registeredName) ?? new Set();
39
+ ownedRegistrations.add(dispose);
40
+ registrations.set(registeredName, ownedRegistrations);
41
+ return dispose;
42
+ },
43
+ unregisterField(name) {
44
+ const ownedRegistrations = registrations.get(name);
45
+ const dispose = ownedRegistrations?.values().next().value;
46
+ dispose?.();
47
+ },
48
+ getFieldSchema: () => ctx.getFieldSchema(),
49
+ get isFormListening() {
50
+ return ctx.isFormListening;
51
+ },
52
+ get isExtracting() {
53
+ return ctx.isExtracting;
54
+ },
55
+ toggleListening: () => ctx.toggleListening(),
56
+ get interactionRegistry() {
57
+ return ctx.interactionRegistry;
58
+ },
59
+ get formId() {
60
+ return ctx.formId;
61
+ },
62
+ };
63
+ return facade;
64
+ }
65
+ function getCallerFormContext(required) {
66
+ const contextMap = getAllContexts();
67
+ const existingFacade = callerFormContextFacades.get(contextMap);
68
+ if (existingFacade)
69
+ return existingFacade;
70
+ const ctx = getContext(SMRT_FORM_KEY);
71
+ if (!ctx) {
72
+ if (!required)
73
+ return null;
74
+ throw new Error('Form context not found. Make sure to wrap your inputs with <SMRTForm>');
75
+ }
76
+ const facade = createFormContextFacade(ctx);
77
+ callerFormContextFacades.set(contextMap, facade);
78
+ setContext(SMRT_FORM_KEY, facade);
79
+ return facade;
80
+ }
9
81
  /**
10
82
  * Set form context (used by SMRTForm)
11
83
  */
@@ -17,15 +89,11 @@ export function setFormContext(ctx) {
17
89
  * @throws If called outside of SMRTForm
18
90
  */
19
91
  export function getFormContext() {
20
- const ctx = getContext(SMRT_FORM_KEY);
21
- if (!ctx) {
22
- throw new Error('Form context not found. Make sure to wrap your inputs with <SMRTForm>');
23
- }
24
- return ctx;
92
+ return getCallerFormContext(true);
25
93
  }
26
94
  /**
27
95
  * Try to get form context (returns null if not available)
28
96
  */
29
97
  export function tryGetFormContext() {
30
- return getContext(SMRT_FORM_KEY) ?? null;
98
+ return getCallerFormContext(false);
31
99
  }
@@ -0,0 +1,62 @@
1
+ <script lang="ts">
2
+ import type { DataSurfaceRegistry } from '@happyvertical/smrt-ui/data';
3
+ import {
4
+ type DataSurfaceDescriptor,
5
+ DataTable,
6
+ } from '@happyvertical/smrt-ui/data';
7
+ import Form from '../../components/forms/Form.svelte';
8
+ import TextInput from '../../components/forms/TextInput.svelte';
9
+ import { useWebMcpTool } from '../webmcp.svelte.js';
10
+
11
+ let { dataSurfaceRegistry }: { dataSurfaceRegistry: DataSurfaceRegistry } =
12
+ $props();
13
+
14
+ useWebMcpTool(() => ({
15
+ name: 'fixture_component_preview',
16
+ description:
17
+ 'Preview the composed fixture without changing application state.',
18
+ inputSchema: { type: 'object', properties: {} },
19
+ annotations: { readOnlyHint: true, openWorldHint: false },
20
+ execute: () => JSON.stringify({ ok: true, source: 'bespoke-component' }),
21
+ }));
22
+
23
+ const tableDescriptor: DataSurfaceDescriptor = {
24
+ version: 1,
25
+ identity: { surfaceId: 'fixture-items', kind: 'table' },
26
+ schemaVersion: 1,
27
+ label: 'Fixture items',
28
+ rowKey: 'id',
29
+ columns: [
30
+ { id: 'id', label: 'ID', capabilities: ['read', 'project'] },
31
+ {
32
+ id: 'name',
33
+ label: 'Name',
34
+ capabilities: ['read', 'search', 'filter', 'sort', 'project'],
35
+ },
36
+ ],
37
+ query: { modes: ['rows', 'count'], projectableColumnIds: ['id', 'name'] },
38
+ controls: ['set-search', 'toggle-sorting'].map((id) => ({ id, label: id })),
39
+ actions: [],
40
+ limits: { maxQueryRows: 50, maxQueryBytes: 10_000, maxSelectionSize: 10 },
41
+ };
42
+
43
+ const rows = [
44
+ { id: 'item-1', name: 'First' },
45
+ { id: 'item-2', name: 'Second' },
46
+ ];
47
+ const columns = [
48
+ { id: 'id', label: 'ID', accessor: 'id' },
49
+ { id: 'name', label: 'Name', accessor: 'name', sortable: true },
50
+ ];
51
+ </script>
52
+
53
+ <Form formId="fixture-form">
54
+ <TextInput name="title" label="Title" />
55
+ </Form>
56
+ <DataTable
57
+ data={rows}
58
+ {columns}
59
+ rowKey="id"
60
+ sortable={true}
61
+ dataSurface={{ registry: dataSurfaceRegistry, descriptor: tableDescriptor }}
62
+ />
@@ -0,0 +1,8 @@
1
+ import type { DataSurfaceRegistry } from '@happyvertical/smrt-ui/data';
2
+ type $$ComponentProps = {
3
+ dataSurfaceRegistry: DataSurfaceRegistry;
4
+ };
5
+ declare const WebmcpComposed: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type WebmcpComposed = ReturnType<typeof WebmcpComposed>;
7
+ export default WebmcpComposed;
8
+ //# sourceMappingURL=webmcp-composed.child.fixture.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webmcp-composed.child.fixture.svelte.d.ts","sourceRoot":"","sources":["../../../src/web/__tests__/webmcp-composed.child.fixture.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAStE,KAAK,gBAAgB,GAAI;IAAE,mBAAmB,EAAE,mBAAmB,CAAA;CAAE,CAAC;AAyDvE,QAAA,MAAM,cAAc,sDAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -0,0 +1,52 @@
1
+ <script lang="ts">
2
+ import type { DataSurfaceRegistry } from '@happyvertical/smrt-ui/data';
3
+ import type {
4
+ RegisterWebMcpToolsOptions,
5
+ WebMcpToolDefinition,
6
+ } from '@happyvertical/smrt-web';
7
+ import Provider from '../../Provider.svelte';
8
+ import type { WebMcpProviderConfig } from '../webmcp-provider.js';
9
+ import Child from './webmcp-composed.child.fixture.svelte';
10
+
11
+ let {
12
+ dataSurfaceRegistry,
13
+ generatedDefinitions = [],
14
+ fetchFn,
15
+ showChild = true,
16
+ }: {
17
+ dataSurfaceRegistry: DataSurfaceRegistry;
18
+ generatedDefinitions?: readonly WebMcpToolDefinition[];
19
+ fetchFn?: RegisterWebMcpToolsOptions['fetchFn'];
20
+ showChild?: boolean;
21
+ } = $props();
22
+
23
+ let cachedDefinitions: readonly WebMcpToolDefinition[] | undefined;
24
+ let cachedFetchFn: RegisterWebMcpToolsOptions['fetchFn'] | undefined;
25
+ let cachedRegistry: DataSurfaceRegistry | undefined;
26
+ let cachedWebmcp: WebMcpProviderConfig | undefined;
27
+ const webmcp = $derived.by(() => {
28
+ if (
29
+ cachedWebmcp &&
30
+ cachedDefinitions === generatedDefinitions &&
31
+ cachedFetchFn === fetchFn &&
32
+ cachedRegistry === dataSurfaceRegistry
33
+ ) {
34
+ return cachedWebmcp;
35
+ }
36
+ cachedDefinitions = generatedDefinitions;
37
+ cachedFetchFn = fetchFn;
38
+ cachedRegistry = dataSurfaceRegistry;
39
+ cachedWebmcp = {
40
+ definitions: generatedDefinitions,
41
+ ...(fetchFn ? { fetchFn } : {}),
42
+ ui: { dataSurfaceRegistry },
43
+ };
44
+ return cachedWebmcp;
45
+ });
46
+ </script>
47
+
48
+ <Provider {webmcp}>
49
+ {#if showChild}
50
+ <Child {dataSurfaceRegistry} />
51
+ {/if}
52
+ </Provider>
@@ -0,0 +1,12 @@
1
+ import type { DataSurfaceRegistry } from '@happyvertical/smrt-ui/data';
2
+ import type { RegisterWebMcpToolsOptions, WebMcpToolDefinition } from '@happyvertical/smrt-web';
3
+ type $$ComponentProps = {
4
+ dataSurfaceRegistry: DataSurfaceRegistry;
5
+ generatedDefinitions?: readonly WebMcpToolDefinition[];
6
+ fetchFn?: RegisterWebMcpToolsOptions['fetchFn'];
7
+ showChild?: boolean;
8
+ };
9
+ declare const WebmcpComposed: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type WebmcpComposed = ReturnType<typeof WebmcpComposed>;
11
+ export default WebmcpComposed;
12
+ //# sourceMappingURL=webmcp-composed.fixture.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webmcp-composed.fixture.svelte.d.ts","sourceRoot":"","sources":["../../../src/web/__tests__/webmcp-composed.fixture.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,KAAK,EACV,0BAA0B,EAC1B,oBAAoB,EACrB,MAAM,yBAAyB,CAAC;AAKhC,KAAK,gBAAgB,GAAI;IACxB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,oBAAoB,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACvD,OAAO,CAAC,EAAE,0BAA0B,CAAC,SAAS,CAAC,CAAC;IAChD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAgDF,QAAA,MAAM,cAAc,sDAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}