@virtualdisplay.io/client 4.0.0-alpha.2 → 4.0.0-alpha.3
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/src/attributes/attribute.d.ts +38 -0
- package/dist/src/attributes/attribute.d.ts.map +1 -0
- package/dist/src/attributes/attributes.d.ts +43 -0
- package/dist/src/attributes/attributes.d.ts.map +1 -0
- package/dist/src/attributes/selections.d.ts +16 -0
- package/dist/src/attributes/selections.d.ts.map +1 -0
- package/dist/src/attributes/value.d.ts +13 -0
- package/dist/src/attributes/value.d.ts.map +1 -0
- package/dist/src/camera/camera.d.ts +40 -0
- package/dist/src/camera/camera.d.ts.map +1 -0
- package/dist/src/camera/index.d.ts +4 -0
- package/dist/src/camera/index.d.ts.map +1 -0
- package/dist/src/camera/position.d.ts +43 -0
- package/dist/src/camera/position.d.ts.map +1 -0
- package/dist/src/client/client.d.ts +83 -0
- package/dist/src/client/client.d.ts.map +1 -0
- package/dist/src/client/error.d.ts +26 -0
- package/dist/src/client/error.d.ts.map +1 -0
- package/dist/src/client/iframe-builder.d.ts +25 -0
- package/dist/src/client/iframe-builder.d.ts.map +1 -0
- package/dist/src/client/options.d.ts +17 -0
- package/dist/src/client/options.d.ts.map +1 -0
- package/dist/src/client/ready-state-tracker.d.ts +26 -0
- package/dist/src/client/ready-state-tracker.d.ts.map +1 -0
- package/dist/src/client/types.d.ts +5 -0
- package/dist/src/client/types.d.ts.map +1 -0
- package/dist/src/index.d.ts +11 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/snapshot/index.d.ts +3 -0
- package/dist/src/snapshot/index.d.ts.map +1 -0
- package/dist/src/snapshot/photo.d.ts +47 -0
- package/dist/src/snapshot/photo.d.ts.map +1 -0
- package/dist/src/snapshot/snapshot.d.ts +30 -0
- package/dist/src/snapshot/snapshot.d.ts.map +1 -0
- package/dist/src/ui/viewer-config.d.ts +63 -0
- package/dist/src/ui/viewer-config.d.ts.map +1 -0
- package/dist/src/utils/logger.d.ts +11 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/virtualdisplay.client.cjs.js +1 -1
- package/dist/virtualdisplay.client.es.js +1 -1
- package/dist/virtualdisplay.client.umd.js +1 -1
- package/package.json +3 -3
- package/dist/index.d.ts +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { AttributeValue } from './value';
|
|
2
|
+
export interface AttributeOptions {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly values: string[];
|
|
5
|
+
readonly onSelect: (name: string, value: string) => void;
|
|
6
|
+
readonly defaultValue?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Represents a single attribute with its available values
|
|
10
|
+
* Flat API - no source/target translation, works with server values directly
|
|
11
|
+
*/
|
|
12
|
+
export declare class Attribute {
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly defaultValue: string | undefined;
|
|
15
|
+
private readonly values;
|
|
16
|
+
private readonly onSelect;
|
|
17
|
+
private onChangeCallback?;
|
|
18
|
+
constructor(options: AttributeOptions);
|
|
19
|
+
/**
|
|
20
|
+
* Select a value for this attribute
|
|
21
|
+
* @throws {VirtualdisplayError} When value not found
|
|
22
|
+
*/
|
|
23
|
+
select(value: string): void;
|
|
24
|
+
getValues(): AttributeValue[];
|
|
25
|
+
getValue(value: string): AttributeValue | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Register callback that fires when selection changes
|
|
28
|
+
* Receives the newly selected AttributeValue
|
|
29
|
+
*/
|
|
30
|
+
onChange(callback: (selectedValue: AttributeValue) => void): void;
|
|
31
|
+
/**
|
|
32
|
+
* Update selection state from server mutation result
|
|
33
|
+
* Direct value comparison - no source/target translation
|
|
34
|
+
*/
|
|
35
|
+
handleResult(serverValue: string): void;
|
|
36
|
+
private createValues;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=attribute.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribute.d.ts","sourceRoot":"","sources":["../../../src/attributes/attribute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;GAGG;AACH,qBAAa,SAAS;IACpB,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B,SAAgB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAEjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IAErD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IAEjE,OAAO,CAAC,gBAAgB,CAAC,CAA2C;gBAExD,OAAO,EAAE,gBAAgB;IAOrC;;;OAGG;IACI,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQ3B,SAAS,IAAI,cAAc,EAAE;IAI7B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI1D;;;OAGG;IACI,QAAQ,CAAC,QAAQ,EAAE,CAAC,aAAa,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;IAIxE;;;OAGG;IACI,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAgB9C,OAAO,CAAC,YAAY;CAarB"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Attribute } from './attribute';
|
|
2
|
+
import { AttributeValue } from './value';
|
|
3
|
+
import { MappingMessage, MessageCallback, MutationResultMessage } from '@virtualdisplay.io/messaging';
|
|
4
|
+
/**
|
|
5
|
+
* Public attribute API.
|
|
6
|
+
* Receives mapping from server, provides query/select API,
|
|
7
|
+
* and sends mutations via postMessage.
|
|
8
|
+
*
|
|
9
|
+
* select() can be called before the mapping arrives — mutations are sent
|
|
10
|
+
* immediately and buffered by the messenger's publisher queue until the
|
|
11
|
+
* iframe is ready. onChange() callbacks registered before the mapping are
|
|
12
|
+
* replayed once the registry is created.
|
|
13
|
+
*/
|
|
14
|
+
export declare class Attributes {
|
|
15
|
+
private readonly send;
|
|
16
|
+
private readonly onMutationFailed?;
|
|
17
|
+
private registry;
|
|
18
|
+
private readonly pendingCallbacks;
|
|
19
|
+
constructor(send: MessageCallback, onMutationFailed?: ((attribute: string, value: string) => void) | undefined);
|
|
20
|
+
/**
|
|
21
|
+
* Handle incoming MAPPING message from server
|
|
22
|
+
*/
|
|
23
|
+
handleMappingReceived(message: MappingMessage): void;
|
|
24
|
+
handleMutationResult(message: MutationResultMessage): void;
|
|
25
|
+
/**
|
|
26
|
+
* Select a value for an attribute - sends mutation to server.
|
|
27
|
+
* Can be called before the mapping arrives — the mutation is sent immediately
|
|
28
|
+
* and the messenger's publisher queue holds it until the iframe is ready.
|
|
29
|
+
*/
|
|
30
|
+
select(name: string, value: string): void;
|
|
31
|
+
getValues(name: string): AttributeValue[];
|
|
32
|
+
getValue(name: string, value: string): AttributeValue | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Register onChange callback for an attribute.
|
|
35
|
+
* Buffers the callback if the mapping hasn't arrived yet.
|
|
36
|
+
*/
|
|
37
|
+
onChange(name: string, callback: (selectedValue: AttributeValue) => void): void;
|
|
38
|
+
getAttribute(name: string): Attribute | undefined;
|
|
39
|
+
get hasMapping(): boolean;
|
|
40
|
+
private sendMutation;
|
|
41
|
+
private replayPendingCallbacks;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=attributes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attributes.d.ts","sourceRoot":"","sources":["../../../src/attributes/attributes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,eAAe,EAGpB,KAAK,qBAAqB,EAC3B,MAAM,8BAA8B,CAAC;AAGtC;;;;;;;;;GASG;AACH,qBAAa,UAAU;IAMnB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IANpC,OAAO,CAAC,QAAQ,CAAgC;IAEhD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkF;gBAGhG,IAAI,EAAE,eAAe,EACrB,gBAAgB,CAAC,GAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,aAAA;IAGhF;;OAEG;IACI,qBAAqB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAmBpD,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAIjE;;;;OAIG;IACI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIzC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE;IAIzC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIxE;;;OAGG;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,aAAa,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;IAe/E,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAIxD,IAAW,UAAU,IAAI,OAAO,CAE/B;IAED,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,sBAAsB;CAU/B"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Attribute } from './attribute';
|
|
2
|
+
import { AttributeDefinition, MutationDto, MutationResult } from '@virtualdisplay.io/messaging';
|
|
3
|
+
/**
|
|
4
|
+
* Creates and tracks attribute instances from server definitions.
|
|
5
|
+
* Handles mutation results by updating the corresponding attribute.
|
|
6
|
+
*/
|
|
7
|
+
export declare class AttributeRegistry {
|
|
8
|
+
private readonly attributes;
|
|
9
|
+
constructor(definitions: AttributeDefinition[], sendMutation: (mutations: MutationDto[], isInitial: boolean) => void, onMutationFailed?: (attribute: string, value: string) => void);
|
|
10
|
+
private readonly onMutationFailed;
|
|
11
|
+
get(name: string): Attribute | undefined;
|
|
12
|
+
defaults(): MutationDto[];
|
|
13
|
+
handleResults(results: MutationResult[]): void;
|
|
14
|
+
private buildOptions;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=selections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selections.d.ts","sourceRoot":"","sources":["../../../src/attributes/selections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAyB,MAAM,aAAa,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAErG;;;GAGG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgC;gBAGzD,WAAW,EAAE,mBAAmB,EAAE,EAClC,YAAY,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,EAAE,SAAS,EAAE,OAAO,KAAK,IAAI,EACpE,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI;IAS/D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA2D;IAErF,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAIxC,QAAQ,IAAI,WAAW,EAAE;IAezB,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,IAAI;IAWrD,OAAO,CAAC,YAAY;CAkBrB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure domain entity representing a single attribute value
|
|
3
|
+
* No side effects - only state
|
|
4
|
+
*/
|
|
5
|
+
export declare class AttributeValue {
|
|
6
|
+
readonly value: string;
|
|
7
|
+
readonly attribute: string;
|
|
8
|
+
private isSelectedValue;
|
|
9
|
+
constructor(value: string, attribute: string);
|
|
10
|
+
get isSelected(): boolean;
|
|
11
|
+
setSelected(selected: boolean): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"value.d.ts","sourceRoot":"","sources":["../../../src/attributes/value.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,cAAc;aAIP,KAAK,EAAE,MAAM;aACb,SAAS,EAAE,MAAM;IAJnC,OAAO,CAAC,eAAe,CAAS;gBAGd,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM;IAGnC,IAAW,UAAU,IAAI,OAAO,CAE/B;IAEM,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;CAG5C"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { MessageCallback } from '@virtualdisplay.io/messaging';
|
|
2
|
+
/**
|
|
3
|
+
* Camera control API for positioning and zoom
|
|
4
|
+
* Uses chaining pattern for building commands
|
|
5
|
+
*/
|
|
6
|
+
export declare class Camera {
|
|
7
|
+
private readonly send;
|
|
8
|
+
private commands;
|
|
9
|
+
constructor(send: MessageCallback);
|
|
10
|
+
/**
|
|
11
|
+
* Rotate camera horizontally
|
|
12
|
+
* @param degrees - Absolute rotation in degrees (0 = front view)
|
|
13
|
+
* @throws VirtualdisplayError if value is not a finite number
|
|
14
|
+
*/
|
|
15
|
+
rotate(degrees: number): this;
|
|
16
|
+
/**
|
|
17
|
+
* Tilt camera vertically
|
|
18
|
+
* @param degrees - Absolute tilt in degrees (0 = top view, 90 = horizontal)
|
|
19
|
+
* @throws VirtualdisplayError if value is not a finite number
|
|
20
|
+
*/
|
|
21
|
+
tilt(degrees: number): this;
|
|
22
|
+
/**
|
|
23
|
+
* Zoom camera
|
|
24
|
+
* @param percentage - Zoom percentage (100 = normal, >100 = zoom in, <100 = zoom out)
|
|
25
|
+
* @throws VirtualdisplayError if value is not a finite number
|
|
26
|
+
*/
|
|
27
|
+
zoom(percentage: number): this;
|
|
28
|
+
/**
|
|
29
|
+
* Execute accumulated camera commands
|
|
30
|
+
* @throws VirtualdisplayError if no commands have been accumulated
|
|
31
|
+
*/
|
|
32
|
+
set(): void;
|
|
33
|
+
private validateFiniteNumber;
|
|
34
|
+
/**
|
|
35
|
+
* Reset camera to initial position
|
|
36
|
+
* This is not chainable and executes immediately
|
|
37
|
+
*/
|
|
38
|
+
reset(): void;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=camera.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../../../src/camera/camera.ts"],"names":[],"mappings":"AACA,OAAO,EAAgE,KAAK,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAElI;;;GAGG;AACH,qBAAa,MAAM;IAIf,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHvB,OAAO,CAAC,QAAQ,CAAuB;gBAGpB,IAAI,EAAE,eAAe;IAGxC;;;;OAIG;IACI,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAMpC;;;;OAIG;IACI,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAMlC;;;;OAIG;IACI,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAMrC;;;OAGG;IACI,GAAG,IAAI,IAAI;IAiBlB,OAAO,CAAC,oBAAoB;IAQ5B;;;OAGG;IACI,KAAK,IAAI,IAAI;CAQrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/camera/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtE,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { CameraParameter, CameraPositionMessage } from '@virtualdisplay.io/messaging';
|
|
2
|
+
/**
|
|
3
|
+
* Camera position state object
|
|
4
|
+
*/
|
|
5
|
+
export interface CameraPositionState {
|
|
6
|
+
rotation: number;
|
|
7
|
+
tilt: number;
|
|
8
|
+
zoom: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Camera position state
|
|
12
|
+
* Tracks current rotation, tilt, and zoom values from server updates
|
|
13
|
+
*/
|
|
14
|
+
export declare class CameraPosition {
|
|
15
|
+
private readonly state;
|
|
16
|
+
private readonly changeCallbacks;
|
|
17
|
+
constructor();
|
|
18
|
+
/**
|
|
19
|
+
* Get current rotation in degrees
|
|
20
|
+
*/
|
|
21
|
+
get rotation(): number;
|
|
22
|
+
/**
|
|
23
|
+
* Get current tilt in degrees
|
|
24
|
+
*/
|
|
25
|
+
get tilt(): number;
|
|
26
|
+
/**
|
|
27
|
+
* Get current zoom percentage
|
|
28
|
+
*/
|
|
29
|
+
get zoom(): number;
|
|
30
|
+
/**
|
|
31
|
+
* Subscribe to camera position changes
|
|
32
|
+
*/
|
|
33
|
+
onChange(callback: (position: CameraPositionState) => void): void;
|
|
34
|
+
/**
|
|
35
|
+
* Handle incoming camera position message from server
|
|
36
|
+
*/
|
|
37
|
+
handlePositionUpdate(message: CameraPositionMessage): void;
|
|
38
|
+
/**
|
|
39
|
+
* Update camera position from server transforms
|
|
40
|
+
*/
|
|
41
|
+
update(transforms: CameraParameter[]): void;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=position.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"position.d.ts","sourceRoot":"","sources":["../../../src/camera/position.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAE3F;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsB;IAE5C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAsD;;IAUtF;;OAEG;IACH,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAED;;OAEG;IACH,IAAW,IAAI,IAAI,MAAM,CAExB;IAED;;OAEG;IACH,IAAW,IAAI,IAAI,MAAM,CAExB;IAED;;OAEG;IACI,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI;IAIxE;;OAEG;IACI,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAIjE;;OAEG;IACI,MAAM,CAAC,UAAU,EAAE,eAAe,EAAE,GAAG,IAAI;CAmCnD"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { ClientOptions } from './options';
|
|
2
|
+
import { MutationFailedEvent } from './types';
|
|
3
|
+
import { Attribute } from '../attributes/attribute';
|
|
4
|
+
import { AttributeValue } from '../attributes/value';
|
|
5
|
+
import { Camera, CameraPosition } from '../camera';
|
|
6
|
+
import { Snapshot } from '../snapshot';
|
|
7
|
+
import { VirtualdisplayViewerService } from '../ui/viewer-config';
|
|
8
|
+
/**
|
|
9
|
+
* Main Virtualdisplay Client
|
|
10
|
+
* Provides the public API for 3D product visualization
|
|
11
|
+
*
|
|
12
|
+
* Acts as the composition root: wires all services together with direct dependency injection
|
|
13
|
+
*/
|
|
14
|
+
export declare class VirtualdisplayClient {
|
|
15
|
+
private readonly attributes;
|
|
16
|
+
private readonly readyStateTracker;
|
|
17
|
+
private readonly messenger;
|
|
18
|
+
private readonly viewerService;
|
|
19
|
+
private readonly cameraApi;
|
|
20
|
+
private readonly cameraPositionApi;
|
|
21
|
+
private readonly snapshotApi;
|
|
22
|
+
private readonly options;
|
|
23
|
+
private iframe;
|
|
24
|
+
private readyCallbacks;
|
|
25
|
+
private readonly mutationFailedCallbacks;
|
|
26
|
+
constructor(options: ClientOptions);
|
|
27
|
+
private registerHandlers;
|
|
28
|
+
private initializeLogging;
|
|
29
|
+
private createAndConnectIframe;
|
|
30
|
+
/**
|
|
31
|
+
* Select a value for an attribute — sends mutation to server.
|
|
32
|
+
* Can be called immediately; the messenger's publisher queue holds
|
|
33
|
+
* the message until the iframe is ready.
|
|
34
|
+
*/
|
|
35
|
+
select(name: string, value: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Get all available values for an attribute
|
|
38
|
+
*/
|
|
39
|
+
getValues(name: string): AttributeValue[];
|
|
40
|
+
/**
|
|
41
|
+
* Get a specific value for an attribute
|
|
42
|
+
*/
|
|
43
|
+
getValue(name: string, value: string): AttributeValue | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Register callback that fires when an attribute's selection changes
|
|
46
|
+
*/
|
|
47
|
+
onChange(name: string, callback: (selectedValue: AttributeValue) => void): void;
|
|
48
|
+
/**
|
|
49
|
+
* Get the Attribute instance for advanced use cases
|
|
50
|
+
*/
|
|
51
|
+
getAttribute(name: string): Attribute | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Check if the client has received initial mutations and is ready
|
|
54
|
+
*/
|
|
55
|
+
get isReady(): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Register a callback to be called when the client is ready
|
|
58
|
+
* If already ready, the callback is called immediately
|
|
59
|
+
*/
|
|
60
|
+
onReady(callback: (client: VirtualdisplayClient) => void): void;
|
|
61
|
+
/**
|
|
62
|
+
* Register a callback for when a mutation fails on the server
|
|
63
|
+
*/
|
|
64
|
+
onMutationFailed(callback: (event: MutationFailedEvent) => void): void;
|
|
65
|
+
/**
|
|
66
|
+
* Get the viewer service for UI configuration
|
|
67
|
+
*/
|
|
68
|
+
get viewer(): VirtualdisplayViewerService;
|
|
69
|
+
/**
|
|
70
|
+
* Get the camera control API
|
|
71
|
+
*/
|
|
72
|
+
get camera(): Camera;
|
|
73
|
+
/**
|
|
74
|
+
* Get the camera position tracking API
|
|
75
|
+
*/
|
|
76
|
+
get cameraPosition(): CameraPosition;
|
|
77
|
+
/**
|
|
78
|
+
* Get the snapshot API for taking screenshots
|
|
79
|
+
*/
|
|
80
|
+
get snapshot(): Snapshot;
|
|
81
|
+
destroy(): void;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/client/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAUnD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAGlE;;;;;GAKG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IAExC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAoB;IAEtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;IAE5C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA8B;IAE5D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAiB;IAEnD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAW;IAEvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IAExC,OAAO,CAAC,MAAM,CAAgC;IAE9C,OAAO,CAAC,cAAc,CAAqD;IAE3E,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAmD;gBAE/E,OAAO,EAAE,aAAa;IA0ClC,OAAO,CAAC,gBAAgB;IAqCxB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,sBAAsB;IAQ9B;;;;OAIG;IACI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIhD;;OAEG;IACI,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE;IAIhD;;OAEG;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIxE;;OAEG;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,aAAa,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;IAItF;;OAEG;IACI,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAIxD;;OAEG;IACH,IAAW,OAAO,IAAI,OAAO,CAE5B;IAED;;;OAGG;IACI,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,GAAG,IAAI;IAStE;;OAEG;IACI,gBAAgB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI;IAI7E;;OAEG;IACH,IAAW,MAAM,IAAI,2BAA2B,CAE/C;IAED;;OAEG;IACH,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED;;OAEG;IACH,IAAW,cAAc,IAAI,cAAc,CAE1C;IAED;;OAEG;IACH,IAAW,QAAQ,IAAI,QAAQ,CAE9B;IAEM,OAAO,IAAI,IAAI;CAevB"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error codes for Virtualdisplay client errors
|
|
3
|
+
*/
|
|
4
|
+
export declare const ERROR_CODES: {
|
|
5
|
+
readonly NO_MAPPING: "NO_MAPPING";
|
|
6
|
+
readonly ATTRIBUTE_NOT_FOUND: "ATTRIBUTE_NOT_FOUND";
|
|
7
|
+
readonly VALUE_NOT_FOUND: "VALUE_NOT_FOUND";
|
|
8
|
+
readonly PARENT_NOT_FOUND: "PARENT_NOT_FOUND";
|
|
9
|
+
readonly INVALID_PARAMETER: "INVALID_PARAMETER";
|
|
10
|
+
readonly SNAPSHOT_FAILED: "SNAPSHOT_FAILED";
|
|
11
|
+
};
|
|
12
|
+
export type ErrorCode = typeof ERROR_CODES[keyof typeof ERROR_CODES];
|
|
13
|
+
/**
|
|
14
|
+
* Custom error class for Virtualdisplay client errors
|
|
15
|
+
*/
|
|
16
|
+
export declare class VirtualdisplayError extends Error {
|
|
17
|
+
readonly code: ErrorCode;
|
|
18
|
+
constructor(message: string, code: ErrorCode);
|
|
19
|
+
static noMapping(): VirtualdisplayError;
|
|
20
|
+
static attributeNotFound(attributeName: string): VirtualdisplayError;
|
|
21
|
+
static valueNotFound(attributeName: string, valueName: string): VirtualdisplayError;
|
|
22
|
+
static parentNotFound(selector: string): VirtualdisplayError;
|
|
23
|
+
static invalidParameter(reason: string): VirtualdisplayError;
|
|
24
|
+
static snapshotFailed(filename: string, reason: string): VirtualdisplayError;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../src/client/error.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;CAOd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,OAAO,WAAW,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAErE;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,SAAgB,IAAI,EAAE,SAAS,CAAC;gBAEpB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS;WAU9B,SAAS,IAAI,mBAAmB;WAOhC,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,mBAAmB;WAO7D,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,mBAAmB;WAO5E,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB;WAOrD,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB;WAIrD,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB;CAMpF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ClientOptions } from './options';
|
|
2
|
+
/**
|
|
3
|
+
* Builds and configures the iframe for Virtualdisplay
|
|
4
|
+
*/
|
|
5
|
+
export declare class IframeBuilder {
|
|
6
|
+
private readonly defaultServer;
|
|
7
|
+
private readonly options;
|
|
8
|
+
constructor(options: ClientOptions);
|
|
9
|
+
/**
|
|
10
|
+
* Create iframe element with Virtualdisplay viewer
|
|
11
|
+
*/
|
|
12
|
+
create(): HTMLIFrameElement;
|
|
13
|
+
private createIframe;
|
|
14
|
+
private attachToParent;
|
|
15
|
+
private buildUrl;
|
|
16
|
+
/**
|
|
17
|
+
* Get server URL from environment or use default
|
|
18
|
+
*/
|
|
19
|
+
private getServerUrl;
|
|
20
|
+
/**
|
|
21
|
+
* Get parent element from selector or element
|
|
22
|
+
*/
|
|
23
|
+
private getParentElement;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=iframe-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iframe-builder.d.ts","sourceRoot":"","sources":["../../../src/client/iframe-builder.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsC;IAEpE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;gBAE5B,OAAO,EAAE,aAAa;IAIlC;;OAEG;IACI,MAAM,IAAI,iBAAiB;IAMlC,OAAO,CAAC,YAAY;IAiBpB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,QAAQ;IAoBhB;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAYzB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CameraConfig, UIConfig } from '@virtualdisplay.io/messaging';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for VirtualdisplayClient
|
|
4
|
+
*/
|
|
5
|
+
export interface ClientOptions {
|
|
6
|
+
readonly parent: string | HTMLElement;
|
|
7
|
+
readonly model: string;
|
|
8
|
+
readonly license: string;
|
|
9
|
+
readonly debug?: boolean;
|
|
10
|
+
readonly language?: string;
|
|
11
|
+
readonly arEnabled?: boolean;
|
|
12
|
+
readonly fullscreenEnabled?: boolean;
|
|
13
|
+
readonly loadingIndicatorEnabled?: boolean;
|
|
14
|
+
readonly ui?: UIConfig;
|
|
15
|
+
readonly camera?: CameraConfig;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/client/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAG3B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAG3C,QAAQ,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC;IAGvB,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { MutationResultMessage } from '@virtualdisplay.io/messaging';
|
|
2
|
+
/**
|
|
3
|
+
* Tracks when the client is ready for use
|
|
4
|
+
*
|
|
5
|
+
* Ready is triggered by whichever arrives first:
|
|
6
|
+
* - A mapping message from the server (server-driven flow)
|
|
7
|
+
* - An initial mutation result (legacy/client-driven flow)
|
|
8
|
+
*/
|
|
9
|
+
export declare class ReadyStateTracker {
|
|
10
|
+
private ready;
|
|
11
|
+
private readonly onReady;
|
|
12
|
+
constructor(onReady?: () => void);
|
|
13
|
+
/**
|
|
14
|
+
* Handle mapping received from server — marks client as ready
|
|
15
|
+
*/
|
|
16
|
+
handleMappingReceived(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Handle incoming mutation result message
|
|
19
|
+
* When the first initial mutation result arrives, the client is considered ready
|
|
20
|
+
*/
|
|
21
|
+
handleMutationResult(message: MutationResultMessage): void;
|
|
22
|
+
get isReady(): boolean;
|
|
23
|
+
clear(): void;
|
|
24
|
+
private markReady;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=ready-state-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ready-state-tracker.d.ts","sourceRoot":"","sources":["../../../src/client/ready-state-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAG1E;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAS;IAEtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;gBAEvC,OAAO,CAAC,EAAE,MAAM,IAAI;IAIhC;;OAEG;IACI,qBAAqB,IAAI,IAAI;IAIpC;;;OAGG;IACI,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAMjE,IAAW,OAAO,IAAI,OAAO,CAE5B;IAEM,KAAK,IAAI,IAAI;IAIpB,OAAO,CAAC,SAAS;CASlB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/client/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { VirtualdisplayClient } from './client/client';
|
|
2
|
+
export type { ClientOptions } from './client/options';
|
|
3
|
+
export { VirtualdisplayError, ERROR_CODES, type ErrorCode } from './client/error';
|
|
4
|
+
export type { MutationFailedEvent } from './client/types';
|
|
5
|
+
export { Attribute } from './attributes/attribute';
|
|
6
|
+
export { AttributeValue } from './attributes/value';
|
|
7
|
+
export { Camera } from './camera';
|
|
8
|
+
export { Snapshot, Photo, type PhotoData } from './snapshot';
|
|
9
|
+
export { VirtualdisplayViewerService } from './ui/viewer-config';
|
|
10
|
+
export { logger, enableDebugMode, isDebugMode } from './utils/logger';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAClF,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG1D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAG7D,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AAGjE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/snapshot/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { VirtualdisplayError } from '../client/error';
|
|
2
|
+
export interface PhotoData {
|
|
3
|
+
readonly filename: string;
|
|
4
|
+
readonly data: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Represents a photo being captured
|
|
8
|
+
* Pure domain object that manages callbacks for when the photo is developed
|
|
9
|
+
*/
|
|
10
|
+
export declare class Photo {
|
|
11
|
+
private readonly filename;
|
|
12
|
+
private readonly developedCallbacks;
|
|
13
|
+
private readonly errorCallbacks;
|
|
14
|
+
private developed;
|
|
15
|
+
private failed;
|
|
16
|
+
private photoData;
|
|
17
|
+
constructor(filename: string);
|
|
18
|
+
/**
|
|
19
|
+
* Register a callback for when the photo is developed
|
|
20
|
+
* If the photo is already developed, the callback is called immediately
|
|
21
|
+
*
|
|
22
|
+
* @param callback Function to call with photo data
|
|
23
|
+
* @returns This Photo instance for chaining
|
|
24
|
+
*/
|
|
25
|
+
onDeveloped(callback: (photo: PhotoData) => void): this;
|
|
26
|
+
/**
|
|
27
|
+
* Register a callback for when the photo capture fails
|
|
28
|
+
*
|
|
29
|
+
* @param callback Function to call with error
|
|
30
|
+
* @returns This Photo instance for chaining
|
|
31
|
+
*/
|
|
32
|
+
onError(callback: (error: VirtualdisplayError) => void): this;
|
|
33
|
+
/**
|
|
34
|
+
* Get the filename for this photo
|
|
35
|
+
*/
|
|
36
|
+
getFilename(): string;
|
|
37
|
+
/**
|
|
38
|
+
* Mark the photo as developed and notify all callbacks
|
|
39
|
+
* This method is called by Snapshot when the photo data arrives from the server
|
|
40
|
+
*/
|
|
41
|
+
develop(photoData: PhotoData): void;
|
|
42
|
+
/**
|
|
43
|
+
* Mark the photo as failed and notify error callbacks
|
|
44
|
+
*/
|
|
45
|
+
fail(error: VirtualdisplayError): void;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=photo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"photo.d.ts","sourceRoot":"","sources":["../../../src/snapshot/photo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,KAAK;IAYd,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAX3B,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA8C;IAEjF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwD;IAEvF,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,SAAS,CAA0B;gBAGxB,QAAQ,EAAE,MAAM;IAGnC;;;;;;OAMG;IACI,WAAW,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,GAAG,IAAI;IAS9D;;;;;OAKG;IACI,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAAG,IAAI;IAKpE;;OAEG;IACI,WAAW,IAAI,MAAM;IAI5B;;;OAGG;IACI,OAAO,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAgB1C;;OAEG;IACI,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;CAc9C"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Photo } from './photo';
|
|
2
|
+
import { MessageCallback, SnapshotResultMessage } from '@virtualdisplay.io/messaging';
|
|
3
|
+
/**
|
|
4
|
+
* API for taking screenshots of the 3D model
|
|
5
|
+
* Following the camera analogy: take() triggers capture, onDeveloped() gets result
|
|
6
|
+
*/
|
|
7
|
+
export declare class Snapshot {
|
|
8
|
+
private readonly send;
|
|
9
|
+
private readonly validExtensions;
|
|
10
|
+
private readonly pendingPhotos;
|
|
11
|
+
constructor(send: MessageCallback);
|
|
12
|
+
/**
|
|
13
|
+
* Take a snapshot of the current 3D model view
|
|
14
|
+
*
|
|
15
|
+
* @param filename The filename for the snapshot (must include valid extension)
|
|
16
|
+
* @returns Photo object for registering callbacks
|
|
17
|
+
* @throws VirtualdisplayError if filename is invalid
|
|
18
|
+
*/
|
|
19
|
+
take(filename: string): Photo;
|
|
20
|
+
/**
|
|
21
|
+
* Handle incoming snapshot result from server
|
|
22
|
+
* Matches the message to a pending photo by filename, then develops or fails it
|
|
23
|
+
*/
|
|
24
|
+
handleSnapshotResult(message: SnapshotResultMessage): void;
|
|
25
|
+
/**
|
|
26
|
+
* Validate filename has a valid image extension
|
|
27
|
+
*/
|
|
28
|
+
private validateFilename;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../../src/snapshot/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,OAAO,EAAiB,KAAK,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAG/G;;;GAGG;AACH,qBAAa,QAAQ;IAMjB,OAAO,CAAC,QAAQ,CAAC,IAAI;IALvB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAY;IAE5C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4B;gBAGvC,IAAI,EAAE,eAAe;IAGxC;;;;;;OAMG;IACI,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK;IAgBpC;;;OAGG;IACI,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAuBjE;;OAEG;IACH,OAAO,CAAC,gBAAgB;CA2BzB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ClientOptions } from '../client/options';
|
|
2
|
+
import { MessageCallback, UIConfig } from '@virtualdisplay.io/messaging';
|
|
3
|
+
/**
|
|
4
|
+
* Service responsible for managing viewer UI configuration
|
|
5
|
+
* Sends CONFIG messages to control AR button, fullscreen button, and loading indicator
|
|
6
|
+
*/
|
|
7
|
+
export declare class VirtualdisplayViewerService {
|
|
8
|
+
private readonly send;
|
|
9
|
+
constructor(send: MessageCallback);
|
|
10
|
+
/**
|
|
11
|
+
* Send initial configuration based on client options
|
|
12
|
+
* Supports both individual properties and ui object
|
|
13
|
+
*/
|
|
14
|
+
sendInitialConfig(options: ClientOptions): void;
|
|
15
|
+
/**
|
|
16
|
+
* Build UI configuration from client options
|
|
17
|
+
*
|
|
18
|
+
* Supports both legacy properties (options.arEnabled) and the newer ui object
|
|
19
|
+
* for backward compatibility. Legacy properties take precedence when both exist.
|
|
20
|
+
*/
|
|
21
|
+
private buildUIConfig;
|
|
22
|
+
/**
|
|
23
|
+
* Extract UI values from options, with legacy properties taking precedence
|
|
24
|
+
*/
|
|
25
|
+
private extractUIValues;
|
|
26
|
+
/**
|
|
27
|
+
* Build viewer configuration from UI config and camera config
|
|
28
|
+
*/
|
|
29
|
+
private buildViewerConfig;
|
|
30
|
+
/**
|
|
31
|
+
* Update AR button visibility
|
|
32
|
+
*/
|
|
33
|
+
setArEnabled(enabled: boolean): void;
|
|
34
|
+
/**
|
|
35
|
+
* Update fullscreen button visibility
|
|
36
|
+
*/
|
|
37
|
+
setFullscreenEnabled(enabled: boolean): void;
|
|
38
|
+
/**
|
|
39
|
+
* Update loading indicator visibility
|
|
40
|
+
*/
|
|
41
|
+
setLoadingIndicatorEnabled(enabled: boolean): void;
|
|
42
|
+
/**
|
|
43
|
+
* Update multiple UI settings at once
|
|
44
|
+
*/
|
|
45
|
+
updateUIConfig(config: Partial<UIConfig>): void;
|
|
46
|
+
/**
|
|
47
|
+
* Hide all UI elements
|
|
48
|
+
*/
|
|
49
|
+
hideAllUI(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Show all UI elements
|
|
52
|
+
*/
|
|
53
|
+
showAllUI(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Send UI configuration to server
|
|
56
|
+
*/
|
|
57
|
+
private sendUIConfig;
|
|
58
|
+
/**
|
|
59
|
+
* Send full viewer configuration to server
|
|
60
|
+
*/
|
|
61
|
+
private sendConfig;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=viewer-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewer-config.d.ts","sourceRoot":"","sources":["../../../src/ui/viewer-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,QAAQ,EAEd,MAAM,8BAA8B,CAAC;AAGtC;;;GAGG;AACH,qBAAa,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkB;gBAE3B,IAAI,EAAE,eAAe;IAIjC;;;OAGG;IACI,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAStD;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAoBrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAavB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAczB;;OAEG;IACI,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAK3C;;OAEG;IACI,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKnD;;OAEG;IACI,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKzD;;OAEG;IACI,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;IAQtD;;OAEG;IACI,SAAS,IAAI,IAAI;IASxB;;OAEG;IACI,SAAS,IAAI,IAAI;IASxB;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;IACH,OAAO,CAAC,UAAU;CAUnB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type Attrs = Record<string, unknown> | unknown;
|
|
2
|
+
export declare let logger: {
|
|
3
|
+
debug: (msg: string, attrs?: Attrs) => void;
|
|
4
|
+
info: (msg: string, attrs?: Attrs) => void;
|
|
5
|
+
warn: (msg: string, attrs?: Attrs) => void;
|
|
6
|
+
error: (msg: string, attrs?: Attrs) => void;
|
|
7
|
+
};
|
|
8
|
+
export declare function enableDebugMode(): void;
|
|
9
|
+
export declare function isDebugMode(): boolean;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;AA4B/C,eAAO,IAAI,MAAM;iBAbF,MAAM,UAAU,KAAK;gBACtB,MAAM,UAAU,KAAK;gBACrB,MAAM,UAAU,KAAK;iBACpB,MAAM,UAAU,KAAK;CAU4C,CAAC;AAEjF,wBAAgB,eAAe,IAAI,IAAI,CAGtC;AAED,wBAAgB,WAAW,IAAI,OAAO,CAErC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={NO_MAPPING:`NO_MAPPING`,ATTRIBUTE_NOT_FOUND:`ATTRIBUTE_NOT_FOUND`,VALUE_NOT_FOUND:`VALUE_NOT_FOUND`,PARENT_NOT_FOUND:`PARENT_NOT_FOUND`,INVALID_PARAMETER:`INVALID_PARAMETER`,SNAPSHOT_FAILED:`SNAPSHOT_FAILED`},t=class t extends Error{code;constructor(e,n){super(e),this.name=`VirtualdisplayError`,this.code=n,Error.captureStackTrace!==void 0&&Error.captureStackTrace(this,t)}static noMapping(){return new t(`No attributes available. Waiting for server metadata.`,e.NO_MAPPING)}static attributeNotFound(n){return new t(`Attribute "${n}" not found in mapping`,e.ATTRIBUTE_NOT_FOUND)}static valueNotFound(n,r){return new t(`Value "${r}" not found for attribute "${n}"`,e.VALUE_NOT_FOUND)}static parentNotFound(n){return new t(`Parent element not found: ${n}`,e.PARENT_NOT_FOUND)}static invalidParameter(n){return new t(n,e.INVALID_PARAMETER)}static snapshotFailed(n,r){return new t(`Snapshot failed for "${n}": ${r}`,e.SNAPSHOT_FAILED)}},n=class{defaultServer=`https://server.virtualdisplay.io`;options;constructor(e){this.options=e}create(){let e=this.createIframe();return this.attachToParent(e),e}createIframe(){let e=document.createElement(`iframe`);return e.src=this.buildUrl(),Object.assign(e.style,{width:`100%`,height:`100%`,border:`none`}),e.setAttribute(`allow`,`xr-spatial-tracking; fullscreen`),e}attachToParent(e){this.getParentElement().appendChild(e)}buildUrl(){let e=this.getServerUrl(),t=new URL(e);return t.searchParams.set(`license`,this.options.license),t.searchParams.set(`model`,this.options.model),this.options.debug===!0&&t.searchParams.set(`debug`,`true`),this.options.language!==void 0&&t.searchParams.set(`language`,this.options.language),t.toString()}getServerUrl(){return this.defaultServer}getParentElement(){if(typeof this.options.parent!=`string`)return this.options.parent;let e=document.querySelector(this.options.parent);if(e===null)throw t.parentNotFound(this.options.parent);return e}};function r(e){let t=new Date(e.timestamp).toLocaleTimeString(`en-GB`,{hour12:!1}),n=e.level.toUpperCase().padEnd(5),r=e.trace_id?.slice(0,8)??`--------`,i=e.msg,a=[`timestamp`,`level`,`msg`,`service`,`trace_id`,`span_id`],o=Object.entries(e).filter(([e])=>!a.includes(e)).map(([e,t])=>`${e}=${JSON.stringify(t)}`).join(` `);return`${t} ${n} [${r}] ${i}${o?` `+o:``}`}function i(e){return JSON.stringify(e)}function a(e,t){let n=t?r(e):i(e);e.level===`error`?console.error(n):e.level===`warn`?console.warn(n):console.log(n)}function o(){return new Date}function s(e){return e.toISOString()}var c=class e{constructor(e){this.config=e}log(e,t,n={}){let r=this.config.traceProvider?.()??{};a({timestamp:s(o()),level:e,msg:t,service:this.config.service,...r,...n},this.config.isDev)}debug(e,t){this.config.isDev&&this.log(`debug`,e,t)}info(e,t){this.log(`info`,e,t)}warn(e,t){this.log(`warn`,e,t)}error(e,t){this.log(`error`,e,t)}with(t){let n=new e(this.config);return n.log=((e,n,r={})=>{this.log(e,n,{...t,...r})}).bind(this),n}};function l(e,t){return new c({service:e,isDev:t?.isDev===void 0?typeof process<`u`?process.env.NODE_ENV!==`production`:!0:t.isDev,traceProvider:t?.traceProvider})}function u(e){if(e!==void 0)return typeof e==`object`&&e&&!Array.isArray(e)&&!(e instanceof Error)?e:e instanceof Error?{error:e.message}:{value:e}}function d(e){return{debug:(t,n)=>e.debug(t,u(n)),info:(t,n)=>e.info(t,u(n)),warn:(t,n)=>e.warn(t,u(n)),error:(t,n)=>e.error(t,u(n))}}var f=!1,p=d(l(`client`,{isDev:!1}));function m(){f=!0,p=d(l(`client`,{isDev:!0}))}function h(){return f}var g=class{ready=!1;onReady;constructor(e){this.onReady=e}handleMappingReceived(){this.markReady(`Mapping received from server`)}handleMutationResult(e){e.isInitial&&this.markReady(`Initial mutations processed`)}get isReady(){return this.ready}clear(){this.ready=!1}markReady(e){this.ready||(this.ready=!0,p.info(`${e} - client is now ready`),this.onReady?.())}},_=class{isSelectedValue=!1;constructor(e,t){this.value=e,this.attribute=t}get isSelected(){return this.isSelectedValue}setSelected(e){this.isSelectedValue=e}},v=class{name;defaultValue;values;onSelect;onChangeCallback;constructor(e){this.name=e.name,this.defaultValue=e.defaultValue,this.onSelect=e.onSelect,this.values=this.createValues(e.values)}select(e){if(!this.values.has(e))throw t.valueNotFound(this.name,e);this.onSelect(this.name,e)}getValues(){return Array.from(this.values.values())}getValue(e){return this.values.get(e)}onChange(e){this.onChangeCallback=e}handleResult(e){let t;for(let n of this.values.values()){let r=n.value===e;n.setSelected(r),r&&(t=n)}t!==void 0&&this.onChangeCallback!==void 0&&this.onChangeCallback(t)}createValues(e){let t=new Map;for(let n of e){let e=new _(n,this.name);n===this.defaultValue&&e.setSelected(!0),t.set(n,e)}return t}},y=class{attributes=new Map;constructor(e,t,n){for(let n of e){let e=this.buildOptions(n,t);this.attributes.set(n.name,new v(e))}this.onMutationFailed=n}onMutationFailed;get(e){return this.attributes.get(e)}defaults(){let e=[];for(let t of this.attributes.values())t.defaultValue!==void 0&&e.push({name:t.name,value:t.defaultValue});return e}handleResults(e){for(let t of e){if(!t.success){this.onMutationFailed?.(t.name,t.value);continue}this.get(t.name)?.handleResult(t.value)}}buildOptions(e,t){let n={name:e.name,values:e.values,onSelect:(e,n)=>{t([{name:e,value:n}],!1)}};return e.defaultValue===void 0?n:{...n,defaultValue:e.defaultValue}}},b={READY:`ready`,MUTATION:`mutation`,STATE:`state`,CONFIG:`config`,CAMERA:`camera`,SNAPSHOT:`snapshot`,MAPPING:`mapping`},x=new Set(Object.values(b));function S(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.target==`string`?!1:typeof t.type==`string`&&x.has(t.type)}function C(e){let t=O(e);return t!==null&&t.type===b.READY}function w(e){let t=O(e);return t!==null&&t.type===b.MUTATION&&Array.isArray(t.results)}function T(e){let t=O(e);return t!==null&&t.type===b.SNAPSHOT&&(`data`in t||`error`in t)}function E(e){let t=O(e);return t!==null&&t.type===b.CAMERA&&Array.isArray(t.transforms)}function D(e){let t=O(e);return t!==null&&t.type===b.MAPPING&&Array.isArray(t.attributes)}function O(e){return typeof e!=`object`||!e?null:e}var k=class{pending=[];isReady=!1;constructor(e){this.processor=e}enqueue(e){if(this.isReady){this.processor(e);return}this.pending.push(e)}markReady(){if(this.isReady||(this.isReady=!0,this.pending.length===0))return;let e=[...this.pending];this.pending.length=0;for(let t of e)this.processor(t)}get ready(){return this.isReady}get pendingCount(){return this.pending.length}hasPending(e){return this.pending.some(t=>t.type===e)}clear(){this.pending.length=0}},A=class{handlers=new Map;publisher;consumer;shouldBuffer;listener=null;sourceId;constructor(e,t){this.getTarget=e,this.sourceId=`vd-${Math.random().toString(36).slice(2,8)}`,this.publisher=new k(e=>this.post(e)),this.consumer=new k(e=>this.routeToHandler(e)),this.shouldBuffer=t?.shouldBuffer??null,t?.bufferIncoming!==!0&&this.consumer.markReady()}on(e,t){this.handlers.set(e,t)}off(e){this.handlers.delete(e)}send(e){this.publisher.enqueue(e)}markReady(){this.publisher.markReady()}markConsumerReady(){this.consumer.markReady()}consumerHasPending(e){return this.consumer.hasPending(e)}start(){this.listener===null&&(this.listener=e=>{let{data:t}=e;if(!S(t)||t._source===this.sourceId)return;let n=t;if(this.shouldBuffer!==null&&!this.shouldBuffer(n)){this.routeToHandler(n);return}this.consumer.enqueue(n)},window.addEventListener(`message`,this.listener))}destroy(){this.listener!==null&&(window.removeEventListener(`message`,this.listener),this.listener=null),this.publisher.clear(),this.consumer.clear(),this.handlers.clear()}get ready(){return this.publisher.ready}get pendingCount(){return this.publisher.pendingCount}post(e){let t=this.getTarget();t!==null&&t.postMessage({...e,_source:this.sourceId},`*`)}routeToHandler(e){let t=this.handlers.get(e.type);if(t===void 0)return;let n=t(e);n instanceof Promise&&n.catch(t=>{let n=t instanceof Error?t.message:String(t);console.error(`Virtualdisplay: error handling ${e.type}: ${n}`)})}};new Set([b.CAMERA]);var j=class{registry;pendingCallbacks=[];constructor(e,t){this.send=e,this.onMutationFailed=t}handleMappingReceived(e){p.debug(`Initializing from server mapping`,{attributeCount:e.attributes.length}),this.registry=new y(e.attributes,(e,t)=>this.sendMutation(e,t),this.onMutationFailed);let t=this.registry.defaults();t.length>0&&this.sendMutation(t,!0),this.replayPendingCallbacks()}handleMutationResult(e){this.registry?.handleResults(e.results)}select(e,t){this.sendMutation([{name:e,value:t}],!1)}getValues(e){return this.registry?.get(e)?.getValues()??[]}getValue(e,t){return this.registry?.get(e)?.getValue(t)}onChange(e,t){if(this.registry===void 0){this.pendingCallbacks.push({name:e,callback:t});return}let n=this.registry.get(e);if(n===void 0){p.warn(`onChange: attribute "${e}" not found — callback will not fire`);return}n.onChange(t)}getAttribute(e){return this.registry?.get(e)}get hasMapping(){return this.registry!==void 0}sendMutation(e,t){let n={type:b.MUTATION,mutations:e,isInitial:t};this.send(n)}replayPendingCallbacks(){for(let{name:e,callback:t}of this.pendingCallbacks){let n=this.registry?.get(e);n===void 0&&p.warn(`onChange: attribute "${e}" not found — buffered callback will not fire`),n?.onChange(t)}this.pendingCallbacks.length=0}},M=class{commands=[];constructor(e){this.send=e}rotate(e){return this.validateFiniteNumber(e,`rotate`),this.commands.push({action:`rotate`,value:e}),this}tilt(e){return this.validateFiniteNumber(e,`tilt`),this.commands.push({action:`tilt`,value:e}),this}zoom(e){return this.validateFiniteNumber(e,`zoom`),this.commands.push({action:`zoom`,value:e}),this}set(){if(this.commands.length===0)throw t.invalidParameter(`No camera commands to execute. Call rotate(), tilt(), or zoom() before set().`);let e={type:b.CAMERA,commands:this.commands};this.send(e),this.commands=[]}validateFiniteNumber(e,n){if(!Number.isFinite(e))throw t.invalidParameter(`${n}() requires a finite number, got ${String(e)}`)}reset(){let e={type:b.CAMERA,commands:[{action:`reset`}]};this.send(e)}},N=class{state;changeCallbacks=[];constructor(){this.state={rotation:0,tilt:0,zoom:0}}get rotation(){return this.state.rotation}get tilt(){return this.state.tilt}get zoom(){return this.state.zoom}onChange(e){this.changeCallbacks.push(e)}handlePositionUpdate(e){this.update(e.transforms)}update(e){let t=!1;for(let n of e)switch(n.type){case`rotation`:this.state.rotation=n.value,t=!0;break;case`tilt`:this.state.tilt=n.value,t=!0;break;case`zoom`:this.state.zoom=n.value,t=!0;break;default:break}if(t){let e={rotation:this.rotation,tilt:this.tilt,zoom:this.zoom};for(let t of this.changeCallbacks)t(e)}}},P=class{developedCallbacks=new Set;errorCallbacks=new Set;developed=!1;failed=!1;photoData=null;constructor(e){this.filename=e}onDeveloped(e){return this.developed&&this.photoData!==null?(e(this.photoData),this):(this.developedCallbacks.add(e),this)}onError(e){return this.errorCallbacks.add(e),this}getFilename(){return this.filename}develop(e){this.developed||this.failed||(this.photoData=e,this.developed=!0,this.developedCallbacks.forEach(e=>{e(this.photoData)}),this.developedCallbacks.clear(),this.errorCallbacks.clear())}fail(e){this.developed||this.failed||(this.failed=!0,this.errorCallbacks.forEach(t=>{t(e)}),this.developedCallbacks.clear(),this.errorCallbacks.clear())}},F=class{validExtensions=[`.png`];pendingPhotos=new Map;constructor(e){this.send=e}take(e){this.validateFilename(e),p.debug(`Taking snapshot`,{filename:e});let t=new P(e);return this.pendingPhotos.set(t.getFilename(),t),this.send({type:b.SNAPSHOT,filename:e}),t}handleSnapshotResult(n){let r=this.pendingPhotos.get(n.filename);if(r===void 0){p.warn(`No pending photo found for filename`,{filename:n.filename,pendingFilenames:Array.from(this.pendingPhotos.keys())});return}if(this.pendingPhotos.delete(n.filename),n.error!==void 0){r.fail(new t(n.error,e.SNAPSHOT_FAILED));return}n.data!==void 0&&r.develop({filename:n.filename,data:n.data})}validateFilename(n){if(n===``||typeof n!=`string`)throw new t(`Filename must be a non-empty string`,e.INVALID_PARAMETER);if(!this.validExtensions.some(e=>n.toLowerCase().endsWith(e)))throw new t(`Invalid filename: "${n}". Filename must end with one of: ${this.validExtensions.join(`, `)}`,e.INVALID_PARAMETER);if(n.includes(`..`)||n.includes(`/`)||n.includes(`\\`))throw new t(`Filename cannot contain path separators or ".."`,e.INVALID_PARAMETER)}},I=class{send;constructor(e){this.send=e}sendInitialConfig(e){let t=this.buildUIConfig(e),n=this.buildViewerConfig(t,e.camera);n!==void 0&&this.sendConfig(n)}buildUIConfig(e){let t=this.extractUIValues(e);if(Object.values(t).some(e=>e!==void 0))return{...t.arEnabled!==void 0&&{arEnabled:t.arEnabled},...t.fullscreenEnabled!==void 0&&{fullscreenEnabled:t.fullscreenEnabled},...t.loadingIndicatorEnabled!==void 0&&{loadingIndicatorEnabled:t.loadingIndicatorEnabled}}}extractUIValues(e){return{arEnabled:e.arEnabled??e.ui?.arEnabled,fullscreenEnabled:e.fullscreenEnabled??e.ui?.fullscreenEnabled,loadingIndicatorEnabled:e.loadingIndicatorEnabled??e.ui?.loadingIndicatorEnabled}}buildViewerConfig(e,t){if(!(e===void 0&&t===void 0))return{...e!==void 0&&{ui:e},...t!==void 0&&{camera:t}}}setArEnabled(e){p.debug(`Setting AR button enabled: ${e}`),this.updateUIConfig({arEnabled:e})}setFullscreenEnabled(e){p.debug(`Setting fullscreen button enabled: ${e}`),this.updateUIConfig({fullscreenEnabled:e})}setLoadingIndicatorEnabled(e){p.debug(`Setting loading indicator enabled: ${e}`),this.updateUIConfig({loadingIndicatorEnabled:e})}updateUIConfig(e){p.debug(`Updating UI configuration`,e),Object.keys(e).length>0&&this.sendConfig({ui:e})}hideAllUI(){p.debug(`Hiding all UI elements`),this.sendUIConfig({arEnabled:!1,fullscreenEnabled:!1,loadingIndicatorEnabled:!1})}showAllUI(){p.debug(`Showing all UI elements`),this.sendUIConfig({arEnabled:!0,fullscreenEnabled:!0,loadingIndicatorEnabled:!0})}sendUIConfig(e){this.sendConfig({ui:e})}sendConfig(e){let t={type:b.CONFIG,config:e};p.debug(`Sending config`,t),this.send(t)}},L=class{attributes;readyStateTracker;messenger;viewerService;cameraApi;cameraPositionApi;snapshotApi;options;iframe;readyCallbacks=[];mutationFailedCallbacks=[];constructor(e){this.options=e,this.initializeLogging(),this.messenger=new A(()=>this.iframe?.contentWindow??null);let t=e=>{this.messenger.send(e)};this.attributes=new j(t,(e,t)=>{for(let n of this.mutationFailedCallbacks)n({attribute:e,value:t})}),this.readyStateTracker=new g(()=>{let e=this.readyCallbacks;this.readyCallbacks=[];for(let t of e)t(this)}),this.viewerService=new I(t),this.cameraApi=new M(t),this.cameraPositionApi=new N,this.snapshotApi=new F(t),this.registerHandlers(),this.messenger.start(),this.createAndConnectIframe()}registerHandlers(){this.messenger.on(b.READY,e=>{C(e)&&(p.info(`Server ready — flushing publisher queue`),this.messenger.markReady(),this.viewerService.sendInitialConfig(this.options))}),this.messenger.on(b.MUTATION,e=>{w(e)&&(this.attributes.handleMutationResult(e),this.readyStateTracker.handleMutationResult(e))}),this.messenger.on(b.SNAPSHOT,e=>{T(e)&&this.snapshotApi.handleSnapshotResult(e)}),this.messenger.on(b.CAMERA,e=>{E(e)&&this.cameraPositionApi.handlePositionUpdate(e)}),this.messenger.on(b.MAPPING,e=>{D(e)&&(this.attributes.handleMappingReceived(e),this.readyStateTracker.handleMappingReceived())})}initializeLogging(){this.options.debug===!0&&m(),p.info(`Initializing Virtualdisplay client`,{model:this.options.model,debug:this.options.debug,language:this.options.language})}createAndConnectIframe(){p.debug(`Creating iframe for Virtualdisplay viewer`),this.iframe=new n(this.options).create(),p.debug(`Iframe created, waiting for server READY`)}select(e,t){this.attributes.select(e,t)}getValues(e){return this.attributes.getValues(e)}getValue(e,t){return this.attributes.getValue(e,t)}onChange(e,t){this.attributes.onChange(e,t)}getAttribute(e){return this.attributes.getAttribute(e)}get isReady(){return this.readyStateTracker.isReady}onReady(e){if(this.readyStateTracker.isReady){e(this);return}this.readyCallbacks.push(e)}onMutationFailed(e){this.mutationFailedCallbacks.push(e)}get viewer(){return this.viewerService}get camera(){return this.cameraApi}get cameraPosition(){return this.cameraPositionApi}get snapshot(){return this.snapshotApi}destroy(){p.info(`Destroying Virtualdisplay client`),this.readyStateTracker.clear(),this.readyCallbacks=[],this.messenger.destroy(),this.iframe?.parentElement!==null&&this.iframe?.parentElement!==void 0&&this.iframe.parentElement.removeChild(this.iframe),this.iframe=void 0,p.debug(`Virtualdisplay client destroyed`)}};exports.Attribute=v,exports.AttributeValue=_,exports.Camera=M,exports.ERROR_CODES=e,exports.Photo=P,exports.Snapshot=F,exports.VirtualdisplayClient=L,exports.VirtualdisplayError=t,exports.VirtualdisplayViewerService=I,exports.enableDebugMode=m,exports.isDebugMode=h,Object.defineProperty(exports,`logger`,{enumerable:!0,get:function(){return p}});
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={NO_MAPPING:`NO_MAPPING`,ATTRIBUTE_NOT_FOUND:`ATTRIBUTE_NOT_FOUND`,VALUE_NOT_FOUND:`VALUE_NOT_FOUND`,PARENT_NOT_FOUND:`PARENT_NOT_FOUND`,INVALID_PARAMETER:`INVALID_PARAMETER`,SNAPSHOT_FAILED:`SNAPSHOT_FAILED`},t=class t extends Error{code;constructor(e,n){super(e),this.name=`VirtualdisplayError`,this.code=n,Error.captureStackTrace?.(this,t)}static noMapping(){return new t(`No attributes available. Waiting for server metadata.`,e.NO_MAPPING)}static attributeNotFound(n){return new t(`Attribute "${n}" not found in mapping`,e.ATTRIBUTE_NOT_FOUND)}static valueNotFound(n,r){return new t(`Value "${r}" not found for attribute "${n}"`,e.VALUE_NOT_FOUND)}static parentNotFound(n){return new t(`Parent element not found: ${n}`,e.PARENT_NOT_FOUND)}static invalidParameter(n){return new t(n,e.INVALID_PARAMETER)}static snapshotFailed(n,r){return new t(`Snapshot failed for "${n}": ${r}`,e.SNAPSHOT_FAILED)}},n=class{defaultServer=`https://server.virtualdisplay.io`;options;constructor(e){this.options=e}create(){let e=this.createIframe();return this.attachToParent(e),e}createIframe(){let e=document.createElement(`iframe`);return e.src=this.buildUrl(),Object.assign(e.style,{width:`100%`,height:`100%`,border:`none`}),e.setAttribute(`allow`,`xr-spatial-tracking; fullscreen`),e}attachToParent(e){this.getParentElement().appendChild(e)}buildUrl(){let e=this.getServerUrl(),t=new URL(e);return t.searchParams.set(`license`,this.options.license),t.searchParams.set(`model`,this.options.model),this.options.debug===!0&&t.searchParams.set(`debug`,`true`),this.options.language!==void 0&&t.searchParams.set(`language`,this.options.language),t.toString()}getServerUrl(){return this.defaultServer}getParentElement(){if(typeof this.options.parent!=`string`)return this.options.parent;let e=document.querySelector(this.options.parent);if(e===null)throw t.parentNotFound(this.options.parent);return e}};function r(e){let t=new Date(e.timestamp).toLocaleTimeString(`en-GB`,{hour12:!1}),n=e.level.toUpperCase().padEnd(5),r=e.trace_id?.slice(0,8)??`--------`,i=e.msg,a=[`timestamp`,`level`,`msg`,`service`,`trace_id`,`span_id`],o=Object.entries(e).filter(([e])=>!a.includes(e)).map(([e,t])=>`${e}=${JSON.stringify(t)}`).join(` `);return`${t} ${n} [${r}] ${i}${o?` `+o:``}`}function i(e){return JSON.stringify(e)}function a(e,t){let n=t?r(e):i(e);e.level===`error`?console.error(n):e.level===`warn`?console.warn(n):console.log(n)}function o(){return new Date}function s(e){return e.toISOString()}var c=class e{constructor(e){this.config=e}log(e,t,n={}){let r=this.config.traceProvider?.()??{};a({timestamp:s(o()),level:e,msg:t,service:this.config.service,...r,...n},this.config.isDev)}debug(e,t){this.config.isDev&&this.log(`debug`,e,t)}info(e,t){this.log(`info`,e,t)}warn(e,t){this.log(`warn`,e,t)}error(e,t){this.log(`error`,e,t)}with(t){let n=new e(this.config);return n.log=((e,n,r={})=>{this.log(e,n,{...t,...r})}).bind(this),n}};function l(e,t){return new c({service:e,isDev:t?.isDev===void 0?typeof process<`u`?process.env.NODE_ENV!==`production`:!0:t.isDev,traceProvider:t?.traceProvider})}function u(e){if(e!==void 0)return typeof e==`object`&&e&&!Array.isArray(e)&&!(e instanceof Error)?e:e instanceof Error?{error:e.message}:{value:e}}function d(e){return{debug:(t,n)=>e.debug(t,u(n)),info:(t,n)=>e.info(t,u(n)),warn:(t,n)=>e.warn(t,u(n)),error:(t,n)=>e.error(t,u(n))}}var f=!1,p=d(l(`client`,{isDev:!1}));function m(){f=!0,p=d(l(`client`,{isDev:!0}))}function h(){return f}var g=class{ready=!1;onReady;constructor(e){this.onReady=e}handleMappingReceived(){this.markReady(`Mapping received from server`)}handleMutationResult(e){e.isInitial&&this.markReady(`Initial mutations processed`)}get isReady(){return this.ready}clear(){this.ready=!1}markReady(e){this.ready||(this.ready=!0,p.info(`${e} - client is now ready`),this.onReady?.())}},_=class{isSelectedValue=!1;constructor(e,t){this.value=e,this.attribute=t}get isSelected(){return this.isSelectedValue}setSelected(e){this.isSelectedValue=e}},v=class{name;defaultValue;values;onSelect;onChangeCallback;constructor(e){this.name=e.name,this.defaultValue=e.defaultValue,this.onSelect=e.onSelect,this.values=this.createValues(e.values)}select(e){if(!this.values.has(e))throw t.valueNotFound(this.name,e);this.onSelect(this.name,e)}getValues(){return Array.from(this.values.values())}getValue(e){return this.values.get(e)}onChange(e){this.onChangeCallback=e}handleResult(e){let t;for(let n of this.values.values()){let r=n.value===e;n.setSelected(r),r&&(t=n)}t!==void 0&&this.onChangeCallback!==void 0&&this.onChangeCallback(t)}createValues(e){let t=new Map;for(let n of e){let e=new _(n,this.name);n===this.defaultValue&&e.setSelected(!0),t.set(n,e)}return t}},y=class{attributes=new Map;constructor(e,t,n){for(let n of e){let e=this.buildOptions(n,t);this.attributes.set(n.name,new v(e))}this.onMutationFailed=n}onMutationFailed;get(e){return this.attributes.get(e)}defaults(){let e=[];for(let t of this.attributes.values())t.defaultValue!==void 0&&e.push({name:t.name,value:t.defaultValue});return e}handleResults(e){for(let t of e){if(!t.success){this.onMutationFailed?.(t.name,t.value);continue}this.get(t.name)?.handleResult(t.value)}}buildOptions(e,t){let n={name:e.name,values:e.values,onSelect:(e,n)=>{t([{name:e,value:n}],!1)}};return e.defaultValue===void 0?n:{...n,defaultValue:e.defaultValue}}},b={READY:`ready`,MUTATION:`mutation`,STATE:`state`,CONFIG:`config`,CAMERA:`camera`,SNAPSHOT:`snapshot`,MAPPING:`mapping`},x=new Set(Object.values(b));function S(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.target==`string`?!1:typeof t.type==`string`&&x.has(t.type)}function C(e){let t=O(e);return t!==null&&t.type===b.READY}function w(e){let t=O(e);return t!==null&&t.type===b.MUTATION&&Array.isArray(t.results)}function T(e){let t=O(e);return t!==null&&t.type===b.SNAPSHOT&&(`data`in t||`error`in t)}function E(e){let t=O(e);return t!==null&&t.type===b.CAMERA&&Array.isArray(t.transforms)}function D(e){let t=O(e);return t!==null&&t.type===b.MAPPING&&Array.isArray(t.attributes)}function O(e){return typeof e!=`object`||!e?null:e}var k=class{pending=[];isReady=!1;constructor(e){this.processor=e}enqueue(e){if(this.isReady){this.processor(e);return}this.pending.push(e)}markReady(){if(this.isReady||(this.isReady=!0,this.pending.length===0))return;let e=[...this.pending];this.pending.length=0;for(let t of e)this.processor(t)}get ready(){return this.isReady}get pendingCount(){return this.pending.length}hasPending(e){return this.pending.some(t=>t.type===e)}clear(){this.pending.length=0}},A=class{handlers=new Map;publisher;consumer;shouldBuffer;listener=null;sourceId;constructor(e,t){this.getTarget=e,this.sourceId=`vd-${Math.random().toString(36).slice(2,8)}`,this.publisher=new k(e=>this.post(e)),this.consumer=new k(e=>this.routeToHandler(e)),this.shouldBuffer=t?.shouldBuffer??null,t?.bufferIncoming!==!0&&this.consumer.markReady()}on(e,t){this.handlers.set(e,t)}off(e){this.handlers.delete(e)}send(e){this.publisher.enqueue(e)}markReady(){this.publisher.markReady()}markConsumerReady(){this.consumer.markReady()}consumerHasPending(e){return this.consumer.hasPending(e)}start(){this.listener===null&&(this.listener=e=>{let{data:t}=e;if(!S(t)||t._source===this.sourceId)return;let n=t;if(this.shouldBuffer!==null&&!this.shouldBuffer(n)){this.routeToHandler(n);return}this.consumer.enqueue(n)},window.addEventListener(`message`,this.listener))}destroy(){this.listener!==null&&(window.removeEventListener(`message`,this.listener),this.listener=null),this.publisher.clear(),this.consumer.clear(),this.handlers.clear()}get ready(){return this.publisher.ready}get pendingCount(){return this.publisher.pendingCount}post(e){let t=this.getTarget();t!==null&&t.postMessage({...e,_source:this.sourceId},`*`)}routeToHandler(e){let t=this.handlers.get(e.type);if(t===void 0)return;let n=t(e);n instanceof Promise&&n.catch(t=>{let n=t instanceof Error?t.message:String(t);console.error(`Virtualdisplay: error handling ${e.type}: ${n}`)})}};new Set([b.CAMERA]);var j=class{registry;pendingCallbacks=[];constructor(e,t){this.send=e,this.onMutationFailed=t}handleMappingReceived(e){p.debug(`Initializing from server mapping`,{attributeCount:e.attributes.length}),this.registry=new y(e.attributes,(e,t)=>this.sendMutation(e,t),this.onMutationFailed);let t=this.registry.defaults();t.length>0&&this.sendMutation(t,!0),this.replayPendingCallbacks()}handleMutationResult(e){this.registry?.handleResults(e.results)}select(e,t){this.sendMutation([{name:e,value:t}],!1)}getValues(e){return this.registry?.get(e)?.getValues()??[]}getValue(e,t){return this.registry?.get(e)?.getValue(t)}onChange(e,t){if(this.registry===void 0){this.pendingCallbacks.push({name:e,callback:t});return}let n=this.registry.get(e);if(n===void 0){p.warn(`onChange: attribute "${e}" not found — callback will not fire`);return}n.onChange(t)}getAttribute(e){return this.registry?.get(e)}get hasMapping(){return this.registry!==void 0}sendMutation(e,t){let n={type:b.MUTATION,mutations:e,isInitial:t};this.send(n)}replayPendingCallbacks(){for(let{name:e,callback:t}of this.pendingCallbacks){let n=this.registry?.get(e);n===void 0&&p.warn(`onChange: attribute "${e}" not found — buffered callback will not fire`),n?.onChange(t)}this.pendingCallbacks.length=0}},M=class{commands=[];constructor(e){this.send=e}rotate(e){return this.validateFiniteNumber(e,`rotate`),this.commands.push({action:`rotate`,value:e}),this}tilt(e){return this.validateFiniteNumber(e,`tilt`),this.commands.push({action:`tilt`,value:e}),this}zoom(e){return this.validateFiniteNumber(e,`zoom`),this.commands.push({action:`zoom`,value:e}),this}set(){if(this.commands.length===0)throw t.invalidParameter(`No camera commands to execute. Call rotate(), tilt(), or zoom() before set().`);let e={type:b.CAMERA,commands:this.commands};this.send(e),this.commands=[]}validateFiniteNumber(e,n){if(!Number.isFinite(e))throw t.invalidParameter(`${n}() requires a finite number, got ${String(e)}`)}reset(){let e={type:b.CAMERA,commands:[{action:`reset`}]};this.send(e)}},N=class{state;changeCallbacks=[];constructor(){this.state={rotation:0,tilt:0,zoom:0}}get rotation(){return this.state.rotation}get tilt(){return this.state.tilt}get zoom(){return this.state.zoom}onChange(e){this.changeCallbacks.push(e)}handlePositionUpdate(e){this.update(e.transforms)}update(e){let t=!1;for(let n of e)switch(n.type){case`rotation`:this.state.rotation=n.value,t=!0;break;case`tilt`:this.state.tilt=n.value,t=!0;break;case`zoom`:this.state.zoom=n.value,t=!0;break;default:break}if(t){let e={rotation:this.rotation,tilt:this.tilt,zoom:this.zoom};for(let t of this.changeCallbacks)t(e)}}},P=class{developedCallbacks=new Set;errorCallbacks=new Set;developed=!1;failed=!1;photoData=null;constructor(e){this.filename=e}onDeveloped(e){return this.developed&&this.photoData!==null?(e(this.photoData),this):(this.developedCallbacks.add(e),this)}onError(e){return this.errorCallbacks.add(e),this}getFilename(){return this.filename}develop(e){this.developed||this.failed||(this.photoData=e,this.developed=!0,this.developedCallbacks.forEach(e=>{e(this.photoData)}),this.developedCallbacks.clear(),this.errorCallbacks.clear())}fail(e){this.developed||this.failed||(this.failed=!0,this.errorCallbacks.forEach(t=>{t(e)}),this.developedCallbacks.clear(),this.errorCallbacks.clear())}},F=class{validExtensions=[`.png`];pendingPhotos=new Map;constructor(e){this.send=e}take(e){this.validateFilename(e),p.debug(`Taking snapshot`,{filename:e});let t=new P(e);return this.pendingPhotos.set(t.getFilename(),t),this.send({type:b.SNAPSHOT,filename:e}),t}handleSnapshotResult(n){let r=this.pendingPhotos.get(n.filename);if(r===void 0){p.warn(`No pending photo found for filename`,{filename:n.filename,pendingFilenames:Array.from(this.pendingPhotos.keys())});return}if(this.pendingPhotos.delete(n.filename),n.error!==void 0){r.fail(new t(n.error,e.SNAPSHOT_FAILED));return}n.data!==void 0&&r.develop({filename:n.filename,data:n.data})}validateFilename(n){if(n===``||typeof n!=`string`)throw new t(`Filename must be a non-empty string`,e.INVALID_PARAMETER);if(!this.validExtensions.some(e=>n.toLowerCase().endsWith(e)))throw new t(`Invalid filename: "${n}". Filename must end with one of: ${this.validExtensions.join(`, `)}`,e.INVALID_PARAMETER);if(n.includes(`..`)||n.includes(`/`)||n.includes(`\\`))throw new t(`Filename cannot contain path separators or ".."`,e.INVALID_PARAMETER)}},I=class{send;constructor(e){this.send=e}sendInitialConfig(e){let t=this.buildUIConfig(e),n=this.buildViewerConfig(t,e.camera);n!==void 0&&this.sendConfig(n)}buildUIConfig(e){let t=this.extractUIValues(e);if(Object.values(t).some(e=>e!==void 0))return{...t.arEnabled!==void 0&&{arEnabled:t.arEnabled},...t.fullscreenEnabled!==void 0&&{fullscreenEnabled:t.fullscreenEnabled},...t.loadingIndicatorEnabled!==void 0&&{loadingIndicatorEnabled:t.loadingIndicatorEnabled}}}extractUIValues(e){return{arEnabled:e.arEnabled??e.ui?.arEnabled,fullscreenEnabled:e.fullscreenEnabled??e.ui?.fullscreenEnabled,loadingIndicatorEnabled:e.loadingIndicatorEnabled??e.ui?.loadingIndicatorEnabled}}buildViewerConfig(e,t){if(!(e===void 0&&t===void 0))return{...e!==void 0&&{ui:e},...t!==void 0&&{camera:t}}}setArEnabled(e){p.debug(`Setting AR button enabled: ${e}`),this.updateUIConfig({arEnabled:e})}setFullscreenEnabled(e){p.debug(`Setting fullscreen button enabled: ${e}`),this.updateUIConfig({fullscreenEnabled:e})}setLoadingIndicatorEnabled(e){p.debug(`Setting loading indicator enabled: ${e}`),this.updateUIConfig({loadingIndicatorEnabled:e})}updateUIConfig(e){p.debug(`Updating UI configuration`,e),Object.keys(e).length>0&&this.sendConfig({ui:e})}hideAllUI(){p.debug(`Hiding all UI elements`),this.sendUIConfig({arEnabled:!1,fullscreenEnabled:!1,loadingIndicatorEnabled:!1})}showAllUI(){p.debug(`Showing all UI elements`),this.sendUIConfig({arEnabled:!0,fullscreenEnabled:!0,loadingIndicatorEnabled:!0})}sendUIConfig(e){this.sendConfig({ui:e})}sendConfig(e){let t={type:b.CONFIG,config:e};p.debug(`Sending config`,t),this.send(t)}},L=class{attributes;readyStateTracker;messenger;viewerService;cameraApi;cameraPositionApi;snapshotApi;options;iframe;readyCallbacks=[];mutationFailedCallbacks=[];constructor(e){this.options=e,this.initializeLogging(),this.messenger=new A(()=>this.iframe?.contentWindow??null);let t=e=>{this.messenger.send(e)};this.attributes=new j(t,(e,t)=>{for(let n of this.mutationFailedCallbacks)n({attribute:e,value:t})}),this.readyStateTracker=new g(()=>{let e=this.readyCallbacks;this.readyCallbacks=[];for(let t of e)t(this)}),this.viewerService=new I(t),this.cameraApi=new M(t),this.cameraPositionApi=new N,this.snapshotApi=new F(t),this.registerHandlers(),this.messenger.start(),this.createAndConnectIframe()}registerHandlers(){this.messenger.on(b.READY,e=>{C(e)&&(p.info(`Server ready — flushing publisher queue`),this.messenger.markReady(),this.viewerService.sendInitialConfig(this.options))}),this.messenger.on(b.MUTATION,e=>{w(e)&&(this.attributes.handleMutationResult(e),this.readyStateTracker.handleMutationResult(e))}),this.messenger.on(b.SNAPSHOT,e=>{T(e)&&this.snapshotApi.handleSnapshotResult(e)}),this.messenger.on(b.CAMERA,e=>{E(e)&&this.cameraPositionApi.handlePositionUpdate(e)}),this.messenger.on(b.MAPPING,e=>{D(e)&&(this.attributes.handleMappingReceived(e),this.readyStateTracker.handleMappingReceived())})}initializeLogging(){this.options.debug===!0&&m(),p.info(`Initializing Virtualdisplay client`,{model:this.options.model,debug:this.options.debug,language:this.options.language})}createAndConnectIframe(){p.debug(`Creating iframe for Virtualdisplay viewer`),this.iframe=new n(this.options).create(),p.debug(`Iframe created, waiting for server READY`)}select(e,t){this.attributes.select(e,t)}getValues(e){return this.attributes.getValues(e)}getValue(e,t){return this.attributes.getValue(e,t)}onChange(e,t){this.attributes.onChange(e,t)}getAttribute(e){return this.attributes.getAttribute(e)}get isReady(){return this.readyStateTracker.isReady}onReady(e){if(this.readyStateTracker.isReady){e(this);return}this.readyCallbacks.push(e)}onMutationFailed(e){this.mutationFailedCallbacks.push(e)}get viewer(){return this.viewerService}get camera(){return this.cameraApi}get cameraPosition(){return this.cameraPositionApi}get snapshot(){return this.snapshotApi}destroy(){p.info(`Destroying Virtualdisplay client`),this.readyStateTracker.clear(),this.readyCallbacks=[],this.messenger.destroy(),this.iframe?.parentElement!==null&&this.iframe?.parentElement!==void 0&&this.iframe.parentElement.removeChild(this.iframe),this.iframe=void 0,p.debug(`Virtualdisplay client destroyed`)}};exports.Attribute=v,exports.AttributeValue=_,exports.Camera=M,exports.ERROR_CODES=e,exports.Photo=P,exports.Snapshot=F,exports.VirtualdisplayClient=L,exports.VirtualdisplayError=t,exports.VirtualdisplayViewerService=I,exports.enableDebugMode=m,exports.isDebugMode=h,Object.defineProperty(exports,`logger`,{enumerable:!0,get:function(){return p}});
|
|
@@ -9,7 +9,7 @@ var e = {
|
|
|
9
9
|
}, t = class t extends Error {
|
|
10
10
|
code;
|
|
11
11
|
constructor(e, n) {
|
|
12
|
-
super(e), this.name = "VirtualdisplayError", this.code = n, Error.captureStackTrace
|
|
12
|
+
super(e), this.name = "VirtualdisplayError", this.code = n, Error.captureStackTrace?.(this, t);
|
|
13
13
|
}
|
|
14
14
|
static noMapping() {
|
|
15
15
|
return new t("No attributes available. Waiting for server metadata.", e.NO_MAPPING);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.VirtualdisplayClient={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t={NO_MAPPING:`NO_MAPPING`,ATTRIBUTE_NOT_FOUND:`ATTRIBUTE_NOT_FOUND`,VALUE_NOT_FOUND:`VALUE_NOT_FOUND`,PARENT_NOT_FOUND:`PARENT_NOT_FOUND`,INVALID_PARAMETER:`INVALID_PARAMETER`,SNAPSHOT_FAILED:`SNAPSHOT_FAILED`},n=class e extends Error{code;constructor(t,n){super(t),this.name=`VirtualdisplayError`,this.code=n,Error.captureStackTrace!==void 0&&Error.captureStackTrace(this,e)}static noMapping(){return new e(`No attributes available. Waiting for server metadata.`,t.NO_MAPPING)}static attributeNotFound(n){return new e(`Attribute "${n}" not found in mapping`,t.ATTRIBUTE_NOT_FOUND)}static valueNotFound(n,r){return new e(`Value "${r}" not found for attribute "${n}"`,t.VALUE_NOT_FOUND)}static parentNotFound(n){return new e(`Parent element not found: ${n}`,t.PARENT_NOT_FOUND)}static invalidParameter(n){return new e(n,t.INVALID_PARAMETER)}static snapshotFailed(n,r){return new e(`Snapshot failed for "${n}": ${r}`,t.SNAPSHOT_FAILED)}},r=class{defaultServer=`https://server.virtualdisplay.io`;options;constructor(e){this.options=e}create(){let e=this.createIframe();return this.attachToParent(e),e}createIframe(){let e=document.createElement(`iframe`);return e.src=this.buildUrl(),Object.assign(e.style,{width:`100%`,height:`100%`,border:`none`}),e.setAttribute(`allow`,`xr-spatial-tracking; fullscreen`),e}attachToParent(e){this.getParentElement().appendChild(e)}buildUrl(){let e=this.getServerUrl(),t=new URL(e);return t.searchParams.set(`license`,this.options.license),t.searchParams.set(`model`,this.options.model),this.options.debug===!0&&t.searchParams.set(`debug`,`true`),this.options.language!==void 0&&t.searchParams.set(`language`,this.options.language),t.toString()}getServerUrl(){return this.defaultServer}getParentElement(){if(typeof this.options.parent!=`string`)return this.options.parent;let e=document.querySelector(this.options.parent);if(e===null)throw n.parentNotFound(this.options.parent);return e}};function i(e){let t=new Date(e.timestamp).toLocaleTimeString(`en-GB`,{hour12:!1}),n=e.level.toUpperCase().padEnd(5),r=e.trace_id?.slice(0,8)??`--------`,i=e.msg,a=[`timestamp`,`level`,`msg`,`service`,`trace_id`,`span_id`],o=Object.entries(e).filter(([e])=>!a.includes(e)).map(([e,t])=>`${e}=${JSON.stringify(t)}`).join(` `);return`${t} ${n} [${r}] ${i}${o?` `+o:``}`}function a(e){return JSON.stringify(e)}function o(e,t){let n=t?i(e):a(e);e.level===`error`?console.error(n):e.level===`warn`?console.warn(n):console.log(n)}function s(){return new Date}function c(e){return e.toISOString()}var l=class e{constructor(e){this.config=e}log(e,t,n={}){let r=this.config.traceProvider?.()??{};o({timestamp:c(s()),level:e,msg:t,service:this.config.service,...r,...n},this.config.isDev)}debug(e,t){this.config.isDev&&this.log(`debug`,e,t)}info(e,t){this.log(`info`,e,t)}warn(e,t){this.log(`warn`,e,t)}error(e,t){this.log(`error`,e,t)}with(t){let n=new e(this.config);return n.log=((e,n,r={})=>{this.log(e,n,{...t,...r})}).bind(this),n}};function u(e,t){return new l({service:e,isDev:t?.isDev===void 0?typeof process<`u`?process.env.NODE_ENV!==`production`:!0:t.isDev,traceProvider:t?.traceProvider})}function d(e){if(e!==void 0)return typeof e==`object`&&e&&!Array.isArray(e)&&!(e instanceof Error)?e:e instanceof Error?{error:e.message}:{value:e}}function f(e){return{debug:(t,n)=>e.debug(t,d(n)),info:(t,n)=>e.info(t,d(n)),warn:(t,n)=>e.warn(t,d(n)),error:(t,n)=>e.error(t,d(n))}}var p=!1,m=f(u(`client`,{isDev:!1}));function h(){p=!0,m=f(u(`client`,{isDev:!0}))}function g(){return p}var _=class{ready=!1;onReady;constructor(e){this.onReady=e}handleMappingReceived(){this.markReady(`Mapping received from server`)}handleMutationResult(e){e.isInitial&&this.markReady(`Initial mutations processed`)}get isReady(){return this.ready}clear(){this.ready=!1}markReady(e){this.ready||(this.ready=!0,m.info(`${e} - client is now ready`),this.onReady?.())}},v=class{isSelectedValue=!1;constructor(e,t){this.value=e,this.attribute=t}get isSelected(){return this.isSelectedValue}setSelected(e){this.isSelectedValue=e}},y=class{name;defaultValue;values;onSelect;onChangeCallback;constructor(e){this.name=e.name,this.defaultValue=e.defaultValue,this.onSelect=e.onSelect,this.values=this.createValues(e.values)}select(e){if(!this.values.has(e))throw n.valueNotFound(this.name,e);this.onSelect(this.name,e)}getValues(){return Array.from(this.values.values())}getValue(e){return this.values.get(e)}onChange(e){this.onChangeCallback=e}handleResult(e){let t;for(let n of this.values.values()){let r=n.value===e;n.setSelected(r),r&&(t=n)}t!==void 0&&this.onChangeCallback!==void 0&&this.onChangeCallback(t)}createValues(e){let t=new Map;for(let n of e){let e=new v(n,this.name);n===this.defaultValue&&e.setSelected(!0),t.set(n,e)}return t}},b=class{attributes=new Map;constructor(e,t,n){for(let n of e){let e=this.buildOptions(n,t);this.attributes.set(n.name,new y(e))}this.onMutationFailed=n}onMutationFailed;get(e){return this.attributes.get(e)}defaults(){let e=[];for(let t of this.attributes.values())t.defaultValue!==void 0&&e.push({name:t.name,value:t.defaultValue});return e}handleResults(e){for(let t of e){if(!t.success){this.onMutationFailed?.(t.name,t.value);continue}this.get(t.name)?.handleResult(t.value)}}buildOptions(e,t){let n={name:e.name,values:e.values,onSelect:(e,n)=>{t([{name:e,value:n}],!1)}};return e.defaultValue===void 0?n:{...n,defaultValue:e.defaultValue}}},x={READY:`ready`,MUTATION:`mutation`,STATE:`state`,CONFIG:`config`,CAMERA:`camera`,SNAPSHOT:`snapshot`,MAPPING:`mapping`},S=new Set(Object.values(x));function C(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.target==`string`?!1:typeof t.type==`string`&&S.has(t.type)}function w(e){let t=k(e);return t!==null&&t.type===x.READY}function T(e){let t=k(e);return t!==null&&t.type===x.MUTATION&&Array.isArray(t.results)}function E(e){let t=k(e);return t!==null&&t.type===x.SNAPSHOT&&(`data`in t||`error`in t)}function D(e){let t=k(e);return t!==null&&t.type===x.CAMERA&&Array.isArray(t.transforms)}function O(e){let t=k(e);return t!==null&&t.type===x.MAPPING&&Array.isArray(t.attributes)}function k(e){return typeof e!=`object`||!e?null:e}var A=class{pending=[];isReady=!1;constructor(e){this.processor=e}enqueue(e){if(this.isReady){this.processor(e);return}this.pending.push(e)}markReady(){if(this.isReady||(this.isReady=!0,this.pending.length===0))return;let e=[...this.pending];this.pending.length=0;for(let t of e)this.processor(t)}get ready(){return this.isReady}get pendingCount(){return this.pending.length}hasPending(e){return this.pending.some(t=>t.type===e)}clear(){this.pending.length=0}},j=class{handlers=new Map;publisher;consumer;shouldBuffer;listener=null;sourceId;constructor(e,t){this.getTarget=e,this.sourceId=`vd-${Math.random().toString(36).slice(2,8)}`,this.publisher=new A(e=>this.post(e)),this.consumer=new A(e=>this.routeToHandler(e)),this.shouldBuffer=t?.shouldBuffer??null,t?.bufferIncoming!==!0&&this.consumer.markReady()}on(e,t){this.handlers.set(e,t)}off(e){this.handlers.delete(e)}send(e){this.publisher.enqueue(e)}markReady(){this.publisher.markReady()}markConsumerReady(){this.consumer.markReady()}consumerHasPending(e){return this.consumer.hasPending(e)}start(){this.listener===null&&(this.listener=e=>{let{data:t}=e;if(!C(t)||t._source===this.sourceId)return;let n=t;if(this.shouldBuffer!==null&&!this.shouldBuffer(n)){this.routeToHandler(n);return}this.consumer.enqueue(n)},window.addEventListener(`message`,this.listener))}destroy(){this.listener!==null&&(window.removeEventListener(`message`,this.listener),this.listener=null),this.publisher.clear(),this.consumer.clear(),this.handlers.clear()}get ready(){return this.publisher.ready}get pendingCount(){return this.publisher.pendingCount}post(e){let t=this.getTarget();t!==null&&t.postMessage({...e,_source:this.sourceId},`*`)}routeToHandler(e){let t=this.handlers.get(e.type);if(t===void 0)return;let n=t(e);n instanceof Promise&&n.catch(t=>{let n=t instanceof Error?t.message:String(t);console.error(`Virtualdisplay: error handling ${e.type}: ${n}`)})}};new Set([x.CAMERA]);var M=class{registry;pendingCallbacks=[];constructor(e,t){this.send=e,this.onMutationFailed=t}handleMappingReceived(e){m.debug(`Initializing from server mapping`,{attributeCount:e.attributes.length}),this.registry=new b(e.attributes,(e,t)=>this.sendMutation(e,t),this.onMutationFailed);let t=this.registry.defaults();t.length>0&&this.sendMutation(t,!0),this.replayPendingCallbacks()}handleMutationResult(e){this.registry?.handleResults(e.results)}select(e,t){this.sendMutation([{name:e,value:t}],!1)}getValues(e){return this.registry?.get(e)?.getValues()??[]}getValue(e,t){return this.registry?.get(e)?.getValue(t)}onChange(e,t){if(this.registry===void 0){this.pendingCallbacks.push({name:e,callback:t});return}let n=this.registry.get(e);if(n===void 0){m.warn(`onChange: attribute "${e}" not found — callback will not fire`);return}n.onChange(t)}getAttribute(e){return this.registry?.get(e)}get hasMapping(){return this.registry!==void 0}sendMutation(e,t){let n={type:x.MUTATION,mutations:e,isInitial:t};this.send(n)}replayPendingCallbacks(){for(let{name:e,callback:t}of this.pendingCallbacks){let n=this.registry?.get(e);n===void 0&&m.warn(`onChange: attribute "${e}" not found — buffered callback will not fire`),n?.onChange(t)}this.pendingCallbacks.length=0}},N=class{commands=[];constructor(e){this.send=e}rotate(e){return this.validateFiniteNumber(e,`rotate`),this.commands.push({action:`rotate`,value:e}),this}tilt(e){return this.validateFiniteNumber(e,`tilt`),this.commands.push({action:`tilt`,value:e}),this}zoom(e){return this.validateFiniteNumber(e,`zoom`),this.commands.push({action:`zoom`,value:e}),this}set(){if(this.commands.length===0)throw n.invalidParameter(`No camera commands to execute. Call rotate(), tilt(), or zoom() before set().`);let e={type:x.CAMERA,commands:this.commands};this.send(e),this.commands=[]}validateFiniteNumber(e,t){if(!Number.isFinite(e))throw n.invalidParameter(`${t}() requires a finite number, got ${String(e)}`)}reset(){let e={type:x.CAMERA,commands:[{action:`reset`}]};this.send(e)}},P=class{state;changeCallbacks=[];constructor(){this.state={rotation:0,tilt:0,zoom:0}}get rotation(){return this.state.rotation}get tilt(){return this.state.tilt}get zoom(){return this.state.zoom}onChange(e){this.changeCallbacks.push(e)}handlePositionUpdate(e){this.update(e.transforms)}update(e){let t=!1;for(let n of e)switch(n.type){case`rotation`:this.state.rotation=n.value,t=!0;break;case`tilt`:this.state.tilt=n.value,t=!0;break;case`zoom`:this.state.zoom=n.value,t=!0;break;default:break}if(t){let e={rotation:this.rotation,tilt:this.tilt,zoom:this.zoom};for(let t of this.changeCallbacks)t(e)}}},F=class{developedCallbacks=new Set;errorCallbacks=new Set;developed=!1;failed=!1;photoData=null;constructor(e){this.filename=e}onDeveloped(e){return this.developed&&this.photoData!==null?(e(this.photoData),this):(this.developedCallbacks.add(e),this)}onError(e){return this.errorCallbacks.add(e),this}getFilename(){return this.filename}develop(e){this.developed||this.failed||(this.photoData=e,this.developed=!0,this.developedCallbacks.forEach(e=>{e(this.photoData)}),this.developedCallbacks.clear(),this.errorCallbacks.clear())}fail(e){this.developed||this.failed||(this.failed=!0,this.errorCallbacks.forEach(t=>{t(e)}),this.developedCallbacks.clear(),this.errorCallbacks.clear())}},I=class{validExtensions=[`.png`];pendingPhotos=new Map;constructor(e){this.send=e}take(e){this.validateFilename(e),m.debug(`Taking snapshot`,{filename:e});let t=new F(e);return this.pendingPhotos.set(t.getFilename(),t),this.send({type:x.SNAPSHOT,filename:e}),t}handleSnapshotResult(e){let r=this.pendingPhotos.get(e.filename);if(r===void 0){m.warn(`No pending photo found for filename`,{filename:e.filename,pendingFilenames:Array.from(this.pendingPhotos.keys())});return}if(this.pendingPhotos.delete(e.filename),e.error!==void 0){r.fail(new n(e.error,t.SNAPSHOT_FAILED));return}e.data!==void 0&&r.develop({filename:e.filename,data:e.data})}validateFilename(e){if(e===``||typeof e!=`string`)throw new n(`Filename must be a non-empty string`,t.INVALID_PARAMETER);if(!this.validExtensions.some(t=>e.toLowerCase().endsWith(t)))throw new n(`Invalid filename: "${e}". Filename must end with one of: ${this.validExtensions.join(`, `)}`,t.INVALID_PARAMETER);if(e.includes(`..`)||e.includes(`/`)||e.includes(`\\`))throw new n(`Filename cannot contain path separators or ".."`,t.INVALID_PARAMETER)}},L=class{send;constructor(e){this.send=e}sendInitialConfig(e){let t=this.buildUIConfig(e),n=this.buildViewerConfig(t,e.camera);n!==void 0&&this.sendConfig(n)}buildUIConfig(e){let t=this.extractUIValues(e);if(Object.values(t).some(e=>e!==void 0))return{...t.arEnabled!==void 0&&{arEnabled:t.arEnabled},...t.fullscreenEnabled!==void 0&&{fullscreenEnabled:t.fullscreenEnabled},...t.loadingIndicatorEnabled!==void 0&&{loadingIndicatorEnabled:t.loadingIndicatorEnabled}}}extractUIValues(e){return{arEnabled:e.arEnabled??e.ui?.arEnabled,fullscreenEnabled:e.fullscreenEnabled??e.ui?.fullscreenEnabled,loadingIndicatorEnabled:e.loadingIndicatorEnabled??e.ui?.loadingIndicatorEnabled}}buildViewerConfig(e,t){if(!(e===void 0&&t===void 0))return{...e!==void 0&&{ui:e},...t!==void 0&&{camera:t}}}setArEnabled(e){m.debug(`Setting AR button enabled: ${e}`),this.updateUIConfig({arEnabled:e})}setFullscreenEnabled(e){m.debug(`Setting fullscreen button enabled: ${e}`),this.updateUIConfig({fullscreenEnabled:e})}setLoadingIndicatorEnabled(e){m.debug(`Setting loading indicator enabled: ${e}`),this.updateUIConfig({loadingIndicatorEnabled:e})}updateUIConfig(e){m.debug(`Updating UI configuration`,e),Object.keys(e).length>0&&this.sendConfig({ui:e})}hideAllUI(){m.debug(`Hiding all UI elements`),this.sendUIConfig({arEnabled:!1,fullscreenEnabled:!1,loadingIndicatorEnabled:!1})}showAllUI(){m.debug(`Showing all UI elements`),this.sendUIConfig({arEnabled:!0,fullscreenEnabled:!0,loadingIndicatorEnabled:!0})}sendUIConfig(e){this.sendConfig({ui:e})}sendConfig(e){let t={type:x.CONFIG,config:e};m.debug(`Sending config`,t),this.send(t)}},R=class{attributes;readyStateTracker;messenger;viewerService;cameraApi;cameraPositionApi;snapshotApi;options;iframe;readyCallbacks=[];mutationFailedCallbacks=[];constructor(e){this.options=e,this.initializeLogging(),this.messenger=new j(()=>this.iframe?.contentWindow??null);let t=e=>{this.messenger.send(e)};this.attributes=new M(t,(e,t)=>{for(let n of this.mutationFailedCallbacks)n({attribute:e,value:t})}),this.readyStateTracker=new _(()=>{let e=this.readyCallbacks;this.readyCallbacks=[];for(let t of e)t(this)}),this.viewerService=new L(t),this.cameraApi=new N(t),this.cameraPositionApi=new P,this.snapshotApi=new I(t),this.registerHandlers(),this.messenger.start(),this.createAndConnectIframe()}registerHandlers(){this.messenger.on(x.READY,e=>{w(e)&&(m.info(`Server ready — flushing publisher queue`),this.messenger.markReady(),this.viewerService.sendInitialConfig(this.options))}),this.messenger.on(x.MUTATION,e=>{T(e)&&(this.attributes.handleMutationResult(e),this.readyStateTracker.handleMutationResult(e))}),this.messenger.on(x.SNAPSHOT,e=>{E(e)&&this.snapshotApi.handleSnapshotResult(e)}),this.messenger.on(x.CAMERA,e=>{D(e)&&this.cameraPositionApi.handlePositionUpdate(e)}),this.messenger.on(x.MAPPING,e=>{O(e)&&(this.attributes.handleMappingReceived(e),this.readyStateTracker.handleMappingReceived())})}initializeLogging(){this.options.debug===!0&&h(),m.info(`Initializing Virtualdisplay client`,{model:this.options.model,debug:this.options.debug,language:this.options.language})}createAndConnectIframe(){m.debug(`Creating iframe for Virtualdisplay viewer`),this.iframe=new r(this.options).create(),m.debug(`Iframe created, waiting for server READY`)}select(e,t){this.attributes.select(e,t)}getValues(e){return this.attributes.getValues(e)}getValue(e,t){return this.attributes.getValue(e,t)}onChange(e,t){this.attributes.onChange(e,t)}getAttribute(e){return this.attributes.getAttribute(e)}get isReady(){return this.readyStateTracker.isReady}onReady(e){if(this.readyStateTracker.isReady){e(this);return}this.readyCallbacks.push(e)}onMutationFailed(e){this.mutationFailedCallbacks.push(e)}get viewer(){return this.viewerService}get camera(){return this.cameraApi}get cameraPosition(){return this.cameraPositionApi}get snapshot(){return this.snapshotApi}destroy(){m.info(`Destroying Virtualdisplay client`),this.readyStateTracker.clear(),this.readyCallbacks=[],this.messenger.destroy(),this.iframe?.parentElement!==null&&this.iframe?.parentElement!==void 0&&this.iframe.parentElement.removeChild(this.iframe),this.iframe=void 0,m.debug(`Virtualdisplay client destroyed`)}};e.Attribute=y,e.AttributeValue=v,e.Camera=N,e.ERROR_CODES=t,e.Photo=F,e.Snapshot=I,e.VirtualdisplayClient=R,e.VirtualdisplayError=n,e.VirtualdisplayViewerService=L,e.enableDebugMode=h,e.isDebugMode=g,Object.defineProperty(e,`logger`,{enumerable:!0,get:function(){return m}})});
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.VirtualdisplayClient={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t={NO_MAPPING:`NO_MAPPING`,ATTRIBUTE_NOT_FOUND:`ATTRIBUTE_NOT_FOUND`,VALUE_NOT_FOUND:`VALUE_NOT_FOUND`,PARENT_NOT_FOUND:`PARENT_NOT_FOUND`,INVALID_PARAMETER:`INVALID_PARAMETER`,SNAPSHOT_FAILED:`SNAPSHOT_FAILED`},n=class e extends Error{code;constructor(t,n){super(t),this.name=`VirtualdisplayError`,this.code=n,Error.captureStackTrace?.(this,e)}static noMapping(){return new e(`No attributes available. Waiting for server metadata.`,t.NO_MAPPING)}static attributeNotFound(n){return new e(`Attribute "${n}" not found in mapping`,t.ATTRIBUTE_NOT_FOUND)}static valueNotFound(n,r){return new e(`Value "${r}" not found for attribute "${n}"`,t.VALUE_NOT_FOUND)}static parentNotFound(n){return new e(`Parent element not found: ${n}`,t.PARENT_NOT_FOUND)}static invalidParameter(n){return new e(n,t.INVALID_PARAMETER)}static snapshotFailed(n,r){return new e(`Snapshot failed for "${n}": ${r}`,t.SNAPSHOT_FAILED)}},r=class{defaultServer=`https://server.virtualdisplay.io`;options;constructor(e){this.options=e}create(){let e=this.createIframe();return this.attachToParent(e),e}createIframe(){let e=document.createElement(`iframe`);return e.src=this.buildUrl(),Object.assign(e.style,{width:`100%`,height:`100%`,border:`none`}),e.setAttribute(`allow`,`xr-spatial-tracking; fullscreen`),e}attachToParent(e){this.getParentElement().appendChild(e)}buildUrl(){let e=this.getServerUrl(),t=new URL(e);return t.searchParams.set(`license`,this.options.license),t.searchParams.set(`model`,this.options.model),this.options.debug===!0&&t.searchParams.set(`debug`,`true`),this.options.language!==void 0&&t.searchParams.set(`language`,this.options.language),t.toString()}getServerUrl(){return this.defaultServer}getParentElement(){if(typeof this.options.parent!=`string`)return this.options.parent;let e=document.querySelector(this.options.parent);if(e===null)throw n.parentNotFound(this.options.parent);return e}};function i(e){let t=new Date(e.timestamp).toLocaleTimeString(`en-GB`,{hour12:!1}),n=e.level.toUpperCase().padEnd(5),r=e.trace_id?.slice(0,8)??`--------`,i=e.msg,a=[`timestamp`,`level`,`msg`,`service`,`trace_id`,`span_id`],o=Object.entries(e).filter(([e])=>!a.includes(e)).map(([e,t])=>`${e}=${JSON.stringify(t)}`).join(` `);return`${t} ${n} [${r}] ${i}${o?` `+o:``}`}function a(e){return JSON.stringify(e)}function o(e,t){let n=t?i(e):a(e);e.level===`error`?console.error(n):e.level===`warn`?console.warn(n):console.log(n)}function s(){return new Date}function c(e){return e.toISOString()}var l=class e{constructor(e){this.config=e}log(e,t,n={}){let r=this.config.traceProvider?.()??{};o({timestamp:c(s()),level:e,msg:t,service:this.config.service,...r,...n},this.config.isDev)}debug(e,t){this.config.isDev&&this.log(`debug`,e,t)}info(e,t){this.log(`info`,e,t)}warn(e,t){this.log(`warn`,e,t)}error(e,t){this.log(`error`,e,t)}with(t){let n=new e(this.config);return n.log=((e,n,r={})=>{this.log(e,n,{...t,...r})}).bind(this),n}};function u(e,t){return new l({service:e,isDev:t?.isDev===void 0?typeof process<`u`?process.env.NODE_ENV!==`production`:!0:t.isDev,traceProvider:t?.traceProvider})}function d(e){if(e!==void 0)return typeof e==`object`&&e&&!Array.isArray(e)&&!(e instanceof Error)?e:e instanceof Error?{error:e.message}:{value:e}}function f(e){return{debug:(t,n)=>e.debug(t,d(n)),info:(t,n)=>e.info(t,d(n)),warn:(t,n)=>e.warn(t,d(n)),error:(t,n)=>e.error(t,d(n))}}var p=!1,m=f(u(`client`,{isDev:!1}));function h(){p=!0,m=f(u(`client`,{isDev:!0}))}function g(){return p}var _=class{ready=!1;onReady;constructor(e){this.onReady=e}handleMappingReceived(){this.markReady(`Mapping received from server`)}handleMutationResult(e){e.isInitial&&this.markReady(`Initial mutations processed`)}get isReady(){return this.ready}clear(){this.ready=!1}markReady(e){this.ready||(this.ready=!0,m.info(`${e} - client is now ready`),this.onReady?.())}},v=class{isSelectedValue=!1;constructor(e,t){this.value=e,this.attribute=t}get isSelected(){return this.isSelectedValue}setSelected(e){this.isSelectedValue=e}},y=class{name;defaultValue;values;onSelect;onChangeCallback;constructor(e){this.name=e.name,this.defaultValue=e.defaultValue,this.onSelect=e.onSelect,this.values=this.createValues(e.values)}select(e){if(!this.values.has(e))throw n.valueNotFound(this.name,e);this.onSelect(this.name,e)}getValues(){return Array.from(this.values.values())}getValue(e){return this.values.get(e)}onChange(e){this.onChangeCallback=e}handleResult(e){let t;for(let n of this.values.values()){let r=n.value===e;n.setSelected(r),r&&(t=n)}t!==void 0&&this.onChangeCallback!==void 0&&this.onChangeCallback(t)}createValues(e){let t=new Map;for(let n of e){let e=new v(n,this.name);n===this.defaultValue&&e.setSelected(!0),t.set(n,e)}return t}},b=class{attributes=new Map;constructor(e,t,n){for(let n of e){let e=this.buildOptions(n,t);this.attributes.set(n.name,new y(e))}this.onMutationFailed=n}onMutationFailed;get(e){return this.attributes.get(e)}defaults(){let e=[];for(let t of this.attributes.values())t.defaultValue!==void 0&&e.push({name:t.name,value:t.defaultValue});return e}handleResults(e){for(let t of e){if(!t.success){this.onMutationFailed?.(t.name,t.value);continue}this.get(t.name)?.handleResult(t.value)}}buildOptions(e,t){let n={name:e.name,values:e.values,onSelect:(e,n)=>{t([{name:e,value:n}],!1)}};return e.defaultValue===void 0?n:{...n,defaultValue:e.defaultValue}}},x={READY:`ready`,MUTATION:`mutation`,STATE:`state`,CONFIG:`config`,CAMERA:`camera`,SNAPSHOT:`snapshot`,MAPPING:`mapping`},S=new Set(Object.values(x));function C(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.target==`string`?!1:typeof t.type==`string`&&S.has(t.type)}function w(e){let t=k(e);return t!==null&&t.type===x.READY}function T(e){let t=k(e);return t!==null&&t.type===x.MUTATION&&Array.isArray(t.results)}function E(e){let t=k(e);return t!==null&&t.type===x.SNAPSHOT&&(`data`in t||`error`in t)}function D(e){let t=k(e);return t!==null&&t.type===x.CAMERA&&Array.isArray(t.transforms)}function O(e){let t=k(e);return t!==null&&t.type===x.MAPPING&&Array.isArray(t.attributes)}function k(e){return typeof e!=`object`||!e?null:e}var A=class{pending=[];isReady=!1;constructor(e){this.processor=e}enqueue(e){if(this.isReady){this.processor(e);return}this.pending.push(e)}markReady(){if(this.isReady||(this.isReady=!0,this.pending.length===0))return;let e=[...this.pending];this.pending.length=0;for(let t of e)this.processor(t)}get ready(){return this.isReady}get pendingCount(){return this.pending.length}hasPending(e){return this.pending.some(t=>t.type===e)}clear(){this.pending.length=0}},j=class{handlers=new Map;publisher;consumer;shouldBuffer;listener=null;sourceId;constructor(e,t){this.getTarget=e,this.sourceId=`vd-${Math.random().toString(36).slice(2,8)}`,this.publisher=new A(e=>this.post(e)),this.consumer=new A(e=>this.routeToHandler(e)),this.shouldBuffer=t?.shouldBuffer??null,t?.bufferIncoming!==!0&&this.consumer.markReady()}on(e,t){this.handlers.set(e,t)}off(e){this.handlers.delete(e)}send(e){this.publisher.enqueue(e)}markReady(){this.publisher.markReady()}markConsumerReady(){this.consumer.markReady()}consumerHasPending(e){return this.consumer.hasPending(e)}start(){this.listener===null&&(this.listener=e=>{let{data:t}=e;if(!C(t)||t._source===this.sourceId)return;let n=t;if(this.shouldBuffer!==null&&!this.shouldBuffer(n)){this.routeToHandler(n);return}this.consumer.enqueue(n)},window.addEventListener(`message`,this.listener))}destroy(){this.listener!==null&&(window.removeEventListener(`message`,this.listener),this.listener=null),this.publisher.clear(),this.consumer.clear(),this.handlers.clear()}get ready(){return this.publisher.ready}get pendingCount(){return this.publisher.pendingCount}post(e){let t=this.getTarget();t!==null&&t.postMessage({...e,_source:this.sourceId},`*`)}routeToHandler(e){let t=this.handlers.get(e.type);if(t===void 0)return;let n=t(e);n instanceof Promise&&n.catch(t=>{let n=t instanceof Error?t.message:String(t);console.error(`Virtualdisplay: error handling ${e.type}: ${n}`)})}};new Set([x.CAMERA]);var M=class{registry;pendingCallbacks=[];constructor(e,t){this.send=e,this.onMutationFailed=t}handleMappingReceived(e){m.debug(`Initializing from server mapping`,{attributeCount:e.attributes.length}),this.registry=new b(e.attributes,(e,t)=>this.sendMutation(e,t),this.onMutationFailed);let t=this.registry.defaults();t.length>0&&this.sendMutation(t,!0),this.replayPendingCallbacks()}handleMutationResult(e){this.registry?.handleResults(e.results)}select(e,t){this.sendMutation([{name:e,value:t}],!1)}getValues(e){return this.registry?.get(e)?.getValues()??[]}getValue(e,t){return this.registry?.get(e)?.getValue(t)}onChange(e,t){if(this.registry===void 0){this.pendingCallbacks.push({name:e,callback:t});return}let n=this.registry.get(e);if(n===void 0){m.warn(`onChange: attribute "${e}" not found — callback will not fire`);return}n.onChange(t)}getAttribute(e){return this.registry?.get(e)}get hasMapping(){return this.registry!==void 0}sendMutation(e,t){let n={type:x.MUTATION,mutations:e,isInitial:t};this.send(n)}replayPendingCallbacks(){for(let{name:e,callback:t}of this.pendingCallbacks){let n=this.registry?.get(e);n===void 0&&m.warn(`onChange: attribute "${e}" not found — buffered callback will not fire`),n?.onChange(t)}this.pendingCallbacks.length=0}},N=class{commands=[];constructor(e){this.send=e}rotate(e){return this.validateFiniteNumber(e,`rotate`),this.commands.push({action:`rotate`,value:e}),this}tilt(e){return this.validateFiniteNumber(e,`tilt`),this.commands.push({action:`tilt`,value:e}),this}zoom(e){return this.validateFiniteNumber(e,`zoom`),this.commands.push({action:`zoom`,value:e}),this}set(){if(this.commands.length===0)throw n.invalidParameter(`No camera commands to execute. Call rotate(), tilt(), or zoom() before set().`);let e={type:x.CAMERA,commands:this.commands};this.send(e),this.commands=[]}validateFiniteNumber(e,t){if(!Number.isFinite(e))throw n.invalidParameter(`${t}() requires a finite number, got ${String(e)}`)}reset(){let e={type:x.CAMERA,commands:[{action:`reset`}]};this.send(e)}},P=class{state;changeCallbacks=[];constructor(){this.state={rotation:0,tilt:0,zoom:0}}get rotation(){return this.state.rotation}get tilt(){return this.state.tilt}get zoom(){return this.state.zoom}onChange(e){this.changeCallbacks.push(e)}handlePositionUpdate(e){this.update(e.transforms)}update(e){let t=!1;for(let n of e)switch(n.type){case`rotation`:this.state.rotation=n.value,t=!0;break;case`tilt`:this.state.tilt=n.value,t=!0;break;case`zoom`:this.state.zoom=n.value,t=!0;break;default:break}if(t){let e={rotation:this.rotation,tilt:this.tilt,zoom:this.zoom};for(let t of this.changeCallbacks)t(e)}}},F=class{developedCallbacks=new Set;errorCallbacks=new Set;developed=!1;failed=!1;photoData=null;constructor(e){this.filename=e}onDeveloped(e){return this.developed&&this.photoData!==null?(e(this.photoData),this):(this.developedCallbacks.add(e),this)}onError(e){return this.errorCallbacks.add(e),this}getFilename(){return this.filename}develop(e){this.developed||this.failed||(this.photoData=e,this.developed=!0,this.developedCallbacks.forEach(e=>{e(this.photoData)}),this.developedCallbacks.clear(),this.errorCallbacks.clear())}fail(e){this.developed||this.failed||(this.failed=!0,this.errorCallbacks.forEach(t=>{t(e)}),this.developedCallbacks.clear(),this.errorCallbacks.clear())}},I=class{validExtensions=[`.png`];pendingPhotos=new Map;constructor(e){this.send=e}take(e){this.validateFilename(e),m.debug(`Taking snapshot`,{filename:e});let t=new F(e);return this.pendingPhotos.set(t.getFilename(),t),this.send({type:x.SNAPSHOT,filename:e}),t}handleSnapshotResult(e){let r=this.pendingPhotos.get(e.filename);if(r===void 0){m.warn(`No pending photo found for filename`,{filename:e.filename,pendingFilenames:Array.from(this.pendingPhotos.keys())});return}if(this.pendingPhotos.delete(e.filename),e.error!==void 0){r.fail(new n(e.error,t.SNAPSHOT_FAILED));return}e.data!==void 0&&r.develop({filename:e.filename,data:e.data})}validateFilename(e){if(e===``||typeof e!=`string`)throw new n(`Filename must be a non-empty string`,t.INVALID_PARAMETER);if(!this.validExtensions.some(t=>e.toLowerCase().endsWith(t)))throw new n(`Invalid filename: "${e}". Filename must end with one of: ${this.validExtensions.join(`, `)}`,t.INVALID_PARAMETER);if(e.includes(`..`)||e.includes(`/`)||e.includes(`\\`))throw new n(`Filename cannot contain path separators or ".."`,t.INVALID_PARAMETER)}},L=class{send;constructor(e){this.send=e}sendInitialConfig(e){let t=this.buildUIConfig(e),n=this.buildViewerConfig(t,e.camera);n!==void 0&&this.sendConfig(n)}buildUIConfig(e){let t=this.extractUIValues(e);if(Object.values(t).some(e=>e!==void 0))return{...t.arEnabled!==void 0&&{arEnabled:t.arEnabled},...t.fullscreenEnabled!==void 0&&{fullscreenEnabled:t.fullscreenEnabled},...t.loadingIndicatorEnabled!==void 0&&{loadingIndicatorEnabled:t.loadingIndicatorEnabled}}}extractUIValues(e){return{arEnabled:e.arEnabled??e.ui?.arEnabled,fullscreenEnabled:e.fullscreenEnabled??e.ui?.fullscreenEnabled,loadingIndicatorEnabled:e.loadingIndicatorEnabled??e.ui?.loadingIndicatorEnabled}}buildViewerConfig(e,t){if(!(e===void 0&&t===void 0))return{...e!==void 0&&{ui:e},...t!==void 0&&{camera:t}}}setArEnabled(e){m.debug(`Setting AR button enabled: ${e}`),this.updateUIConfig({arEnabled:e})}setFullscreenEnabled(e){m.debug(`Setting fullscreen button enabled: ${e}`),this.updateUIConfig({fullscreenEnabled:e})}setLoadingIndicatorEnabled(e){m.debug(`Setting loading indicator enabled: ${e}`),this.updateUIConfig({loadingIndicatorEnabled:e})}updateUIConfig(e){m.debug(`Updating UI configuration`,e),Object.keys(e).length>0&&this.sendConfig({ui:e})}hideAllUI(){m.debug(`Hiding all UI elements`),this.sendUIConfig({arEnabled:!1,fullscreenEnabled:!1,loadingIndicatorEnabled:!1})}showAllUI(){m.debug(`Showing all UI elements`),this.sendUIConfig({arEnabled:!0,fullscreenEnabled:!0,loadingIndicatorEnabled:!0})}sendUIConfig(e){this.sendConfig({ui:e})}sendConfig(e){let t={type:x.CONFIG,config:e};m.debug(`Sending config`,t),this.send(t)}},R=class{attributes;readyStateTracker;messenger;viewerService;cameraApi;cameraPositionApi;snapshotApi;options;iframe;readyCallbacks=[];mutationFailedCallbacks=[];constructor(e){this.options=e,this.initializeLogging(),this.messenger=new j(()=>this.iframe?.contentWindow??null);let t=e=>{this.messenger.send(e)};this.attributes=new M(t,(e,t)=>{for(let n of this.mutationFailedCallbacks)n({attribute:e,value:t})}),this.readyStateTracker=new _(()=>{let e=this.readyCallbacks;this.readyCallbacks=[];for(let t of e)t(this)}),this.viewerService=new L(t),this.cameraApi=new N(t),this.cameraPositionApi=new P,this.snapshotApi=new I(t),this.registerHandlers(),this.messenger.start(),this.createAndConnectIframe()}registerHandlers(){this.messenger.on(x.READY,e=>{w(e)&&(m.info(`Server ready — flushing publisher queue`),this.messenger.markReady(),this.viewerService.sendInitialConfig(this.options))}),this.messenger.on(x.MUTATION,e=>{T(e)&&(this.attributes.handleMutationResult(e),this.readyStateTracker.handleMutationResult(e))}),this.messenger.on(x.SNAPSHOT,e=>{E(e)&&this.snapshotApi.handleSnapshotResult(e)}),this.messenger.on(x.CAMERA,e=>{D(e)&&this.cameraPositionApi.handlePositionUpdate(e)}),this.messenger.on(x.MAPPING,e=>{O(e)&&(this.attributes.handleMappingReceived(e),this.readyStateTracker.handleMappingReceived())})}initializeLogging(){this.options.debug===!0&&h(),m.info(`Initializing Virtualdisplay client`,{model:this.options.model,debug:this.options.debug,language:this.options.language})}createAndConnectIframe(){m.debug(`Creating iframe for Virtualdisplay viewer`),this.iframe=new r(this.options).create(),m.debug(`Iframe created, waiting for server READY`)}select(e,t){this.attributes.select(e,t)}getValues(e){return this.attributes.getValues(e)}getValue(e,t){return this.attributes.getValue(e,t)}onChange(e,t){this.attributes.onChange(e,t)}getAttribute(e){return this.attributes.getAttribute(e)}get isReady(){return this.readyStateTracker.isReady}onReady(e){if(this.readyStateTracker.isReady){e(this);return}this.readyCallbacks.push(e)}onMutationFailed(e){this.mutationFailedCallbacks.push(e)}get viewer(){return this.viewerService}get camera(){return this.cameraApi}get cameraPosition(){return this.cameraPositionApi}get snapshot(){return this.snapshotApi}destroy(){m.info(`Destroying Virtualdisplay client`),this.readyStateTracker.clear(),this.readyCallbacks=[],this.messenger.destroy(),this.iframe?.parentElement!==null&&this.iframe?.parentElement!==void 0&&this.iframe.parentElement.removeChild(this.iframe),this.iframe=void 0,m.debug(`Virtualdisplay client destroyed`)}};e.Attribute=y,e.AttributeValue=v,e.Camera=N,e.ERROR_CODES=t,e.Photo=F,e.Snapshot=I,e.VirtualdisplayClient=R,e.VirtualdisplayError=n,e.VirtualdisplayViewerService=L,e.enableDebugMode=h,e.isDebugMode=g,Object.defineProperty(e,`logger`,{enumerable:!0,get:function(){return m}})});
|
package/package.json
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@virtualdisplay.io/client",
|
|
3
3
|
"description": "TypeScript-first 3D model integration library with iframe-based architecture",
|
|
4
|
-
"version": "4.0.0-alpha.
|
|
4
|
+
"version": "4.0.0-alpha.3",
|
|
5
5
|
"author": "Virtualdisplay <support@virtualdisplay.io>",
|
|
6
6
|
"homepage": "https://virtualdisplay.io",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
|
-
"types": "./dist/index.d.ts",
|
|
11
|
+
"types": "./dist/src/index.d.ts",
|
|
12
12
|
"import": "./dist/virtualdisplay.client.es.js",
|
|
13
13
|
"require": "./dist/virtualdisplay.client.cjs.js"
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"main": "dist/virtualdisplay.client.cjs.js",
|
|
17
17
|
"module": "dist/virtualdisplay.client.es.js",
|
|
18
|
-
"types": "dist/index.d.ts",
|
|
18
|
+
"types": "dist/src/index.d.ts",
|
|
19
19
|
"files": [
|
|
20
20
|
"dist",
|
|
21
21
|
"CHANGELOG.md"
|
package/dist/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { }
|