@virtualdisplay.io/client 4.0.0-alpha.15 → 4.0.0-alpha.16
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/CHANGELOG.md +6 -0
- package/dist/index.d.ts +1064 -0
- package/dist/virtualdisplay.client.cjs.js +3 -3
- package/dist/virtualdisplay.client.es.js +448 -448
- package/dist/virtualdisplay.client.umd.js +4 -4
- package/package.json +3 -3
- package/dist/src/annotations/annotations.d.ts +0 -20
- package/dist/src/annotations/annotations.d.ts.map +0 -1
- package/dist/src/annotations/index.d.ts +0 -2
- package/dist/src/annotations/index.d.ts.map +0 -1
- package/dist/src/attributes/attribute.d.ts +0 -40
- package/dist/src/attributes/attribute.d.ts.map +0 -1
- package/dist/src/attributes/attributes.d.ts +0 -45
- package/dist/src/attributes/attributes.d.ts.map +0 -1
- package/dist/src/attributes/selections.d.ts +0 -17
- package/dist/src/attributes/selections.d.ts.map +0 -1
- package/dist/src/attributes/value.d.ts +0 -13
- package/dist/src/attributes/value.d.ts.map +0 -1
- package/dist/src/camera/camera.d.ts +0 -40
- package/dist/src/camera/camera.d.ts.map +0 -1
- package/dist/src/camera/index.d.ts +0 -4
- package/dist/src/camera/index.d.ts.map +0 -1
- package/dist/src/camera/position.d.ts +0 -56
- package/dist/src/camera/position.d.ts.map +0 -1
- package/dist/src/client/client.d.ts +0 -71
- package/dist/src/client/client.d.ts.map +0 -1
- package/dist/src/client/error.d.ts +0 -23
- package/dist/src/client/error.d.ts.map +0 -1
- package/dist/src/client/events.d.ts +0 -22
- package/dist/src/client/events.d.ts.map +0 -1
- package/dist/src/client/iframe-builder.d.ts +0 -27
- package/dist/src/client/iframe-builder.d.ts.map +0 -1
- package/dist/src/client/options.d.ts +0 -19
- package/dist/src/client/options.d.ts.map +0 -1
- package/dist/src/client/ready-state-tracker.d.ts +0 -13
- package/dist/src/client/ready-state-tracker.d.ts.map +0 -1
- package/dist/src/client/types.d.ts +0 -20
- package/dist/src/client/types.d.ts.map +0 -1
- package/dist/src/configuration/configuration.d.ts +0 -113
- package/dist/src/configuration/configuration.d.ts.map +0 -1
- package/dist/src/configuration/index.d.ts +0 -2
- package/dist/src/configuration/index.d.ts.map +0 -1
- package/dist/src/configuration/resolver.d.ts +0 -16
- package/dist/src/configuration/resolver.d.ts.map +0 -1
- package/dist/src/focus/focus.d.ts +0 -43
- package/dist/src/focus/focus.d.ts.map +0 -1
- package/dist/src/focus/index.d.ts +0 -2
- package/dist/src/focus/index.d.ts.map +0 -1
- package/dist/src/index.d.ts +0 -16
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/snapshot/index.d.ts +0 -3
- package/dist/src/snapshot/index.d.ts.map +0 -1
- package/dist/src/snapshot/photo.d.ts +0 -47
- package/dist/src/snapshot/photo.d.ts.map +0 -1
- package/dist/src/snapshot/snapshot.d.ts +0 -36
- package/dist/src/snapshot/snapshot.d.ts.map +0 -1
- package/dist/src/ui/action-bar.d.ts +0 -18
- package/dist/src/ui/action-bar.d.ts.map +0 -1
- package/dist/src/ui/camera-controls.d.ts +0 -8
- package/dist/src/ui/camera-controls.d.ts.map +0 -1
- package/dist/src/ui/commerce-panel.d.ts +0 -31
- package/dist/src/ui/commerce-panel.d.ts.map +0 -1
- package/dist/src/ui/controls/attribute-group.d.ts +0 -6
- package/dist/src/ui/controls/attribute-group.d.ts.map +0 -1
- package/dist/src/ui/event-bus.d.ts +0 -12
- package/dist/src/ui/event-bus.d.ts.map +0 -1
- package/dist/src/ui/layouts/inframe-layout.d.ts +0 -13
- package/dist/src/ui/layouts/inframe-layout.d.ts.map +0 -1
- package/dist/src/ui/layouts/layout.d.ts +0 -15
- package/dist/src/ui/layouts/layout.d.ts.map +0 -1
- package/dist/src/ui/layouts/null-layout.d.ts +0 -12
- package/dist/src/ui/layouts/null-layout.d.ts.map +0 -1
- package/dist/src/ui/layouts/registry.d.ts +0 -4
- package/dist/src/ui/layouts/registry.d.ts.map +0 -1
- package/dist/src/ui/layouts/sidebar-layout.d.ts +0 -24
- package/dist/src/ui/layouts/sidebar-layout.d.ts.map +0 -1
- package/dist/src/ui/loading.d.ts +0 -43
- package/dist/src/ui/loading.d.ts.map +0 -1
- package/dist/src/ui/standard-interface.d.ts +0 -47
- package/dist/src/ui/standard-interface.d.ts.map +0 -1
- package/dist/src/ui/styles.d.ts +0 -3
- package/dist/src/ui/styles.d.ts.map +0 -1
- package/dist/src/utils/logger.d.ts +0 -11
- package/dist/src/utils/logger.d.ts.map +0 -1
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1064 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Virtualdisplay iframe messaging protocol
|
|
3
|
+
*
|
|
4
|
+
* All message types exchanged between client (parent page)
|
|
5
|
+
* and server (iframe viewer engine) via postMessage.
|
|
6
|
+
*/
|
|
7
|
+
declare const MESSAGE_TYPES$1: {
|
|
8
|
+
readonly HANDSHAKE: "handshake";
|
|
9
|
+
readonly MUTATION: "mutation";
|
|
10
|
+
readonly STATE: "state";
|
|
11
|
+
readonly LOADING_INDICATOR: "loading_indicator";
|
|
12
|
+
readonly CAMERA: "camera";
|
|
13
|
+
readonly SNAPSHOT: "snapshot";
|
|
14
|
+
readonly MAPPING: "mapping";
|
|
15
|
+
readonly AR_ACTIVATE: "ar_activate";
|
|
16
|
+
readonly CONFIG: "config";
|
|
17
|
+
readonly ANNOTATION_PLACE_MODE: "annotation_place_mode";
|
|
18
|
+
readonly ANNOTATION_PLACED: "annotation_placed";
|
|
19
|
+
readonly ANNOTATION_TOGGLE: "annotation_toggle";
|
|
20
|
+
readonly FOCUS: "focus";
|
|
21
|
+
readonly PRICING: "pricing";
|
|
22
|
+
};
|
|
23
|
+
interface MutationDto$1 {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly value: string;
|
|
26
|
+
}
|
|
27
|
+
interface MutationResult$1 {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly value: string;
|
|
30
|
+
readonly success: boolean;
|
|
31
|
+
readonly error?: string;
|
|
32
|
+
}
|
|
33
|
+
interface MutationMessage$1 {
|
|
34
|
+
readonly type: typeof MESSAGE_TYPES$1.MUTATION;
|
|
35
|
+
readonly mutations: MutationDto$1[];
|
|
36
|
+
readonly isInitial: boolean;
|
|
37
|
+
}
|
|
38
|
+
interface MutationResultMessage$1 {
|
|
39
|
+
readonly type: typeof MESSAGE_TYPES$1.MUTATION;
|
|
40
|
+
readonly results: MutationResult$1[];
|
|
41
|
+
readonly isInitial: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Viewer settings from model metadata (server → client via MAPPING).
|
|
45
|
+
* Customer-configured in the portal.
|
|
46
|
+
*/
|
|
47
|
+
interface ViewerSettings$1 {
|
|
48
|
+
readonly ar?: boolean;
|
|
49
|
+
readonly fullscreen?: boolean;
|
|
50
|
+
readonly screenshot?: boolean;
|
|
51
|
+
readonly cameraControls?: boolean;
|
|
52
|
+
readonly annotations?: boolean;
|
|
53
|
+
readonly language?: string;
|
|
54
|
+
/** Where the attribute controls sit: in-frame bottom-left (default) or a docked right panel. */
|
|
55
|
+
readonly configuratorLayout?: 'inframe-bottom-left' | 'sidebar-right' | 'hidden';
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Camera movement limits sent to the client via CONFIG.
|
|
59
|
+
* Used to disable camera control buttons when a limit is reached.
|
|
60
|
+
* Units match the camera position: zoom = percentage (0–200), tilt/rotate = degrees.
|
|
61
|
+
*/
|
|
62
|
+
interface CameraLimits$1 {
|
|
63
|
+
readonly minZoom?: number;
|
|
64
|
+
readonly maxZoom?: number;
|
|
65
|
+
readonly minTilt?: number;
|
|
66
|
+
readonly maxTilt?: number;
|
|
67
|
+
readonly minRotate?: number;
|
|
68
|
+
readonly maxRotate?: number;
|
|
69
|
+
}
|
|
70
|
+
interface CameraCommand$1 {
|
|
71
|
+
readonly action: 'rotate' | 'tilt' | 'zoom' | 'reset';
|
|
72
|
+
readonly value?: number;
|
|
73
|
+
}
|
|
74
|
+
interface CameraParameter$1 {
|
|
75
|
+
readonly type: 'rotation' | 'tilt' | 'zoom';
|
|
76
|
+
readonly value: number;
|
|
77
|
+
}
|
|
78
|
+
interface CameraCommandMessage$1 {
|
|
79
|
+
readonly type: typeof MESSAGE_TYPES$1.CAMERA;
|
|
80
|
+
readonly commands: CameraCommand$1[];
|
|
81
|
+
}
|
|
82
|
+
interface CameraPositionMessage$1 {
|
|
83
|
+
readonly type: typeof MESSAGE_TYPES$1.CAMERA;
|
|
84
|
+
readonly transforms: CameraParameter$1[];
|
|
85
|
+
}
|
|
86
|
+
interface SnapshotRequestMessage$1 {
|
|
87
|
+
readonly type: typeof MESSAGE_TYPES$1.SNAPSHOT;
|
|
88
|
+
readonly filename: string;
|
|
89
|
+
}
|
|
90
|
+
interface SnapshotResultMessage$1 {
|
|
91
|
+
readonly type: typeof MESSAGE_TYPES$1.SNAPSHOT;
|
|
92
|
+
readonly filename: string;
|
|
93
|
+
readonly data?: string;
|
|
94
|
+
readonly error?: string;
|
|
95
|
+
}
|
|
96
|
+
interface AttributeDefinition$1 {
|
|
97
|
+
readonly name: string;
|
|
98
|
+
readonly values: string[];
|
|
99
|
+
readonly defaultValue?: string;
|
|
100
|
+
}
|
|
101
|
+
interface MappingMessage$1 {
|
|
102
|
+
readonly type: typeof MESSAGE_TYPES$1.MAPPING;
|
|
103
|
+
readonly attributes: AttributeDefinition$1[];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Loading indicator (server → client): progress percentage, phase label, or error.
|
|
107
|
+
* Sent during model download and parse so the client loading indicator can update.
|
|
108
|
+
*/
|
|
109
|
+
interface LoadingIndicatorMessage$1 {
|
|
110
|
+
readonly type: typeof MESSAGE_TYPES$1.LOADING_INDICATOR;
|
|
111
|
+
/** 0–100 */
|
|
112
|
+
readonly progress: number;
|
|
113
|
+
/** Human-readable phase label, e.g. "downloading" */
|
|
114
|
+
readonly phase: string;
|
|
115
|
+
/** Set when loading failed; client shows error state instead of hiding the overlay. */
|
|
116
|
+
readonly error?: string;
|
|
117
|
+
}
|
|
118
|
+
/** AR activate (client → server): user clicked the AR button. Server handles activation. */
|
|
119
|
+
interface ArActivateMessage$1 {
|
|
120
|
+
readonly type: typeof MESSAGE_TYPES$1.AR_ACTIVATE;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Config (server → client): viewer settings and camera limits from model metadata.
|
|
124
|
+
* Sent early — before MAPPING — so the client can show/hide controls and disable
|
|
125
|
+
* camera buttons at limits as soon as metadata is available.
|
|
126
|
+
*/
|
|
127
|
+
interface ConfigMessage$1 {
|
|
128
|
+
readonly type: typeof MESSAGE_TYPES$1.CONFIG;
|
|
129
|
+
readonly viewerSettings: ViewerSettings$1;
|
|
130
|
+
readonly cameraLimits?: CameraLimits$1;
|
|
131
|
+
}
|
|
132
|
+
interface HandshakeMessage$1 {
|
|
133
|
+
readonly type: typeof MESSAGE_TYPES$1.HANDSHAKE;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Annotation place mode (parent → server): enable or disable click-to-place.
|
|
137
|
+
* When enabled, clicking on the model surface sends back an ANNOTATION_PLACED message.
|
|
138
|
+
*/
|
|
139
|
+
interface AnnotationPlaceModeMessage$1 {
|
|
140
|
+
readonly type: typeof MESSAGE_TYPES$1.ANNOTATION_PLACE_MODE;
|
|
141
|
+
readonly enabled: boolean;
|
|
142
|
+
}
|
|
143
|
+
/** Position on the model surface returned by raycasting. */
|
|
144
|
+
interface AnnotationPosition$1 {
|
|
145
|
+
readonly x: number;
|
|
146
|
+
readonly y: number;
|
|
147
|
+
readonly z: number;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Annotation placed (server → parent): user clicked on the model surface.
|
|
151
|
+
* Only sent when place mode is active.
|
|
152
|
+
*/
|
|
153
|
+
interface AnnotationPlacedMessage$1 {
|
|
154
|
+
readonly type: typeof MESSAGE_TYPES$1.ANNOTATION_PLACED;
|
|
155
|
+
readonly position: AnnotationPosition$1;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Annotation toggle (parent → server): show or hide annotation markers.
|
|
159
|
+
* Only works when annotations exist in metadata (grand switch).
|
|
160
|
+
*/
|
|
161
|
+
interface AnnotationToggleMessage$1 {
|
|
162
|
+
readonly type: typeof MESSAGE_TYPES$1.ANNOTATION_TOGGLE;
|
|
163
|
+
readonly enabled: boolean;
|
|
164
|
+
}
|
|
165
|
+
/** Focus actions (client → server). */
|
|
166
|
+
declare const FOCUS_ACTIONS$1: {
|
|
167
|
+
readonly FOCUS: "focus";
|
|
168
|
+
readonly UNFOCUS: "unfocus";
|
|
169
|
+
};
|
|
170
|
+
/** Focus states (server → client). */
|
|
171
|
+
declare const FOCUS_STATES$1: {
|
|
172
|
+
readonly FOCUSED: "focused";
|
|
173
|
+
readonly UNFOCUSED: "unfocused";
|
|
174
|
+
};
|
|
175
|
+
type FocusAction$1 = typeof FOCUS_ACTIONS$1[keyof typeof FOCUS_ACTIONS$1];
|
|
176
|
+
type FocusStateValue$1 = typeof FOCUS_STATES$1[keyof typeof FOCUS_STATES$1];
|
|
177
|
+
/**
|
|
178
|
+
* Focus (client → server): isolate and frame a component, or return to overview.
|
|
179
|
+
* Programmatic — the API, the (future) component menu, and the portal editors all
|
|
180
|
+
* send this. `component` is a name from the `components` metadata, or a raw mesh
|
|
181
|
+
* name as a fallback (resolved server-side); required when action is `focus`.
|
|
182
|
+
*/
|
|
183
|
+
interface FocusMessage$1 {
|
|
184
|
+
readonly type: typeof MESSAGE_TYPES$1.FOCUS;
|
|
185
|
+
readonly action: FocusAction$1;
|
|
186
|
+
readonly component?: string;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Focus state (server → client): confirms the focus state after the camera and
|
|
190
|
+
* opacity transition. `attributes` lists which attributes are relevant to the
|
|
191
|
+
* focused component, so a custom UI can filter its selectors.
|
|
192
|
+
*/
|
|
193
|
+
interface FocusStateMessage$1 {
|
|
194
|
+
readonly type: typeof MESSAGE_TYPES$1.FOCUS;
|
|
195
|
+
readonly state: FocusStateValue$1;
|
|
196
|
+
readonly component?: string;
|
|
197
|
+
readonly attributes?: string[];
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* What the configurator does with a matched configuration. Mirrors the backend
|
|
201
|
+
* `availability` enum (pricing rule provenance lives on `PricingRule.source`).
|
|
202
|
+
*/
|
|
203
|
+
declare const AVAILABILITY$1: {
|
|
204
|
+
/** Price and submit button both shown (default). */
|
|
205
|
+
readonly AVAILABLE: "available";
|
|
206
|
+
/** Price shown, submit hidden (sold out / coming soon). */
|
|
207
|
+
readonly VIEW_ONLY: "view_only";
|
|
208
|
+
/** Behaves exactly like an unpriced combination: no price, no button. */
|
|
209
|
+
readonly HIDDEN: "hidden";
|
|
210
|
+
};
|
|
211
|
+
type Availability$1 = typeof AVAILABILITY$1[keyof typeof AVAILABILITY$1];
|
|
212
|
+
/**
|
|
213
|
+
* One pricing rule: a subset of attribute values mapped to a reference + price.
|
|
214
|
+
* Matches the backend pricing read contract (`GET /api/public/models/.../pricing`).
|
|
215
|
+
*/
|
|
216
|
+
interface PricingRule$1 {
|
|
217
|
+
/**
|
|
218
|
+
* The attribute name→value pairs this rule names. `{}` is a catch-all;
|
|
219
|
+
* omitted names are wildcards. A rule matches when every pair equals the
|
|
220
|
+
* current selection; the rule naming the most attributes wins.
|
|
221
|
+
*/
|
|
222
|
+
readonly attributes: Record<string, string>;
|
|
223
|
+
/** The customer's own identifier (SKU, EAN, artikelnummer, name code). */
|
|
224
|
+
readonly reference: string;
|
|
225
|
+
/** Price in minor units (cents), exactly as the source displays it. */
|
|
226
|
+
readonly priceCents: number;
|
|
227
|
+
readonly availability: Availability$1;
|
|
228
|
+
/** Provenance (manual | imported); audit-only, unused by the resolver. */
|
|
229
|
+
readonly source: 'manual' | 'imported';
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* A model's pricing document. The viewer's fetcher merges it into the model
|
|
233
|
+
* metadata and the server forwards it to the client via {@link PricingMessage}.
|
|
234
|
+
*/
|
|
235
|
+
interface PricingDocument$1 {
|
|
236
|
+
/** Optimistic-concurrency version from the editor; unused by the viewer. */
|
|
237
|
+
readonly version: number;
|
|
238
|
+
/** Customer-authored CTA label; null when the adapter's defaultLabel fills in. */
|
|
239
|
+
readonly buttonLabel: string | null;
|
|
240
|
+
/** ISO 4217 currency code for price formatting. */
|
|
241
|
+
readonly currency: string;
|
|
242
|
+
/** VAT label for bare embeds, e.g. "incl. btw". */
|
|
243
|
+
readonly vatDisplay: string;
|
|
244
|
+
readonly rules: PricingRule$1[];
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Pricing (server → client): the model's pricing document. Sent once at startup
|
|
248
|
+
* after MAPPING so the client's resolver can price the current configuration.
|
|
249
|
+
*/
|
|
250
|
+
interface PricingMessage$1 {
|
|
251
|
+
readonly type: typeof MESSAGE_TYPES$1.PRICING;
|
|
252
|
+
readonly pricing: PricingDocument$1;
|
|
253
|
+
}
|
|
254
|
+
type Message$1 = HandshakeMessage$1 | MutationMessage$1 | MutationResultMessage$1 | CameraCommandMessage$1 | CameraPositionMessage$1 | SnapshotRequestMessage$1 | SnapshotResultMessage$1 | MappingMessage$1 | LoadingIndicatorMessage$1 | ArActivateMessage$1 | ConfigMessage$1 | AnnotationPlaceModeMessage$1 | AnnotationPlacedMessage$1 | AnnotationToggleMessage$1 | FocusMessage$1 | FocusStateMessage$1 | PricingMessage$1;
|
|
255
|
+
type MessageCallback = (message: Message$1) => void | Promise<void>;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Configuration options for VirtualdisplayClient
|
|
259
|
+
*/
|
|
260
|
+
interface ClientOptions {
|
|
261
|
+
readonly parent: string | HTMLElement;
|
|
262
|
+
readonly model: string;
|
|
263
|
+
readonly license: string;
|
|
264
|
+
readonly debug?: boolean;
|
|
265
|
+
readonly language?: string;
|
|
266
|
+
/** W3C traceparent string to propagate to the viewer iframe for end-to-end tracing. */
|
|
267
|
+
readonly traceparent?: string;
|
|
268
|
+
/**
|
|
269
|
+
* Override viewer settings from metadata. Omitted fields use the metadata value.
|
|
270
|
+
* A warning is logged when an override differs from the metadata value.
|
|
271
|
+
*/
|
|
272
|
+
readonly viewerSettings?: Partial<ViewerSettings$1>;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* The Virtualdisplay client's DOM event names, in one registry.
|
|
277
|
+
*
|
|
278
|
+
* - `ui:*` events dispatch on the container (non-bubbling). They are the typed
|
|
279
|
+
* surface of `client.on(...)` — payloads in `VirtualdisplayUiEventMap` (./types).
|
|
280
|
+
* - `vd:*` events bubble into the customer's page, so a page can react with
|
|
281
|
+
* `addEventListener` without registering a client callback.
|
|
282
|
+
*/
|
|
283
|
+
declare const VD_EVENTS: {
|
|
284
|
+
/** Attribute selection requested (cancelable). `detail`: `{ attribute, value }`. */
|
|
285
|
+
readonly SELECT: "ui:select";
|
|
286
|
+
/** Attribute selection applied. `detail`: `{ attribute, value }`. */
|
|
287
|
+
readonly SELECTED: "ui:selected";
|
|
288
|
+
/** Focus changed (bubbles). `detail`: `{ component, attributes }`, or `null` for the overview. */
|
|
289
|
+
readonly FOCUS_CHANGE: "vd:focus-change";
|
|
290
|
+
/** Resolved configuration changed (bubbles). `detail`: the resolved configuration, or `null` when nothing matches. */
|
|
291
|
+
readonly CONFIGURATION_CHANGE: "vd:configuration-change";
|
|
292
|
+
/** Configuration submitted (bubbles). `detail`: the resolved configuration handed to the host. */
|
|
293
|
+
readonly CONFIGURATION_SUBMIT: "vd:configuration-submit";
|
|
294
|
+
};
|
|
295
|
+
type VdEvent = typeof VD_EVENTS[keyof typeof VD_EVENTS];
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Error codes for Virtualdisplay client errors
|
|
299
|
+
*/
|
|
300
|
+
declare const ERROR_CODES: {
|
|
301
|
+
readonly NO_MAPPING: "NO_MAPPING";
|
|
302
|
+
readonly ATTRIBUTE_NOT_FOUND: "ATTRIBUTE_NOT_FOUND";
|
|
303
|
+
readonly VALUE_NOT_FOUND: "VALUE_NOT_FOUND";
|
|
304
|
+
readonly PARENT_NOT_FOUND: "PARENT_NOT_FOUND";
|
|
305
|
+
readonly INVALID_PARAMETER: "INVALID_PARAMETER";
|
|
306
|
+
readonly SNAPSHOT_FAILED: "SNAPSHOT_FAILED";
|
|
307
|
+
};
|
|
308
|
+
type ErrorCode = typeof ERROR_CODES[keyof typeof ERROR_CODES];
|
|
309
|
+
/**
|
|
310
|
+
* Custom error class for Virtualdisplay client errors
|
|
311
|
+
*/
|
|
312
|
+
declare class VirtualdisplayError extends Error {
|
|
313
|
+
readonly code: ErrorCode;
|
|
314
|
+
constructor(message: string, code: ErrorCode);
|
|
315
|
+
static valueNotFound(attributeName: string, valueName: string): VirtualdisplayError;
|
|
316
|
+
static parentNotFound(selector: string): VirtualdisplayError;
|
|
317
|
+
static invalidParameter(reason: string): VirtualdisplayError;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
interface MutationFailedEvent {
|
|
321
|
+
readonly attribute: string;
|
|
322
|
+
readonly value: string;
|
|
323
|
+
}
|
|
324
|
+
interface VirtualdisplaySelectEvent {
|
|
325
|
+
readonly attribute: string;
|
|
326
|
+
readonly value: string;
|
|
327
|
+
preventDefault(): void;
|
|
328
|
+
}
|
|
329
|
+
interface VirtualdisplaySelectedEvent {
|
|
330
|
+
readonly attribute: string;
|
|
331
|
+
readonly value: string;
|
|
332
|
+
}
|
|
333
|
+
type VirtualdisplayUiEventMap = {
|
|
334
|
+
[VD_EVENTS.SELECT]: VirtualdisplaySelectEvent;
|
|
335
|
+
[VD_EVENTS.SELECTED]: VirtualdisplaySelectedEvent;
|
|
336
|
+
};
|
|
337
|
+
type VirtualdisplayUiEventType = keyof VirtualdisplayUiEventMap;
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Pure domain entity representing a single attribute value
|
|
341
|
+
* No side effects - only state
|
|
342
|
+
*/
|
|
343
|
+
declare class AttributeValue {
|
|
344
|
+
readonly value: string;
|
|
345
|
+
readonly attribute: string;
|
|
346
|
+
private isSelectedValue;
|
|
347
|
+
constructor(value: string, attribute: string);
|
|
348
|
+
get isSelected(): boolean;
|
|
349
|
+
setSelected(selected: boolean): void;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
interface AttributeOptions {
|
|
353
|
+
readonly name: string;
|
|
354
|
+
readonly values: string[];
|
|
355
|
+
readonly onSelect: (name: string, value: string) => void;
|
|
356
|
+
readonly defaultValue?: string;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Represents a single attribute with its available values
|
|
360
|
+
* Flat API - no source/target translation, works with server values directly
|
|
361
|
+
*/
|
|
362
|
+
declare class Attribute {
|
|
363
|
+
readonly name: string;
|
|
364
|
+
readonly defaultValue: string | undefined;
|
|
365
|
+
private readonly values;
|
|
366
|
+
private readonly onSelect;
|
|
367
|
+
private onChangeCallback?;
|
|
368
|
+
constructor(options: AttributeOptions);
|
|
369
|
+
/**
|
|
370
|
+
* Select a value for this attribute
|
|
371
|
+
* @throws {VirtualdisplayError} When value not found
|
|
372
|
+
*/
|
|
373
|
+
select(value: string): void;
|
|
374
|
+
getValues(): AttributeValue[];
|
|
375
|
+
getValue(value: string): AttributeValue | undefined;
|
|
376
|
+
/** The currently selected value, or undefined before any selection lands. */
|
|
377
|
+
get selected(): string | undefined;
|
|
378
|
+
/**
|
|
379
|
+
* Register callback that fires when selection changes
|
|
380
|
+
* Receives the newly selected AttributeValue
|
|
381
|
+
*/
|
|
382
|
+
onChange(callback: (selectedValue: AttributeValue) => void): void;
|
|
383
|
+
/**
|
|
384
|
+
* Update selection state from server mutation result
|
|
385
|
+
* Direct value comparison - no source/target translation
|
|
386
|
+
*/
|
|
387
|
+
handleResult(serverValue: string): void;
|
|
388
|
+
private createValues;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Camera control API for positioning and zoom
|
|
393
|
+
* Uses chaining pattern for building commands
|
|
394
|
+
*/
|
|
395
|
+
declare class Camera {
|
|
396
|
+
private readonly send;
|
|
397
|
+
private commands;
|
|
398
|
+
constructor(send: MessageCallback);
|
|
399
|
+
/**
|
|
400
|
+
* Rotate camera horizontally
|
|
401
|
+
* @param degrees - Absolute rotation in degrees (0 = front view)
|
|
402
|
+
* @throws VirtualdisplayError if value is not a finite number
|
|
403
|
+
*/
|
|
404
|
+
rotate(degrees: number): this;
|
|
405
|
+
/**
|
|
406
|
+
* Tilt camera vertically
|
|
407
|
+
* @param degrees - Absolute tilt in degrees (0 = top view, 90 = horizontal)
|
|
408
|
+
* @throws VirtualdisplayError if value is not a finite number
|
|
409
|
+
*/
|
|
410
|
+
tilt(degrees: number): this;
|
|
411
|
+
/**
|
|
412
|
+
* Zoom camera
|
|
413
|
+
* @param percentage - Zoom percentage (100 = normal, >100 = zoom in, <100 = zoom out)
|
|
414
|
+
* @throws VirtualdisplayError if value is not a finite number
|
|
415
|
+
*/
|
|
416
|
+
zoom(percentage: number): this;
|
|
417
|
+
/**
|
|
418
|
+
* Execute accumulated camera commands
|
|
419
|
+
* @throws VirtualdisplayError if no commands have been accumulated
|
|
420
|
+
*/
|
|
421
|
+
set(): void;
|
|
422
|
+
private validateFiniteNumber;
|
|
423
|
+
/**
|
|
424
|
+
* Reset camera to initial position
|
|
425
|
+
* This is not chainable and executes immediately
|
|
426
|
+
*/
|
|
427
|
+
reset(): void;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Camera position state object
|
|
432
|
+
*/
|
|
433
|
+
interface CameraPositionState {
|
|
434
|
+
rotation: number;
|
|
435
|
+
tilt: number;
|
|
436
|
+
zoom: number;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Camera position state
|
|
440
|
+
* Tracks current rotation, tilt, zoom, and movement limits from server updates.
|
|
441
|
+
*/
|
|
442
|
+
declare class CameraPosition {
|
|
443
|
+
private readonly state;
|
|
444
|
+
private limitsState;
|
|
445
|
+
private readonly changeCallbacks;
|
|
446
|
+
constructor();
|
|
447
|
+
/**
|
|
448
|
+
* Get current rotation in degrees
|
|
449
|
+
*/
|
|
450
|
+
get rotation(): number;
|
|
451
|
+
/**
|
|
452
|
+
* Get current tilt in degrees
|
|
453
|
+
*/
|
|
454
|
+
get tilt(): number;
|
|
455
|
+
/**
|
|
456
|
+
* Get current zoom percentage
|
|
457
|
+
*/
|
|
458
|
+
get zoom(): number;
|
|
459
|
+
/**
|
|
460
|
+
* Subscribe to camera position changes.
|
|
461
|
+
* Also fires when limits are applied via applyLimits() so components
|
|
462
|
+
* can re-evaluate disabled states without a separate callback.
|
|
463
|
+
*/
|
|
464
|
+
onChange(callback: (position: CameraPositionState) => void): void;
|
|
465
|
+
/**
|
|
466
|
+
* Current camera movement limits (set from CONFIG message).
|
|
467
|
+
* Undefined until the server sends limits in its CONFIG payload.
|
|
468
|
+
*/
|
|
469
|
+
get limits(): CameraLimits$1 | undefined;
|
|
470
|
+
/**
|
|
471
|
+
* Apply camera limits received from the server CONFIG message.
|
|
472
|
+
* Fires onChange callbacks so button disabled states update immediately.
|
|
473
|
+
*/
|
|
474
|
+
applyLimits(limits: CameraLimits$1 | undefined): void;
|
|
475
|
+
/**
|
|
476
|
+
* Handle incoming camera position message from server
|
|
477
|
+
*/
|
|
478
|
+
handlePositionUpdate(message: CameraPositionMessage$1): void;
|
|
479
|
+
/**
|
|
480
|
+
* Update camera position from server transforms
|
|
481
|
+
*/
|
|
482
|
+
update(transforms: CameraParameter$1[]): void;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/** The focus state reported to `onChange` and the `vd:focus-change` event. */
|
|
486
|
+
interface FocusState {
|
|
487
|
+
readonly component: string;
|
|
488
|
+
readonly attributes: string[];
|
|
489
|
+
}
|
|
490
|
+
type FocusChange = FocusState | null;
|
|
491
|
+
type FocusChangeCallback = (state: FocusChange) => void;
|
|
492
|
+
type DispatchFn = (state: FocusChange) => void;
|
|
493
|
+
/**
|
|
494
|
+
* Focus control API — isolate and frame a component, or return to overview.
|
|
495
|
+
*
|
|
496
|
+
* Programmatic by design: `set('Seat')` needs no user selection, which is how the
|
|
497
|
+
* (future) component menu and the portal/admin editors drive it over the same
|
|
498
|
+
* message bus. Alongside `onChange`, the container dispatches a bubbling
|
|
499
|
+
* `vd:focus-change` CustomEvent so a page can react without registering a callback.
|
|
500
|
+
*/
|
|
501
|
+
declare class Focus {
|
|
502
|
+
private readonly send;
|
|
503
|
+
private readonly dispatch;
|
|
504
|
+
private focused;
|
|
505
|
+
private attributes;
|
|
506
|
+
private readonly changeCallbacks;
|
|
507
|
+
constructor(send: MessageCallback, dispatch: DispatchFn);
|
|
508
|
+
/** The focused component name, or null in overview. */
|
|
509
|
+
get current(): string | null;
|
|
510
|
+
/**
|
|
511
|
+
* Focus a component by name. Sends a focus message to the viewer.
|
|
512
|
+
* @throws VirtualdisplayError if component is not a non-empty string
|
|
513
|
+
*/
|
|
514
|
+
set(component: string): void;
|
|
515
|
+
/** Return to the overview — unfocus the current component. */
|
|
516
|
+
clear(): void;
|
|
517
|
+
/**
|
|
518
|
+
* Subscribe to focus changes. The callback fires with the focus state when a
|
|
519
|
+
* component is focused, and with null when returning to overview.
|
|
520
|
+
*/
|
|
521
|
+
onChange(callback: FocusChangeCallback): void;
|
|
522
|
+
/** Called by the client when a FocusStateMessage is received from the viewer. */
|
|
523
|
+
handleStateReceived(message: FocusStateMessage$1): void;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/** The buyer's current configuration as attribute name→value pairs. */
|
|
527
|
+
type Selection = Record<string, string>;
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* The buyer's current configuration once it resolves to a price. `availability`
|
|
531
|
+
* is `available` (price + submit) or `view_only` (price, no submit); a matched
|
|
532
|
+
* `hidden` rule and a no-match both surface as `undefined` instead.
|
|
533
|
+
*/
|
|
534
|
+
interface ResolvedConfiguration {
|
|
535
|
+
readonly attributes: Record<string, string>;
|
|
536
|
+
readonly reference: string;
|
|
537
|
+
/** Price in minor units (cents), exactly as the source displays it. */
|
|
538
|
+
readonly price: number;
|
|
539
|
+
readonly currency: string;
|
|
540
|
+
readonly availability: 'available' | 'view_only';
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* What submit hands to the host: the buyer's selection and the reference to act
|
|
544
|
+
* on. Deliberately carries no price — the shop's checkout price is binding and
|
|
545
|
+
* ours is display-only, so handing it into the cart hand-off would only invite a
|
|
546
|
+
* wrong-price error. Price stays on the display side (`current`, `onChange`).
|
|
547
|
+
*/
|
|
548
|
+
interface SubmittedConfiguration {
|
|
549
|
+
readonly attributes: Record<string, string>;
|
|
550
|
+
readonly reference: string;
|
|
551
|
+
}
|
|
552
|
+
type ChangeCallback = (configuration: ResolvedConfiguration | undefined) => void;
|
|
553
|
+
type SubmitCallback = (configuration: SubmittedConfiguration) => void | Promise<unknown>;
|
|
554
|
+
type Dispatch<T> = (detail: T) => void;
|
|
555
|
+
/** Options for {@link Configuration.onSubmit}. */
|
|
556
|
+
interface SubmitOptions {
|
|
557
|
+
/** Fallback button label when the customer authored none (the adapter brings it). */
|
|
558
|
+
readonly defaultLabel?: string;
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Configuration API — resolves the buyer's selection to a reference + price and
|
|
562
|
+
* carries it to the host page.
|
|
563
|
+
*
|
|
564
|
+
* Follows the existing facade style (`client.camera`, `client.focus`). It holds
|
|
565
|
+
* the pricing document and the latest selection, re-resolving on every change.
|
|
566
|
+
* `onChange` fires with the resolved configuration (or `undefined` when nothing
|
|
567
|
+
* matches); alongside it the container dispatches a bubbling `vd:configuration-change`
|
|
568
|
+
* CustomEvent so a page reacts without registering a callback. `onSubmit` registers
|
|
569
|
+
* the host handler that the CTA hands the configuration to.
|
|
570
|
+
*/
|
|
571
|
+
declare class Configuration {
|
|
572
|
+
private readonly dispatchChange;
|
|
573
|
+
private readonly dispatchSubmit;
|
|
574
|
+
private pricing;
|
|
575
|
+
private selection;
|
|
576
|
+
private resolved;
|
|
577
|
+
private readonly changeCallbacks;
|
|
578
|
+
private readonly renderCallbacks;
|
|
579
|
+
private submitCallback;
|
|
580
|
+
private submitDefaultLabel;
|
|
581
|
+
constructor(dispatchChange: Dispatch<ResolvedConfiguration | undefined>, dispatchSubmit: Dispatch<SubmittedConfiguration>);
|
|
582
|
+
/** The resolved configuration, or undefined when nothing matches. */
|
|
583
|
+
get current(): ResolvedConfiguration | undefined;
|
|
584
|
+
/** The VAT label for bare embeds (e.g. "incl. btw"), or undefined without pricing. */
|
|
585
|
+
get vatDisplay(): string | undefined;
|
|
586
|
+
/**
|
|
587
|
+
* The CTA label: the customer's `button_label`, or the adapter's `defaultLabel`
|
|
588
|
+
* when that is empty. Undefined when neither is set — a button must know what
|
|
589
|
+
* it says, so the CTA does not render.
|
|
590
|
+
*/
|
|
591
|
+
get buttonLabel(): string | undefined;
|
|
592
|
+
/**
|
|
593
|
+
* Whether the current configuration may be submitted: a handler is registered
|
|
594
|
+
* and the configuration is either price-less or an `available` priced one. The
|
|
595
|
+
* CTA's visibility ({@link submitEnabled}) layers a label requirement on top of
|
|
596
|
+
* this; a programmatic `submit()` does not need a label.
|
|
597
|
+
*/
|
|
598
|
+
private get submittable();
|
|
599
|
+
/**
|
|
600
|
+
* Whether the CTA should render: the configuration is submittable and a label
|
|
601
|
+
* exists. A button must say something, so an empty label hides the CTA rather
|
|
602
|
+
* than rendering blank.
|
|
603
|
+
*/
|
|
604
|
+
get submitEnabled(): boolean;
|
|
605
|
+
/**
|
|
606
|
+
* Subscribe to configuration changes. Fires after every selection change with
|
|
607
|
+
* the resolved configuration, including undefined when nothing matches.
|
|
608
|
+
*/
|
|
609
|
+
onChange(callback: ChangeCallback): void;
|
|
610
|
+
/**
|
|
611
|
+
* Register the submit handler the CTA hands the configuration to. Registering
|
|
612
|
+
* one is what switches the button on (capability driven). `defaultLabel` fills
|
|
613
|
+
* in when the customer authored no button label.
|
|
614
|
+
*/
|
|
615
|
+
onSubmit(callback: SubmitCallback, options?: SubmitOptions): void;
|
|
616
|
+
/**
|
|
617
|
+
* Subscribe the built-in UI to re-render the price + CTA. Fires on every
|
|
618
|
+
* resolve and when a submit handler is registered (which can switch the button
|
|
619
|
+
* on without a configuration change). Separate from `onChange`, which stays the
|
|
620
|
+
* host-facing, mutation-driven contract. Returns a disposer.
|
|
621
|
+
*/
|
|
622
|
+
onRender(callback: () => void): () => void;
|
|
623
|
+
/**
|
|
624
|
+
* Hand the current configuration to the registered handler and fire the
|
|
625
|
+
* bubbling `vd:configuration-submit` event. No-op without a handler or a
|
|
626
|
+
* resolved configuration. Returns the handler's promise so the caller can
|
|
627
|
+
* reflect the result (bezig / gelukt / mislukt).
|
|
628
|
+
*/
|
|
629
|
+
submit(): Promise<void>;
|
|
630
|
+
/** Called by the client when a PRICING message arrives from the viewer. */
|
|
631
|
+
handlePricingReceived(pricing: PricingDocument$1): void;
|
|
632
|
+
/** Called by the client after every mutation result, with the full selection. */
|
|
633
|
+
handleSelectionChanged(selection: Selection): void;
|
|
634
|
+
private recompute;
|
|
635
|
+
private notifyRender;
|
|
636
|
+
private resolve;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
interface PhotoData {
|
|
640
|
+
readonly filename: string;
|
|
641
|
+
readonly data: string;
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Represents a photo being captured
|
|
645
|
+
* Pure domain object that manages callbacks for when the photo is developed
|
|
646
|
+
*/
|
|
647
|
+
declare class Photo {
|
|
648
|
+
private readonly filename;
|
|
649
|
+
private readonly developedCallbacks;
|
|
650
|
+
private readonly errorCallbacks;
|
|
651
|
+
private developed;
|
|
652
|
+
private failed;
|
|
653
|
+
private photoData;
|
|
654
|
+
constructor(filename: string);
|
|
655
|
+
/**
|
|
656
|
+
* Register a callback for when the photo is developed
|
|
657
|
+
* If the photo is already developed, the callback is called immediately
|
|
658
|
+
*
|
|
659
|
+
* @param callback Function to call with photo data
|
|
660
|
+
* @returns This Photo instance for chaining
|
|
661
|
+
*/
|
|
662
|
+
onDeveloped(callback: (photo: PhotoData) => void): this;
|
|
663
|
+
/**
|
|
664
|
+
* Register a callback for when the photo capture fails
|
|
665
|
+
*
|
|
666
|
+
* @param callback Function to call with error
|
|
667
|
+
* @returns This Photo instance for chaining
|
|
668
|
+
*/
|
|
669
|
+
onError(callback: (error: VirtualdisplayError) => void): this;
|
|
670
|
+
/**
|
|
671
|
+
* Get the filename for this photo
|
|
672
|
+
*/
|
|
673
|
+
getFilename(): string;
|
|
674
|
+
/**
|
|
675
|
+
* Mark the photo as developed and notify all callbacks
|
|
676
|
+
* This method is called by Snapshot when the photo data arrives from the server
|
|
677
|
+
*/
|
|
678
|
+
develop(photoData: PhotoData): void;
|
|
679
|
+
/**
|
|
680
|
+
* Mark the photo as failed and notify error callbacks
|
|
681
|
+
*/
|
|
682
|
+
fail(error: VirtualdisplayError): void;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* API for taking screenshots of the 3D model
|
|
687
|
+
* Following the camera analogy: take() triggers capture, onDeveloped() gets result
|
|
688
|
+
*/
|
|
689
|
+
declare class Snapshot {
|
|
690
|
+
private readonly send;
|
|
691
|
+
private readonly validExtensions;
|
|
692
|
+
private readonly pendingPhotos;
|
|
693
|
+
constructor(send: MessageCallback);
|
|
694
|
+
/**
|
|
695
|
+
* Take a snapshot of the current 3D model view
|
|
696
|
+
*
|
|
697
|
+
* @param filename The filename for the snapshot (must include valid extension)
|
|
698
|
+
* @returns Photo object for registering callbacks
|
|
699
|
+
* @throws VirtualdisplayError if filename is invalid
|
|
700
|
+
*/
|
|
701
|
+
take(filename: string): Photo;
|
|
702
|
+
/**
|
|
703
|
+
* Handle incoming snapshot result from server
|
|
704
|
+
* Matches the message to a pending photo by filename, then develops or fails it
|
|
705
|
+
*/
|
|
706
|
+
handleSnapshotResult(message: SnapshotResultMessage$1): void;
|
|
707
|
+
/**
|
|
708
|
+
* Fail any pending photos and forget them. Called from client destroy
|
|
709
|
+
* so callers awaiting onError() see a deterministic outcome instead of
|
|
710
|
+
* leaking captures whose results will never arrive.
|
|
711
|
+
*/
|
|
712
|
+
clear(): void;
|
|
713
|
+
/**
|
|
714
|
+
* Validate filename has a valid image extension
|
|
715
|
+
*/
|
|
716
|
+
private validateFilename;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
type Attrs = Record<string, unknown> | unknown;
|
|
720
|
+
declare let logger: {
|
|
721
|
+
debug: (msg: string, attrs?: Attrs) => void;
|
|
722
|
+
info: (msg: string, attrs?: Attrs) => void;
|
|
723
|
+
warn: (msg: string, attrs?: Attrs) => void;
|
|
724
|
+
error: (msg: string, attrs?: Attrs) => void;
|
|
725
|
+
};
|
|
726
|
+
declare function enableDebugMode(): void;
|
|
727
|
+
declare function isDebugMode(): boolean;
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Virtualdisplay iframe messaging protocol
|
|
731
|
+
*
|
|
732
|
+
* All message types exchanged between client (parent page)
|
|
733
|
+
* and server (iframe viewer engine) via postMessage.
|
|
734
|
+
*/
|
|
735
|
+
declare const MESSAGE_TYPES: {
|
|
736
|
+
readonly HANDSHAKE: "handshake";
|
|
737
|
+
readonly MUTATION: "mutation";
|
|
738
|
+
readonly STATE: "state";
|
|
739
|
+
readonly LOADING_INDICATOR: "loading_indicator";
|
|
740
|
+
readonly CAMERA: "camera";
|
|
741
|
+
readonly SNAPSHOT: "snapshot";
|
|
742
|
+
readonly MAPPING: "mapping";
|
|
743
|
+
readonly AR_ACTIVATE: "ar_activate";
|
|
744
|
+
readonly CONFIG: "config";
|
|
745
|
+
readonly ANNOTATION_PLACE_MODE: "annotation_place_mode";
|
|
746
|
+
readonly ANNOTATION_PLACED: "annotation_placed";
|
|
747
|
+
readonly ANNOTATION_TOGGLE: "annotation_toggle";
|
|
748
|
+
readonly FOCUS: "focus";
|
|
749
|
+
readonly PRICING: "pricing";
|
|
750
|
+
};
|
|
751
|
+
interface MutationDto {
|
|
752
|
+
readonly name: string;
|
|
753
|
+
readonly value: string;
|
|
754
|
+
}
|
|
755
|
+
interface MutationResult {
|
|
756
|
+
readonly name: string;
|
|
757
|
+
readonly value: string;
|
|
758
|
+
readonly success: boolean;
|
|
759
|
+
readonly error?: string;
|
|
760
|
+
}
|
|
761
|
+
interface MutationMessage {
|
|
762
|
+
readonly type: typeof MESSAGE_TYPES.MUTATION;
|
|
763
|
+
readonly mutations: MutationDto[];
|
|
764
|
+
readonly isInitial: boolean;
|
|
765
|
+
}
|
|
766
|
+
interface MutationResultMessage {
|
|
767
|
+
readonly type: typeof MESSAGE_TYPES.MUTATION;
|
|
768
|
+
readonly results: MutationResult[];
|
|
769
|
+
readonly isInitial: boolean;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Viewer settings from model metadata (server → client via MAPPING).
|
|
773
|
+
* Customer-configured in the portal.
|
|
774
|
+
*/
|
|
775
|
+
interface ViewerSettings {
|
|
776
|
+
readonly ar?: boolean;
|
|
777
|
+
readonly fullscreen?: boolean;
|
|
778
|
+
readonly screenshot?: boolean;
|
|
779
|
+
readonly cameraControls?: boolean;
|
|
780
|
+
readonly annotations?: boolean;
|
|
781
|
+
readonly language?: string;
|
|
782
|
+
/** Where the attribute controls sit: in-frame bottom-left (default) or a docked right panel. */
|
|
783
|
+
readonly configuratorLayout?: 'inframe-bottom-left' | 'sidebar-right' | 'hidden';
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Camera movement limits sent to the client via CONFIG.
|
|
787
|
+
* Used to disable camera control buttons when a limit is reached.
|
|
788
|
+
* Units match the camera position: zoom = percentage (0–200), tilt/rotate = degrees.
|
|
789
|
+
*/
|
|
790
|
+
interface CameraLimits {
|
|
791
|
+
readonly minZoom?: number;
|
|
792
|
+
readonly maxZoom?: number;
|
|
793
|
+
readonly minTilt?: number;
|
|
794
|
+
readonly maxTilt?: number;
|
|
795
|
+
readonly minRotate?: number;
|
|
796
|
+
readonly maxRotate?: number;
|
|
797
|
+
}
|
|
798
|
+
interface CameraCommand {
|
|
799
|
+
readonly action: 'rotate' | 'tilt' | 'zoom' | 'reset';
|
|
800
|
+
readonly value?: number;
|
|
801
|
+
}
|
|
802
|
+
interface CameraParameter {
|
|
803
|
+
readonly type: 'rotation' | 'tilt' | 'zoom';
|
|
804
|
+
readonly value: number;
|
|
805
|
+
}
|
|
806
|
+
interface CameraCommandMessage {
|
|
807
|
+
readonly type: typeof MESSAGE_TYPES.CAMERA;
|
|
808
|
+
readonly commands: CameraCommand[];
|
|
809
|
+
}
|
|
810
|
+
interface CameraPositionMessage {
|
|
811
|
+
readonly type: typeof MESSAGE_TYPES.CAMERA;
|
|
812
|
+
readonly transforms: CameraParameter[];
|
|
813
|
+
}
|
|
814
|
+
interface SnapshotRequestMessage {
|
|
815
|
+
readonly type: typeof MESSAGE_TYPES.SNAPSHOT;
|
|
816
|
+
readonly filename: string;
|
|
817
|
+
}
|
|
818
|
+
interface SnapshotResultMessage {
|
|
819
|
+
readonly type: typeof MESSAGE_TYPES.SNAPSHOT;
|
|
820
|
+
readonly filename: string;
|
|
821
|
+
readonly data?: string;
|
|
822
|
+
readonly error?: string;
|
|
823
|
+
}
|
|
824
|
+
interface AttributeDefinition {
|
|
825
|
+
readonly name: string;
|
|
826
|
+
readonly values: string[];
|
|
827
|
+
readonly defaultValue?: string;
|
|
828
|
+
}
|
|
829
|
+
interface MappingMessage {
|
|
830
|
+
readonly type: typeof MESSAGE_TYPES.MAPPING;
|
|
831
|
+
readonly attributes: AttributeDefinition[];
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Loading indicator (server → client): progress percentage, phase label, or error.
|
|
835
|
+
* Sent during model download and parse so the client loading indicator can update.
|
|
836
|
+
*/
|
|
837
|
+
interface LoadingIndicatorMessage {
|
|
838
|
+
readonly type: typeof MESSAGE_TYPES.LOADING_INDICATOR;
|
|
839
|
+
/** 0–100 */
|
|
840
|
+
readonly progress: number;
|
|
841
|
+
/** Human-readable phase label, e.g. "downloading" */
|
|
842
|
+
readonly phase: string;
|
|
843
|
+
/** Set when loading failed; client shows error state instead of hiding the overlay. */
|
|
844
|
+
readonly error?: string;
|
|
845
|
+
}
|
|
846
|
+
/** AR activate (client → server): user clicked the AR button. Server handles activation. */
|
|
847
|
+
interface ArActivateMessage {
|
|
848
|
+
readonly type: typeof MESSAGE_TYPES.AR_ACTIVATE;
|
|
849
|
+
}
|
|
850
|
+
/**
|
|
851
|
+
* Config (server → client): viewer settings and camera limits from model metadata.
|
|
852
|
+
* Sent early — before MAPPING — so the client can show/hide controls and disable
|
|
853
|
+
* camera buttons at limits as soon as metadata is available.
|
|
854
|
+
*/
|
|
855
|
+
interface ConfigMessage {
|
|
856
|
+
readonly type: typeof MESSAGE_TYPES.CONFIG;
|
|
857
|
+
readonly viewerSettings: ViewerSettings;
|
|
858
|
+
readonly cameraLimits?: CameraLimits;
|
|
859
|
+
}
|
|
860
|
+
interface HandshakeMessage {
|
|
861
|
+
readonly type: typeof MESSAGE_TYPES.HANDSHAKE;
|
|
862
|
+
}
|
|
863
|
+
/**
|
|
864
|
+
* Annotation place mode (parent → server): enable or disable click-to-place.
|
|
865
|
+
* When enabled, clicking on the model surface sends back an ANNOTATION_PLACED message.
|
|
866
|
+
*/
|
|
867
|
+
interface AnnotationPlaceModeMessage {
|
|
868
|
+
readonly type: typeof MESSAGE_TYPES.ANNOTATION_PLACE_MODE;
|
|
869
|
+
readonly enabled: boolean;
|
|
870
|
+
}
|
|
871
|
+
/** Position on the model surface returned by raycasting. */
|
|
872
|
+
interface AnnotationPosition {
|
|
873
|
+
readonly x: number;
|
|
874
|
+
readonly y: number;
|
|
875
|
+
readonly z: number;
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Annotation placed (server → parent): user clicked on the model surface.
|
|
879
|
+
* Only sent when place mode is active.
|
|
880
|
+
*/
|
|
881
|
+
interface AnnotationPlacedMessage {
|
|
882
|
+
readonly type: typeof MESSAGE_TYPES.ANNOTATION_PLACED;
|
|
883
|
+
readonly position: AnnotationPosition;
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Annotation toggle (parent → server): show or hide annotation markers.
|
|
887
|
+
* Only works when annotations exist in metadata (grand switch).
|
|
888
|
+
*/
|
|
889
|
+
interface AnnotationToggleMessage {
|
|
890
|
+
readonly type: typeof MESSAGE_TYPES.ANNOTATION_TOGGLE;
|
|
891
|
+
readonly enabled: boolean;
|
|
892
|
+
}
|
|
893
|
+
/** Focus actions (client → server). */
|
|
894
|
+
declare const FOCUS_ACTIONS: {
|
|
895
|
+
readonly FOCUS: "focus";
|
|
896
|
+
readonly UNFOCUS: "unfocus";
|
|
897
|
+
};
|
|
898
|
+
/** Focus states (server → client). */
|
|
899
|
+
declare const FOCUS_STATES: {
|
|
900
|
+
readonly FOCUSED: "focused";
|
|
901
|
+
readonly UNFOCUSED: "unfocused";
|
|
902
|
+
};
|
|
903
|
+
type FocusAction = typeof FOCUS_ACTIONS[keyof typeof FOCUS_ACTIONS];
|
|
904
|
+
type FocusStateValue = typeof FOCUS_STATES[keyof typeof FOCUS_STATES];
|
|
905
|
+
/**
|
|
906
|
+
* Focus (client → server): isolate and frame a component, or return to overview.
|
|
907
|
+
* Programmatic — the API, the (future) component menu, and the portal editors all
|
|
908
|
+
* send this. `component` is a name from the `components` metadata, or a raw mesh
|
|
909
|
+
* name as a fallback (resolved server-side); required when action is `focus`.
|
|
910
|
+
*/
|
|
911
|
+
interface FocusMessage {
|
|
912
|
+
readonly type: typeof MESSAGE_TYPES.FOCUS;
|
|
913
|
+
readonly action: FocusAction;
|
|
914
|
+
readonly component?: string;
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* Focus state (server → client): confirms the focus state after the camera and
|
|
918
|
+
* opacity transition. `attributes` lists which attributes are relevant to the
|
|
919
|
+
* focused component, so a custom UI can filter its selectors.
|
|
920
|
+
*/
|
|
921
|
+
interface FocusStateMessage {
|
|
922
|
+
readonly type: typeof MESSAGE_TYPES.FOCUS;
|
|
923
|
+
readonly state: FocusStateValue;
|
|
924
|
+
readonly component?: string;
|
|
925
|
+
readonly attributes?: string[];
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* What the configurator does with a matched configuration. Mirrors the backend
|
|
929
|
+
* `availability` enum (pricing rule provenance lives on `PricingRule.source`).
|
|
930
|
+
*/
|
|
931
|
+
declare const AVAILABILITY: {
|
|
932
|
+
/** Price and submit button both shown (default). */
|
|
933
|
+
readonly AVAILABLE: "available";
|
|
934
|
+
/** Price shown, submit hidden (sold out / coming soon). */
|
|
935
|
+
readonly VIEW_ONLY: "view_only";
|
|
936
|
+
/** Behaves exactly like an unpriced combination: no price, no button. */
|
|
937
|
+
readonly HIDDEN: "hidden";
|
|
938
|
+
};
|
|
939
|
+
type Availability = typeof AVAILABILITY[keyof typeof AVAILABILITY];
|
|
940
|
+
/**
|
|
941
|
+
* One pricing rule: a subset of attribute values mapped to a reference + price.
|
|
942
|
+
* Matches the backend pricing read contract (`GET /api/public/models/.../pricing`).
|
|
943
|
+
*/
|
|
944
|
+
interface PricingRule {
|
|
945
|
+
/**
|
|
946
|
+
* The attribute name→value pairs this rule names. `{}` is a catch-all;
|
|
947
|
+
* omitted names are wildcards. A rule matches when every pair equals the
|
|
948
|
+
* current selection; the rule naming the most attributes wins.
|
|
949
|
+
*/
|
|
950
|
+
readonly attributes: Record<string, string>;
|
|
951
|
+
/** The customer's own identifier (SKU, EAN, artikelnummer, name code). */
|
|
952
|
+
readonly reference: string;
|
|
953
|
+
/** Price in minor units (cents), exactly as the source displays it. */
|
|
954
|
+
readonly priceCents: number;
|
|
955
|
+
readonly availability: Availability;
|
|
956
|
+
/** Provenance (manual | imported); audit-only, unused by the resolver. */
|
|
957
|
+
readonly source: 'manual' | 'imported';
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* A model's pricing document. The viewer's fetcher merges it into the model
|
|
961
|
+
* metadata and the server forwards it to the client via {@link PricingMessage}.
|
|
962
|
+
*/
|
|
963
|
+
interface PricingDocument {
|
|
964
|
+
/** Optimistic-concurrency version from the editor; unused by the viewer. */
|
|
965
|
+
readonly version: number;
|
|
966
|
+
/** Customer-authored CTA label; null when the adapter's defaultLabel fills in. */
|
|
967
|
+
readonly buttonLabel: string | null;
|
|
968
|
+
/** ISO 4217 currency code for price formatting. */
|
|
969
|
+
readonly currency: string;
|
|
970
|
+
/** VAT label for bare embeds, e.g. "incl. btw". */
|
|
971
|
+
readonly vatDisplay: string;
|
|
972
|
+
readonly rules: PricingRule[];
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* Pricing (server → client): the model's pricing document. Sent once at startup
|
|
976
|
+
* after MAPPING so the client's resolver can price the current configuration.
|
|
977
|
+
*/
|
|
978
|
+
interface PricingMessage {
|
|
979
|
+
readonly type: typeof MESSAGE_TYPES.PRICING;
|
|
980
|
+
readonly pricing: PricingDocument;
|
|
981
|
+
}
|
|
982
|
+
type Message = HandshakeMessage | MutationMessage | MutationResultMessage | CameraCommandMessage | CameraPositionMessage | SnapshotRequestMessage | SnapshotResultMessage | MappingMessage | LoadingIndicatorMessage | ArActivateMessage | ConfigMessage | AnnotationPlaceModeMessage | AnnotationPlacedMessage | AnnotationToggleMessage | FocusMessage | FocusStateMessage | PricingMessage;
|
|
983
|
+
|
|
984
|
+
type SendFn = (message: Message) => void;
|
|
985
|
+
type PlacedCallback = (position: AnnotationPosition) => void;
|
|
986
|
+
/**
|
|
987
|
+
* Annotation controls for the viewer.
|
|
988
|
+
* Toggle visibility, and manage click-to-place for the annotation editor.
|
|
989
|
+
*/
|
|
990
|
+
declare class Annotations {
|
|
991
|
+
private readonly send;
|
|
992
|
+
private readonly placedCallbacks;
|
|
993
|
+
constructor(send: SendFn);
|
|
994
|
+
setEnabled(enabled: boolean): void;
|
|
995
|
+
startPlacing(): void;
|
|
996
|
+
stopPlacing(): void;
|
|
997
|
+
onPlaced(callback: PlacedCallback): void;
|
|
998
|
+
/** Called by the client when an ANNOTATION_PLACED message is received. */
|
|
999
|
+
handlePlaced(position: AnnotationPosition): void;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/**
|
|
1003
|
+
* Main Virtualdisplay Client — composition root.
|
|
1004
|
+
* Wires all services together and exposes the public API.
|
|
1005
|
+
*/
|
|
1006
|
+
declare class VirtualdisplayClient {
|
|
1007
|
+
private readonly attributes;
|
|
1008
|
+
private readonly readyStateTracker;
|
|
1009
|
+
private readonly messenger;
|
|
1010
|
+
private readonly cameraApi;
|
|
1011
|
+
private readonly cameraPositionApi;
|
|
1012
|
+
private readonly focusApi;
|
|
1013
|
+
private readonly configurationApi;
|
|
1014
|
+
private readonly snapshotApi;
|
|
1015
|
+
private readonly annotationsApi;
|
|
1016
|
+
private readonly eventBus;
|
|
1017
|
+
private readonly ui;
|
|
1018
|
+
private readonly qrModal;
|
|
1019
|
+
private readonly options;
|
|
1020
|
+
private iframe;
|
|
1021
|
+
private container;
|
|
1022
|
+
private readyCallbacks;
|
|
1023
|
+
private readonly mutationFailedCallbacks;
|
|
1024
|
+
constructor(options: ClientOptions);
|
|
1025
|
+
private registerHandlers;
|
|
1026
|
+
/** Handlers that feed viewer-reported state into the facades (focus, pricing). */
|
|
1027
|
+
private registerFacadeStateHandlers;
|
|
1028
|
+
/**
|
|
1029
|
+
* Dispatch a bubbling `vd:focus-change` event on the container so a page can
|
|
1030
|
+
* react to focus without registering an `onChange` callback.
|
|
1031
|
+
*/
|
|
1032
|
+
private dispatchFocusChange;
|
|
1033
|
+
/**
|
|
1034
|
+
* Dispatch a bubbling `vd:configuration-change` event on the container so a
|
|
1035
|
+
* page or tag manager can react to price changes without a client callback.
|
|
1036
|
+
*/
|
|
1037
|
+
private dispatchConfigurationChange;
|
|
1038
|
+
/** Dispatch a bubbling `vd:configuration-submit` event when the CTA is used. */
|
|
1039
|
+
private dispatchConfigurationSubmit;
|
|
1040
|
+
private handleConfig;
|
|
1041
|
+
private activateAr;
|
|
1042
|
+
private initializeLogging;
|
|
1043
|
+
private createAndConnectIframe;
|
|
1044
|
+
select(name: string, value: string): void;
|
|
1045
|
+
getValues(name: string): AttributeValue[];
|
|
1046
|
+
getValue(name: string, value: string): AttributeValue | undefined;
|
|
1047
|
+
onChange(name: string, callback: (selectedValue: AttributeValue) => void): void;
|
|
1048
|
+
getAttribute(name: string): Attribute | undefined;
|
|
1049
|
+
get isReady(): boolean;
|
|
1050
|
+
onReady(callback: (client: VirtualdisplayClient) => void): void;
|
|
1051
|
+
onMutationFailed(callback: (event: MutationFailedEvent) => void): void;
|
|
1052
|
+
on<T extends VirtualdisplayUiEventType>(type: T, callback: (event: VirtualdisplayUiEventMap[T]) => void): void;
|
|
1053
|
+
get annotations(): Annotations;
|
|
1054
|
+
get camera(): Camera;
|
|
1055
|
+
get focus(): Focus;
|
|
1056
|
+
get configuration(): Configuration;
|
|
1057
|
+
get cameraPosition(): CameraPosition;
|
|
1058
|
+
get snapshot(): Snapshot;
|
|
1059
|
+
get viewerSettings(): ViewerSettings;
|
|
1060
|
+
destroy(): void;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
export { Annotations, Attribute, AttributeValue, Camera, Configuration, ERROR_CODES, Focus, Photo, Snapshot, VD_EVENTS, VirtualdisplayClient, VirtualdisplayError, enableDebugMode, isDebugMode, logger };
|
|
1064
|
+
export type { AnnotationPosition, Availability, ClientOptions, ErrorCode, FocusState, MutationFailedEvent, PhotoData, PricingDocument, PricingRule, ResolvedConfiguration, SubmitOptions, SubmittedConfiguration, VdEvent, ViewerSettings, VirtualdisplaySelectEvent, VirtualdisplaySelectedEvent, VirtualdisplayUiEventMap, VirtualdisplayUiEventType };
|