@virtualdisplay.io/client 4.0.0-alpha.27 → 4.0.0-alpha.29
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 +16 -0
- package/dist/index.d.ts +159 -373
- package/dist/virtualdisplay.client.cjs.js +42 -27
- package/dist/virtualdisplay.client.es.js +1425 -1327
- package/dist/virtualdisplay.client.umd.js +26 -11
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -24,12 +24,13 @@ declare const MESSAGE_TYPES: {
|
|
|
24
24
|
readonly SELECTABLE: "selectable";
|
|
25
25
|
readonly APP_RESOLVED: "app_resolved";
|
|
26
26
|
};
|
|
27
|
-
/** The
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
/** The app types this protocol version knows. The wire field stays a plain
|
|
28
|
+
* string on purpose: a newer viewer may report a type this bundle predates,
|
|
29
|
+
* and the host must receive it to fail visibly (never a quiet downgrade). */
|
|
30
|
+
type AppType = 'viewer' | 'configurator';
|
|
31
|
+
/** What a configurator app's submit form renders. Any field may be absent; an
|
|
32
|
+
* absent field means the form's own default. */
|
|
33
|
+
interface AppSubmitSettings {
|
|
33
34
|
readonly fields?: string[];
|
|
34
35
|
readonly ctaLabel?: string;
|
|
35
36
|
readonly privacyUrl?: string;
|
|
@@ -50,7 +51,7 @@ interface AppResolvedMessage {
|
|
|
50
51
|
* no other way to learn it, so the shell treats absence as "submit
|
|
51
52
|
* unavailable" rather than the guard dropping the whole report. */
|
|
52
53
|
readonly slug?: string;
|
|
53
|
-
readonly submit?: AppSubmitSettings
|
|
54
|
+
readonly submit?: AppSubmitSettings;
|
|
54
55
|
}
|
|
55
56
|
/** One mesh or material variant in a model, as reported by STATE. */
|
|
56
57
|
interface ModelNodeDto {
|
|
@@ -62,11 +63,6 @@ interface ModelNodeDto {
|
|
|
62
63
|
/**
|
|
63
64
|
* State (viewer → client): the meshes and material variants of one instance,
|
|
64
65
|
* with their current visibility.
|
|
65
|
-
*
|
|
66
|
-
* Its shape used to live in server-core, marked "server-only", while its type
|
|
67
|
-
* value sat in the public MESSAGE_TYPES and the client read it: a public
|
|
68
|
-
* message whose shape only one side declared, which is how two shapes of one
|
|
69
|
-
* thing start to drift.
|
|
70
66
|
*/
|
|
71
67
|
interface StateMessage {
|
|
72
68
|
readonly type: typeof MESSAGE_TYPES.STATE;
|
|
@@ -85,16 +81,18 @@ interface MutationResult {
|
|
|
85
81
|
readonly success: boolean;
|
|
86
82
|
readonly error?: string;
|
|
87
83
|
}
|
|
84
|
+
/** One instance's configuration: attribute name to the value selected for it. */
|
|
85
|
+
type InstanceAttributes = Readonly<Record<string, string>>;
|
|
88
86
|
/**
|
|
89
|
-
* The folded
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* on the same message is only the delta that triggered the broadcast.
|
|
87
|
+
* The folded session state carried by a live sync broadcast: the same shape the
|
|
88
|
+
* public session-state read returns. It is authoritative, where `mutations` on
|
|
89
|
+
* the same message is only the change that triggered the broadcast.
|
|
93
90
|
*/
|
|
94
91
|
interface SyncStateSnapshot {
|
|
95
92
|
readonly license: string;
|
|
96
93
|
readonly model: string;
|
|
97
|
-
|
|
94
|
+
/** The folded configuration, keyed by instance and then by attribute name. */
|
|
95
|
+
readonly attributes: Readonly<Record<string, InstanceAttributes>>;
|
|
98
96
|
}
|
|
99
97
|
interface MutationMessage {
|
|
100
98
|
readonly type: typeof MESSAGE_TYPES.MUTATION;
|
|
@@ -102,39 +100,23 @@ interface MutationMessage {
|
|
|
102
100
|
readonly instance: string;
|
|
103
101
|
readonly mutations: MutationDto[];
|
|
104
102
|
readonly isInitial: boolean;
|
|
105
|
-
/**
|
|
106
|
-
* Live sync channel extras (ar-session-handoff, sync-channel.md), present
|
|
107
|
-
* only on a mutation the viewer engine's sync module received over the SSE
|
|
108
|
-
* live-state channel; a MutationMessage posted locally by the client never
|
|
109
|
-
* carries these. `origin` is the sender's page session id: its presence
|
|
110
|
-
* marks the mutation as remote, so the tracker must never record it again
|
|
111
|
-
* (the no-re-track loop guard, decision 15), and the sync module drops it
|
|
112
|
-
* when it equals the receiving engine's own session id (the echo filter).
|
|
113
|
-
* `seq` is the sender's per-session sequence number, used by the sync
|
|
114
|
-
* module to track how far the channel has progressed. `state` is the
|
|
115
|
-
* authoritative folded family state: the sync module diffs it against the
|
|
116
|
-
* channel's last-seen state and applies the difference, so a catch-up
|
|
117
|
-
* (empty `mutations`) or a broadcast the hub dropped still converges the
|
|
118
|
-
* subscriber. None of these fields are read by `MutationPipeline`.
|
|
119
|
-
*/
|
|
103
|
+
/** The sending page's session id, present when the mutation came from another device. */
|
|
120
104
|
readonly origin?: string;
|
|
105
|
+
/** The sender's per-session sequence number. */
|
|
121
106
|
readonly seq?: number;
|
|
107
|
+
/** The authoritative session state at the moment of the broadcast. */
|
|
122
108
|
readonly state?: SyncStateSnapshot;
|
|
123
109
|
/**
|
|
124
|
-
* A drag's intermediate step
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* this flag. Only the client knows when a drag settles, which is why this
|
|
128
|
-
* travels on the message instead of being guessed viewer-side.
|
|
110
|
+
* A drag's intermediate step: the viewer applies it so the model follows the
|
|
111
|
+
* hand but does not record it. The settled value arrives afterwards as an
|
|
112
|
+
* ordinary mutation without this flag.
|
|
129
113
|
*/
|
|
130
114
|
readonly transient?: boolean;
|
|
131
115
|
}
|
|
132
116
|
/**
|
|
133
|
-
* Sync
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* client exposes it as `onSyncChange`; the studio composes nothing, so its
|
|
137
|
-
* engine never sends this (it never opens the channel).
|
|
117
|
+
* Sync status (viewer → client): whether the live channel is connected to the
|
|
118
|
+
* hand-off session. One-way and latest-wins, with no history or buffering. The
|
|
119
|
+
* client exposes it as `onSyncChange`.
|
|
138
120
|
*/
|
|
139
121
|
interface SyncMessage {
|
|
140
122
|
readonly type: typeof MESSAGE_TYPES.SYNC;
|
|
@@ -148,17 +130,18 @@ interface MutationResultMessage {
|
|
|
148
130
|
readonly isInitial: boolean;
|
|
149
131
|
}
|
|
150
132
|
/**
|
|
151
|
-
* How a model's annotations present to the
|
|
152
|
-
* (show), or under
|
|
153
|
-
*
|
|
154
|
-
*
|
|
133
|
+
* How a model's annotations present to the visitor: never (hide), always
|
|
134
|
+
* (show), or under their own control via a viewer toggle, starting visible
|
|
135
|
+
* (toggle-shown) or hidden (toggle-hidden). Resolved per app, defaulting to
|
|
136
|
+
* hide.
|
|
155
137
|
*/
|
|
156
|
-
type AnnotationVisibility
|
|
138
|
+
type AnnotationVisibility = 'hide' | 'show' | 'toggle-shown' | 'toggle-hidden';
|
|
157
139
|
/**
|
|
158
|
-
*
|
|
159
|
-
*
|
|
140
|
+
* Which viewer controls the model shows, as configured for it. Sent with the
|
|
141
|
+
* mapping; every field is optional and an absent field means the viewer's own
|
|
142
|
+
* default.
|
|
160
143
|
*/
|
|
161
|
-
interface ViewerSettings
|
|
144
|
+
interface ViewerSettings {
|
|
162
145
|
readonly ar?: boolean;
|
|
163
146
|
readonly fullscreen?: boolean;
|
|
164
147
|
readonly screenshot?: boolean;
|
|
@@ -168,7 +151,7 @@ interface ViewerSettings$1 {
|
|
|
168
151
|
* annotations, so a control can never render with nothing to govern;
|
|
169
152
|
* absent means there is nothing to show or toggle.
|
|
170
153
|
*/
|
|
171
|
-
readonly annotations?: AnnotationVisibility
|
|
154
|
+
readonly annotations?: AnnotationVisibility;
|
|
172
155
|
readonly language?: string;
|
|
173
156
|
/** Where the attribute controls sit: in-frame bottom-left (default) or a docked right panel. */
|
|
174
157
|
readonly configuratorLayout?: 'inframe-bottom-left' | 'sidebar-right' | 'hidden';
|
|
@@ -254,12 +237,10 @@ interface SelectableAttribute {
|
|
|
254
237
|
readonly hidden?: boolean;
|
|
255
238
|
}
|
|
256
239
|
/**
|
|
257
|
-
* Selectability snapshot (
|
|
258
|
-
* every choice that changes the picture.
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
* `selectable`, not availability: that word is taken by pricing
|
|
262
|
-
* (AVAILABILITY, available/view_only).
|
|
240
|
+
* Selectability snapshot (viewer → client): which values can still be picked,
|
|
241
|
+
* sent after the mapping and after every choice that changes the picture.
|
|
242
|
+
* Always the complete state, never a difference; a value not in its list is
|
|
243
|
+
* not pickable and the client greys it out.
|
|
263
244
|
*/
|
|
264
245
|
interface SelectableMessage {
|
|
265
246
|
readonly type: typeof MESSAGE_TYPES.SELECTABLE;
|
|
@@ -268,25 +249,8 @@ interface SelectableMessage {
|
|
|
268
249
|
readonly attributes: SelectableAttribute[];
|
|
269
250
|
}
|
|
270
251
|
/**
|
|
271
|
-
* Loading indicator (
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
* This message concerns one model at five of its seven call sites (download
|
|
275
|
-
* progress, a load error, the rendering phase) and is fatal with no model to
|
|
276
|
-
* blame at the other two (no WebGL, the boot-failure path), so by the
|
|
277
|
-
* message-scope rule it takes an instance id optionally.
|
|
278
|
-
*
|
|
279
|
-
* It does not carry one yet, on purpose. `publishLoadingProgress` is the only
|
|
280
|
-
* publisher and knows no instance, so the field would be absent at all seven
|
|
281
|
-
* sites while its documented meaning is "absent means the viewer could not
|
|
282
|
-
* start". An integrator branching on that would read every progress update as
|
|
283
|
-
* a viewer failure, which is worse than no field at all.
|
|
284
|
-
*
|
|
285
|
-
* Nothing is lost by waiting: an optional field is additive, so unlike the
|
|
286
|
-
* required ids in this file it carries no alpha-window pressure. Composition
|
|
287
|
-
* task 10 brings a second model and with it the choice the spec parked, thread
|
|
288
|
-
* the id through the five model sites, or split the fatal case onto its own
|
|
289
|
-
* message. Decide it there, with a real second instance to test against.
|
|
252
|
+
* Loading indicator (viewer → client): download progress, the phase it is in, or
|
|
253
|
+
* an error, sent while the model loads so the client's loading UI can follow.
|
|
290
254
|
*/
|
|
291
255
|
interface LoadingIndicatorMessage {
|
|
292
256
|
readonly type: typeof MESSAGE_TYPES.LOADING_INDICATOR;
|
|
@@ -310,11 +274,8 @@ interface FullscreenMessage {
|
|
|
310
274
|
readonly type: typeof MESSAGE_TYPES.FULLSCREEN;
|
|
311
275
|
}
|
|
312
276
|
/**
|
|
313
|
-
* QR shown (client →
|
|
314
|
-
*
|
|
315
|
-
* only lets the server record the engagement (`qr_shown`, the funnel's
|
|
316
|
-
* denominator) against the tracking session it owns. One-way, fire-and-forget,
|
|
317
|
-
* nothing to act on, same shape as FULLSCREEN.
|
|
277
|
+
* QR shown (client → viewer): the desktop hand-off QR was displayed. One-way and
|
|
278
|
+
* fire-and-forget, with nothing to act on.
|
|
318
279
|
*/
|
|
319
280
|
interface QrShownMessage {
|
|
320
281
|
readonly type: typeof MESSAGE_TYPES.QR_SHOWN;
|
|
@@ -326,7 +287,7 @@ interface QrShownMessage {
|
|
|
326
287
|
*/
|
|
327
288
|
interface ConfigMessage {
|
|
328
289
|
readonly type: typeof MESSAGE_TYPES.CONFIG;
|
|
329
|
-
readonly viewerSettings: ViewerSettings
|
|
290
|
+
readonly viewerSettings: ViewerSettings;
|
|
330
291
|
readonly cameraLimits?: CameraLimits;
|
|
331
292
|
}
|
|
332
293
|
interface HandshakeMessage {
|
|
@@ -356,6 +317,13 @@ interface AnnotationToggleMessage {
|
|
|
356
317
|
*/
|
|
357
318
|
readonly instance: string;
|
|
358
319
|
readonly enabled: boolean;
|
|
320
|
+
/**
|
|
321
|
+
* Who sent it: `control` marks the client's own visible toggle button, the
|
|
322
|
+
* only sender that counts as Shopper use in the viewer statistics. Absent
|
|
323
|
+
* means programmatic (the boot-time config echo, an integrator's
|
|
324
|
+
* `client.annotations` call), which must never be measured as interest.
|
|
325
|
+
*/
|
|
326
|
+
readonly origin?: 'control';
|
|
359
327
|
}
|
|
360
328
|
/** Focus actions (client → server). */
|
|
361
329
|
declare const FOCUS_ACTIONS: {
|
|
@@ -370,10 +338,9 @@ declare const FOCUS_STATES: {
|
|
|
370
338
|
type FocusAction = (typeof FOCUS_ACTIONS)[keyof typeof FOCUS_ACTIONS];
|
|
371
339
|
type FocusStateValue = (typeof FOCUS_STATES)[keyof typeof FOCUS_STATES];
|
|
372
340
|
/**
|
|
373
|
-
* Focus (client →
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
* name as a fallback (resolved server-side); required when action is `focus`.
|
|
341
|
+
* Focus (client → viewer): isolate and frame one component, or return to the
|
|
342
|
+
* overview. `component` is a name from the model's components, or a mesh name as
|
|
343
|
+
* a fallback, and is required when the action is `focus`.
|
|
377
344
|
*/
|
|
378
345
|
interface FocusMessage {
|
|
379
346
|
readonly type: typeof MESSAGE_TYPES.FOCUS;
|
|
@@ -396,10 +363,9 @@ interface FocusStateMessage {
|
|
|
396
363
|
readonly attributes?: string[];
|
|
397
364
|
}
|
|
398
365
|
/**
|
|
399
|
-
* What the configurator does with a matched configuration.
|
|
400
|
-
* `availability` enum (pricing rule provenance lives on `PricingRule.source`).
|
|
366
|
+
* What the configurator does with a matched configuration.
|
|
401
367
|
*/
|
|
402
|
-
declare const AVAILABILITY
|
|
368
|
+
declare const AVAILABILITY: {
|
|
403
369
|
/** Price and submit button both shown (default). */
|
|
404
370
|
readonly AVAILABLE: "available";
|
|
405
371
|
/** Price shown, submit hidden (sold out / coming soon). */
|
|
@@ -407,12 +373,12 @@ declare const AVAILABILITY$1: {
|
|
|
407
373
|
/** Behaves exactly like an unpriced combination: no price, no button. */
|
|
408
374
|
readonly HIDDEN: "hidden";
|
|
409
375
|
};
|
|
410
|
-
type Availability
|
|
376
|
+
type Availability = (typeof AVAILABILITY)[keyof typeof AVAILABILITY];
|
|
411
377
|
/**
|
|
412
|
-
* One pricing rule: a subset of attribute values mapped to a reference
|
|
413
|
-
*
|
|
378
|
+
* One pricing rule: a subset of attribute values mapped to a reference and a
|
|
379
|
+
* price.
|
|
414
380
|
*/
|
|
415
|
-
interface PricingRule
|
|
381
|
+
interface PricingRule {
|
|
416
382
|
/**
|
|
417
383
|
* The attribute name→value pairs this rule names. `{}` is a catch-all;
|
|
418
384
|
* omitted names are wildcards. A rule matches when every pair equals the
|
|
@@ -423,7 +389,7 @@ interface PricingRule$1 {
|
|
|
423
389
|
readonly reference: string;
|
|
424
390
|
/** Price in minor units (cents), exactly as the source displays it. */
|
|
425
391
|
readonly priceCents: number;
|
|
426
|
-
readonly availability: Availability
|
|
392
|
+
readonly availability: Availability;
|
|
427
393
|
/** Provenance (manual | imported); audit-only, unused by the resolver. */
|
|
428
394
|
readonly source: 'manual' | 'imported';
|
|
429
395
|
}
|
|
@@ -431,7 +397,7 @@ interface PricingRule$1 {
|
|
|
431
397
|
* A model's pricing document. The viewer's fetcher merges it into the model
|
|
432
398
|
* metadata and the server forwards it to the client via {@link PricingMessage}.
|
|
433
399
|
*/
|
|
434
|
-
interface PricingDocument
|
|
400
|
+
interface PricingDocument {
|
|
435
401
|
/** Optimistic-concurrency version from the editor; unused by the viewer. */
|
|
436
402
|
readonly version: number;
|
|
437
403
|
/** Customer-authored CTA label; null when the adapter's defaultLabel fills in. */
|
|
@@ -440,7 +406,7 @@ interface PricingDocument$1 {
|
|
|
440
406
|
readonly currency: string;
|
|
441
407
|
/** VAT label for bare embeds, e.g. "incl. btw". */
|
|
442
408
|
readonly vatDisplay: string;
|
|
443
|
-
readonly rules: PricingRule
|
|
409
|
+
readonly rules: PricingRule[];
|
|
444
410
|
}
|
|
445
411
|
/**
|
|
446
412
|
* Pricing (server → client): the model's pricing document. Sent once at startup
|
|
@@ -455,7 +421,7 @@ interface PricingMessage {
|
|
|
455
421
|
* exactly this field.
|
|
456
422
|
*/
|
|
457
423
|
readonly instance: string;
|
|
458
|
-
readonly pricing: PricingDocument
|
|
424
|
+
readonly pricing: PricingDocument;
|
|
459
425
|
}
|
|
460
426
|
type Message = HandshakeMessage | SessionMessage | MutationMessage | MutationResultMessage | CameraCommandMessage | CameraPositionMessage | SnapshotRequestMessage | SnapshotResultMessage | MappingMessage | LoadingIndicatorMessage | ArActivateMessage | FullscreenMessage | ConfigMessage | AnnotationToggleMessage | FocusMessage | FocusStateMessage | PricingMessage | QrShownMessage | SyncMessage | SelectableMessage | AppResolvedMessage | StateMessage;
|
|
461
427
|
type MessageCallback = (message: Message) => void | Promise<void>;
|
|
@@ -470,29 +436,16 @@ interface MessengerOptions {
|
|
|
470
436
|
*/
|
|
471
437
|
bufferIncoming?: boolean;
|
|
472
438
|
/**
|
|
473
|
-
* Which protocol to validate incoming messages against
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
* `isValidStudioMessageData`, which accepts the public protocol plus the studio
|
|
477
|
-
* messages (e.g. annotation placement), so the public bundle stays lean.
|
|
439
|
+
* Which protocol to validate incoming messages against, never whether to
|
|
440
|
+
* validate: both sides always reject unknown types and browser-extension
|
|
441
|
+
* noise. Defaults to the public protocol.
|
|
478
442
|
*/
|
|
479
443
|
isValid?: (data: unknown) => boolean;
|
|
480
444
|
}
|
|
481
445
|
/**
|
|
482
|
-
*
|
|
446
|
+
* A bidirectional message port between a parent page and an iframe.
|
|
483
447
|
*
|
|
484
|
-
*
|
|
485
|
-
* a parent page and an iframe. Both client and server use this —
|
|
486
|
-
* the only difference is the target window.
|
|
487
|
-
*
|
|
488
|
-
* Features:
|
|
489
|
-
* - Publisher queue: outgoing messages buffered until markReady()
|
|
490
|
-
* - Consumer queue: incoming messages buffered until markConsumerReady() (opt-in)
|
|
491
|
-
* - Handler registration: route incoming messages by type
|
|
492
|
-
* - Echo prevention: tags outgoing messages to filter self-delivery
|
|
493
|
-
* - Cleanup: removes listener on destroy
|
|
494
|
-
*
|
|
495
|
-
* @example Client (parent page — publisher queue only)
|
|
448
|
+
* @example Client (parent page, publisher queue only)
|
|
496
449
|
* ```ts
|
|
497
450
|
* const messenger = new IframeMessenger(() => iframe.contentWindow);
|
|
498
451
|
* messenger.on('mutation', handleMutationResult);
|
|
@@ -503,7 +456,7 @@ interface MessengerOptions {
|
|
|
503
456
|
* messenger.send({ type: 'mutation', mutations, isInitial: true });
|
|
504
457
|
* ```
|
|
505
458
|
*
|
|
506
|
-
* @example
|
|
459
|
+
* @example Viewer (inside the iframe, both queues)
|
|
507
460
|
* ```ts
|
|
508
461
|
* const messenger = new IframeMessenger(
|
|
509
462
|
* () => window.parent !== window ? window.parent : null,
|
|
@@ -542,13 +495,8 @@ declare class IframeMessenger {
|
|
|
542
495
|
*/
|
|
543
496
|
send(message: Message): void;
|
|
544
497
|
/**
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
* against `isValid`, and still respects the consumer queue's buffering. For
|
|
548
|
-
* a transport that delivers messages some
|
|
549
|
-
* other way than the iframe channel this messenger already listens on (the
|
|
550
|
-
* viewer engine's SSE-sourced live sync channel, ar-session-handoff) and
|
|
551
|
-
* needs them to land exactly where a postMessage would.
|
|
498
|
+
* Route a message as if it had arrived by postMessage, without the round trip.
|
|
499
|
+
* Still validated against `isValid` and still subject to the consumer queue.
|
|
552
500
|
*/
|
|
553
501
|
receive(message: Message): void;
|
|
554
502
|
/**
|
|
@@ -576,18 +524,65 @@ declare class IframeMessenger {
|
|
|
576
524
|
private routeToHandler;
|
|
577
525
|
}
|
|
578
526
|
|
|
579
|
-
type SendFn$1 = (message: Message) => void;
|
|
580
527
|
/**
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
*
|
|
584
|
-
|
|
528
|
+
* The client's DOM event names, in one registry. The two selection events are
|
|
529
|
+
* what `client.on(...)` subscribes to; the other three bubble out of the
|
|
530
|
+
* container, so the host page can reach them with `addEventListener`.
|
|
531
|
+
*/
|
|
532
|
+
declare const VD_EVENTS: {
|
|
533
|
+
/** Attribute selection requested (cancelable, does not bubble). `detail`: `{ attribute, value }`. */
|
|
534
|
+
readonly SELECT: "vd:select";
|
|
535
|
+
/** Attribute selection applied (does not bubble). `detail`: `{ attribute, value }`. */
|
|
536
|
+
readonly SELECTED: "vd:selected";
|
|
537
|
+
/** Focus changed (bubbles). `detail`: `{ component, attributes }`, or `null` for the overview. */
|
|
538
|
+
readonly FOCUS_CHANGE: "vd:focus-change";
|
|
539
|
+
/** Resolved configuration changed (bubbles). `detail`: the resolved configuration, or `null` when nothing matches. */
|
|
540
|
+
readonly CONFIGURATION_CHANGE: "vd:configuration-change";
|
|
541
|
+
/** Configuration submitted (bubbles). `detail`: the resolved configuration handed to the host. */
|
|
542
|
+
readonly CONFIGURATION_SUBMIT: "vd:configuration-submit";
|
|
543
|
+
};
|
|
544
|
+
type VdEvent = typeof VD_EVENTS[keyof typeof VD_EVENTS];
|
|
545
|
+
|
|
546
|
+
/** Hands a message to the viewer iframe. */
|
|
547
|
+
type SendFn = (message: Message) => void;
|
|
548
|
+
interface MutationFailedEvent {
|
|
549
|
+
readonly attribute: string;
|
|
550
|
+
readonly value: string;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Which app the viewer resolved, as handed to an `onAppResolved` callback.
|
|
554
|
+
*/
|
|
555
|
+
interface ResolvedAppInfo {
|
|
556
|
+
/** Known values: `AppType`. An unknown value means a newer server; report it, never downgrade to a viewer. */
|
|
557
|
+
readonly appType: string;
|
|
558
|
+
readonly name: string;
|
|
559
|
+
/** The app's public slug (the address a submit POSTs to). Absent from a pre-slug server. */
|
|
560
|
+
readonly slug?: string;
|
|
561
|
+
readonly submit?: AppSubmitSettings;
|
|
562
|
+
}
|
|
563
|
+
interface VirtualdisplaySelectEvent {
|
|
564
|
+
readonly attribute: string;
|
|
565
|
+
readonly value: string;
|
|
566
|
+
preventDefault(): void;
|
|
567
|
+
}
|
|
568
|
+
interface VirtualdisplaySelectedEvent {
|
|
569
|
+
readonly attribute: string;
|
|
570
|
+
readonly value: string;
|
|
571
|
+
}
|
|
572
|
+
type VirtualdisplayUiEventMap = {
|
|
573
|
+
[VD_EVENTS.SELECT]: VirtualdisplaySelectEvent;
|
|
574
|
+
[VD_EVENTS.SELECTED]: VirtualdisplaySelectedEvent;
|
|
575
|
+
};
|
|
576
|
+
type VirtualdisplayUiEventType = keyof VirtualdisplayUiEventMap;
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Annotation display: show or hide the model's existing markers.
|
|
585
580
|
*/
|
|
586
581
|
declare class Annotations {
|
|
587
582
|
private readonly send;
|
|
588
583
|
/** Whose pins this facade toggles: a pin lives in one model's local space. */
|
|
589
584
|
private readonly instance;
|
|
590
|
-
constructor(send: SendFn
|
|
585
|
+
constructor(send: SendFn,
|
|
591
586
|
/** Whose pins this facade toggles: a pin lives in one model's local space. */
|
|
592
587
|
instance: string);
|
|
593
588
|
setEnabled(enabled: boolean): void;
|
|
@@ -724,15 +719,10 @@ interface SubmitOptions {
|
|
|
724
719
|
readonly defaultLabel?: string;
|
|
725
720
|
}
|
|
726
721
|
/**
|
|
727
|
-
*
|
|
728
|
-
*
|
|
729
|
-
*
|
|
730
|
-
*
|
|
731
|
-
* the pricing document and the latest selection, re-resolving on every change.
|
|
732
|
-
* `onChange` fires with the resolved configuration (or `undefined` when nothing
|
|
733
|
-
* matches); alongside it the container dispatches a bubbling `vd:configuration-change`
|
|
734
|
-
* CustomEvent so a page reacts without registering a callback. `onSubmit` registers
|
|
735
|
-
* the host handler that the CTA hands the configuration to.
|
|
722
|
+
* Resolves the current selection to a reference and a price, and carries it to
|
|
723
|
+
* the host page. `onChange` fires with the resolved configuration, or
|
|
724
|
+
* `undefined` when nothing matches; `onSubmit` registers the handler the CTA
|
|
725
|
+
* hands that configuration to.
|
|
736
726
|
*/
|
|
737
727
|
declare class Configuration {
|
|
738
728
|
private readonly dispatchChange;
|
|
@@ -794,7 +784,7 @@ declare class Configuration {
|
|
|
794
784
|
*/
|
|
795
785
|
submit(): Promise<void>;
|
|
796
786
|
/** Called by the client when a PRICING message arrives from the viewer. */
|
|
797
|
-
handlePricingReceived(pricing: PricingDocument
|
|
787
|
+
handlePricingReceived(pricing: PricingDocument): void;
|
|
798
788
|
/** Called by the client after every mutation result, with the full selection. */
|
|
799
789
|
handleSelectionChanged(selection: Selection): void;
|
|
800
790
|
private recompute;
|
|
@@ -811,12 +801,9 @@ type FocusChange = FocusState | null;
|
|
|
811
801
|
type FocusChangeCallback = (state: FocusChange) => void;
|
|
812
802
|
type DispatchFn = (state: FocusChange) => void;
|
|
813
803
|
/**
|
|
814
|
-
*
|
|
815
|
-
*
|
|
816
|
-
*
|
|
817
|
-
* (future) component menu and the portal/admin editors drive it over the same
|
|
818
|
-
* message bus. Alongside `onChange`, the container dispatches a bubbling
|
|
819
|
-
* `vd:focus-change` CustomEvent so a page can react without registering a callback.
|
|
804
|
+
* Isolate and frame one component, or return to the overview. Alongside
|
|
805
|
+
* `onChange` the container dispatches a bubbling `vd:focus-change` event, so a
|
|
806
|
+
* page can react without registering a callback.
|
|
820
807
|
*/
|
|
821
808
|
declare class Focus {
|
|
822
809
|
private readonly send;
|
|
@@ -1008,8 +995,8 @@ declare class Attribute {
|
|
|
1008
995
|
* they normalise before the merge (`true` → `show`, `false` → `hide`), so
|
|
1009
996
|
* existing mounts keep compiling while the package is in alpha.
|
|
1010
997
|
*/
|
|
1011
|
-
type ViewerSettingsOverride = Omit<Partial<ViewerSettings
|
|
1012
|
-
readonly annotations?: boolean | AnnotationVisibility
|
|
998
|
+
type ViewerSettingsOverride = Omit<Partial<ViewerSettings>, 'annotations'> & {
|
|
999
|
+
readonly annotations?: boolean | AnnotationVisibility;
|
|
1013
1000
|
};
|
|
1014
1001
|
/**
|
|
1015
1002
|
* Options shared by both address forms.
|
|
@@ -1034,17 +1021,9 @@ interface ClientOptionsBase {
|
|
|
1034
1021
|
readonly viewerSettings?: ViewerSettingsOverride;
|
|
1035
1022
|
}
|
|
1036
1023
|
/**
|
|
1037
|
-
*
|
|
1038
|
-
*
|
|
1039
|
-
*
|
|
1040
|
-
* resolves that app and renders it with its own configuration.
|
|
1041
|
-
* - `{ license, model }`: the classic pair, which resolves to the model's
|
|
1042
|
-
* default app. Every existing integration keeps working unchanged.
|
|
1043
|
-
*
|
|
1044
|
-
* Supplying both is allowed so a migration is additive (add `app`, done):
|
|
1045
|
-
* `app` wins and a warning is logged that the pair was ignored. Supplying
|
|
1046
|
-
* neither is a compile error, which is the guarantee this union buys over a
|
|
1047
|
-
* bag of three optional fields.
|
|
1024
|
+
* What the client shows, given either way of naming it: `{ app }`, an app's
|
|
1025
|
+
* public link key, or `{ license, model }`, which resolves to that model's
|
|
1026
|
+
* default app. Given both, `app` wins and the pair is ignored with a warning.
|
|
1048
1027
|
*/
|
|
1049
1028
|
type ClientAddress = {
|
|
1050
1029
|
readonly app: string;
|
|
@@ -1060,68 +1039,7 @@ type ClientAddress = {
|
|
|
1060
1039
|
*/
|
|
1061
1040
|
type ClientOptions = ClientOptionsBase & ClientAddress;
|
|
1062
1041
|
|
|
1063
|
-
/**
|
|
1064
|
-
* The Virtualdisplay client's DOM event names, in one registry.
|
|
1065
|
-
*
|
|
1066
|
-
* - `ui:*` events dispatch on the container (non-bubbling). They are the typed
|
|
1067
|
-
* surface of `client.on(...)` — payloads in `VirtualdisplayUiEventMap` (./types).
|
|
1068
|
-
* - `vd:*` events bubble into the customer's page, so a page can react with
|
|
1069
|
-
* `addEventListener` without registering a client callback.
|
|
1070
|
-
*/
|
|
1071
|
-
declare const VD_EVENTS: {
|
|
1072
|
-
/** Attribute selection requested (cancelable). `detail`: `{ attribute, value }`. */
|
|
1073
|
-
readonly SELECT: "ui:select";
|
|
1074
|
-
/** Attribute selection applied. `detail`: `{ attribute, value }`. */
|
|
1075
|
-
readonly SELECTED: "ui:selected";
|
|
1076
|
-
/** Focus changed (bubbles). `detail`: `{ component, attributes }`, or `null` for the overview. */
|
|
1077
|
-
readonly FOCUS_CHANGE: "vd:focus-change";
|
|
1078
|
-
/** Resolved configuration changed (bubbles). `detail`: the resolved configuration, or `null` when nothing matches. */
|
|
1079
|
-
readonly CONFIGURATION_CHANGE: "vd:configuration-change";
|
|
1080
|
-
/** Configuration submitted (bubbles). `detail`: the resolved configuration handed to the host. */
|
|
1081
|
-
readonly CONFIGURATION_SUBMIT: "vd:configuration-submit";
|
|
1082
|
-
};
|
|
1083
|
-
type VdEvent = typeof VD_EVENTS[keyof typeof VD_EVENTS];
|
|
1084
|
-
|
|
1085
|
-
interface MutationFailedEvent {
|
|
1086
|
-
readonly attribute: string;
|
|
1087
|
-
readonly value: string;
|
|
1088
|
-
}
|
|
1089
|
-
/**
|
|
1090
|
-
* Which app this viewer resolved (the apps spec's one-read inversion): the
|
|
1091
|
-
* `onAppResolved` callback payload. The protocol message minus its wire
|
|
1092
|
-
* discriminator; only the parent-safe submit settings ride along, never the
|
|
1093
|
-
* delivery recipient (removed in SQL on the public read).
|
|
1094
|
-
*/
|
|
1095
|
-
interface ResolvedAppInfo {
|
|
1096
|
-
/** Known values: `AppType`. An unknown value means a newer server; report it, never downgrade to a viewer. */
|
|
1097
|
-
readonly appType: string;
|
|
1098
|
-
readonly name: string;
|
|
1099
|
-
/** The app's public slug (the address a submit POSTs to). Absent from a pre-slug server. */
|
|
1100
|
-
readonly slug?: string;
|
|
1101
|
-
readonly submit?: AppSubmitSettings$1;
|
|
1102
|
-
}
|
|
1103
|
-
interface VirtualdisplaySelectEvent {
|
|
1104
|
-
readonly attribute: string;
|
|
1105
|
-
readonly value: string;
|
|
1106
|
-
preventDefault(): void;
|
|
1107
|
-
}
|
|
1108
|
-
interface VirtualdisplaySelectedEvent {
|
|
1109
|
-
readonly attribute: string;
|
|
1110
|
-
readonly value: string;
|
|
1111
|
-
}
|
|
1112
|
-
type VirtualdisplayUiEventMap = {
|
|
1113
|
-
[VD_EVENTS.SELECT]: VirtualdisplaySelectEvent;
|
|
1114
|
-
[VD_EVENTS.SELECTED]: VirtualdisplaySelectedEvent;
|
|
1115
|
-
};
|
|
1116
|
-
type VirtualdisplayUiEventType = keyof VirtualdisplayUiEventMap;
|
|
1117
|
-
|
|
1118
|
-
type SendFn = (message: Message) => void;
|
|
1119
|
-
/**
|
|
1120
|
-
* The seam for the AR flow behind the standard interface's AR button. The base
|
|
1121
|
-
* only routes to it: the implementation (mobile AR_ACTIVATE, desktop hand-off
|
|
1122
|
-
* QR) lives in the public client package (`@virtualdisplay.io/client`), which
|
|
1123
|
-
* composes it via {@link BaseClientExtensions.createArActivation}.
|
|
1124
|
-
*/
|
|
1042
|
+
/** The AR flow behind the standard interface's AR button. */
|
|
1125
1043
|
interface ArFlow {
|
|
1126
1044
|
/** The AR button handler. */
|
|
1127
1045
|
activate(): void;
|
|
@@ -1129,57 +1047,27 @@ interface ArFlow {
|
|
|
1129
1047
|
onSession(sessionId: string): void;
|
|
1130
1048
|
destroy(): void;
|
|
1131
1049
|
}
|
|
1132
|
-
/**
|
|
1133
|
-
* The seam for the live sync channel's connection status (ar-session-handoff,
|
|
1134
|
-
* sync-channel.md). The base only routes SYNC messages to it; the concrete
|
|
1135
|
-
* tracker (callback list + `onSyncChange`) lives in the public client package,
|
|
1136
|
-
* composed via {@link BaseClientExtensions.createSyncTracker}. The studio
|
|
1137
|
-
* composes nothing, so `onSyncChange` does not exist on the studio client
|
|
1138
|
-
* (its engine never opens the channel, so it never sends SYNC either).
|
|
1139
|
-
*/
|
|
1050
|
+
/** The live channel's connection status, as the client surfaces it. */
|
|
1140
1051
|
interface SyncTracker {
|
|
1141
1052
|
/** Latest-wins, no buffering: the channel's current connection state. */
|
|
1142
1053
|
handleSync(connected: boolean): void;
|
|
1143
1054
|
}
|
|
1144
|
-
/**
|
|
1145
|
-
* Extensions a subclass (the studio client) layers onto the base composition without
|
|
1146
|
-
* re-implementing it: a custom incoming-message validator and extra message handlers.
|
|
1147
|
-
*/
|
|
1055
|
+
/** What a subclass layers onto the base composition instead of re-implementing it. */
|
|
1148
1056
|
interface BaseClientExtensions {
|
|
1149
1057
|
readonly messengerOptions?: MessengerOptions;
|
|
1150
1058
|
readonly registerHandlers?: (messenger: IframeMessenger, send: SendFn) => void;
|
|
1151
|
-
/**
|
|
1152
|
-
* The server host this client's viewer iframe targets — a fixed fact per client
|
|
1153
|
-
* type, injected like the validator, not a per-instance setting. The studio client
|
|
1154
|
-
* fixes it to the studio viewer build; the public client leaves it unset and uses
|
|
1155
|
-
* the default public viewer. Both clients are bundled into one portal/admin build,
|
|
1156
|
-
* so the host cannot be a single build-time env shared by both.
|
|
1157
|
-
*/
|
|
1059
|
+
/** The viewer host this client's iframe targets. Unset means the default viewer. */
|
|
1158
1060
|
readonly serverHost?: string;
|
|
1159
|
-
/**
|
|
1160
|
-
* Extra query parameters for the viewer iframe URL. An extension seam like
|
|
1161
|
-
* `serverHost`: a client type's fixed capability flags (the studio client's
|
|
1162
|
-
* metadata-override boot mode), never a per-instance public option.
|
|
1163
|
-
*/
|
|
1061
|
+
/** A client type's fixed capability flags, appended to the viewer iframe URL. */
|
|
1164
1062
|
readonly iframeParams?: Readonly<Record<string, string>>;
|
|
1165
|
-
/**
|
|
1166
|
-
* The AR flow behind the standard interface's AR button. The public client
|
|
1167
|
-
* composes its `ArActivation` here; the studio composes nothing (the editor
|
|
1168
|
-
* has no AR use case), so the base wires no AR button at all.
|
|
1169
|
-
*/
|
|
1063
|
+
/** Builds the AR flow behind the standard interface's AR button. */
|
|
1170
1064
|
readonly createArActivation?: (send: SendFn) => ArFlow;
|
|
1171
|
-
/**
|
|
1172
|
-
* The live sync channel's connection tracker (ar-session-handoff). The
|
|
1173
|
-
* public client composes a tracker and exposes `onSyncChange`; the studio
|
|
1174
|
-
* composes nothing, so SYNC messages (which its own engine never sends
|
|
1175
|
-
* anyway) are simply dropped.
|
|
1176
|
-
*/
|
|
1065
|
+
/** Builds the tracker behind `onSyncChange`. */
|
|
1177
1066
|
readonly createSyncTracker?: () => SyncTracker;
|
|
1178
1067
|
}
|
|
1179
1068
|
/**
|
|
1180
|
-
* The shared client composition root
|
|
1181
|
-
* the
|
|
1182
|
-
* client extends it with the studio facades via {@link BaseClientExtensions}.
|
|
1069
|
+
* The shared client composition root: wires the transport, facades and UI, and
|
|
1070
|
+
* exposes the integrator-facing API.
|
|
1183
1071
|
*/
|
|
1184
1072
|
declare class BaseClient {
|
|
1185
1073
|
private readonly attributes;
|
|
@@ -1197,9 +1085,9 @@ declare class BaseClient {
|
|
|
1197
1085
|
private readonly options;
|
|
1198
1086
|
private readonly serverHost;
|
|
1199
1087
|
private readonly iframeParams;
|
|
1200
|
-
/** The composed AR flow, or undefined in
|
|
1088
|
+
/** The composed AR flow, or undefined in a build that composes none. */
|
|
1201
1089
|
private readonly arActivation;
|
|
1202
|
-
/** The composed sync tracker, or undefined in
|
|
1090
|
+
/** The composed sync tracker, or undefined in a build that composes none. */
|
|
1203
1091
|
private readonly syncTracker;
|
|
1204
1092
|
private iframe;
|
|
1205
1093
|
private container;
|
|
@@ -1213,6 +1101,7 @@ declare class BaseClient {
|
|
|
1213
1101
|
constructor(options: ClientOptions, extensions?: BaseClientExtensions);
|
|
1214
1102
|
/** The configurator UI, every callback bridging it to the facade that owns the action. */
|
|
1215
1103
|
private createStandardInterface;
|
|
1104
|
+
private sendControlAnnotationToggle;
|
|
1216
1105
|
/** Wire the inbound viewer protocol to the facades. */
|
|
1217
1106
|
private wireIncomingMessages;
|
|
1218
1107
|
/** Store the resolved app and notify every registered `onAppResolved` callback. */
|
|
@@ -1237,11 +1126,8 @@ declare class BaseClient {
|
|
|
1237
1126
|
private dispatchConfigurationSubmit;
|
|
1238
1127
|
private handleConfig;
|
|
1239
1128
|
/**
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1242
|
-
* integrator override) differs from what CONFIG announced, in either
|
|
1243
|
-
* direction. Equal modes echo nothing, so a boot without overrides sends
|
|
1244
|
-
* no toggle at all.
|
|
1129
|
+
* Tell the viewer about the annotation mode only when the merged mode differs
|
|
1130
|
+
* from the one it announced.
|
|
1245
1131
|
*/
|
|
1246
1132
|
private echoAnnotationsDifference;
|
|
1247
1133
|
/** Tell the viewer the user entered fullscreen, so it records the engagement. */
|
|
@@ -1257,11 +1143,9 @@ declare class BaseClient {
|
|
|
1257
1143
|
onReady(callback: (client: this) => void): void;
|
|
1258
1144
|
onMutationFailed(callback: (event: MutationFailedEvent) => void): void;
|
|
1259
1145
|
/**
|
|
1260
|
-
* Subscribe to
|
|
1261
|
-
*
|
|
1262
|
-
*
|
|
1263
|
-
* exclusions never sends one: everything stays selectable and this never
|
|
1264
|
-
* fires.
|
|
1146
|
+
* Subscribe to which values can be picked right now, per attribute. Fires
|
|
1147
|
+
* immediately when a snapshot already arrived. A model with no exclusions
|
|
1148
|
+
* never sends one, so this never fires and everything stays selectable.
|
|
1265
1149
|
*/
|
|
1266
1150
|
onSelectableChange(callback: (snapshot: SelectableSnapshot) => void): void;
|
|
1267
1151
|
/**
|
|
@@ -1273,11 +1157,8 @@ declare class BaseClient {
|
|
|
1273
1157
|
/** The selectable values for one attribute right now, or null when unrestricted. */
|
|
1274
1158
|
getSelectable(name: string): readonly string[] | null;
|
|
1275
1159
|
/**
|
|
1276
|
-
*
|
|
1277
|
-
*
|
|
1278
|
-
* e.g. the AR landing, which owns a single custom AR affordance) still needs
|
|
1279
|
-
* an entry point to the same flow that button would have called. A no-op
|
|
1280
|
-
* where no AR flow is composed (the studio client has none).
|
|
1160
|
+
* Start the AR flow directly, as the built-in AR button would. Does nothing
|
|
1161
|
+
* when `viewerSettings.ar` is off or the build composes no AR flow.
|
|
1281
1162
|
*/
|
|
1282
1163
|
activateAr(): void;
|
|
1283
1164
|
on<T extends VirtualdisplayUiEventType>(type: T, callback: (event: VirtualdisplayUiEventMap[T]) => void): void;
|
|
@@ -1289,7 +1170,7 @@ declare class BaseClient {
|
|
|
1289
1170
|
get snapshot(): Snapshot;
|
|
1290
1171
|
/** The viewer's tracking session id, for a host page to correlate its own actions. */
|
|
1291
1172
|
get sessionId(): string | undefined;
|
|
1292
|
-
get viewerSettings(): ViewerSettings
|
|
1173
|
+
get viewerSettings(): ViewerSettings;
|
|
1293
1174
|
destroy(): void;
|
|
1294
1175
|
}
|
|
1295
1176
|
|
|
@@ -1309,15 +1190,8 @@ declare function enableDebugMode(): void;
|
|
|
1309
1190
|
declare function isDebugMode(): boolean;
|
|
1310
1191
|
|
|
1311
1192
|
/**
|
|
1312
|
-
* The
|
|
1313
|
-
*
|
|
1314
|
-
* `@virtualdisplay.io/client`. The internal studio client adds the editing facades over the
|
|
1315
|
-
* same base in `@virtualdisplay.io/client-studio`.
|
|
1316
|
-
*
|
|
1317
|
-
* The AR flow (mobile AR_ACTIVATE, desktop hand-off QR) is composed here: it is a shopper
|
|
1318
|
-
* feature, so the studio client does not compose it and renders no AR button. The live sync
|
|
1319
|
-
* channel's connection status (`onSyncChange`) is composed the same way: the studio client
|
|
1320
|
-
* has no such method, its engine never opens the channel.
|
|
1193
|
+
* The Virtualdisplay client: point it at a container and an app or model, and it
|
|
1194
|
+
* renders the viewer with the standard interface, the configurator and AR.
|
|
1321
1195
|
*/
|
|
1322
1196
|
declare class VirtualdisplayClient extends BaseClient {
|
|
1323
1197
|
private readonly syncStatusTracker;
|
|
@@ -1326,93 +1200,5 @@ declare class VirtualdisplayClient extends BaseClient {
|
|
|
1326
1200
|
onSyncChange(callback: (connected: boolean) => void): void;
|
|
1327
1201
|
}
|
|
1328
1202
|
|
|
1329
|
-
/** The app types this protocol version knows. The wire field stays a plain
|
|
1330
|
-
* string on purpose: a newer viewer may report a type this bundle predates,
|
|
1331
|
-
* and the host must receive it to fail visibly (never a quiet downgrade). */
|
|
1332
|
-
type AppType = 'viewer' | 'configurator';
|
|
1333
|
-
/** The public submit settings of a configurator-type app, as the form renders
|
|
1334
|
-
* them. Never the recipient: that section is removed in SQL on the public
|
|
1335
|
-
* read and cannot ride any message. Sparse like every config section: an
|
|
1336
|
-
* absent field means the renderer's default (the backend stores the section
|
|
1337
|
-
* as written and omits empty keys), so nothing here is guaranteed present. */
|
|
1338
|
-
interface AppSubmitSettings {
|
|
1339
|
-
readonly fields?: string[];
|
|
1340
|
-
readonly ctaLabel?: string;
|
|
1341
|
-
readonly privacyUrl?: string;
|
|
1342
|
-
}
|
|
1343
|
-
/**
|
|
1344
|
-
* How a model's annotations present to the Shopper: never (hide), always
|
|
1345
|
-
* (show), or under the Shopper's own control via a viewer toggle, starting
|
|
1346
|
-
* visible (toggle-shown) or hidden (toggle-hidden). Resolved per app; the
|
|
1347
|
-
* backend's `Resolve` owns the `hide` default.
|
|
1348
|
-
*/
|
|
1349
|
-
type AnnotationVisibility = 'hide' | 'show' | 'toggle-shown' | 'toggle-hidden';
|
|
1350
|
-
/**
|
|
1351
|
-
* Viewer settings from model metadata (server → client via MAPPING).
|
|
1352
|
-
* Customer-configured in the portal.
|
|
1353
|
-
*/
|
|
1354
|
-
interface ViewerSettings {
|
|
1355
|
-
readonly ar?: boolean;
|
|
1356
|
-
readonly fullscreen?: boolean;
|
|
1357
|
-
readonly screenshot?: boolean;
|
|
1358
|
-
readonly cameraControls?: boolean;
|
|
1359
|
-
/**
|
|
1360
|
-
* The resolved per-app annotation mode. Present only when the model has
|
|
1361
|
-
* annotations, so a control can never render with nothing to govern;
|
|
1362
|
-
* absent means there is nothing to show or toggle.
|
|
1363
|
-
*/
|
|
1364
|
-
readonly annotations?: AnnotationVisibility;
|
|
1365
|
-
readonly language?: string;
|
|
1366
|
-
/** Where the attribute controls sit: in-frame bottom-left (default) or a docked right panel. */
|
|
1367
|
-
readonly configuratorLayout?: 'inframe-bottom-left' | 'sidebar-right' | 'hidden';
|
|
1368
|
-
}
|
|
1369
|
-
/**
|
|
1370
|
-
* What the configurator does with a matched configuration. Mirrors the backend
|
|
1371
|
-
* `availability` enum (pricing rule provenance lives on `PricingRule.source`).
|
|
1372
|
-
*/
|
|
1373
|
-
declare const AVAILABILITY: {
|
|
1374
|
-
/** Price and submit button both shown (default). */
|
|
1375
|
-
readonly AVAILABLE: "available";
|
|
1376
|
-
/** Price shown, submit hidden (sold out / coming soon). */
|
|
1377
|
-
readonly VIEW_ONLY: "view_only";
|
|
1378
|
-
/** Behaves exactly like an unpriced combination: no price, no button. */
|
|
1379
|
-
readonly HIDDEN: "hidden";
|
|
1380
|
-
};
|
|
1381
|
-
type Availability = (typeof AVAILABILITY)[keyof typeof AVAILABILITY];
|
|
1382
|
-
/**
|
|
1383
|
-
* One pricing rule: a subset of attribute values mapped to a reference + price.
|
|
1384
|
-
* Matches the backend pricing read contract (`GET /api/public/models/.../pricing`).
|
|
1385
|
-
*/
|
|
1386
|
-
interface PricingRule {
|
|
1387
|
-
/**
|
|
1388
|
-
* The attribute name→value pairs this rule names. `{}` is a catch-all;
|
|
1389
|
-
* omitted names are wildcards. A rule matches when every pair equals the
|
|
1390
|
-
* current selection; the rule naming the most attributes wins.
|
|
1391
|
-
*/
|
|
1392
|
-
readonly attributes: Record<string, string>;
|
|
1393
|
-
/** The customer's own identifier (SKU, EAN, artikelnummer, name code). */
|
|
1394
|
-
readonly reference: string;
|
|
1395
|
-
/** Price in minor units (cents), exactly as the source displays it. */
|
|
1396
|
-
readonly priceCents: number;
|
|
1397
|
-
readonly availability: Availability;
|
|
1398
|
-
/** Provenance (manual | imported); audit-only, unused by the resolver. */
|
|
1399
|
-
readonly source: 'manual' | 'imported';
|
|
1400
|
-
}
|
|
1401
|
-
/**
|
|
1402
|
-
* A model's pricing document. The viewer's fetcher merges it into the model
|
|
1403
|
-
* metadata and the server forwards it to the client via {@link PricingMessage}.
|
|
1404
|
-
*/
|
|
1405
|
-
interface PricingDocument {
|
|
1406
|
-
/** Optimistic-concurrency version from the editor; unused by the viewer. */
|
|
1407
|
-
readonly version: number;
|
|
1408
|
-
/** Customer-authored CTA label; null when the adapter's defaultLabel fills in. */
|
|
1409
|
-
readonly buttonLabel: string | null;
|
|
1410
|
-
/** ISO 4217 currency code for price formatting. */
|
|
1411
|
-
readonly currency: string;
|
|
1412
|
-
/** VAT label for bare embeds, e.g. "incl. btw". */
|
|
1413
|
-
readonly vatDisplay: string;
|
|
1414
|
-
readonly rules: PricingRule[];
|
|
1415
|
-
}
|
|
1416
|
-
|
|
1417
1203
|
export { Annotations, Attribute, AttributeValue, Camera, Configuration, ERROR_CODES, Focus, Photo, Snapshot, VD_EVENTS, VirtualdisplayClient, VirtualdisplayError, enableDebugMode, isDebugMode, logger };
|
|
1418
1204
|
export type { AppSubmitSettings, AppType, Availability, ClientOptions, ErrorCode, FocusState, MutationFailedEvent, PhotoData, PricingDocument, PricingRule, ResolvedAppInfo, ResolvedConfiguration, SubmitOptions, SubmittedConfiguration, VdEvent, ViewerSettings, VirtualdisplaySelectEvent, VirtualdisplaySelectedEvent, VirtualdisplayUiEventMap, VirtualdisplayUiEventType };
|