@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,4 +1,4 @@
1
- import { type ControlInteractionEvent, type ControlInteractionRegistry } from '@happyvertical/smrt-ui/forms';
1
+ import { type ControlInteractionEvent, type ControlInteractionRegistry, type ControlSubject } from '@happyvertical/smrt-ui/forms';
2
2
  import type { Snippet } from 'svelte';
3
3
  import type { LLMModelId, STTAdapterType } from './types.js';
4
4
  export interface Props {
@@ -16,7 +16,7 @@ export interface Props {
16
16
  llmModel?: LLMModelId;
17
17
  /** Called when form is submitted (if provided, prevents native submission) */
18
18
  onsubmit?: (data: Record<string, unknown>) => void | Promise<void>;
19
- /** Expose this form's submit intent to WebMCP. */
19
+ /** Let WebMCP propose field changes for local human review. */
20
20
  webmcp?: boolean | {
21
21
  name?: string;
22
22
  description?: string;
@@ -29,8 +29,12 @@ export interface Props {
29
29
  action?: string;
30
30
  /** Stable identity used by control/agent interaction adapters. */
31
31
  formId?: string;
32
+ /** Default record-qualified identity for registered fields. */
33
+ subject?: ControlSubject;
32
34
  interactionRegistry?: ControlInteractionRegistry;
33
35
  oninteraction?: (event: ControlInteractionEvent) => void;
36
+ /** Render the built-in human review surface for staged changes. */
37
+ stagedReview?: boolean;
34
38
  id?: string;
35
39
  name?: string;
36
40
  class?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"Form.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/Form.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,EAIhC,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAatC,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG7D,MAAM,WAAW,KAAK;IACpB,oBAAoB;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,8BAA8B;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oCAAoC;IACpC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uBAAuB;IACvB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,kDAAkD;IAClD,MAAM,CAAC,EAAE,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3D,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,CAAC,EAAE,0BAA0B,CAAC;IACjD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACzD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAs4BD,QAAA,MAAM,IAAI;uBAhFe,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kCAQZ,0BAA0B;MAwEZ,CAAC;AACnD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;AACpC,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"Form.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/Form.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,EAG/B,KAAK,cAAc,EAIpB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAatC,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG7D,MAAM,WAAW,KAAK;IACpB,oBAAoB;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,8BAA8B;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oCAAoC;IACpC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uBAAuB;IACvB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,+DAA+D;IAC/D,MAAM,CAAC,EAAE,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3D,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,mBAAmB,CAAC,EAAE,0BAA0B,CAAC;IACjD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACzD,mEAAmE;IACnE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA04CD,QAAA,MAAM,IAAI;uBAjFe,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kCAQZ,0BAA0B;MAyEZ,CAAC;AACnD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;AACpC,eAAe,IAAI,CAAC"}
@@ -1,12 +1,12 @@
1
1
  <script lang="ts">
2
2
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
3
- import { onDestroy, onMount } from 'svelte';
4
3
  import { useAppState } from '../../hooks/useAppState.svelte.js';
5
4
  import { M } from '../../i18n/strings.forms.js';
6
5
  import {
7
6
  type FieldDefinition,
8
7
  tryGetFormContext,
9
8
  } from '../../state/form-context.js';
9
+ import { invalidStagedValue } from './prepare-field-value.js';
10
10
  import type { MeasurementUnit, MeasurementValue } from './types.js';
11
11
 
12
12
  const { t } = useI18n();
@@ -89,16 +89,24 @@ let {
89
89
 
90
90
  const app = useAppState();
91
91
  const formContext = tryGetFormContext();
92
+ const fieldOwnerId = $props.id();
93
+ const fieldOwnerToken = `smrt-rich-field-${fieldOwnerId}`;
92
94
 
93
95
  const isSmrt = $derived(app.state.mode === 'smrt');
94
96
 
95
97
  // Validation
96
- const isInRange = $derived.by(() => {
97
- if (value === null) return true;
98
- if (min !== undefined && value < min) return false;
99
- if (max !== undefined && value > max) return false;
98
+ function measurementIsInRange(candidate: number | null): boolean {
99
+ if (candidate === null) return true;
100
+ if (min !== undefined && candidate < min) return false;
101
+ if (max !== undefined && candidate > max) return false;
100
102
  return true;
101
- });
103
+ }
104
+ function measurementMatchesStep(candidate: number): boolean {
105
+ if (!Number.isFinite(step) || step <= 0) return true;
106
+ const offset = (candidate - (min ?? 0)) / step;
107
+ return Math.abs(offset - Math.round(offset)) <= 1e-9;
108
+ }
109
+ const isInRange = $derived(measurementIsInRange(value));
102
110
  const showInvalid = $derived((value !== null && !isInRange) || !!error);
103
111
 
104
112
  function updateValue(newValue: number | null, newUnit?: MeasurementUnit) {
@@ -262,25 +270,31 @@ function parseSpokenMeasurement(text: string): MeasurementValue | null {
262
270
  }
263
271
 
264
272
  // Register with form context
265
- onMount(() => {
273
+ $effect(() => {
266
274
  if (formContext) {
267
- let rangeDesc = '';
268
- if (min !== undefined && max !== undefined) {
269
- rangeDesc = ` (between ${min} and ${max})`;
270
- } else if (min !== undefined) {
271
- rangeDesc = ` (minimum ${min})`;
272
- } else if (max !== undefined) {
273
- rangeDesc = ` (maximum ${max})`;
274
- }
275
-
275
+ const registeredName = name;
276
276
  const fieldDef: FieldDefinition = {
277
- name,
277
+ name: registeredName,
278
+ ownerToken: fieldOwnerToken,
278
279
  type: 'measurement',
279
- label,
280
- description:
281
- (description ||
282
- 'A measurement with value and unit (e.g., "12 feet 6 inches")') +
283
- rangeDesc,
280
+ get label() {
281
+ return label;
282
+ },
283
+ get description() {
284
+ let rangeDescription = '';
285
+ if (min !== undefined && max !== undefined) {
286
+ rangeDescription = ` (between ${min} and ${max})`;
287
+ } else if (min !== undefined) {
288
+ rangeDescription = ` (minimum ${min})`;
289
+ } else if (max !== undefined) {
290
+ rangeDescription = ` (maximum ${max})`;
291
+ }
292
+ return (
293
+ (description ||
294
+ 'A measurement with value and unit (e.g., "12 feet 6 inches")') +
295
+ rangeDescription
296
+ );
297
+ },
284
298
  setValue: (v: unknown) => {
285
299
  if (v === null || v === undefined || v === '') {
286
300
  updateValue(null);
@@ -302,17 +316,109 @@ onMount(() => {
302
316
  }
303
317
  },
304
318
  getValue: () => (value !== null ? { value, unit } : null),
305
- constraints: { required, min, max },
319
+ prepareValue: (candidate) => {
320
+ if (candidate === null || candidate === undefined || candidate === '') {
321
+ return null;
322
+ }
323
+ if (typeof candidate === 'number') {
324
+ return Number.isFinite(candidate)
325
+ ? { value: candidate, unit }
326
+ : invalidStagedValue();
327
+ }
328
+ if (typeof candidate === 'string') {
329
+ return parseSpokenMeasurement(candidate) ?? invalidStagedValue();
330
+ }
331
+ if (
332
+ typeof candidate !== 'object' ||
333
+ Array.isArray(candidate) ||
334
+ ![Object.prototype, null].includes(Object.getPrototypeOf(candidate))
335
+ ) {
336
+ return invalidStagedValue();
337
+ }
338
+ const measurement = candidate as Record<string, unknown>;
339
+ return {
340
+ value: measurement.value,
341
+ unit: measurement.unit,
342
+ ...Object.fromEntries(
343
+ Object.entries(measurement).filter(
344
+ ([key]) => key !== 'value' && key !== 'unit',
345
+ ),
346
+ ),
347
+ };
348
+ },
349
+ clear: () => {
350
+ updateValue(null);
351
+ return true;
352
+ },
353
+ get unit() {
354
+ return unit;
355
+ },
356
+ getState: () => ({ disabled }),
357
+ get constraints() {
358
+ return { required, min, max, step };
359
+ },
360
+ get webMcpSchema() {
361
+ return {
362
+ type: 'object',
363
+ additionalProperties: false,
364
+ properties: {
365
+ value: {
366
+ type: 'number',
367
+ ...(min !== undefined ? { minimum: min } : {}),
368
+ ...(max !== undefined ? { maximum: max } : {}),
369
+ ...(Number.isFinite(step) &&
370
+ step > 0 &&
371
+ (min === undefined || measurementMatchesStep(0))
372
+ ? { multipleOf: step }
373
+ : {}),
374
+ },
375
+ unit: { type: 'string', enum: [...units] },
376
+ },
377
+ ...(required ? { required: ['value', 'unit'] } : {}),
378
+ };
379
+ },
380
+ validateValue: (candidate) => {
381
+ if (candidate === null || candidate === undefined || candidate === '') {
382
+ return !required;
383
+ }
384
+ let proposed: MeasurementValue | null = null;
385
+ if (
386
+ typeof candidate === 'object' &&
387
+ candidate !== null &&
388
+ !Array.isArray(candidate)
389
+ ) {
390
+ const measurement = candidate as Record<string, unknown>;
391
+ if (
392
+ [Object.prototype, null].includes(
393
+ Object.getPrototypeOf(measurement),
394
+ ) &&
395
+ Object.keys(measurement).every((key) =>
396
+ ['value', 'unit'].includes(key),
397
+ ) &&
398
+ Object.hasOwn(measurement, 'value') &&
399
+ Object.hasOwn(measurement, 'unit') &&
400
+ typeof measurement.value === 'number' &&
401
+ typeof measurement.unit === 'string'
402
+ ) {
403
+ proposed = measurement as unknown as MeasurementValue;
404
+ }
405
+ } else if (typeof candidate === 'number') {
406
+ proposed = { value: candidate, unit };
407
+ } else {
408
+ proposed = parseSpokenMeasurement(String(candidate));
409
+ }
410
+ return (
411
+ proposed !== null &&
412
+ Number.isFinite(proposed.value) &&
413
+ units.includes(proposed.unit) &&
414
+ measurementIsInRange(proposed.value) &&
415
+ measurementMatchesStep(proposed.value)
416
+ );
417
+ },
306
418
  validate: () =>
307
419
  value === null ? !required : Number.isFinite(value) && isInRange,
308
420
  };
309
- formContext.registerField(fieldDef);
310
- }
311
- });
312
-
313
- onDestroy(() => {
314
- if (formContext) {
315
- formContext.unregisterField(name);
421
+ return formContext.registerField(fieldDef);
316
422
  }
317
423
  });
318
424
 
@@ -334,7 +440,7 @@ function handleUnitChange(e: Event) {
334
440
  }
335
441
  </script>
336
442
 
337
- <div class="smrt-measurement">
443
+ <div class="smrt-measurement" data-smrt-field-owner={fieldOwnerToken}>
338
444
  {#if label}
339
445
  <label for={name} class="smrt-label">
340
446
  {label}
@@ -1 +1 @@
1
- {"version":3,"file":"MeasurementInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/MeasurementInput.svelte.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGpE,MAAM,WAAW,KAAK;IACpB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,qCAAqC;IACrC,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;IAC1B,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,gBAAgB,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3D;AAsVD,QAAA,MAAM,gBAAgB,yDAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"MeasurementInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/MeasurementInput.svelte.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGpE,MAAM,WAAW,KAAK;IACpB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,qCAAqC;IACrC,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;IAC1B,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,gBAAgB,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3D;AAgcD,QAAA,MAAM,gBAAgB,yDAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
@@ -1,12 +1,12 @@
1
1
  <script lang="ts">
2
2
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
3
- import { onDestroy, onMount } from 'svelte';
4
3
  import { useAppState } from '../../hooks/useAppState.svelte.js';
5
4
  import { M } from '../../i18n/strings.forms.js';
6
5
  import {
7
6
  type FieldDefinition,
8
7
  tryGetFormContext,
9
8
  } from '../../state/form-context.js';
9
+ import { invalidStagedValue } from './prepare-field-value.js';
10
10
 
11
11
  const { t } = useI18n();
12
12
 
@@ -216,22 +216,28 @@ function parseSpokenMoney(text: string): number | null {
216
216
  }
217
217
 
218
218
  // Register with form context
219
- onMount(() => {
219
+ $effect(() => {
220
220
  if (formContext) {
221
- let rangeDesc = '';
222
- if (min !== undefined && max !== undefined) {
223
- rangeDesc = ` (between $${(min / 100).toFixed(2)} and $${(max / 100).toFixed(2)})`;
224
- } else if (min !== undefined) {
225
- rangeDesc = ` (minimum $${(min / 100).toFixed(2)})`;
226
- } else if (max !== undefined) {
227
- rangeDesc = ` (maximum $${(max / 100).toFixed(2)})`;
228
- }
229
-
221
+ const registeredName = name;
230
222
  const fieldDef: FieldDefinition = {
231
- name,
223
+ name: registeredName,
232
224
  type: 'money',
233
- label,
234
- description: (description || 'A monetary amount in dollars') + rangeDesc,
225
+ get label() {
226
+ return label;
227
+ },
228
+ get description() {
229
+ let rangeDescription = '';
230
+ if (min !== undefined && max !== undefined) {
231
+ rangeDescription = ` (between $${(min / 100).toFixed(2)} and $${(max / 100).toFixed(2)})`;
232
+ } else if (min !== undefined) {
233
+ rangeDescription = ` (minimum $${(min / 100).toFixed(2)})`;
234
+ } else if (max !== undefined) {
235
+ rangeDescription = ` (maximum $${(max / 100).toFixed(2)})`;
236
+ }
237
+ return (
238
+ (description || 'A monetary amount in dollars') + rangeDescription
239
+ );
240
+ },
235
241
  setValue: (v: unknown) => {
236
242
  if (v === null || v === undefined || v === '') {
237
243
  updateValue(null);
@@ -252,17 +258,30 @@ onMount(() => {
252
258
  }
253
259
  },
254
260
  getValue: () => value,
255
- constraints: { required, min, max },
261
+ prepareValue: (candidate) => {
262
+ if (candidate === null || candidate === undefined || candidate === '') {
263
+ return null;
264
+ }
265
+ if (typeof candidate === 'number') {
266
+ return candidate;
267
+ }
268
+ if (typeof candidate !== 'string') return invalidStagedValue();
269
+ return parseSpokenMoney(candidate) ?? invalidStagedValue();
270
+ },
271
+ getState: () => ({ disabled }),
272
+ get constraints() {
273
+ return { required, min, max };
274
+ },
275
+ validateValue: (candidate) =>
276
+ (candidate === null && !required) ||
277
+ (typeof candidate === 'number' &&
278
+ Number.isSafeInteger(candidate) &&
279
+ (min === undefined || candidate >= min) &&
280
+ (max === undefined || candidate <= max)),
256
281
  validate: () =>
257
- value === null ? !required : Number.isFinite(value) && isInRange,
282
+ value === null ? !required : Number.isSafeInteger(value) && isInRange,
258
283
  };
259
- formContext.registerField(fieldDef);
260
- }
261
- });
262
-
263
- onDestroy(() => {
264
- if (formContext) {
265
- formContext.unregisterField(name);
284
+ return formContext.registerField(fieldDef);
266
285
  }
267
286
  });
268
287
 
@@ -1 +1 @@
1
- {"version":3,"file":"MoneyInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/MoneyInput.svelte.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,KAAK;IACpB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACzB,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3C;AAoSD,QAAA,MAAM,UAAU,gDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"MoneyInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/MoneyInput.svelte.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,KAAK;IACpB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACzB,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3C;AAuTD,QAAA,MAAM,UAAU,gDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -1,12 +1,12 @@
1
1
  <script lang="ts">
2
2
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
3
- import { onDestroy, onMount } from 'svelte';
4
3
  import { useAppState } from '../../hooks/useAppState.svelte.js';
5
4
  import { M } from '../../i18n/strings.forms.js';
6
5
  import {
7
6
  type FieldDefinition,
8
7
  tryGetFormContext,
9
8
  } from '../../state/form-context.js';
9
+ import { invalidStagedValue } from './prepare-field-value.js';
10
10
 
11
11
  const { t } = useI18n();
12
12
 
@@ -55,12 +55,18 @@ const formContext = tryGetFormContext();
55
55
  const isSmrt = $derived(app.state.mode === 'smrt');
56
56
 
57
57
  // Validation
58
- const isInRange = $derived.by(() => {
59
- if (value === null) return true;
60
- if (min !== undefined && value < min) return false;
61
- if (max !== undefined && value > max) return false;
58
+ function numberIsInRange(candidate: number | null): boolean {
59
+ if (candidate === null) return true;
60
+ if (min !== undefined && candidate < min) return false;
61
+ if (max !== undefined && candidate > max) return false;
62
62
  return true;
63
- });
63
+ }
64
+ function numberMatchesStep(candidate: number): boolean {
65
+ if (!Number.isFinite(step) || step <= 0) return true;
66
+ const offset = (candidate - (min ?? 0)) / step;
67
+ return Math.abs(offset - Math.round(offset)) <= 1e-9;
68
+ }
69
+ const isInRange = $derived(numberIsInRange(value));
64
70
  const showInvalid = $derived(value !== null && !isInRange);
65
71
 
66
72
  function updateValue(newValue: number | null) {
@@ -143,22 +149,26 @@ function parseSpokenNumber(text: string): number | null {
143
149
  }
144
150
 
145
151
  // Register with form context
146
- onMount(() => {
152
+ $effect(() => {
147
153
  if (formContext) {
148
- let rangeDesc = '';
149
- if (min !== undefined && max !== undefined) {
150
- rangeDesc = ` (between ${min} and ${max})`;
151
- } else if (min !== undefined) {
152
- rangeDesc = ` (minimum ${min})`;
153
- } else if (max !== undefined) {
154
- rangeDesc = ` (maximum ${max})`;
155
- }
156
-
154
+ const registeredName = name;
157
155
  const fieldDef: FieldDefinition = {
158
- name,
156
+ name: registeredName,
159
157
  type: 'number',
160
- label,
161
- description: (description || 'A number') + rangeDesc,
158
+ get label() {
159
+ return label;
160
+ },
161
+ get description() {
162
+ let rangeDescription = '';
163
+ if (min !== undefined && max !== undefined) {
164
+ rangeDescription = ` (between ${min} and ${max})`;
165
+ } else if (min !== undefined) {
166
+ rangeDescription = ` (minimum ${min})`;
167
+ } else if (max !== undefined) {
168
+ rangeDescription = ` (maximum ${max})`;
169
+ }
170
+ return (description || 'A number') + rangeDescription;
171
+ },
162
172
  setValue: (v: unknown) => {
163
173
  if (v === null || v === undefined || v === '') {
164
174
  updateValue(null);
@@ -175,17 +185,39 @@ onMount(() => {
175
185
  }
176
186
  },
177
187
  getValue: () => value,
178
- constraints: { required, min, max, step },
188
+ prepareValue: (candidate) => {
189
+ if (candidate === null || candidate === undefined || candidate === '') {
190
+ return null;
191
+ }
192
+ if (typeof candidate === 'number') {
193
+ return candidate;
194
+ }
195
+ if (typeof candidate !== 'string') return invalidStagedValue();
196
+ return parseSpokenNumber(candidate) ?? invalidStagedValue();
197
+ },
198
+ getState: () => ({ disabled }),
199
+ get constraints() {
200
+ return { required, min, max, step };
201
+ },
202
+ validateValue: (candidate) => {
203
+ if (candidate === null || candidate === undefined || candidate === '') {
204
+ return !required;
205
+ }
206
+ const proposed =
207
+ typeof candidate === 'number'
208
+ ? candidate
209
+ : parseSpokenNumber(String(candidate));
210
+ return (
211
+ proposed !== null &&
212
+ Number.isFinite(proposed) &&
213
+ numberIsInRange(proposed) &&
214
+ numberMatchesStep(proposed)
215
+ );
216
+ },
179
217
  validate: () =>
180
218
  value === null ? !required : Number.isFinite(value) && isInRange,
181
219
  };
182
- formContext.registerField(fieldDef);
183
- }
184
- });
185
-
186
- onDestroy(() => {
187
- if (formContext) {
188
- formContext.unregisterField(name);
220
+ return formContext.registerField(fieldDef);
189
221
  }
190
222
  });
191
223
 
@@ -1 +1 @@
1
- {"version":3,"file":"NumberInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/NumberInput.svelte.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,KAAK;IACpB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3C;AAuMD,QAAA,MAAM,WAAW,gDAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"NumberInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/NumberInput.svelte.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,KAAK;IACpB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3C;AAuOD,QAAA,MAAM,WAAW,gDAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -1,6 +1,5 @@
1
1
  <script lang="ts">
2
2
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
3
- import { onDestroy, onMount } from 'svelte';
4
3
  import { useAppState } from '../../hooks/useAppState.svelte.js';
5
4
  import { useSTT } from '../../hooks/useSTT.svelte.js';
6
5
  import { M } from '../../i18n/strings.forms.js';
@@ -9,6 +8,10 @@ import {
9
8
  type FieldDefinition,
10
9
  tryGetFormContext,
11
10
  } from '../../state/form-context.js';
11
+ import {
12
+ invalidStagedValue,
13
+ prepareTextFieldValue,
14
+ } from './prepare-field-value.js';
12
15
 
13
16
  const { t } = useI18n();
14
17
 
@@ -60,11 +63,13 @@ const isInitializing = $derived(stt.isInitializing);
60
63
  const downloadProgress = $derived(stt.downloadProgress);
61
64
 
62
65
  // Phone validation (basic North American format)
63
- const isValidPhone = $derived.by(() => {
64
- if (!value) return true;
65
- const digits = value.replace(/\D/g, '');
66
- return digits.length >= 10 && digits.length <= 11;
67
- });
66
+ function isValidPhoneValue(candidate: unknown): boolean {
67
+ if (typeof candidate !== 'string') return false;
68
+ if (!candidate) return !required;
69
+ const digits = candidate.replace(/\D/g, '');
70
+ return digits.length === 10 || (digits.length === 11 && digits[0] === '1');
71
+ }
72
+ const isValidPhone = $derived.by(() => isValidPhoneValue(value));
68
73
  const showInvalid = $derived(value && !isValidPhone);
69
74
 
70
75
  function updateValue(newValue: string) {
@@ -91,7 +96,7 @@ function formatPhoneNumber(input: string): string {
91
96
  }
92
97
 
93
98
  // Parse spoken phone number
94
- function parseSpokenPhone(text: string): string {
99
+ function extractSpokenPhoneDigits(text: string): string {
95
100
  const wordNumbers: Record<string, string> = {
96
101
  zero: '0',
97
102
  oh: '0',
@@ -130,35 +135,59 @@ function parseSpokenPhone(text: string): string {
130
135
  result = result.replace(/\btriple\s*(\d)/gi, '$1$1$1');
131
136
 
132
137
  // Extract just digits
133
- const digits = result.replace(/\D/g, '');
138
+ return result.replace(/\D/g, '');
139
+ }
134
140
 
135
- return formatPhoneNumber(digits);
141
+ function parseSpokenPhone(text: string): string {
142
+ return formatPhoneNumber(extractSpokenPhoneDigits(text));
136
143
  }
137
144
 
138
145
  // Register with form context
139
- onMount(() => {
146
+ $effect(() => {
140
147
  if (formContext) {
148
+ const registeredName = name;
141
149
  const fieldDef: FieldDefinition = {
142
- name,
150
+ name: registeredName,
143
151
  type: 'phone',
144
- label,
145
- description: description || 'Phone number',
152
+ get label() {
153
+ return label;
154
+ },
155
+ get description() {
156
+ return description || 'Phone number';
157
+ },
146
158
  setValue: (v: unknown) => {
147
159
  const strVal = String(v ?? '');
148
160
  const formatted = parseSpokenPhone(strVal);
149
161
  updateValue(formatted);
150
162
  },
151
163
  getValue: () => value,
152
- constraints: { required },
153
- validate: () => !required || value.trim().length > 0,
164
+ prepareValue: (candidate) => {
165
+ const prepared = prepareTextFieldValue(candidate);
166
+ if (prepared === '') return '';
167
+ const digits = extractSpokenPhoneDigits(prepared);
168
+ if (
169
+ digits.length !== 10 &&
170
+ !(digits.length === 11 && digits[0] === '1')
171
+ ) {
172
+ return prepared;
173
+ }
174
+ return formatPhoneNumber(digits) || invalidStagedValue();
175
+ },
176
+ getState: () => ({ disabled }),
177
+ get constraints() {
178
+ return { required };
179
+ },
180
+ validateValue: (candidate) => {
181
+ if (typeof candidate !== 'string') return false;
182
+ if (candidate === '') return !required;
183
+ const digits = extractSpokenPhoneDigits(candidate);
184
+ return (
185
+ digits.length === 10 || (digits.length === 11 && digits[0] === '1')
186
+ );
187
+ },
188
+ validate: () => isValidPhoneValue(value),
154
189
  };
155
- formContext.registerField(fieldDef);
156
- }
157
- });
158
-
159
- onDestroy(() => {
160
- if (formContext) {
161
- formContext.unregisterField(name);
190
+ return formContext.registerField(fieldDef);
162
191
  }
163
192
  });
164
193
 
@@ -1 +1 @@
1
- {"version":3,"file":"PhoneInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/PhoneInput.svelte.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,KAAK;IACpB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AA8SD,QAAA,MAAM,UAAU,gDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"PhoneInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/PhoneInput.svelte.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,KAAK;IACpB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAwUD,QAAA,MAAM,UAAU,gDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}