@virtualdisplay.io/client 3.4.0 → 3.5.0
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 +12 -0
- package/dist/index.d.ts +66 -1
- package/dist/virtualdisplay.client.cjs.js +3 -3
- package/dist/virtualdisplay.client.cjs.js.map +1 -1
- package/dist/virtualdisplay.client.es.js +86 -13
- package/dist/virtualdisplay.client.es.js.map +1 -1
- package/dist/virtualdisplay.client.umd.js +3 -3
- package/dist/virtualdisplay.client.umd.js.map +1 -1
- package/package.json +1 -1
|
@@ -56,6 +56,8 @@ const EVENT_NAMES = {
|
|
|
56
56
|
MUTATION_MESSAGE: "mutation:message",
|
|
57
57
|
// Config flow (Client → Server)
|
|
58
58
|
CONFIG_MESSAGE: "config:message",
|
|
59
|
+
// Camera flow (Client → Server)
|
|
60
|
+
CAMERA_MESSAGE: "camera:message",
|
|
59
61
|
// State flow (Server → Client)
|
|
60
62
|
MESSAGE_RECEIVED: "message:received",
|
|
61
63
|
STATE_CHANGED: "state:changed",
|
|
@@ -396,7 +398,6 @@ class IframeBuilder {
|
|
|
396
398
|
height: "100%",
|
|
397
399
|
border: "none"
|
|
398
400
|
});
|
|
399
|
-
iframe.setAttribute("allowfullscreen", "true");
|
|
400
401
|
iframe.setAttribute("allow", "xr-spatial-tracking; fullscreen");
|
|
401
402
|
iframe.addEventListener("load", () => {
|
|
402
403
|
logger.info("Virtualdisplay iframe loaded");
|
|
@@ -6929,7 +6930,8 @@ class MappingValidator {
|
|
|
6929
6930
|
const MESSAGE_TYPES = {
|
|
6930
6931
|
MUTATION: "mutation",
|
|
6931
6932
|
STATE: "state",
|
|
6932
|
-
CONFIG: "config"
|
|
6933
|
+
CONFIG: "config",
|
|
6934
|
+
CAMERA: "camera"
|
|
6933
6935
|
};
|
|
6934
6936
|
function createMutationMessage(mutations) {
|
|
6935
6937
|
if (!Array.isArray(mutations)) {
|
|
@@ -7053,6 +7055,61 @@ class AttributeService {
|
|
|
7053
7055
|
this.isInitialized = false;
|
|
7054
7056
|
}
|
|
7055
7057
|
}
|
|
7058
|
+
class Camera {
|
|
7059
|
+
constructor(eventBus) {
|
|
7060
|
+
this.eventBus = eventBus;
|
|
7061
|
+
}
|
|
7062
|
+
commands = [];
|
|
7063
|
+
/**
|
|
7064
|
+
* Rotate camera horizontally
|
|
7065
|
+
* @param degrees - Absolute rotation in degrees (0 = front view)
|
|
7066
|
+
*/
|
|
7067
|
+
rotate(degrees) {
|
|
7068
|
+
this.commands.push({ action: "rotate", value: degrees });
|
|
7069
|
+
return this;
|
|
7070
|
+
}
|
|
7071
|
+
/**
|
|
7072
|
+
* Tilt camera vertically
|
|
7073
|
+
* @param degrees - Absolute tilt in degrees (0 = top view, 90 = horizontal)
|
|
7074
|
+
*/
|
|
7075
|
+
tilt(degrees) {
|
|
7076
|
+
this.commands.push({ action: "tilt", value: degrees });
|
|
7077
|
+
return this;
|
|
7078
|
+
}
|
|
7079
|
+
/**
|
|
7080
|
+
* Zoom camera
|
|
7081
|
+
* @param percentage - Zoom percentage (100 = normal, >100 = zoom in, <100 = zoom out)
|
|
7082
|
+
*/
|
|
7083
|
+
zoom(percentage) {
|
|
7084
|
+
this.commands.push({ action: "zoom", value: percentage });
|
|
7085
|
+
return this;
|
|
7086
|
+
}
|
|
7087
|
+
/**
|
|
7088
|
+
* Execute accumulated camera commands
|
|
7089
|
+
*/
|
|
7090
|
+
set() {
|
|
7091
|
+
if (this.commands.length === 0) {
|
|
7092
|
+
return;
|
|
7093
|
+
}
|
|
7094
|
+
const message = {
|
|
7095
|
+
type: MESSAGE_TYPES.CAMERA,
|
|
7096
|
+
commands: this.commands
|
|
7097
|
+
};
|
|
7098
|
+
this.eventBus.emit(EVENT_NAMES.CAMERA_MESSAGE, { message });
|
|
7099
|
+
this.commands = [];
|
|
7100
|
+
}
|
|
7101
|
+
/**
|
|
7102
|
+
* Reset camera to initial position
|
|
7103
|
+
* This is not chainable and executes immediately
|
|
7104
|
+
*/
|
|
7105
|
+
reset() {
|
|
7106
|
+
const message = {
|
|
7107
|
+
type: MESSAGE_TYPES.CAMERA,
|
|
7108
|
+
commands: [{ action: "reset" }]
|
|
7109
|
+
};
|
|
7110
|
+
this.eventBus.emit(EVENT_NAMES.CAMERA_MESSAGE, { message });
|
|
7111
|
+
}
|
|
7112
|
+
}
|
|
7056
7113
|
class EventBus {
|
|
7057
7114
|
listeners = /* @__PURE__ */ new Map();
|
|
7058
7115
|
on(event, listener) {
|
|
@@ -7061,8 +7118,19 @@ class EventBus {
|
|
|
7061
7118
|
this.listeners.set(event, handlers);
|
|
7062
7119
|
}
|
|
7063
7120
|
emit(event, payload) {
|
|
7064
|
-
this.listeners.get(event)
|
|
7121
|
+
const handlers = this.listeners.get(event);
|
|
7122
|
+
if (handlers === void 0 || handlers.length === 0) {
|
|
7123
|
+
return;
|
|
7124
|
+
}
|
|
7125
|
+
const handlersCopy = [...handlers];
|
|
7126
|
+
handlersCopy.forEach((listener) => {
|
|
7127
|
+
listener(payload);
|
|
7128
|
+
});
|
|
7065
7129
|
}
|
|
7130
|
+
/**
|
|
7131
|
+
* Register a listener that will be called only once
|
|
7132
|
+
* The listener is automatically removed after the first call
|
|
7133
|
+
*/
|
|
7066
7134
|
once(event, listener) {
|
|
7067
7135
|
const onceWrapper = (payload) => {
|
|
7068
7136
|
this.off(event, onceWrapper);
|
|
@@ -7070,6 +7138,9 @@ class EventBus {
|
|
|
7070
7138
|
};
|
|
7071
7139
|
this.on(event, onceWrapper);
|
|
7072
7140
|
}
|
|
7141
|
+
/**
|
|
7142
|
+
* Remove a specific listener for an event
|
|
7143
|
+
*/
|
|
7073
7144
|
off(event, listener) {
|
|
7074
7145
|
const handlers = this.listeners.get(event);
|
|
7075
7146
|
if (handlers === void 0) {
|
|
@@ -7094,16 +7165,11 @@ class MessageHandler {
|
|
|
7094
7165
|
}
|
|
7095
7166
|
setIframe(iframe) {
|
|
7096
7167
|
this.iframe = iframe;
|
|
7097
|
-
logger.debug("Message handler configured with iframe", {
|
|
7098
|
-
src: iframe.src,
|
|
7099
|
-
loaded: iframe.contentWindow !== null
|
|
7100
|
-
});
|
|
7101
7168
|
}
|
|
7102
7169
|
destroy() {
|
|
7103
7170
|
window.removeEventListener("message", this.handleWindowMessage);
|
|
7104
7171
|
this.queue.length = 0;
|
|
7105
7172
|
this.isReady = false;
|
|
7106
|
-
logger.debug("Message handler destroyed");
|
|
7107
7173
|
}
|
|
7108
7174
|
queueOrSend(message) {
|
|
7109
7175
|
if (!this.isReady) {
|
|
@@ -7128,7 +7194,7 @@ class MessageHandler {
|
|
|
7128
7194
|
payload: message
|
|
7129
7195
|
});
|
|
7130
7196
|
this.iframe.contentWindow.postMessage(message, targetOrigin);
|
|
7131
|
-
logger.
|
|
7197
|
+
logger.debug("Message sent to server", message);
|
|
7132
7198
|
}
|
|
7133
7199
|
canSend() {
|
|
7134
7200
|
return this.iframe?.contentWindow !== null && this.iframe?.contentWindow !== void 0;
|
|
@@ -7156,12 +7222,12 @@ class MessageHandler {
|
|
|
7156
7222
|
};
|
|
7157
7223
|
setupIncomingMessages() {
|
|
7158
7224
|
window.addEventListener("message", this.handleWindowMessage);
|
|
7159
|
-
logger.debug("Message handler started listening");
|
|
7160
7225
|
}
|
|
7161
7226
|
setupOutgoingMessages() {
|
|
7162
7227
|
const outgoingEvents = [
|
|
7163
7228
|
EVENT_NAMES.MUTATION_MESSAGE,
|
|
7164
|
-
EVENT_NAMES.CONFIG_MESSAGE
|
|
7229
|
+
EVENT_NAMES.CONFIG_MESSAGE,
|
|
7230
|
+
EVENT_NAMES.CAMERA_MESSAGE
|
|
7165
7231
|
];
|
|
7166
7232
|
outgoingEvents.forEach((eventName) => {
|
|
7167
7233
|
this.eventBus.on(eventName, (event) => {
|
|
@@ -7374,7 +7440,6 @@ class VirtualdisplayViewerService {
|
|
|
7374
7440
|
config.loadingIndicatorEnabled = false;
|
|
7375
7441
|
}
|
|
7376
7442
|
if (Object.keys(config).length > 0) {
|
|
7377
|
-
logger.debug("Sending initial UI configuration", config);
|
|
7378
7443
|
this.sendUIConfig(config);
|
|
7379
7444
|
}
|
|
7380
7445
|
}
|
|
@@ -7437,7 +7502,6 @@ class VirtualdisplayViewerService {
|
|
|
7437
7502
|
type: MESSAGE_TYPES.CONFIG,
|
|
7438
7503
|
config
|
|
7439
7504
|
};
|
|
7440
|
-
logger.debug("Emitting CONFIG message", message);
|
|
7441
7505
|
this.eventBus.emit(EVENT_NAMES.CONFIG_MESSAGE, { message });
|
|
7442
7506
|
}
|
|
7443
7507
|
}
|
|
@@ -7447,6 +7511,7 @@ class VirtualdisplayClient {
|
|
|
7447
7511
|
stateService;
|
|
7448
7512
|
messageHandler;
|
|
7449
7513
|
viewerService;
|
|
7514
|
+
cameraApi;
|
|
7450
7515
|
options;
|
|
7451
7516
|
iframe;
|
|
7452
7517
|
constructor(options) {
|
|
@@ -7456,6 +7521,7 @@ class VirtualdisplayClient {
|
|
|
7456
7521
|
this.stateService = new StateService(this.eventBus);
|
|
7457
7522
|
this.messageHandler = new MessageHandler(this.eventBus);
|
|
7458
7523
|
this.viewerService = new VirtualdisplayViewerService(this.eventBus);
|
|
7524
|
+
this.cameraApi = new Camera(this.eventBus);
|
|
7459
7525
|
this.initializeLogging();
|
|
7460
7526
|
this.createAndConnectIframe();
|
|
7461
7527
|
this.setupInitialConfig();
|
|
@@ -7549,6 +7615,12 @@ class VirtualdisplayClient {
|
|
|
7549
7615
|
get viewer() {
|
|
7550
7616
|
return this.viewerService;
|
|
7551
7617
|
}
|
|
7618
|
+
/**
|
|
7619
|
+
* Get the camera control API
|
|
7620
|
+
*/
|
|
7621
|
+
get camera() {
|
|
7622
|
+
return this.cameraApi;
|
|
7623
|
+
}
|
|
7552
7624
|
destroy() {
|
|
7553
7625
|
logger.info("Destroying Virtualdisplay client");
|
|
7554
7626
|
this.attributeService.clear();
|
|
@@ -7563,6 +7635,7 @@ class VirtualdisplayClient {
|
|
|
7563
7635
|
}
|
|
7564
7636
|
export {
|
|
7565
7637
|
AttributeSelector,
|
|
7638
|
+
Camera,
|
|
7566
7639
|
ERROR_CODES,
|
|
7567
7640
|
EVENT_NAMES,
|
|
7568
7641
|
MESSAGE_TYPES,
|