@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
package/AGENTS.md
CHANGED
|
@@ -16,6 +16,15 @@ subpath you are editing. This file keeps what holds in every module.
|
|
|
16
16
|
| `src/components/settings/` (`./settings`) | `SettingsCatalog`, `paginateSettingsCatalog`, and the summary-vs-detail scalability contract | [agents/settings.md](agents/settings.md) |
|
|
17
17
|
| `src/components/workspace/` (`./workspace` + `./web`) | the AdminShell family and its principles, the legacy ToolsDock surface, the `./web` activity-feed and `updateAvailable` adapters, and server-side dock gates | [agents/workspace.md](agents/workspace.md) |
|
|
18
18
|
| `src/web/remote-query.svelte.ts` | Svelte 5 binding for query-shaped remote pages: rows, page, totals, loading/refreshing/stale/error, retry, last-updated, and query-scoped live subscriptions (#2445) | — |
|
|
19
|
+
| `src/web/webmcp-provider.ts` | Provider config for generated data/model WebMCP tools: definitions, effect policy, namespace, budget, legacy/canonical filters, and fetcher seams (#2520) | — |
|
|
20
|
+
| `src/web/webmcp-ui.ts` | Fixed, low-cardinality WebMCP adapter over the Provider's mounted form-control and data-surface registries (#2521) | — |
|
|
21
|
+
|
|
22
|
+
The composed WebMCP fixture in
|
|
23
|
+
`src/web/__tests__/webmcp-composed.integration.svelte.test.ts` mounts a real
|
|
24
|
+
Provider, rich Form, DataTable/DataSurface, and a bespoke `useWebMcpTool`
|
|
25
|
+
component intent. Preserve its lifecycle assertions: SSR and missing
|
|
26
|
+
`document.modelContext` are no-ops, mounted tools are fixed-cardinality, and
|
|
27
|
+
all registrations abort when their owning component unmounts.
|
|
19
28
|
|
|
20
29
|
## The UI split — primitive-adoption contract (#1589)
|
|
21
30
|
|
|
@@ -53,6 +62,17 @@ migration; flips strict per package as it adopts the primitives).
|
|
|
53
62
|
|
|
54
63
|
Wraps app in `+layout.svelte`. Provides auth state, permissions, WebSocket, and AI capabilities.
|
|
55
64
|
|
|
65
|
+
The rich `Form` uses smrt-ui's shared staged-edit review contract. Agent
|
|
66
|
+
proposals never mutate field bindings directly: they remain staged until a
|
|
67
|
+
human applies or discards them in the form's local review surface. Keep this
|
|
68
|
+
state machine in smrt-ui; smrt-svelte contributes Provider-backed field
|
|
69
|
+
registration and consumes the shared component rather than duplicating it.
|
|
70
|
+
The generated WebMCP form tool proposes registry stages; it never writes or
|
|
71
|
+
submits field values directly.
|
|
72
|
+
Rich `FieldDefinition` registrations may carry a `subject` for record-qualified
|
|
73
|
+
identity. The Form bridge also folds live DOM disabled/read-only state into the
|
|
74
|
+
registry and omits those fields from WebMCP schemas and staging.
|
|
75
|
+
|
|
56
76
|
```svelte
|
|
57
77
|
<script>
|
|
58
78
|
let { data, children } = $props();
|
|
@@ -64,6 +84,26 @@ Wraps app in `+layout.svelte`. Provides auth state, permissions, WebSocket, and
|
|
|
64
84
|
</Provider>
|
|
65
85
|
```
|
|
66
86
|
|
|
87
|
+
An object `webmcp` config with `definitions` registers generated data/model
|
|
88
|
+
tools through the same registrar as direct smrt-web callers. With no `effects`
|
|
89
|
+
policy, only `read`-effect tools register; `write` and `destructive` require
|
|
90
|
+
explicit opt-in. Use `filter` for legacy collection definitions and `filterTool`
|
|
91
|
+
for canonical definitions; a filter supplied for definitions of the other kind
|
|
92
|
+
fails closed. Namespace, budget, resolver, annotation, and atomic-validation
|
|
93
|
+
behavior must stay identical between Provider and direct registration. The
|
|
94
|
+
authenticated REST route remains the execution authorization boundary.
|
|
95
|
+
|
|
96
|
+
With the fixed mounted-UI adapter enabled, Provider also owns shared
|
|
97
|
+
control/data-surface registries and registers six fixed `smrt_ui_*` tools. This
|
|
98
|
+
adapter is a separate, consent-gated surface and is not governed by the
|
|
99
|
+
generated-model effect policy. Descendant rich Forms use the shared
|
|
100
|
+
control registry unless their explicit `interactionRegistry` prop overrides it.
|
|
101
|
+
Supply `webmcp.ui.dataSurfaceRegistry` when mounted surface components already
|
|
102
|
+
share an application registry. The adapter resolves registry state at execution
|
|
103
|
+
time, never reads the DOM, never accepts agent confirmation, and removes the
|
|
104
|
+
entire tool set with one abort signal. A document may have only one active
|
|
105
|
+
adapter for a prefix; configure distinct prefixes for intentional coexistence.
|
|
106
|
+
|
|
67
107
|
## Hooks
|
|
68
108
|
|
|
69
109
|
| Hook | Returns |
|
|
@@ -78,6 +118,11 @@ Wraps app in `+layout.svelte`. Provides auth state, permissions, WebSocket, and
|
|
|
78
118
|
|
|
79
119
|
## AI System
|
|
80
120
|
|
|
121
|
+
- Rich Form WebMCP tools only stage review proposals. Structured payloads are
|
|
122
|
+
limited to published schema properties, money uses safe integer minor units,
|
|
123
|
+
and injected legacy registries without `executeBatch` use ordered `execute`
|
|
124
|
+
calls.
|
|
125
|
+
|
|
81
126
|
- **Preload strategies**: `none`, `eager`, `idle` (recommended), `on-visible`
|
|
82
127
|
- **Warm client cache**: module-level Map survives navigation/remounts -- avoids re-downloading WASM/models
|
|
83
128
|
- **Adapters**: STT (browser-speech, whisper-cpp, whisper-wasm), TTS (browser-synthesis), LLM (webllm, transformers-llm)
|
package/README.md
CHANGED
|
@@ -92,6 +92,79 @@ hydrating its whole collection. It exposes `rows`, `page`, `total`,
|
|
|
92
92
|
</Provider>
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
The Provider can own generated WebMCP tools for the same lifecycle. Its policy
|
|
96
|
+
is identical to `registerWebMcpTools`; omitted `effects` exposes reads only:
|
|
97
|
+
|
|
98
|
+
```svelte
|
|
99
|
+
<Provider webmcp={{
|
|
100
|
+
definitions,
|
|
101
|
+
effects: ['read', 'write'],
|
|
102
|
+
namespace: 'workspace',
|
|
103
|
+
maxTools: 24
|
|
104
|
+
}}>
|
|
105
|
+
{@render children()}
|
|
106
|
+
</Provider>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
This controls capability exposure, not authorization. Tool execution still
|
|
110
|
+
crosses the authenticated REST boundary and must retain its auth and tenancy
|
|
111
|
+
guards. The `effects`, `filter`, and `filterTool` policy applies to generated
|
|
112
|
+
data/model tools only; the fixed mounted-UI adapter has the separate controls
|
|
113
|
+
described below.
|
|
114
|
+
|
|
115
|
+
WebMCP test doubles and polyfills should implement the browser's
|
|
116
|
+
promise-returning `document.modelContext.registerTool()` contract; declare the
|
|
117
|
+
function `async` when migrating older void-returning fixtures.
|
|
118
|
+
|
|
119
|
+
### Mounted UI through WebMCP
|
|
120
|
+
|
|
121
|
+
`<Provider webmcp>` registers six fixed `smrt_ui_*` tools for the mounted UI:
|
|
122
|
+
list, inspect, and execute for form controls and data surfaces. The tool set does
|
|
123
|
+
not change as components mount and unmount; each call reads the current
|
|
124
|
+
transport-neutral registries instead of inspecting or simulating the DOM.
|
|
125
|
+
|
|
126
|
+
Forms automatically join the Provider's control registry. An explicit Form
|
|
127
|
+
`interactionRegistry` still takes precedence. Pass the same data-surface
|
|
128
|
+
registry used by `DataTable` or `CollectionToolbar` when those mounted surfaces
|
|
129
|
+
should be discoverable:
|
|
130
|
+
|
|
131
|
+
```svelte
|
|
132
|
+
<script lang="ts">
|
|
133
|
+
import { createDataSurfaceRegistry } from '@happyvertical/smrt-ui/data';
|
|
134
|
+
import { Provider } from '@happyvertical/smrt-svelte';
|
|
135
|
+
|
|
136
|
+
const surfaces = createDataSurfaceRegistry();
|
|
137
|
+
</script>
|
|
138
|
+
|
|
139
|
+
<Provider webmcp={{ ui: { dataSurfaceRegistry: surfaces } }}>
|
|
140
|
+
<!-- pass {surfaces} to mounted data-surface components -->
|
|
141
|
+
{@render children()}
|
|
142
|
+
</Provider>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The default prefix is `smrt_ui_`. Configure `ui.prefix` when multiple Providers
|
|
146
|
+
must coexist in one document; the same prefix cannot be registered twice.
|
|
147
|
+
`ui: false` disables only the fixed UI adapter while leaving generated model
|
|
148
|
+
tools enabled. For compatibility, an object config that omits `ui` continues to
|
|
149
|
+
enable only generated model tools; use `webmcp={true}` or provide `ui: {}` to
|
|
150
|
+
enable the mounted-UI adapter.
|
|
151
|
+
|
|
152
|
+
Form commands always run with `source: 'agent'`. WebMCP input cannot assert
|
|
153
|
+
confirmation: staging is allowed by the registry policy, while apply, clear,
|
|
154
|
+
and undo require a separate human-confirmed path. Secret control values and
|
|
155
|
+
hidden data-surface columns are not serialized. Read responses are marked as
|
|
156
|
+
untrusted content. Bespoke `useWebMcpTool` and `<Form webmcp>` tools retain their
|
|
157
|
+
existing lifecycle and submit behavior.
|
|
158
|
+
|
|
159
|
+
Custom rich fields may continue to call `registerField(field)` and later
|
|
160
|
+
`unregisterField(name)`. New code should retain and invoke the disposer returned
|
|
161
|
+
by `registerField`: it is bound to that exact registration, so cleanup cannot
|
|
162
|
+
remove a same-name replacement. The return value is additive; legacy form
|
|
163
|
+
contexts whose `registerField` returns `void` remain supported. Context accessors
|
|
164
|
+
bind legacy name-based cleanup to registrations made by that caller, so
|
|
165
|
+
overlapping same-name fields can unmount in either order without retaining a
|
|
166
|
+
detached control.
|
|
167
|
+
|
|
95
168
|
### Form Components
|
|
96
169
|
|
|
97
170
|
```svelte
|
package/dist/Provider.svelte
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { createDataSurfaceRegistry } from '@happyvertical/smrt-ui/data';
|
|
3
|
+
import { createControlInteractionRegistry } from '@happyvertical/smrt-ui/forms';
|
|
2
4
|
import {
|
|
3
5
|
createI18nContext,
|
|
4
6
|
type I18nSnapshot,
|
|
5
7
|
setI18nContext,
|
|
6
8
|
} from '@happyvertical/smrt-ui/i18n';
|
|
7
|
-
import {
|
|
8
|
-
type RegisterWebMcpToolsOptions,
|
|
9
|
-
type SmrtWebClient,
|
|
10
|
-
type SmrtWebCollectionDefinition,
|
|
11
|
-
} from '@happyvertical/smrt-web';
|
|
12
9
|
import type { Snippet } from 'svelte';
|
|
13
10
|
import { onDestroy, untrack } from 'svelte';
|
|
14
11
|
import { logger } from './internal/logger.js';
|
|
@@ -21,6 +18,9 @@ import type {
|
|
|
21
18
|
} from './state/app-state.js';
|
|
22
19
|
import { createAppState } from './state/app-state.svelte.js';
|
|
23
20
|
import { setAppStateContext } from './state/context.js';
|
|
21
|
+
import type { WebMcpProviderConfig } from './web/webmcp-provider.js';
|
|
22
|
+
import { registerWebMcpUiTools } from './web/webmcp-ui.js';
|
|
23
|
+
import { setWebMcpUiContext } from './web/webmcp-ui-context.js';
|
|
24
24
|
|
|
25
25
|
interface Props {
|
|
26
26
|
/**
|
|
@@ -84,9 +84,9 @@ interface Props {
|
|
|
84
84
|
*/
|
|
85
85
|
i18n?: I18nSnapshot;
|
|
86
86
|
/**
|
|
87
|
-
* Opt in to
|
|
88
|
-
* WebMCP is feature-detected
|
|
89
|
-
* browsers that do not expose `document.modelContext`.
|
|
87
|
+
* Opt in to generated data tools and the fixed mounted-UI tool adapter for
|
|
88
|
+
* this browser surface. WebMCP is feature-detected, so this is safe during
|
|
89
|
+
* SSR and on browsers that do not expose `document.modelContext`.
|
|
90
90
|
*/
|
|
91
91
|
webmcp?: boolean | WebMcpProviderConfig;
|
|
92
92
|
/**
|
|
@@ -95,15 +95,6 @@ interface Props {
|
|
|
95
95
|
children: Snippet;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
export interface WebMcpProviderConfig {
|
|
99
|
-
definitions?: SmrtWebCollectionDefinition[];
|
|
100
|
-
client?: SmrtWebClient;
|
|
101
|
-
basePath?: string;
|
|
102
|
-
fetchFn?: typeof fetch;
|
|
103
|
-
scope?: string;
|
|
104
|
-
filter?: RegisterWebMcpToolsOptions['filter'];
|
|
105
|
-
}
|
|
106
|
-
|
|
107
98
|
const {
|
|
108
99
|
mode,
|
|
109
100
|
autoEnableSmrt = true,
|
|
@@ -135,6 +126,35 @@ const appState = createAppState({
|
|
|
135
126
|
},
|
|
136
127
|
});
|
|
137
128
|
|
|
129
|
+
const localControlRegistry = createControlInteractionRegistry();
|
|
130
|
+
const localDataSurfaceRegistry = createDataSurfaceRegistry();
|
|
131
|
+
const webMcpConfig = $derived(typeof webmcp === 'object' ? webmcp : undefined);
|
|
132
|
+
const webMcpUiConfig = $derived(
|
|
133
|
+
webmcp === true
|
|
134
|
+
? {}
|
|
135
|
+
: typeof webMcpConfig?.ui === 'object'
|
|
136
|
+
? webMcpConfig.ui
|
|
137
|
+
: undefined,
|
|
138
|
+
);
|
|
139
|
+
const resolvedControlRegistry = $derived(
|
|
140
|
+
webMcpUiConfig?.controlRegistry ?? localControlRegistry,
|
|
141
|
+
);
|
|
142
|
+
const resolvedDataSurfaceRegistry = $derived(
|
|
143
|
+
webMcpUiConfig?.dataSurfaceRegistry ?? localDataSurfaceRegistry,
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
setWebMcpUiContext({
|
|
147
|
+
get enabled() {
|
|
148
|
+
return webMcpUiConfig !== undefined;
|
|
149
|
+
},
|
|
150
|
+
get controlRegistry() {
|
|
151
|
+
return resolvedControlRegistry;
|
|
152
|
+
},
|
|
153
|
+
get dataSurfaceRegistry() {
|
|
154
|
+
return resolvedDataSurfaceRegistry;
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
138
158
|
$effect(() => {
|
|
139
159
|
const currentPreferences = untrack(() => appState.state.session.preferences);
|
|
140
160
|
if (currentPreferences.autoEnableSmrt === autoEnableSmrt) {
|
|
@@ -149,6 +169,21 @@ $effect(() => {
|
|
|
149
169
|
});
|
|
150
170
|
});
|
|
151
171
|
|
|
172
|
+
// Register one fixed UI tool set. Mounted components change registry contents,
|
|
173
|
+
// not the document-level WebMCP tool set.
|
|
174
|
+
$effect(() => {
|
|
175
|
+
if (typeof window === 'undefined' || !webmcp || !webMcpUiConfig) return;
|
|
176
|
+
try {
|
|
177
|
+
return registerWebMcpUiTools({
|
|
178
|
+
controlRegistry: resolvedControlRegistry,
|
|
179
|
+
dataSurfaceRegistry: resolvedDataSurfaceRegistry,
|
|
180
|
+
...(webMcpUiConfig.prefix ? { prefix: webMcpUiConfig.prefix } : {}),
|
|
181
|
+
});
|
|
182
|
+
} catch (error) {
|
|
183
|
+
logger.warn('Provider: WebMCP UI tool registration rejected', { error });
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
152
187
|
// Keep generated data-plane tools scoped to this Provider. The registrar
|
|
153
188
|
// feature-detects WebMCP itself; effects do not run during SSR.
|
|
154
189
|
$effect(() => {
|
|
@@ -160,16 +195,38 @@ $effect(() => {
|
|
|
160
195
|
|
|
161
196
|
// Keep the data-plane engine out of applications that do not opt in. The
|
|
162
197
|
// dynamic import also means SSR never evaluates browser-only engine code.
|
|
163
|
-
void import('@happyvertical/smrt-web')
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
198
|
+
void import('@happyvertical/smrt-web')
|
|
199
|
+
.then(({ registerWebMcpTools }) => {
|
|
200
|
+
if (cancelled) return;
|
|
201
|
+
const registration = registerWebMcpTools(config.definitions ?? [], {
|
|
202
|
+
client: config.client,
|
|
203
|
+
basePath: config.basePath,
|
|
204
|
+
fetchFn: config.fetchFn,
|
|
205
|
+
scope: config.scope,
|
|
206
|
+
filter: config.filter,
|
|
207
|
+
filterTool: config.filterTool,
|
|
208
|
+
resolveFetchers: config.resolveFetchers,
|
|
209
|
+
resolveToolFetchers: config.resolveToolFetchers,
|
|
210
|
+
effects: config.effects,
|
|
211
|
+
namespace: config.namespace,
|
|
212
|
+
maxTools: config.maxTools,
|
|
213
|
+
});
|
|
214
|
+
dispose = registration;
|
|
215
|
+
void registration.ready.catch((error) => {
|
|
216
|
+
if (!cancelled) {
|
|
217
|
+
logger.warn('Provider: WebMCP data tool registration rejected', {
|
|
218
|
+
error,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
})
|
|
223
|
+
.catch((error) => {
|
|
224
|
+
if (!cancelled) {
|
|
225
|
+
logger.warn('Provider: WebMCP data tool registration rejected', {
|
|
226
|
+
error,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
171
229
|
});
|
|
172
|
-
});
|
|
173
230
|
|
|
174
231
|
return () => {
|
|
175
232
|
cancelled = true;
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import { type I18nSnapshot } from '@happyvertical/smrt-ui/i18n';
|
|
2
|
-
import { type RegisterWebMcpToolsOptions, type SmrtWebClient, type SmrtWebCollectionDefinition } from '@happyvertical/smrt-web';
|
|
3
2
|
import type { Snippet } from 'svelte';
|
|
4
3
|
import type { AIConfig, AILoadingState, AppMode, SocketConfig, User } from './state/app-state.js';
|
|
5
|
-
|
|
6
|
-
definitions?: SmrtWebCollectionDefinition[];
|
|
7
|
-
client?: SmrtWebClient;
|
|
8
|
-
basePath?: string;
|
|
9
|
-
fetchFn?: typeof fetch;
|
|
10
|
-
scope?: string;
|
|
11
|
-
filter?: RegisterWebMcpToolsOptions['filter'];
|
|
12
|
-
}
|
|
4
|
+
import type { WebMcpProviderConfig } from './web/webmcp-provider.js';
|
|
13
5
|
interface Props {
|
|
14
6
|
/**
|
|
15
7
|
* Initial mode: 'default' | 'smrt'
|
|
@@ -72,9 +64,9 @@ interface Props {
|
|
|
72
64
|
*/
|
|
73
65
|
i18n?: I18nSnapshot;
|
|
74
66
|
/**
|
|
75
|
-
* Opt in to
|
|
76
|
-
* WebMCP is feature-detected
|
|
77
|
-
* browsers that do not expose `document.modelContext`.
|
|
67
|
+
* Opt in to generated data tools and the fixed mounted-UI tool adapter for
|
|
68
|
+
* this browser surface. WebMCP is feature-detected, so this is safe during
|
|
69
|
+
* SSR and on browsers that do not expose `document.modelContext`.
|
|
78
70
|
*/
|
|
79
71
|
webmcp?: boolean | WebMcpProviderConfig;
|
|
80
72
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Provider.svelte.d.ts","sourceRoot":"","sources":["../src/Provider.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Provider.svelte.d.ts","sourceRoot":"","sources":["../src/Provider.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,YAAY,EAElB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,KAAK,EACV,QAAQ,EACR,cAAc,EACd,OAAO,EACP,YAAY,EACZ,IAAI,EACL,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAKrE,UAAU,KAAK;IACb;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;;OAGG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;;;;;;;;;;;;OAeG;IACH,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACpD;;;;;OAKG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,oBAAoB,CAAC;IACxC;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB;AAiPD,QAAA,MAAM,QAAQ,2CAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Provider from '../Provider.svelte';
|
|
3
|
+
import type { WebMcpProviderConfig } from '../web/webmcp-provider.js';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
webmcp: WebMcpProviderConfig;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const { webmcp }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<Provider {webmcp}>
|
|
13
|
+
<span></span>
|
|
14
|
+
</Provider>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { WebMcpProviderConfig } from '../web/webmcp-provider.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
webmcp: WebMcpProviderConfig;
|
|
4
|
+
}
|
|
5
|
+
declare const ProviderWebmcpHarness: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type ProviderWebmcpHarness = ReturnType<typeof ProviderWebmcpHarness>;
|
|
7
|
+
export default ProviderWebmcpHarness;
|
|
8
|
+
//# sourceMappingURL=provider-webmcp-harness.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-webmcp-harness.svelte.d.ts","sourceRoot":"","sources":["../../src/__tests__/provider-webmcp-harness.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAGtE,UAAU,KAAK;IACb,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAeD,QAAA,MAAM,qBAAqB,2CAAwC,CAAC;AACpE,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACtE,eAAe,qBAAqB,CAAC"}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
3
|
-
import {
|
|
3
|
+
import { untrack } from 'svelte';
|
|
4
4
|
import { useAppState } from '../../hooks/useAppState.svelte.js';
|
|
5
5
|
import { M } from '../../i18n/strings.forms.js';
|
|
6
6
|
import {
|
|
7
7
|
type FieldDefinition,
|
|
8
8
|
tryGetFormContext,
|
|
9
9
|
} from '../../state/form-context.js';
|
|
10
|
+
import {
|
|
11
|
+
invalidStagedValue,
|
|
12
|
+
prepareTextFieldValue,
|
|
13
|
+
} from './prepare-field-value.js';
|
|
10
14
|
import type { AddressValue } from './types.js';
|
|
11
15
|
|
|
12
16
|
const { t } = useI18n();
|
|
@@ -80,8 +84,66 @@ let {
|
|
|
80
84
|
onchange,
|
|
81
85
|
}: Props = $props();
|
|
82
86
|
|
|
87
|
+
function countryValues(): string[] {
|
|
88
|
+
return [...new Set(countries.map((option) => option.value))];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function provinceValues(): string[] {
|
|
92
|
+
return [
|
|
93
|
+
...new Set([
|
|
94
|
+
...(!required ? [''] : []),
|
|
95
|
+
...provinces.map((option) => option.value),
|
|
96
|
+
]),
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function schemaForField(field: AddressField): Record<string, unknown> {
|
|
101
|
+
if (field === 'country') return { type: 'string', enum: countryValues() };
|
|
102
|
+
if (field === 'province') return { type: 'string', enum: provinceValues() };
|
|
103
|
+
return { type: 'string' };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function validatesAddressMembers(candidate: unknown): boolean {
|
|
107
|
+
if (typeof candidate !== 'object' || Array.isArray(candidate)) return false;
|
|
108
|
+
const address = candidate as Record<string, unknown>;
|
|
109
|
+
if (
|
|
110
|
+
![Object.prototype, null].includes(Object.getPrototypeOf(address)) ||
|
|
111
|
+
!Object.keys(address).every((key) =>
|
|
112
|
+
fields.includes(key as AddressField),
|
|
113
|
+
) ||
|
|
114
|
+
!fields.every(
|
|
115
|
+
(field) =>
|
|
116
|
+
!Object.hasOwn(address, field) || typeof address[field] === 'string',
|
|
117
|
+
)
|
|
118
|
+
) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
if (
|
|
122
|
+
(Object.hasOwn(address, 'country') &&
|
|
123
|
+
!countryValues().includes(address.country as string)) ||
|
|
124
|
+
(Object.hasOwn(address, 'province') &&
|
|
125
|
+
!provinceValues().includes(address.province as string))
|
|
126
|
+
) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function validatesAddressCandidate(candidate: unknown): boolean {
|
|
133
|
+
if (candidate === null || candidate === undefined) return !required;
|
|
134
|
+
if (!validatesAddressMembers(candidate)) return false;
|
|
135
|
+
if (!required) return true;
|
|
136
|
+
const address = candidate as Record<string, unknown>;
|
|
137
|
+
return fields.every(
|
|
138
|
+
(field) =>
|
|
139
|
+
typeof address[field] === 'string' && address[field].trim().length > 0,
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
83
143
|
const app = useAppState();
|
|
84
144
|
const formContext = tryGetFormContext();
|
|
145
|
+
const fieldOwnerId = $props.id();
|
|
146
|
+
const fieldOwnerToken = `smrt-rich-field-${fieldOwnerId}`;
|
|
85
147
|
|
|
86
148
|
const isSmrt = $derived(app.state.mode === 'smrt');
|
|
87
149
|
|
|
@@ -90,7 +152,7 @@ let street = $state(value.street ?? '');
|
|
|
90
152
|
let city = $state(value.city ?? '');
|
|
91
153
|
let province = $state(value.province ?? '');
|
|
92
154
|
let postalCode = $state(value.postalCode ?? '');
|
|
93
|
-
let country = $state(value.country ?? '
|
|
155
|
+
let country = $state(value.country ?? untrack(() => countries[0]?.value ?? ''));
|
|
94
156
|
|
|
95
157
|
// Keep in sync with external value changes
|
|
96
158
|
$effect(() => {
|
|
@@ -105,13 +167,18 @@ $effect(() => {
|
|
|
105
167
|
country = value.country;
|
|
106
168
|
});
|
|
107
169
|
|
|
108
|
-
function
|
|
170
|
+
function currentValue(): Partial<AddressValue> {
|
|
109
171
|
const newValue: Partial<AddressValue> = {};
|
|
110
172
|
if (fields.includes('street')) newValue.street = street;
|
|
111
173
|
if (fields.includes('city')) newValue.city = city;
|
|
112
174
|
if (fields.includes('province')) newValue.province = province;
|
|
113
175
|
if (fields.includes('postalCode')) newValue.postalCode = postalCode;
|
|
114
176
|
if (fields.includes('country')) newValue.country = country;
|
|
177
|
+
return newValue;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function updateValue() {
|
|
181
|
+
const newValue = currentValue();
|
|
115
182
|
value = newValue;
|
|
116
183
|
onchange?.(newValue);
|
|
117
184
|
}
|
|
@@ -141,11 +208,16 @@ function parseSpokenAddress(text: string): Partial<AddressValue> {
|
|
|
141
208
|
}
|
|
142
209
|
}
|
|
143
210
|
|
|
144
|
-
// Try to extract country
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
211
|
+
// Try to extract a currently configured country by its label or value.
|
|
212
|
+
for (const option of countries) {
|
|
213
|
+
const matches = [option.label, option.value].some((candidate) => {
|
|
214
|
+
const escaped = candidate.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
215
|
+
return new RegExp(`(^|\\W)${escaped}(?=$|\\W)`, 'i').test(normalized);
|
|
216
|
+
});
|
|
217
|
+
if (matches) {
|
|
218
|
+
result.country = option.value;
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
149
221
|
}
|
|
150
222
|
|
|
151
223
|
// Common city extraction patterns
|
|
@@ -192,26 +264,33 @@ const primaryFieldId = $derived.by(() => {
|
|
|
192
264
|
});
|
|
193
265
|
|
|
194
266
|
// Register with form context
|
|
195
|
-
|
|
267
|
+
$effect(() => {
|
|
196
268
|
if (formContext) {
|
|
269
|
+
const registeredName = name;
|
|
197
270
|
const fieldDef: FieldDefinition = {
|
|
198
|
-
name,
|
|
271
|
+
name: registeredName,
|
|
272
|
+
ownerToken: fieldOwnerToken,
|
|
199
273
|
type: 'address',
|
|
200
|
-
label
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
274
|
+
get label() {
|
|
275
|
+
return label;
|
|
276
|
+
},
|
|
277
|
+
get description() {
|
|
278
|
+
return (
|
|
279
|
+
description ||
|
|
280
|
+
'A mailing address with street, city, province, postal code, and country'
|
|
281
|
+
);
|
|
282
|
+
},
|
|
204
283
|
setValue: (v: unknown) => {
|
|
205
284
|
if (v === null || v === undefined) {
|
|
206
285
|
street = '';
|
|
207
286
|
city = '';
|
|
208
287
|
province = '';
|
|
209
288
|
postalCode = '';
|
|
210
|
-
country = '
|
|
289
|
+
country = countries[0]?.value ?? '';
|
|
211
290
|
updateValue();
|
|
212
291
|
return;
|
|
213
292
|
}
|
|
214
|
-
if (
|
|
293
|
+
if (validatesAddressMembers(v)) {
|
|
215
294
|
const addr = v as Partial<AddressValue>;
|
|
216
295
|
if (addr.street !== undefined) street = addr.street;
|
|
217
296
|
if (addr.city !== undefined) city = addr.city;
|
|
@@ -222,36 +301,70 @@ onMount(() => {
|
|
|
222
301
|
return;
|
|
223
302
|
}
|
|
224
303
|
// Try to parse spoken address
|
|
225
|
-
const parsed =
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (parsed.
|
|
304
|
+
const parsed = Object.fromEntries(
|
|
305
|
+
Object.entries(parseSpokenAddress(String(v))).filter(([field]) =>
|
|
306
|
+
fields.includes(field as AddressField),
|
|
307
|
+
),
|
|
308
|
+
) as Partial<AddressValue>;
|
|
309
|
+
if (Object.keys(parsed).length > 0 && validatesAddressMembers(parsed)) {
|
|
310
|
+
if (parsed.street !== undefined) street = parsed.street;
|
|
311
|
+
if (parsed.city !== undefined) city = parsed.city;
|
|
312
|
+
if (parsed.province !== undefined) province = parsed.province;
|
|
313
|
+
if (parsed.postalCode !== undefined) postalCode = parsed.postalCode;
|
|
314
|
+
if (parsed.country !== undefined) country = parsed.country;
|
|
232
315
|
updateValue();
|
|
233
316
|
}
|
|
234
317
|
},
|
|
235
|
-
getValue:
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
318
|
+
getValue: currentValue,
|
|
319
|
+
prepareValue: (candidate) => {
|
|
320
|
+
if (candidate === null || candidate === undefined) {
|
|
321
|
+
return Object.fromEntries(
|
|
322
|
+
fields.map((field) => [
|
|
323
|
+
field,
|
|
324
|
+
field === 'country' ? (countries[0]?.value ?? '') : '',
|
|
325
|
+
]),
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
if (typeof candidate === 'object' && !Array.isArray(candidate)) {
|
|
329
|
+
return candidate;
|
|
330
|
+
}
|
|
331
|
+
const parsed = parseSpokenAddress(prepareTextFieldValue(candidate));
|
|
332
|
+
const configured = Object.fromEntries(
|
|
333
|
+
Object.entries(parsed).filter(([field]) =>
|
|
334
|
+
fields.includes(field as AddressField),
|
|
335
|
+
),
|
|
336
|
+
);
|
|
337
|
+
return Object.keys(configured).length > 0
|
|
338
|
+
? { ...currentValue(), ...configured }
|
|
339
|
+
: invalidStagedValue();
|
|
340
|
+
},
|
|
341
|
+
clear: () => {
|
|
342
|
+
street = '';
|
|
343
|
+
city = '';
|
|
344
|
+
province = '';
|
|
345
|
+
postalCode = '';
|
|
346
|
+
country = countries[0]?.value ?? '';
|
|
347
|
+
updateValue();
|
|
348
|
+
return true;
|
|
349
|
+
},
|
|
350
|
+
getState: () => ({ disabled }),
|
|
351
|
+
get constraints() {
|
|
352
|
+
return { required };
|
|
353
|
+
},
|
|
354
|
+
get webMcpSchema() {
|
|
355
|
+
return {
|
|
356
|
+
type: 'object',
|
|
357
|
+
additionalProperties: false,
|
|
358
|
+
properties: Object.fromEntries(
|
|
359
|
+
fields.map((field) => [field, schemaForField(field)]),
|
|
360
|
+
),
|
|
361
|
+
...(required ? { required: [...fields] } : {}),
|
|
362
|
+
};
|
|
243
363
|
},
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
fields.every((field) => String(value[field] ?? '').trim().length > 0),
|
|
364
|
+
validateValue: validatesAddressCandidate,
|
|
365
|
+
validate: () => validatesAddressCandidate(currentValue()),
|
|
247
366
|
};
|
|
248
|
-
formContext.registerField(fieldDef);
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
onDestroy(() => {
|
|
253
|
-
if (formContext) {
|
|
254
|
-
formContext.unregisterField(name);
|
|
367
|
+
return formContext.registerField(fieldDef);
|
|
255
368
|
}
|
|
256
369
|
});
|
|
257
370
|
|
|
@@ -281,7 +394,7 @@ function handleCountryChange(e: Event) {
|
|
|
281
394
|
}
|
|
282
395
|
</script>
|
|
283
396
|
|
|
284
|
-
<div class="smrt-address">
|
|
397
|
+
<div class="smrt-address" data-smrt-field-owner={fieldOwnerToken}>
|
|
285
398
|
{#if label}
|
|
286
399
|
<label class="smrt-label" for={primaryFieldId}>
|
|
287
400
|
{label}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddressInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/AddressInput.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AddressInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/AddressInput.svelte.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,KAAK,YAAY,GAAG,MAAM,YAAY,CAAC;AAEvC,MAAM,WAAW,KAAK;IACpB,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9B,2BAA2B;IAC3B,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;IACxB,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,mCAAmC;IACnC,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,0CAA0C;IAC1C,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,gCAAgC;IAChC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;CACnD;AAibD,QAAA,MAAM,YAAY,gDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|