@virtualdisplay.io/client 3.6.0 → 4.0.0-alpha.1

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/dist/index.d.ts CHANGED
@@ -1,153 +1,95 @@
1
- import { Logger } from '@virtualdisplay-io/logger';
1
+ import { CameraConfig } from '@virtualdisplay.io/messaging';
2
+ import { CameraParameter } from '@virtualdisplay.io/messaging';
3
+ import { CameraPositionMessage } from '@virtualdisplay.io/messaging';
4
+ import { MessageCallback } from '@virtualdisplay.io/messaging';
5
+ import { SnapshotResultMessage } from '@virtualdisplay.io/messaging';
6
+ import { UIConfig } from '@virtualdisplay.io/messaging';
2
7
 
3
8
  /**
4
- * Pure domain aggregate for managing attribute values
5
- * No side effects - only business logic and state management
9
+ * Represents a single attribute with its available values
10
+ * Flat API - no source/target translation, works with server values directly
6
11
  */
7
- declare class Attribute {
8
- private readonly attributeName;
9
- private readonly values;
10
- constructor(name: string);
11
- addValue(attributeValue: AttributeValue): void;
12
- /**
13
- * Select a value - returns mutations needed for the change
14
- * Pure function - no side effects
15
- */
16
- select(value: string): Mutation[];
17
- getDefaultMutations(): Mutation[];
18
- getCurrentValue(): AttributeValue | undefined;
19
- getValue(valueName: string): AttributeValue | undefined;
20
- getAllValues(): AttributeValue[];
21
- hasValue(valueName: string): boolean;
22
- get name(): string;
23
- get currentSelection(): string | undefined;
24
- }
25
-
26
- /**
27
- * Configuration for a single attribute
28
- */
29
- export declare interface AttributeConfig {
12
+ export declare class Attribute {
30
13
  readonly name: string;
31
- readonly values: AttributeValueConfig[];
32
- }
33
-
34
- /**
35
- * Public API for selecting attribute values
36
- * Provides fluent interface for client usage
37
- */
38
- export declare class AttributeSelector {
39
- private readonly attributeService;
40
- private readonly attributeName;
41
- constructor(attributeService: AttributeService, attributeName: string);
14
+ readonly defaultValue: string | undefined;
15
+ private readonly values;
16
+ private readonly onSelect;
17
+ private onChangeCallback?;
18
+ constructor(options: AttributeOptions);
42
19
  /**
43
20
  * Select a value for this attribute
44
- * Fire-and-forget: returns immediately, 3D updates asynchronously
45
- * @returns this AttributeSelector for method chaining
46
- * @throws {VirtualdisplayError} When value not found for attribute
47
- */
48
- select(value: string): AttributeSelector;
49
- get name(): string;
50
- get currentValue(): string | undefined;
51
- get availableValues(): string[];
52
- /**
53
- * Register a callback to be called when any value's selection state changes
54
- * This registers the callback on all AttributeValue objects for this attribute
55
- * @param callback Function to call when selection state changes
56
- * @returns this AttributeSelector for method chaining
21
+ * @throws {VirtualdisplayError} When value not found
57
22
  */
58
- onChange(callback: () => void): AttributeSelector;
23
+ select(value: string): void;
24
+ getValues(): AttributeValue[];
25
+ getValue(value: string): AttributeValue | undefined;
59
26
  /**
60
- * Get all AttributeValue objects for direct property access
61
- * @returns Array of AttributeValue objects
27
+ * Register callback that fires when selection changes
28
+ * Receives the newly selected AttributeValue
62
29
  */
63
- getValues(): AttributeValue[];
30
+ onChange(callback: (selectedValue: AttributeValue) => void): void;
64
31
  /**
65
- * Get a specific AttributeValue object by value name
66
- * @param value The value name to find
67
- * @returns AttributeValue object or undefined if not found
32
+ * Update selection state from server mutation result
33
+ * Direct value comparison - no source/target translation
68
34
  */
69
- getValue(value: string): AttributeValue | undefined;
70
- private getAttribute;
35
+ handleResult(serverValue: string): void;
36
+ private createValues;
71
37
  }
72
38
 
73
- /**
74
- * Application service for managing attributes
75
- * Handles business logic and coordinates with other domains via events
76
- */
77
- declare class AttributeService {
78
- private readonly attributes;
79
- private readonly eventBus;
80
- private isInitialized;
81
- constructor(eventBus: EventBus);
82
- /**
83
- * Load mapping configuration and apply defaults
84
- * @throws {VirtualdisplayError} When mapping configuration is invalid
85
- */
86
- loadMapping(config: MappingConfiguration): void;
87
- selectAttributeValue(attributeName: string, value: string): void;
88
- getAttribute(name: string): Attribute | undefined;
89
- getAllAttributes(): Attribute[];
90
- get initialized(): boolean;
91
- private syncStateWithAttributes;
92
- private getAttributeValueForNode;
93
- clear(): void;
39
+ declare interface AttributeOptions {
40
+ readonly name: string;
41
+ readonly values: string[];
42
+ readonly onSelect: (name: string, value: string) => void;
43
+ readonly defaultValue?: string;
94
44
  }
95
45
 
96
46
  /**
97
47
  * Pure domain entity representing a single attribute value
98
- * No side effects - only business logic and data
48
+ * No side effects - only state
99
49
  */
100
- declare class AttributeValue {
101
- private readonly attributeValue;
102
- private readonly nodeIds;
103
- private selected;
104
- onChange?: () => void;
105
- constructor(value: string, nodeIds: string[], isSelected?: boolean);
106
- getMutations(): Mutation[];
107
- setSelected(selected: boolean): void;
108
- get value(): string;
109
- get nodeList(): string[];
110
- hasNode(nodeId: string): boolean;
50
+ export declare class AttributeValue {
51
+ readonly value: string;
52
+ readonly attribute: string;
53
+ private isSelectedValue;
54
+ constructor(value: string, attribute: string);
111
55
  get isSelected(): boolean;
112
- setOnChange(callback: () => void): void;
56
+ setSelected(selected: boolean): void;
113
57
  }
114
58
 
115
- /**
116
- * Configuration for a single attribute value
117
- */
118
- export declare interface AttributeValueConfig {
119
- readonly value: string;
120
- readonly nodeIds: string[];
121
- readonly isSelected?: boolean;
122
- }
59
+ declare type Attrs = Record<string, unknown> | unknown;
123
60
 
124
61
  /**
125
62
  * Camera control API for positioning and zoom
126
63
  * Uses chaining pattern for building commands
127
64
  */
128
65
  export declare class Camera {
129
- private readonly eventBus;
66
+ private readonly send;
130
67
  private commands;
131
- constructor(eventBus: EventBus);
68
+ constructor(send: MessageCallback);
132
69
  /**
133
70
  * Rotate camera horizontally
134
71
  * @param degrees - Absolute rotation in degrees (0 = front view)
72
+ * @throws VirtualdisplayError if value is not a finite number
135
73
  */
136
74
  rotate(degrees: number): this;
137
75
  /**
138
76
  * Tilt camera vertically
139
77
  * @param degrees - Absolute tilt in degrees (0 = top view, 90 = horizontal)
78
+ * @throws VirtualdisplayError if value is not a finite number
140
79
  */
141
80
  tilt(degrees: number): this;
142
81
  /**
143
82
  * Zoom camera
144
83
  * @param percentage - Zoom percentage (100 = normal, >100 = zoom in, <100 = zoom out)
84
+ * @throws VirtualdisplayError if value is not a finite number
145
85
  */
146
86
  zoom(percentage: number): this;
147
87
  /**
148
88
  * Execute accumulated camera commands
89
+ * @throws VirtualdisplayError if no commands have been accumulated
149
90
  */
150
91
  set(): void;
92
+ private validateFiniteNumber;
151
93
  /**
152
94
  * Reset camera to initial position
153
95
  * This is not chainable and executes immediately
@@ -156,32 +98,46 @@ export declare class Camera {
156
98
  }
157
99
 
158
100
  /**
159
- * Camera command
160
- */
161
- export declare interface CameraCommand {
162
- readonly action: 'rotate' | 'tilt' | 'zoom' | 'reset';
163
- readonly value?: number;
164
- }
165
-
166
- /**
167
- * Camera configuration options
101
+ * Camera position state
102
+ * Tracks current rotation, tilt, and zoom values from server updates
168
103
  */
169
- export declare interface CameraConfig {
170
- readonly initialRotate?: number;
171
- readonly initialTilt?: number;
172
- readonly initialZoom?: number;
173
- readonly minZoom?: number;
174
- readonly maxZoom?: number;
175
- readonly minTilt?: number;
176
- readonly maxTilt?: number;
104
+ declare class CameraPosition {
105
+ private readonly state;
106
+ private readonly changeCallbacks;
107
+ constructor();
108
+ /**
109
+ * Get current rotation in degrees
110
+ */
111
+ get rotation(): number;
112
+ /**
113
+ * Get current tilt in degrees
114
+ */
115
+ get tilt(): number;
116
+ /**
117
+ * Get current zoom percentage
118
+ */
119
+ get zoom(): number;
120
+ /**
121
+ * Subscribe to camera position changes
122
+ */
123
+ onChange(callback: (position: CameraPositionState) => void): void;
124
+ /**
125
+ * Handle incoming camera position message from server
126
+ */
127
+ handlePositionUpdate(message: CameraPositionMessage): void;
128
+ /**
129
+ * Update camera position from server transforms
130
+ */
131
+ update(transforms: CameraParameter[]): void;
177
132
  }
178
133
 
179
134
  /**
180
- * Camera message sent to server
135
+ * Camera position state object
181
136
  */
182
- export declare interface CameraMessage {
183
- readonly type: typeof MESSAGE_TYPES.CAMERA;
184
- readonly commands: CameraCommand[];
137
+ declare interface CameraPositionState {
138
+ rotation: number;
139
+ tilt: number;
140
+ zoom: number;
185
141
  }
186
142
 
187
143
  /**
@@ -200,34 +156,6 @@ export declare interface ClientOptions {
200
156
  readonly camera?: CameraConfig;
201
157
  }
202
158
 
203
- /**
204
- * Configuration message sent to server
205
- */
206
- export declare interface ConfigMessage {
207
- readonly type: typeof MESSAGE_TYPES.CONFIG;
208
- readonly config: ViewerConfig;
209
- }
210
-
211
- declare interface CreateNodeParams {
212
- id: string;
213
- name: string;
214
- type: NodeType;
215
- visible: boolean;
216
- }
217
-
218
- /**
219
- * Central Event Registry
220
- */
221
- export declare interface DomainEvents extends Record<string, unknown> {
222
- [EVENT_NAMES.IFRAME_READY]: VoidEvent;
223
- [EVENT_NAMES.MUTATION_MESSAGE]: MessageEvent_2<MutationMessage>;
224
- [EVENT_NAMES.CONFIG_MESSAGE]: MessageEvent_2<ConfigMessage>;
225
- [EVENT_NAMES.CAMERA_MESSAGE]: MessageEvent_2<CameraMessage>;
226
- [EVENT_NAMES.MESSAGE_RECEIVED]: MessageEvent_2;
227
- [EVENT_NAMES.STATE_CHANGED]: StateChangedEvent;
228
- [EVENT_NAMES.INITIAL_STATE_RECEIVED]: VoidEvent;
229
- }
230
-
231
159
  export declare function enableDebugMode(): void;
232
160
 
233
161
  /**
@@ -237,272 +165,37 @@ export declare const ERROR_CODES: {
237
165
  readonly NO_MAPPING: "NO_MAPPING";
238
166
  readonly ATTRIBUTE_NOT_FOUND: "ATTRIBUTE_NOT_FOUND";
239
167
  readonly VALUE_NOT_FOUND: "VALUE_NOT_FOUND";
240
- readonly INVALID_MAPPING: "INVALID_MAPPING";
241
168
  readonly PARENT_NOT_FOUND: "PARENT_NOT_FOUND";
242
- readonly INVALID_MUTATIONS: "INVALID_MUTATIONS";
243
169
  readonly INVALID_PARAMETER: "INVALID_PARAMETER";
170
+ readonly SNAPSHOT_FAILED: "SNAPSHOT_FAILED";
244
171
  };
245
172
 
246
173
  export declare type ErrorCode = typeof ERROR_CODES[keyof typeof ERROR_CODES];
247
174
 
248
- /**
249
- * Event name constants for type-safe event communication
250
- */
251
- export declare const EVENT_NAMES: {
252
- readonly IFRAME_READY: "iframe:ready";
253
- readonly MUTATION_MESSAGE: "mutation:message";
254
- readonly CONFIG_MESSAGE: "config:message";
255
- readonly CAMERA_MESSAGE: "camera:message";
256
- readonly MESSAGE_RECEIVED: "message:received";
257
- readonly STATE_CHANGED: "state:changed";
258
- readonly INITIAL_STATE_RECEIVED: "state:initial-received";
259
- readonly SNAPSHOT_MESSAGE: "snapshot:take";
260
- readonly SNAPSHOT_DEVELOPED: "snapshot:developed";
261
- };
262
-
263
- /**
264
- * EventBus for domain coordination
265
- * Provides loose coupling between domains via events
266
- */
267
- declare class EventBus {
268
- private readonly listeners;
269
- on<K extends keyof DomainEvents>(event: K, listener: EventListener_2<DomainEvents[K]>): void;
270
- emit<K extends keyof DomainEvents>(event: K, payload: DomainEvents[K]): void;
271
- /**
272
- * Register a listener that will be called only once
273
- * The listener is automatically removed after the first call
274
- */
275
- once<K extends keyof DomainEvents>(event: K, listener: EventListener_2<DomainEvents[K]>): void;
276
- /**
277
- * Remove a specific listener for an event
278
- */
279
- off<K extends keyof DomainEvents>(event: K, listener: EventListener_2<DomainEvents[K]>): void;
280
- }
281
-
282
- declare type EventListener_2<T> = (payload: T) => void;
283
-
284
175
  export declare function isDebugMode(): boolean;
285
176
 
286
- export declare const logger: Logger;
287
-
288
- /**
289
- * Complete mapping configuration
290
- * Defines how product attributes map to 3D nodes
291
- */
292
- export declare interface MappingConfiguration {
293
- readonly attributes: AttributeConfig[];
294
- }
295
-
296
- export declare const mappingSchema: {
297
- "$schema": "http://json-schema.org/draft-07/schema#",
298
- "title": "Virtualdisplay mapping configuration",
299
- "description": "Schema for attribute-based 3D model configuration",
300
- "type": "object",
301
- "required": ["attributes"],
302
- "definitions": {
303
- "attribute": {
304
- "type": "object",
305
- "description": "A configurable attribute with multiple possible values",
306
- "required": ["name", "values"],
307
- "properties": {
308
- "name": {
309
- "type": "string",
310
- "description": "Unique attribute name (e.g., 'Color', 'Size')",
311
- "minLength": 1,
312
- "pattern": "^\\S.*\\S$|^\\S$"
313
- },
314
- "values": {
315
- "type": "array",
316
- "description": "Possible values for this attribute",
317
- "minItems": 1,
318
- "items": {
319
- "$ref": "#/definitions/attributeValue"
320
- }
321
- }
322
- }
323
- },
324
- "attributeValue": {
325
- "type": "object",
326
- "description": "A single value option for an attribute",
327
- "required": ["value", "nodeIds"],
328
- "properties": {
329
- "value": {
330
- "type": "string",
331
- "description": "Display value (e.g., 'Red', 'Large')",
332
- "minLength": 1,
333
- "pattern": "^\\S.*\\S$|^\\S$"
334
- },
335
- "nodeIds": {
336
- "type": "array",
337
- "description": "3D model node IDs controlled by this value",
338
- "items": {
339
- "type": "string",
340
- "description": "Node ID in the 3D model"
341
- }
342
- },
343
- "isSelected": {
344
- "type": "boolean",
345
- "description": "Whether this value is selected by default",
346
- "default": false
347
- }
348
- }
349
- }
350
- },
351
- "properties": {
352
- "attributes": {
353
- "type": "array",
354
- "description": "List of all configurable attributes",
355
- "minItems": 1,
356
- "items": {
357
- "$ref": "#/definitions/attribute"
358
- }
359
- }
360
- }
361
- };
362
-
363
- /**
364
- * Validator for mapping configuration using AJV
365
- */
366
- export declare class MappingValidator {
367
- private static readonly ajv;
368
- private static readonly validateFn;
369
- /**
370
- * Validate complete mapping configuration
371
- * @throws {VirtualdisplayError} When mapping configuration is invalid
372
- */
373
- static validate(config: MappingConfiguration): void;
374
- }
375
-
376
- /**
377
- * Union of all possible messages
378
- */
379
- export declare type Message = MutationMessage | StateMessage | ConfigMessage | CameraMessage | SnapshotRequestMessage | SnapshotDevelopedMessage;
380
-
381
- /**
382
- * Types of messages exchanged between client and server
383
- * Using lowercase format to match server
384
- */
385
- export declare const MESSAGE_TYPES: {
386
- readonly MUTATION: "mutation";
387
- readonly STATE: "state";
388
- readonly CONFIG: "config";
389
- readonly CAMERA: "camera";
390
- readonly SNAPSHOT: "snapshot";
391
- };
392
-
393
- /**
394
- * Generic message event - used for all message passing
395
- */
396
- declare interface MessageEvent_2<T extends Message = Message> {
397
- message: T;
398
- }
399
-
400
- /**
401
- * Represents a 3D node in the scene
402
- * Live object that can be updated to reflect state changes
403
- */
404
- export declare class ModelNode {
405
- readonly id: string;
406
- readonly name: string;
407
- readonly type: NodeType;
408
- private visible;
409
- onChange?: () => void;
410
- constructor(params: CreateNodeParams);
411
- get isVisible(): boolean;
412
- show(): void;
413
- hide(): void;
414
- }
415
-
416
- /**
417
- * DTO for model node data received from server
418
- */
419
- export declare interface ModelNodeDto {
420
- readonly id: string;
421
- readonly name: string;
422
- readonly type: string;
423
- readonly visible: boolean;
424
- }
425
-
426
- /**
427
- * A mutation represents a change to be applied to a 3D node
428
- * This is a pure data class with no side effects
429
- */
430
- export declare class Mutation {
431
- readonly type: MutationType;
432
- readonly nodeId: string;
433
- constructor(type: MutationType, nodeId: string);
434
- static show(nodeId: string): Mutation;
435
- static hide(nodeId: string): Mutation;
436
- inverse(): Mutation;
437
- equals(other: Mutation): boolean;
438
- toDto(): MutationDto;
439
- }
440
-
441
- /**
442
- * Types of mutations that can be applied to 3D nodes
443
- */
444
- export declare const MUTATION_TYPES: {
445
- readonly SHOW: "show";
446
- readonly HIDE: "hide";
177
+ export declare let logger: {
178
+ debug: (msg: string, attrs?: Attrs) => void;
179
+ info: (msg: string, attrs?: Attrs) => void;
180
+ warn: (msg: string, attrs?: Attrs) => void;
181
+ error: (msg: string, attrs?: Attrs) => void;
447
182
  };
448
183
 
449
- /**
450
- * Data Transfer Object for mutations
451
- * Plain object for client-server communication without methods
452
- */
453
- export declare interface MutationDto {
454
- readonly type: MutationType;
455
- readonly nodeId: string;
184
+ export declare interface MutationFailedEvent {
185
+ attribute: string;
186
+ value: string;
456
187
  }
457
188
 
458
- /**
459
- * Mutation message sent to server
460
- */
461
- export declare interface MutationMessage {
462
- readonly type: typeof MESSAGE_TYPES.MUTATION;
463
- readonly mutations: MutationDto[];
464
- }
465
-
466
- export declare type MutationType = typeof MUTATION_TYPES[keyof typeof MUTATION_TYPES];
467
-
468
- /**
469
- * Types of nodes in the 3D scene
470
- */
471
- export declare const NODE_TYPES: {
472
- readonly MESH: "mesh";
473
- readonly VARIANT: "variant";
474
- };
475
-
476
- /**
477
- * Public API for controlling individual nodes
478
- * Provides direct node manipulation without attribute mapping
479
- */
480
- export declare class NodeSelector {
481
- private readonly eventBus;
482
- private readonly stateService;
483
- private readonly nodeId;
484
- constructor(eventBus: EventBus, stateService: StateService, nodeId: string);
485
- show(): void;
486
- hide(): void;
487
- toggle(): void;
488
- get id(): string;
489
- get isVisible(): boolean;
490
- getNode(): ModelNode | undefined;
491
- get type(): string | undefined;
492
- get name(): string | undefined;
493
- private emitMutation;
494
- }
495
-
496
- declare type NodeType = typeof NODE_TYPES[keyof typeof NODE_TYPES];
497
-
498
189
  /**
499
190
  * Represents a photo being captured
500
191
  * Pure domain object that manages callbacks for when the photo is developed
501
192
  */
502
193
  export declare class Photo {
503
194
  private readonly filename;
504
- private readonly callbacks;
195
+ private readonly developedCallbacks;
196
+ private readonly errorCallbacks;
505
197
  private developed;
198
+ private failed;
506
199
  private photoData;
507
200
  constructor(filename: string);
508
201
  /**
@@ -513,15 +206,26 @@ export declare class Photo {
513
206
  * @returns This Photo instance for chaining
514
207
  */
515
208
  onDeveloped(callback: (photo: PhotoData) => void): this;
209
+ /**
210
+ * Register a callback for when the photo capture fails
211
+ *
212
+ * @param callback Function to call with error
213
+ * @returns This Photo instance for chaining
214
+ */
215
+ onError(callback: (error: VirtualdisplayError) => void): this;
516
216
  /**
517
217
  * Get the filename for this photo
518
218
  */
519
219
  getFilename(): string;
520
220
  /**
521
221
  * Mark the photo as developed and notify all callbacks
522
- * This method is called by the SnapshotMessageHandler when the photo data arrives
222
+ * This method is called by Snapshot when the photo data arrives from the server
523
223
  */
524
224
  develop(photoData: PhotoData): void;
225
+ /**
226
+ * Mark the photo as failed and notify error callbacks
227
+ */
228
+ fail(error: VirtualdisplayError): void;
525
229
  }
526
230
 
527
231
  export declare interface PhotoData {
@@ -534,10 +238,10 @@ export declare interface PhotoData {
534
238
  * Following the camera analogy: take() triggers capture, onDeveloped() gets result
535
239
  */
536
240
  export declare class Snapshot {
537
- private readonly eventBus;
241
+ private readonly send;
538
242
  private readonly validExtensions;
539
- private readonly messageHandler;
540
- constructor(eventBus: EventBus);
243
+ private readonly pendingPhotos;
244
+ constructor(send: MessageCallback);
541
245
  /**
542
246
  * Take a snapshot of the current 3D model view
543
247
  *
@@ -546,125 +250,74 @@ export declare class Snapshot {
546
250
  * @throws VirtualdisplayError if filename is invalid
547
251
  */
548
252
  take(filename: string): Photo;
253
+ /**
254
+ * Handle incoming snapshot result from server
255
+ * Matches the message to a pending photo by filename, then develops or fails it
256
+ */
257
+ handleSnapshotResult(message: SnapshotResultMessage): void;
549
258
  /**
550
259
  * Validate filename has a valid image extension
551
260
  */
552
261
  private validateFilename;
553
262
  }
554
263
 
555
- /**
556
- * Snapshot developed message received from server
557
- */
558
- export declare interface SnapshotDevelopedMessage {
559
- readonly type: typeof MESSAGE_TYPES.SNAPSHOT;
560
- readonly filename: string;
561
- readonly data: string;
562
- }
563
-
564
- /**
565
- * Snapshot request message sent to server
566
- */
567
- export declare interface SnapshotRequestMessage {
568
- readonly type: typeof MESSAGE_TYPES.SNAPSHOT;
569
- readonly filename: string;
570
- }
571
-
572
- declare interface StateChangedEvent {
573
- nodes: ModelNode[];
574
- }
575
-
576
- /**
577
- * State message received from server
578
- * Contains array of model node DTOs
579
- */
580
- export declare interface StateMessage {
581
- readonly type: typeof MESSAGE_TYPES.STATE;
582
- readonly nodes: ModelNodeDto[];
583
- readonly isInitial: boolean;
584
- }
585
-
586
- /**
587
- * Application service for managing node state
588
- * Handles state updates from server and emits node change events
589
- */
590
- declare class StateService {
591
- private readonly nodes;
592
- private readonly eventBus;
593
- private hasReceivedInitialSync;
594
- constructor(eventBus: EventBus);
595
- private handleMessage;
596
- private updateState;
597
- private updateOrCreateNode;
598
- private createNewNode;
599
- getNode(id: string): ModelNode | undefined;
600
- getAllNodes(): ModelNode[];
601
- get isReady(): boolean;
602
- get nodeCount(): number;
603
- clear(): void;
604
- }
605
-
606
- /**
607
- * UI configuration options
608
- */
609
- export declare interface UIConfig {
610
- readonly arEnabled?: boolean;
611
- readonly fullscreenEnabled?: boolean;
612
- readonly loadingIndicatorEnabled?: boolean;
613
- }
614
-
615
- /**
616
- * Viewer configuration
617
- */
618
- export declare interface ViewerConfig {
619
- readonly ui?: UIConfig;
620
- readonly camera?: CameraConfig;
621
- }
622
-
623
264
  /**
624
265
  * Main Virtualdisplay Client
625
266
  * Provides the public API for 3D product visualization
267
+ *
268
+ * Acts as the composition root: wires all services together with direct dependency injection
626
269
  */
627
270
  export declare class VirtualdisplayClient {
628
- private readonly eventBus;
629
- private readonly attributeService;
630
- private readonly stateService;
631
- private readonly messageHandler;
271
+ private readonly attributes;
272
+ private readonly readyStateTracker;
273
+ private readonly messenger;
632
274
  private readonly viewerService;
633
275
  private readonly cameraApi;
276
+ private readonly cameraPositionApi;
634
277
  private readonly snapshotApi;
635
278
  private readonly options;
636
279
  private iframe;
280
+ private readyCallbacks;
281
+ private readonly mutationFailedCallbacks;
637
282
  constructor(options: ClientOptions);
283
+ private registerHandlers;
638
284
  private initializeLogging;
639
285
  private createAndConnectIframe;
640
- private setupInitialConfig;
641
286
  /**
642
- * Load attribute mapping configuration
643
- * @throws {VirtualdisplayError} When mapping configuration is invalid
287
+ * Select a value for an attribute — sends mutation to server.
288
+ * Can be called immediately; the messenger's publisher queue holds
289
+ * the message until the iframe is ready.
644
290
  */
645
- setMapping(config: MappingConfiguration): void;
291
+ select(name: string, value: string): void;
646
292
  /**
647
- * Get attribute selector for fluent API
648
- * @throws {VirtualdisplayError} When no mapping is configured or attribute not found
293
+ * Get all available values for an attribute
649
294
  */
650
- getAttribute(name: string): AttributeSelector;
295
+ getValues(name: string): AttributeValue[];
651
296
  /**
652
- * Get node selector for direct node control
653
- * @param nodeId The node ID to control
654
- * @returns NodeSelector if node exists, undefined otherwise
297
+ * Get a specific value for an attribute
655
298
  */
656
- getNodeSelector(nodeId: string): NodeSelector | undefined;
657
- getNode(id: string): ModelNode | undefined;
658
- getNodes(): ModelNode[];
299
+ getValue(name: string, value: string): AttributeValue | undefined;
659
300
  /**
660
- * Check if the client has received initial state and is ready
301
+ * Register callback that fires when an attribute's selection changes
302
+ */
303
+ onChange(name: string, callback: (selectedValue: AttributeValue) => void): void;
304
+ /**
305
+ * Get the Attribute instance for advanced use cases
306
+ */
307
+ getAttribute(name: string): Attribute | undefined;
308
+ /**
309
+ * Check if the client has received initial mutations and is ready
661
310
  */
662
311
  get isReady(): boolean;
663
312
  /**
664
313
  * Register a callback to be called when the client is ready
665
314
  * If already ready, the callback is called immediately
666
315
  */
667
- onReady(callback: () => void): void;
316
+ onReady(callback: (client: VirtualdisplayClient) => void): void;
317
+ /**
318
+ * Register a callback for when a mutation fails on the server
319
+ */
320
+ onMutationFailed(callback: (event: MutationFailedEvent) => void): void;
668
321
  /**
669
322
  * Get the viewer service for UI configuration
670
323
  */
@@ -673,6 +326,10 @@ export declare class VirtualdisplayClient {
673
326
  * Get the camera control API
674
327
  */
675
328
  get camera(): Camera;
329
+ /**
330
+ * Get the camera position tracking API
331
+ */
332
+ get cameraPosition(): CameraPosition;
676
333
  /**
677
334
  * Get the snapshot API for taking screenshots
678
335
  */
@@ -689,9 +346,9 @@ export declare class VirtualdisplayError extends Error {
689
346
  static noMapping(): VirtualdisplayError;
690
347
  static attributeNotFound(attributeName: string): VirtualdisplayError;
691
348
  static valueNotFound(attributeName: string, valueName: string): VirtualdisplayError;
692
- static invalidMapping(reason?: string): VirtualdisplayError;
693
349
  static parentNotFound(selector: string): VirtualdisplayError;
694
- static invalidMutations(reason?: string): VirtualdisplayError;
350
+ static invalidParameter(reason: string): VirtualdisplayError;
351
+ static snapshotFailed(filename: string, reason: string): VirtualdisplayError;
695
352
  }
696
353
 
697
354
  /**
@@ -699,8 +356,8 @@ export declare class VirtualdisplayError extends Error {
699
356
  * Sends CONFIG messages to control AR button, fullscreen button, and loading indicator
700
357
  */
701
358
  export declare class VirtualdisplayViewerService {
702
- private readonly eventBus;
703
- constructor(eventBus: EventBus);
359
+ private readonly send;
360
+ constructor(send: MessageCallback);
704
361
  /**
705
362
  * Send initial configuration based on client options
706
363
  * Supports both individual properties and ui object
@@ -755,7 +412,4 @@ export declare class VirtualdisplayViewerService {
755
412
  private sendConfig;
756
413
  }
757
414
 
758
- declare interface VoidEvent {
759
- }
760
-
761
415
  export { }