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

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.
Files changed (68) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/README.md +105 -157
  3. package/dist/browser-CDLfpTNV.cjs +8 -0
  4. package/dist/browser-DxtIwHNu.js +1227 -0
  5. package/dist/chunk-BcutgqC9.cjs +1 -0
  6. package/dist/chunk-C_CI6nMA.js +13 -0
  7. package/dist/src/annotations/annotations.d.ts +20 -0
  8. package/dist/src/annotations/annotations.d.ts.map +1 -0
  9. package/dist/src/annotations/index.d.ts +2 -0
  10. package/dist/src/annotations/index.d.ts.map +1 -0
  11. package/dist/src/attributes/attribute.d.ts +38 -0
  12. package/dist/src/attributes/attribute.d.ts.map +1 -0
  13. package/dist/src/attributes/attributes.d.ts +43 -0
  14. package/dist/src/attributes/attributes.d.ts.map +1 -0
  15. package/dist/src/attributes/selections.d.ts +16 -0
  16. package/dist/src/attributes/selections.d.ts.map +1 -0
  17. package/dist/src/attributes/value.d.ts +13 -0
  18. package/dist/src/attributes/value.d.ts.map +1 -0
  19. package/dist/src/camera/camera.d.ts +40 -0
  20. package/dist/src/camera/camera.d.ts.map +1 -0
  21. package/dist/src/camera/index.d.ts +4 -0
  22. package/dist/src/camera/index.d.ts.map +1 -0
  23. package/dist/src/camera/position.d.ts +56 -0
  24. package/dist/src/camera/position.d.ts.map +1 -0
  25. package/dist/src/client/client.d.ts +51 -0
  26. package/dist/src/client/client.d.ts.map +1 -0
  27. package/dist/src/client/error.d.ts +26 -0
  28. package/dist/src/client/error.d.ts.map +1 -0
  29. package/dist/src/client/iframe-builder.d.ts +27 -0
  30. package/dist/src/client/iframe-builder.d.ts.map +1 -0
  31. package/dist/src/client/options.d.ts +19 -0
  32. package/dist/src/client/options.d.ts.map +1 -0
  33. package/dist/src/client/ready-state-tracker.d.ts +13 -0
  34. package/dist/src/client/ready-state-tracker.d.ts.map +1 -0
  35. package/dist/src/client/types.d.ts +19 -0
  36. package/dist/src/client/types.d.ts.map +1 -0
  37. package/dist/src/index.d.ts +12 -0
  38. package/dist/src/index.d.ts.map +1 -0
  39. package/dist/src/snapshot/index.d.ts +3 -0
  40. package/dist/src/snapshot/index.d.ts.map +1 -0
  41. package/dist/src/snapshot/photo.d.ts +47 -0
  42. package/dist/src/snapshot/photo.d.ts.map +1 -0
  43. package/dist/src/snapshot/snapshot.d.ts +30 -0
  44. package/dist/src/snapshot/snapshot.d.ts.map +1 -0
  45. package/dist/src/ui/action-bar.d.ts +18 -0
  46. package/dist/src/ui/action-bar.d.ts.map +1 -0
  47. package/dist/src/ui/camera-controls.d.ts +8 -0
  48. package/dist/src/ui/camera-controls.d.ts.map +1 -0
  49. package/dist/src/ui/controls/attribute-group.d.ts +6 -0
  50. package/dist/src/ui/controls/attribute-group.d.ts.map +1 -0
  51. package/dist/src/ui/event-bus.d.ts +12 -0
  52. package/dist/src/ui/event-bus.d.ts.map +1 -0
  53. package/dist/src/ui/loading.d.ts +43 -0
  54. package/dist/src/ui/loading.d.ts.map +1 -0
  55. package/dist/src/ui/standard-interface.d.ts +41 -0
  56. package/dist/src/ui/standard-interface.d.ts.map +1 -0
  57. package/dist/src/ui/styles.d.ts +3 -0
  58. package/dist/src/ui/styles.d.ts.map +1 -0
  59. package/dist/src/utils/logger.d.ts +11 -0
  60. package/dist/src/utils/logger.d.ts.map +1 -0
  61. package/dist/virtualdisplay.client.cjs.js +303 -2
  62. package/dist/virtualdisplay.client.es.js +2213 -2
  63. package/dist/virtualdisplay.client.umd.js +310 -2
  64. package/package.json +3 -3
  65. package/dist/index.d.ts +0 -415
  66. package/dist/virtualdisplay.client.cjs.js.map +0 -1
  67. package/dist/virtualdisplay.client.es.js.map +0 -1
  68. package/dist/virtualdisplay.client.umd.js.map +0 -1
@@ -0,0 +1,8 @@
1
+ import { Camera, CameraPosition } from '../camera';
2
+ export declare class CameraControls {
3
+ readonly element: HTMLElement;
4
+ constructor(camera: Camera, position: CameraPosition);
5
+ private static buildZoom;
6
+ private static buildDpad;
7
+ }
8
+ //# sourceMappingURL=camera-controls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"camera-controls.d.ts","sourceRoot":"","sources":["../../../src/ui/camera-controls.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAuB,MAAM,WAAW,CAAC;AAY7E,qBAAa,cAAc;IACzB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;gBAElB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc;IAuBpD,OAAO,CAAC,MAAM,CAAC,SAAS;IAQxB,OAAO,CAAC,MAAM,CAAC,SAAS;CAiBzB"}
@@ -0,0 +1,6 @@
1
+ import { AttributeDefinition } from '@virtualdisplay.io/messaging';
2
+ import { Attributes } from '../../attributes/attributes';
3
+ import { AttributeValue } from '../../attributes/value';
4
+ import { UiEventBus } from '../event-bus';
5
+ export declare function buildAttributeGroup(def: AttributeDefinition, attributes: Attributes, eventBus: UiEventBus, onSelect: (name: string, value: string) => void, onSubscribe: (name: string, callback: (v: AttributeValue) => void) => void): HTMLElement;
6
+ //# sourceMappingURL=attribute-group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribute-group.d.ts","sourceRoot":"","sources":["../../../../src/ui/controls/attribute-group.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAU/C,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,mBAAmB,EACxB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,EAC/C,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,IAAI,KAAK,IAAI,GACzE,WAAW,CA4Bb"}
@@ -0,0 +1,12 @@
1
+ import { VirtualdisplayUiEventMap, VirtualdisplayUiEventType } from '../client/types';
2
+ /**
3
+ * Dispatches and subscribes to UI events on the client container element.
4
+ * These are DOM CustomEvents for developers — not postMessages to the server.
5
+ */
6
+ export declare class UiEventBus {
7
+ private container;
8
+ attach(container: HTMLElement): void;
9
+ dispatch<T extends VirtualdisplayUiEventType>(type: T, detail: Omit<VirtualdisplayUiEventMap[T], 'preventDefault'>, cancelable?: boolean): CustomEvent;
10
+ on<T extends VirtualdisplayUiEventType>(type: T, callback: (event: VirtualdisplayUiEventMap[T]) => void): () => void;
11
+ }
12
+ //# sourceMappingURL=event-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../../src/ui/event-bus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,yBAAyB,EAC1B,MAAM,iBAAiB,CAAC;AAEzB;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAA4B;IAE7C,MAAM,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI;IAIpC,QAAQ,CAAC,CAAC,SAAS,yBAAyB,EAC1C,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC,EAC3D,UAAU,UAAQ,GACjB,WAAW;IAMd,EAAE,CAAC,CAAC,SAAS,yBAAyB,EACpC,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC,CAAC,KAAK,IAAI,GACrD,MAAM,IAAI;CASd"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Loading indicator with building-cube wireframe animation.
3
+ *
4
+ * Self-contained overlay that shows during model loading.
5
+ * The cube edges draw → hold → reverse → pause in a loop.
6
+ *
7
+ * Supports delayed showing — only becomes visible if loading
8
+ * takes longer than the configured threshold.
9
+ */
10
+ export interface LoadingIndicatorConfig {
11
+ showDelay?: number;
12
+ }
13
+ export declare class LoadingIndicator {
14
+ private readonly overlay;
15
+ private readonly canvas;
16
+ private readonly ctx;
17
+ private readonly pctEl;
18
+ private readonly phaseEl;
19
+ private animationId;
20
+ private showTimerId;
21
+ private readonly startTime;
22
+ private hidden;
23
+ private visible;
24
+ constructor(container: HTMLElement, config?: LoadingIndicatorConfig);
25
+ get loadingTexts(): {
26
+ downloading: string;
27
+ rendering: string;
28
+ };
29
+ updateProgress(pct: number, status: string): void;
30
+ /**
31
+ * Show an error state — stops animation and displays the error message.
32
+ * The overlay stays visible so the user knows something went wrong.
33
+ */
34
+ showError(message: string): void;
35
+ hide(): void;
36
+ destroy(): void;
37
+ private reveal;
38
+ private cancelShowTimer;
39
+ private sizeCanvas;
40
+ private tick;
41
+ private drawFrame;
42
+ }
43
+ //# sourceMappingURL=loading.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loading.d.ts","sourceRoot":"","sources":["../../../src/ui/loading.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAkEH,MAAM,WAAW,sBAAsB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAoDD,qBAAa,gBAAgB;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkC;IACtD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAC1C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;gBAEZ,SAAS,EAAE,WAAW,EAAE,MAAM,GAAE,sBAA2B;IAsBvE,IAAI,YAAY,IAAI;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAK7D;IAED,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAQjD;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IA2BhC,IAAI,IAAI,IAAI;IAqBZ,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,IAAI,CAMV;IAEF,OAAO,CAAC,SAAS;CAmDpB"}
@@ -0,0 +1,41 @@
1
+ import { ViewerSettings, AttributeDefinition } from '@virtualdisplay.io/messaging';
2
+ import { Snapshot } from '../snapshot';
3
+ import { Camera, CameraPosition } from '../camera';
4
+ import { Attributes } from '../attributes/attributes';
5
+ import { AttributeValue } from '../attributes/value';
6
+ import { UiEventBus } from './event-bus';
7
+ export interface StandardInterfaceOptions {
8
+ snapshotApi: Snapshot;
9
+ cameraApi: Camera;
10
+ cameraPositionApi: CameraPosition;
11
+ eventBus: UiEventBus;
12
+ onSelect: (name: string, value: string) => void;
13
+ onSubscribe: (name: string, callback: (v: AttributeValue) => void) => void;
14
+ onAr?: () => void;
15
+ }
16
+ export declare class StandardInterface {
17
+ private readonly options;
18
+ private settings;
19
+ private container;
20
+ private loading;
21
+ private slots;
22
+ private screenshotBtn;
23
+ private actionBar;
24
+ private cameraControls;
25
+ private attributes;
26
+ constructor(options: StandardInterfaceOptions);
27
+ attach(container: HTMLElement): void;
28
+ onReady(): void;
29
+ private mountToolbar;
30
+ private toggleFullscreen;
31
+ updateProgress(progress: number, phase: string): void;
32
+ showError(message: string): void;
33
+ applyViewerSettings(settings: ViewerSettings): void;
34
+ renderAttributeControls(attributes: Attributes, definitions: AttributeDefinition[]): void;
35
+ get viewerSettings(): ViewerSettings;
36
+ destroy(): void;
37
+ private createSlot;
38
+ private syncScreenshotButton;
39
+ private placeScreenshotButton;
40
+ }
41
+ //# sourceMappingURL=standard-interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard-interface.d.ts","sourceRoot":"","sources":["../../../src/ui/standard-interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAKxF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAc9C,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,QAAQ,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,cAAc,CAAC;IAClC,QAAQ,EAAE,UAAU,CAAC;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,IAAI,KAAK,IAAI,CAAC;IAC3E,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,KAAK,CAA6H;IAC1I,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,UAAU,CAA4B;gBAElC,OAAO,EAAE,wBAAwB;IAI7C,MAAM,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI;IAYpC,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,YAAY;IAwBpB,OAAO,CAAC,gBAAgB;IASxB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIrD,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIhC,mBAAmB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAanD,uBAAuB,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,mBAAmB,EAAE,GAAG,IAAI;IAqCzF,IAAI,cAAc,IAAI,cAAc,CAA0B;IAE9D,OAAO,IAAI,IAAI;IAWf,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,oBAAoB;IAoB5B,OAAO,CAAC,qBAAqB;CAQ9B"}
@@ -0,0 +1,3 @@
1
+ export declare const STYLES: string;
2
+ export declare function injectStyles(): void;
3
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/ui/styles.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,MAAM,QAsFlB,CAAC;AAEF,wBAAgB,YAAY,IAAI,IAAI,CAOnC"}
@@ -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,2 +1,303 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const 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"};class t extends Error{code;constructor(e,s){super(e),this.name="VirtualdisplayError",this.code=s,void 0!==Error.captureStackTrace&&Error.captureStackTrace(this,t)}static noMapping(){return new t("No attributes available. Waiting for server metadata.",e.NO_MAPPING)}static attributeNotFound(s){return new t(`Attribute "${s}" not found in mapping`,e.ATTRIBUTE_NOT_FOUND)}static valueNotFound(s,i){return new t(`Value "${i}" not found for attribute "${s}"`,e.VALUE_NOT_FOUND)}static parentNotFound(s){return new t(`Parent element not found: ${s}`,e.PARENT_NOT_FOUND)}static invalidParameter(s){return new t(s,e.INVALID_PARAMETER)}static snapshotFailed(s,i){return new t(`Snapshot failed for "${s}": ${i}`,e.SNAPSHOT_FAILED)}}const s={};class i{defaultServer="https://server.virtualdisplay.io";options;constructor(e){this.options=e}create(){const e=this.createIframe();return this.attachToParent(e),e}createIframe(){const 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(){const e=this.getServerUrl(),t=new URL(e);return t.searchParams.set("license",this.options.license),t.searchParams.set("model",this.options.model),!0===this.options.debug&&t.searchParams.set("debug","true"),void 0!==this.options.language&&t.searchParams.set("language",this.options.language),t.toString()}getServerUrl(){if(void 0===s?.VITE_VIRTUALDISPLAY_SERVER_HOST)return this.defaultServer}getParentElement(){if("string"!=typeof this.options.parent)return this.options.parent;const e=document.querySelector(this.options.parent);if(null===e)throw t.parentNotFound(this.options.parent);return e}}function n(e,t){const s=t?function(e){const t=new Date(e.timestamp).toLocaleTimeString("en-GB",{hour12:!1}),s=e.level.toUpperCase().padEnd(5),i=e.trace_id?.slice(0,8)??"--------",n=e.msg,r=["timestamp","level","msg","service","trace_id","span_id"],a=Object.entries(e).filter(([e])=>!r.includes(e)).map(([e,t])=>`${e}=${JSON.stringify(t)}`).join(" ");return`${t} ${s} [${i}] ${n}${a?" "+a:""}`}(e):function(e){return JSON.stringify(e)}(e);"error"===e.level?console.error(s):"warn"===e.level?console.warn(s):console.log(s)}class r{constructor(e){this.config=e}log(e,t,s={}){const i=this.config.traceProvider?.()??{};var r;n({timestamp:(r=new Date,r.toISOString()),level:e,msg:t,service:this.config.service,...i,...s},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(e){const t=new r(this.config);return t.log=((t,s,i={})=>{this.log(t,s,{...e,...i})}).bind(this),t}}function a(e,t){const s=void 0!==t?.isDev?t.isDev:"undefined"==typeof process||"production"!==process.env.NODE_ENV;return new r({service:e,isDev:s,traceProvider:t?.traceProvider})}function o(e){if(void 0!==e)return"object"!=typeof e||null===e||Array.isArray(e)||e instanceof Error?e instanceof Error?{error:e.message}:{value:e}:e}function l(e){return{debug:(t,s)=>e.debug(t,o(s)),info:(t,s)=>e.info(t,o(s)),warn:(t,s)=>e.warn(t,o(s)),error:(t,s)=>e.error(t,o(s))}}let d=!1;function u(){d=!0,exports.logger=l(a("client",{isDev:!0}))}exports.logger=l(a("client",{isDev:!1}));class h{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,exports.logger.info(`${e} - client is now ready`),this.onReady?.())}}class c{constructor(e,t){this.value=e,this.attribute=t}isSelectedValue=!1;get isSelected(){return this.isSelectedValue}setSelected(e){this.isSelectedValue=e}}class g{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(const s of this.values.values()){const i=s.value===e;s.setSelected(i),i&&(t=s)}void 0!==t&&void 0!==this.onChangeCallback&&this.onChangeCallback(t)}createValues(e){const t=new Map;for(const s of e){const e=new c(s,this.name);s===this.defaultValue&&e.setSelected(!0),t.set(s,e)}return t}}class p{attributes=new Map;constructor(e,t,s){for(const i of e){const e=this.buildOptions(i,t);this.attributes.set(i.name,new g(e))}this.onMutationFailed=s}onMutationFailed;get(e){return this.attributes.get(e)}defaults(){const e=[];for(const t of this.attributes.values())void 0!==t.defaultValue&&e.push({name:t.name,value:t.defaultValue});return e}handleResults(e){for(const t of e)t.success?this.get(t.name)?.handleResult(t.value):this.onMutationFailed?.(t.name,t.value)}buildOptions(e,t){const s={name:e.name,values:e.values,onSelect:(e,s)=>{t([{name:e,value:s}],!1)}};return void 0!==e.defaultValue?{...s,defaultValue:e.defaultValue}:s}}const f={READY:"ready",MUTATION:"mutation",STATE:"state",CONFIG:"config",CAMERA:"camera",SNAPSHOT:"snapshot",MAPPING:"mapping"},m=new Set(Object.values(f));function b(e){return"object"!=typeof e||null===e?null:e}class v{constructor(e){this.processor=e}pending=[];isReady=!1;enqueue(e){this.isReady?this.processor(e):this.pending.push(e)}markReady(){if(this.isReady)return;if(this.isReady=!0,0===this.pending.length)return;const e=[...this.pending];this.pending.length=0;for(const 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}}class y{constructor(e,t){this.getTarget=e,this.sourceId=`vd-${Math.random().toString(36).slice(2,8)}`,this.publisher=new v(e=>this.post(e)),this.consumer=new v(e=>this.routeToHandler(e)),this.shouldBuffer=t?.shouldBuffer??null,!0!==t?.bufferIncoming&&this.consumer.markReady()}handlers=new Map;publisher;consumer;shouldBuffer;listener=null;sourceId;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(){null===this.listener&&(this.listener=e=>{const{data:t}=e;if(!function(e){if("object"!=typeof e||null===e)return!1;const t=e;return"string"!=typeof t.target&&"string"==typeof t.type&&m.has(t.type)}(t))return;if(t._source===this.sourceId)return;const s=t;null===this.shouldBuffer||this.shouldBuffer(s)?this.consumer.enqueue(s):this.routeToHandler(s)},window.addEventListener("message",this.listener))}destroy(){null!==this.listener&&(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){const t=this.getTarget();null!==t&&t.postMessage({...e,_source:this.sourceId},"*")}routeToHandler(e){const t=this.handlers.get(e.type);if(void 0===t)return;const s=t(e);s instanceof Promise&&s.catch(t=>{const s=t instanceof Error?t.message:String(t);console.error(`Virtualdisplay: error handling ${e.type}: ${s}`)})}}class A{constructor(e,t){this.send=e,this.onMutationFailed=t}registry;pendingCallbacks=[];handleMappingReceived(e){exports.logger.debug("Initializing from server mapping",{attributeCount:e.attributes.length}),this.registry=new p(e.attributes,(e,t)=>this.sendMutation(e,t),this.onMutationFailed);const 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(void 0===this.registry)return void this.pendingCallbacks.push({name:e,callback:t});const s=this.registry.get(e);void 0!==s?s.onChange(t):exports.logger.warn(`onChange: attribute "${e}" not found — callback will not fire`)}getAttribute(e){return this.registry?.get(e)}get hasMapping(){return void 0!==this.registry}sendMutation(e,t){const s={type:f.MUTATION,mutations:e,isInitial:t};this.send(s)}replayPendingCallbacks(){for(const{name:e,callback:t}of this.pendingCallbacks){const s=this.registry?.get(e);void 0===s&&exports.logger.warn(`onChange: attribute "${e}" not found — buffered callback will not fire`),s?.onChange(t)}this.pendingCallbacks.length=0}}class E{constructor(e){this.send=e}commands=[];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(0===this.commands.length)throw t.invalidParameter("No camera commands to execute. Call rotate(), tilt(), or zoom() before set().");const e={type:f.CAMERA,commands:this.commands};this.send(e),this.commands=[]}validateFiniteNumber(e,s){if(!Number.isFinite(e))throw t.invalidParameter(`${s}() requires a finite number, got ${String(e)}`)}reset(){const e={type:f.CAMERA,commands:[{action:"reset"}]};this.send(e)}}class C{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(const s of e)switch(s.type){case"rotation":this.state.rotation=s.value,t=!0;break;case"tilt":this.state.tilt=s.value,t=!0;break;case"zoom":this.state.zoom=s.value,t=!0}if(t){const e={rotation:this.rotation,tilt:this.tilt,zoom:this.zoom};for(const t of this.changeCallbacks)t(e)}}}class I{constructor(e){this.filename=e}developedCallbacks=new Set;errorCallbacks=new Set;developed=!1;failed=!1;photoData=null;onDeveloped(e){return this.developed&&null!==this.photoData?(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())}}class w{constructor(e){this.send=e}validExtensions=[".png"];pendingPhotos=new Map;take(e){this.validateFilename(e),exports.logger.debug("Taking snapshot",{filename:e});const t=new I(e);return this.pendingPhotos.set(t.getFilename(),t),this.send({type:f.SNAPSHOT,filename:e}),t}handleSnapshotResult(s){const i=this.pendingPhotos.get(s.filename);void 0!==i?(this.pendingPhotos.delete(s.filename),void 0===s.error?void 0!==s.data&&i.develop({filename:s.filename,data:s.data}):i.fail(new t(s.error,e.SNAPSHOT_FAILED))):exports.logger.warn("No pending photo found for filename",{filename:s.filename,pendingFilenames:Array.from(this.pendingPhotos.keys())})}validateFilename(s){if(""===s||"string"!=typeof s)throw new t("Filename must be a non-empty string",e.INVALID_PARAMETER);if(!this.validExtensions.some(e=>s.toLowerCase().endsWith(e)))throw new t(`Invalid filename: "${s}". Filename must end with one of: ${this.validExtensions.join(", ")}`,e.INVALID_PARAMETER);if(s.includes("..")||s.includes("/")||s.includes("\\"))throw new t('Filename cannot contain path separators or ".."',e.INVALID_PARAMETER)}}class S{send;constructor(e){this.send=e}sendInitialConfig(e){const t=this.buildUIConfig(e),s=this.buildViewerConfig(t,e.camera);void 0!==s&&this.sendConfig(s)}buildUIConfig(e){const t=this.extractUIValues(e);if(Object.values(t).some(e=>void 0!==e))return{...void 0!==t.arEnabled&&{arEnabled:t.arEnabled},...void 0!==t.fullscreenEnabled&&{fullscreenEnabled:t.fullscreenEnabled},...void 0!==t.loadingIndicatorEnabled&&{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(void 0!==e||void 0!==t)return{...void 0!==e&&{ui:e},...void 0!==t&&{camera:t}}}setArEnabled(e){exports.logger.debug(`Setting AR button enabled: ${e}`),this.updateUIConfig({arEnabled:e})}setFullscreenEnabled(e){exports.logger.debug(`Setting fullscreen button enabled: ${e}`),this.updateUIConfig({fullscreenEnabled:e})}setLoadingIndicatorEnabled(e){exports.logger.debug(`Setting loading indicator enabled: ${e}`),this.updateUIConfig({loadingIndicatorEnabled:e})}updateUIConfig(e){exports.logger.debug("Updating UI configuration",e),Object.keys(e).length>0&&this.sendConfig({ui:e})}hideAllUI(){exports.logger.debug("Hiding all UI elements"),this.sendUIConfig({arEnabled:!1,fullscreenEnabled:!1,loadingIndicatorEnabled:!1})}showAllUI(){exports.logger.debug("Showing all UI elements"),this.sendUIConfig({arEnabled:!0,fullscreenEnabled:!0,loadingIndicatorEnabled:!0})}sendUIConfig(e){this.sendConfig({ui:e})}sendConfig(e){const t={type:f.CONFIG,config:e};exports.logger.debug("Sending config",t),this.send(t)}}exports.Attribute=g,exports.AttributeValue=c,exports.Camera=E,exports.ERROR_CODES=e,exports.Photo=I,exports.Snapshot=w,exports.VirtualdisplayClient=class{attributes;readyStateTracker;messenger;viewerService;cameraApi;cameraPositionApi;snapshotApi;options;iframe;readyCallbacks=[];mutationFailedCallbacks=[];constructor(e){this.options=e,this.initializeLogging(),this.messenger=new y(()=>this.iframe?.contentWindow??null);const t=e=>{this.messenger.send(e)};this.attributes=new A(t,(e,t)=>{for(const s of this.mutationFailedCallbacks)s({attribute:e,value:t})}),this.readyStateTracker=new h(()=>{const e=this.readyCallbacks;this.readyCallbacks=[];for(const t of e)t(this)}),this.viewerService=new S(t),this.cameraApi=new E(t),this.cameraPositionApi=new C,this.snapshotApi=new w(t),this.registerHandlers(),this.messenger.start(),this.createAndConnectIframe()}registerHandlers(){this.messenger.on(f.READY,e=>{(function(e){const t=b(e);return null!==t&&t.type===f.READY})(e)&&(exports.logger.info("Server ready — flushing publisher queue"),this.messenger.markReady(),this.viewerService.sendInitialConfig(this.options))}),this.messenger.on(f.MUTATION,e=>{(function(e){const t=b(e);return null!==t&&t.type===f.MUTATION&&Array.isArray(t.results)})(e)&&(this.attributes.handleMutationResult(e),this.readyStateTracker.handleMutationResult(e))}),this.messenger.on(f.SNAPSHOT,e=>{(function(e){const t=b(e);return null!==t&&t.type===f.SNAPSHOT&&("data"in t||"error"in t)})(e)&&this.snapshotApi.handleSnapshotResult(e)}),this.messenger.on(f.CAMERA,e=>{(function(e){const t=b(e);return null!==t&&t.type===f.CAMERA&&Array.isArray(t.transforms)})(e)&&this.cameraPositionApi.handlePositionUpdate(e)}),this.messenger.on(f.MAPPING,e=>{(function(e){const t=b(e);return null!==t&&t.type===f.MAPPING&&Array.isArray(t.attributes)})(e)&&(this.attributes.handleMappingReceived(e),this.readyStateTracker.handleMappingReceived())})}initializeLogging(){!0===this.options.debug&&u(),exports.logger.info("Initializing Virtualdisplay client",{model:this.options.model,debug:this.options.debug,language:this.options.language})}createAndConnectIframe(){exports.logger.debug("Creating iframe for Virtualdisplay viewer");const e=new i(this.options);this.iframe=e.create(),exports.logger.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){this.readyStateTracker.isReady?e(this):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(){exports.logger.info("Destroying Virtualdisplay client"),this.readyStateTracker.clear(),this.readyCallbacks=[],this.messenger.destroy(),null!==this.iframe?.parentElement&&void 0!==this.iframe?.parentElement&&this.iframe.parentElement.removeChild(this.iframe),this.iframe=void 0,exports.logger.debug("Virtualdisplay client destroyed")}},exports.VirtualdisplayError=t,exports.VirtualdisplayViewerService=S,exports.enableDebugMode=u,exports.isDebugMode=function(){return d};
2
- //# sourceMappingURL=virtualdisplay.client.cjs.js.map
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./chunk-BcutgqC9.cjs`);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(e,t){super(e),this.name=`VirtualdisplayError`,this.code=t}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.createContainer(),t=this.createIframe();return e.appendChild(t),this.attachToParent(e),{container:e,iframe:t}}createContainer(){let e=document.createElement(`div`);return e.className=`vd-container`,Object.assign(e.style,{position:`relative`,width:`100%`,height:`100%`,overflow:`hidden`}),e}createIframe(){let e=document.createElement(`iframe`);return e.src=this.buildUrl(),Object.assign(e.style,{width:`100%`,height:`100%`,border:`none`,display:`block`}),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.language!==void 0&&t.searchParams.set(`language`,this.options.language),this.options.debug===!0&&t.searchParams.set(`debug`,`true`),this.options.traceparent!==void 0&&t.searchParams.set(`traceparent`,this.options.traceparent),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(e,t=0){let n={name:e.name,message:e.message};e.stack!==void 0&&(n.stack=e.stack);for(let t of Object.getOwnPropertyNames(e)){if(t===`name`||t===`message`||t===`stack`||t===`cause`)continue;let r=e[t];r!==void 0&&(n[t]=r)}return e.cause!==void 0&&e.cause!==null&&(n.cause=e.cause instanceof Error&&t<5?s(e.cause,t+1):String(e.cause)),n}function c(e){let t={};for(let[n,r]of Object.entries(e))t[n]=r instanceof Error?s(r):r;return t}function l(){return new Date}function u(e){return e.toISOString()}function d(){return typeof navigator>`u`?``:navigator.userAgent}function f(){return typeof navigator>`u`?!1:navigator.platform===`MacIntel`&&navigator.maxTouchPoints>1}function p(){return/iPhone|iPad|iPod/i.test(d())||f()}function m(){return/Android/i.test(d())}function h(){return p()||m()}var g=class e{constructor(e){this.config=e}log(e,t,n={}){let r=this.config.traceProvider?.()??{};o({timestamp:u(l()),level:e,msg:t,service:this.config.service,...r,...c(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 _(e,t){return new g({service:e,isDev:t?.isDev===void 0?typeof process<`u`?process.env.NODE_ENV!==`production`:!0:t.isDev,traceProvider:t?.traceProvider})}function v(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 ee(e){return{debug:(t,n)=>e.debug(t,v(n)),info:(t,n)=>e.info(t,v(n)),warn:(t,n)=>e.warn(t,v(n)),error:(t,n)=>e.error(t,v(n))}}var te=!1,y=ee(_(`client`,{isDev:!1}));function ne(){te=!0,y=ee(_(`client`,{isDev:!0}))}function re(){return te}var ie=class{ready=!1;onReady;constructor(e){this.onReady=e}handleMappingReceived(){this.ready||(this.ready=!0,y.info(`Mapping received from server, client is now ready`),this.onReady?.())}get isReady(){return this.ready}clear(){this.ready=!1}},b={HANDSHAKE:`handshake`,MUTATION:`mutation`,STATE:`state`,LOADING_INDICATOR:`loading_indicator`,CAMERA:`camera`,SNAPSHOT:`snapshot`,MAPPING:`mapping`,AR_ACTIVATE:`ar_activate`,CONFIG:`config`,INTERACTION:`interaction`,ANNOTATION_PLACE_MODE:`annotation_place_mode`,ANNOTATION_PLACED:`annotation_placed`,ANNOTATION_TOGGLE:`annotation_toggle`},ae=new Set(Object.values(b));function oe(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.target==`string`?!1:typeof t.type==`string`&&ae.has(t.type)}function se(e){let t=x(e);return t!==null&&t.type===b.HANDSHAKE}function ce(e){let t=x(e);return t!==null&&t.type===b.MUTATION&&Array.isArray(t.results)}function le(e){let t=x(e);return t!==null&&t.type===b.SNAPSHOT&&(`data`in t||`error`in t)}function ue(e){let t=x(e);return t!==null&&t.type===b.CAMERA&&Array.isArray(t.transforms)}function de(e){let t=x(e);return t!==null&&t.type===b.MAPPING&&Array.isArray(t.attributes)}function fe(e){let t=x(e);return t!==null&&t.type===b.LOADING_INDICATOR&&typeof t.progress==`number`}function pe(e){let t=x(e);return t!==null&&t.type===b.CONFIG&&typeof t.viewerSettings==`object`}function me(e){let t=x(e);return t!==null&&t.type===b.ANNOTATION_PLACED&&typeof t.position==`object`&&t.position!==null}function x(e){return typeof e!=`object`||!e?null:e}var he=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}},ge=class{handlers=new Map;publisher;consumer;shouldBuffer;listener=null;sourceId;targetOrigin;constructor(e,t){this.getTarget=e,this.sourceId=`vd-${Math.random().toString(36).slice(2,8)}`,this.targetOrigin=t?.targetOrigin??`*`,this.publisher=new he(e=>this.post(e)),this.consumer=new he(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)}setTargetOrigin(e){this.targetOrigin=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(!oe(t)||t._source===this.sourceId)return;let n=this.getTarget();if(n!==null&&e.source!==null&&e.source!==n)return;let r=t;if(this.shouldBuffer!==null&&!this.shouldBuffer(r)){this.routeToHandler(r);return}this.consumer.enqueue(r)},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},this.targetOrigin)}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 S=class{placedCallbacks=[];constructor(e){this.send=e}setEnabled(e){this.send({type:b.ANNOTATION_TOGGLE,enabled:e})}startPlacing(){this.send({type:b.ANNOTATION_PLACE_MODE,enabled:!0})}stopPlacing(){this.send({type:b.ANNOTATION_PLACE_MODE,enabled:!1})}onPlaced(e){this.placedCallbacks.push(e)}handlePlaced(e){for(let t of this.placedCallbacks)t(e)}},C=class{isSelectedValue=!1;constructor(e,t){this.value=e,this.attribute=t}get isSelected(){return this.isSelectedValue}setSelected(e){this.isSelectedValue=e}},_e=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 C(n,this.name);n===this.defaultValue&&e.setSelected(!0),t.set(n,e)}return t}},ve=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 _e(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}}},ye=class{registry;pendingCallbacks=[];constructor(e,t){this.send=e,this.onMutationFailed=t}handleMappingReceived(e){y.debug(`Initializing from server mapping`,{attributeCount:e.attributes.length}),this.registry=new ve(e.attributes,(e,t)=>this.sendMutation(e,t),this.onMutationFailed),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){y.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&&y.warn(`onChange: attribute "${e}" not found — buffered callback will not fire`),n?.onChange(t)}this.pendingCallbacks.length=0}},be=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:b.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:b.CAMERA,commands:[{action:`reset`}]};this.send(e)}},xe=class{state;limitsState;changeCallbacks=[];constructor(){this.state={rotation:0,tilt:0,zoom:100}}get rotation(){return this.state.rotation}get tilt(){return this.state.tilt}get zoom(){return this.state.zoom}onChange(e){this.changeCallbacks.push(e)}get limits(){return this.limitsState}applyLimits(e){this.limitsState=e;let t={rotation:this.rotation,tilt:this.tilt,zoom:this.zoom};for(let e of this.changeCallbacks)e(t)}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)}}},Se=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())}},Ce=class{validExtensions=[`.png`];pendingPhotos=new Map;constructor(e){this.send=e}take(e){this.validateFilename(e),y.debug(`Taking snapshot`,{filename:e});let t=new Se(e);return this.pendingPhotos.set(t.getFilename(),t),this.send({type:b.SNAPSHOT,filename:e}),t}handleSnapshotResult(e){let r=this.pendingPhotos.get(e.filename);if(r===void 0){y.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)}},we=class{container=null;attach(e){this.container=e}dispatch(e,t,n=!1){let r=new CustomEvent(e,{detail:t,cancelable:n});return this.container?.dispatchEvent(r),r}on(e,t){let n=e=>{let n=e;t({...n.detail,preventDefault:()=>{n.preventDefault()}})};return this.container?.addEventListener(e,n),()=>{this.container?.removeEventListener(e,n)}}},Te={},Ee=[`en`,`nl`,`de`],w=[`baseLocale`],De=[],Oe,ke;function Ae(e){if(De.length===0)return;let t=typeof e==`string`?e:e.href;if(Oe===t)return ke;let n=new URL(t,`http://dummy.com`),r;for(let e of De)if(new Te(e.match,n.href).exec(n.href)){r=e;break}return Oe=t,ke=r,r}function je(e){let t=Ae(e);return t&&t.exclude!==!0&&Array.isArray(t.strategy)?t.strategy:w}var Me=void 0,T=typeof window>`u`;globalThis.__paraglide=globalThis.__paraglide??{},globalThis.__paraglide.ssr=globalThis.__paraglide.ssr??{};var E=!1,D=()=>{if(Me){let e=Me?.getStore()?.locale;if(e)return e}let e=w;!T&&typeof window<`u`&&window.location?.href&&(e=je(window.location.href));let t=Ne(e,typeof window<`u`?window.location?.href:void 0);if(t)return E||(E=!0,O(t,{reload:!1})),t;throw Error(`No locale found. Read the docs https://inlang.com/m/gerre34r/library-inlang-paraglideJs/errors#no-locale-found`)};function Ne(e,t){let n;for(let t of e){if(t===`baseLocale`)n=`en`;else if(j(t)&&A.has(t)){let e=A.get(t);if(e){let t=e.getLocale();if(t instanceof Promise)continue;if(t!==void 0)return Fe(t)}}let e=k(n);if(e)return e}}var Pe=e=>{e?window.location.href=e:window.location.reload()},O=(e,t)=>{let n={reload:!0,...t},r;try{r=D()}catch{}let i=[],a=w;!T&&typeof window<`u`&&window.location?.href&&(a=je(window.location.href));for(let t of a)if(t===`baseLocale`)continue;else if(j(t)&&A.has(t)){let n=A.get(t);if(n){let r=n.setLocale(e);r instanceof Promise&&(r=r.catch(e=>{throw Error(`Custom strategy "${t}" setLocale failed.`,{cause:e})}),i.push(r))}}let o=()=>{!T&&n.reload&&window.location&&e!==r&&Pe(void 0)};if(i.length)return Promise.all(i).then(()=>{o()});o()};function k(e){if(typeof e!=`string`)return;let t=e.toLowerCase();for(let e of Ee)if(e.toLowerCase()===t)return e}function Fe(e){let t=k(e);if(t)return t;throw Error(`Invalid locale: ${e}. Expected one of: ${Ee.join(`, `)}`)}var A=new Map;function j(e){return typeof e==`string`&&/^custom-[A-Za-z0-9_-]+$/.test(e)}var Ie=()=>`Activate AR`,Le=()=>`AR activeren`,Re=()=>`AR aktivieren`,ze=((e={},t={})=>{let n=t.locale??D();return n===`en`?Ie(e):n===`nl`?Le(e):Re(e)}),Be=()=>`Scan to view in AR`,Ve=()=>`Scan om in AR te bekijken`,He=()=>`Scannen für AR-Ansicht`,Ue=((e={},t={})=>{let n=t.locale??D();return n===`en`?Be(e):n===`nl`?Ve(e):He(e)}),We=()=>`Use your smartphone camera to scan this QR code`,Ge=()=>`Gebruik de camera van je smartphone om deze QR-code te scannen`,Ke=()=>`Verwenden Sie die Kamera Ihres Smartphones, um diesen QR-Code zu scannen`,qe=((e={},t={})=>{let n=t.locale??D();return n===`en`?We(e):n===`nl`?Ge(e):Ke(e)}),Je=()=>`The 3D model will open in your phone's AR mode`,Ye=()=>`Het 3D-model wordt geopend in de AR-modus van je telefoon`,Xe=()=>`Das 3D-Modell wird im AR-Modus Ihres Telefons geöffnet`,Ze=((e={},t={})=>{let n=t.locale??D();return n===`en`?Je(e):n===`nl`?Ye(e):Xe(e)}),Qe=()=>`Close`,$e=()=>`Sluiten`,et=()=>`Schließen`,tt=((e={},t={})=>{let n=t.locale??D();return n===`en`?Qe(e):n===`nl`?$e(e):et(e)}),nt=()=>`Toggle fullscreen`,rt=()=>`Volledig scherm`,it=()=>`Vollbild umschalten`,at=((e={},t={})=>{let n=t.locale??D();return n===`en`?nt(e):n===`nl`?rt(e):it(e)}),ot=()=>`Downloading`,st=()=>`Downloaden`,ct=()=>`Herunterladen`,M=((e={},t={})=>{let n=t.locale??D();return n===`en`?ot(e):n===`nl`?st(e):ct(e)}),lt=()=>`Rendering`,ut=()=>`Renderen`,dt=()=>`Rendern`,ft=((e={},t={})=>{let n=t.locale??D();return n===`en`?lt(e):n===`nl`?ut(e):dt(e)}),pt=()=>`Screenshot`,mt=()=>`Screenshot`,ht=()=>`Screenshot`,gt=((e={},t={})=>{let n=t.locale??D();return n===`en`?pt(e):n===`nl`?mt(e):ht(e)}),_t=()=>`Reset camera`,vt=()=>`Camera resetten`,yt=()=>`Kamera zurücksetzen`,bt=((e={},t={})=>{let n=t.locale??D();return n===`en`?_t(e):n===`nl`?vt(e):yt(e)}),xt=()=>`Zoom in`,St=()=>`Inzoomen`,Ct=()=>`Hineinzoomen`,wt=((e={},t={})=>{let n=t.locale??D();return n===`en`?xt(e):n===`nl`?St(e):Ct(e)}),Tt=()=>`Zoom out`,Et=()=>`Uitzoomen`,Dt=()=>`Herauszoomen`,Ot=((e={},t={})=>{let n=t.locale??D();return n===`en`?Tt(e):n===`nl`?Et(e):Dt(e)}),kt=()=>`Rotate left`,At=()=>`Naar links draaien`,jt=()=>`Nach links drehen`,Mt=((e={},t={})=>{let n=t.locale??D();return n===`en`?kt(e):n===`nl`?At(e):jt(e)}),Nt=()=>`Rotate right`,Pt=()=>`Naar rechts draaien`,Ft=()=>`Nach rechts drehen`,It=((e={},t={})=>{let n=t.locale??D();return n===`en`?Nt(e):n===`nl`?Pt(e):Ft(e)}),Lt=()=>`Tilt up`,Rt=()=>`Omhoog kantelen`,zt=()=>`Nach oben kippen`,Bt=((e={},t={})=>{let n=t.locale??D();return n===`en`?Lt(e):n===`nl`?Rt(e):zt(e)}),Vt=()=>`Tilt down`,Ht=()=>`Omlaag kantelen`,Ut=()=>`Nach unten kippen`,Wt=((e={},t={})=>{let n=t.locale??D();return n===`en`?Vt(e):n===`nl`?Ht(e):Ut(e)}),Gt={xmlns:`http://www.w3.org/2000/svg`,width:24,height:24,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":2,"stroke-linecap":`round`,"stroke-linejoin":`round`},N=([e,t,n])=>{let r=document.createElementNS(`http://www.w3.org/2000/svg`,e);return Object.keys(t).forEach(e=>{r.setAttribute(e,String(t[e]))}),n?.length&&n.forEach(e=>{let t=N(e);r.appendChild(t)}),r},P=(e,t={})=>N([`svg`,{...Gt,...t},e]),Kt=[[`path`,{d:`M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z`}],[`path`,{d:`m3.3 7 8.7 5 8.7-5`}],[`path`,{d:`M12 22V12`}]],qt=[[`path`,{d:`M13.997 4a2 2 0 0 1 1.76 1.05l.486.9A2 2 0 0 0 18.003 7H20a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h1.997a2 2 0 0 0 1.759-1.048l.489-.904A2 2 0 0 1 10.004 4z`}],[`circle`,{cx:`12`,cy:`13`,r:`3`}]],F=[[`path`,{d:`m6 9 6 6 6-6`}]],Jt=[[`path`,{d:`m15 18-6-6 6-6`}]],Yt=[[`path`,{d:`m9 18 6-6-6-6`}]],Xt=[[`path`,{d:`m18 15-6-6-6 6`}]],Zt=[[`path`,{d:`M15 3h6v6`}],[`path`,{d:`m21 3-7 7`}],[`path`,{d:`m3 21 7-7`}],[`path`,{d:`M9 21H3v-6`}]],Qt=[[`path`,{d:`m14 10 7-7`}],[`path`,{d:`M20 10h-6V4`}],[`path`,{d:`m3 21 7-7`}],[`path`,{d:`M4 14h6v6`}]],$t=[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`}],[`path`,{d:`M3 3v5h5`}]],en=[[`circle`,{cx:`11`,cy:`11`,r:`8`}],[`line`,{x1:`21`,x2:`16.65`,y1:`21`,y2:`16.65`}],[`line`,{x1:`11`,x2:`11`,y1:`8`,y2:`14`}],[`line`,{x1:`8`,x2:`14`,y1:`11`,y2:`11`}]],tn=[[`circle`,{cx:`11`,cy:`11`,r:`8`}],[`line`,{x1:`21`,x2:`16.65`,y1:`21`,y2:`16.65`}],[`line`,{x1:`8`,x2:`14`,y1:`11`,y2:`11`}]];function I(e,{size:t=20,strokeWidth:n=1.75}={}){return P(e,{width:t,height:t,"stroke-width":n})}var L={ar:e=>I(Kt,e),fullscreen:e=>I(Zt,e),exitFullscreen:e=>I(Qt,e),screenshot:e=>I(qt,e),tiltUp:e=>I(Xt,e),tiltDown:e=>I(F,e),rotateLeft:e=>I(Jt,e),rotateRight:e=>I(Yt,e),zoomIn:e=>I(en,e),zoomOut:e=>I(tn,e),reset:e=>I($t,e)},R=class{element;constructor({variant:e=`default`,size:t=`default`,label:n,icon:r,onClick:i,disabled:a=!1}={}){this.element=document.createElement(`button`),this.element.className=`ui-btn ui-btn--${e} ui-btn--size-${t}`,n!==void 0&&(this.element.setAttribute(`aria-label`,n),this.element.title=n),r===void 0?n!==void 0&&(this.element.textContent=n):this.element.appendChild(r),i&&this.element.addEventListener(`click`,i),this.element.disabled=a}setIcon(e){let t=this.element.querySelector(`svg`);t===null?this.element.appendChild(e):t.replaceWith(e)}},z={brand:{DEFAULT:`#171717`,primary:`#171717`,hover:`#262626`,light:`#f5f5f5`,50:`#fafafa`,100:`#f5f5f5`,200:`#e5e5e5`,300:`#d4d4d4`,400:`#a3a3a3`,500:`#737373`,600:`#525252`,700:`#404040`,800:`#262626`,900:`#171717`,950:`#0a0a0a`},semantic:{success:`#16a34a`,warning:`#ca8a04`,error:`#dc2626`,info:`#0891b2`},neutral:{50:`#fafafa`,100:`#f5f5f5`,200:`#e5e5e5`,300:`#d4d4d4`,400:`#a3a3a3`,500:`#737373`,600:`#525252`,700:`#404040`,800:`#262626`,900:`#171717`,950:`#0a0a0a`},white:`#ffffff`,black:`#000000`},B={px:`1px`,0:`0`,.5:`0.125rem`,1:`0.25rem`,1.5:`0.375rem`,2:`0.5rem`,2.5:`0.625rem`,3:`0.75rem`,3.5:`0.875rem`,4:`1rem`,5:`1.25rem`,6:`1.5rem`,7:`1.75rem`,8:`2rem`,9:`2.25rem`,10:`2.5rem`,12:`3rem`,14:`3.5rem`,16:`4rem`,20:`5rem`,24:`6rem`};B[1],B[2],B[4],B[6],B[8],B[12];var nn=class{element;constructor(){this.element=document.createElement(`div`),Object.assign(this.element.style,{background:z.white,borderRadius:B[3],padding:B[6],boxShadow:`0 ${B[2]} ${B[8]} oklch(0% 0 0 / 20%)`,maxWidth:`20rem`,width:`100%`})}},rn=class{card;backdrop;keyHandler=null;constructor(e={}){this.options=e,this.card=new nn,this.backdrop=this.createBackdrop(),this.backdrop.appendChild(this.card.element)}open(){document.body.appendChild(this.backdrop),this.keyHandler=e=>{e.key===`Escape`&&this.close()},document.addEventListener(`keydown`,this.keyHandler)}close(){this.backdrop.remove(),this.keyHandler!==null&&(document.removeEventListener(`keydown`,this.keyHandler),this.keyHandler=null),this.options.onClose?.()}createBackdrop(){let e=document.createElement(`div`);return Object.assign(e.style,{position:`fixed`,inset:B[0],background:`oklch(0% 0 0 / 50%)`,zIndex:`9999`,display:`flex`,alignItems:`center`,justifyContent:`center`}),e.addEventListener(`click`,t=>{t.target===e&&this.close()}),e}},an=class{element;selectCallback=null;constructor(e,t,n){this.element=document.createElement(`div`),this.element.className=`ui-toggle-group`;for(let r=0;r<e.length;r++){let i=e[r],a=document.createElement(`button`);a.className=`ui-toggle-group-item`,a.dataset.value=i,a.textContent=n?.[r]??i,a.dataset.state=i===t?`on`:`off`,a.addEventListener(`click`,()=>{this.selectCallback?.(i)}),this.element.appendChild(a)}}setSelected(e){for(let t of this.element.querySelectorAll(`.ui-toggle-group-item`))t.dataset.state=t.dataset.value===e?`on`:`off`}onSelect(e){this.selectCallback=e}},on=class{element;select;constructor(e,t,n,r,i){this.select=document.createElement(`select`),this.select.className=`ui-native-select`,this.select.dataset.name=e;let a=document.createElement(`option`);a.value=``,a.disabled=!0,a.textContent=n,this.select.appendChild(a);let o=!1;for(let e=0;e<t.length;e++){let n=t[e],a=document.createElement(`option`);a.value=n,a.textContent=i?.[e]??n,n===r&&(a.selected=!0,o=!0),this.select.appendChild(a)}o||(a.selected=!0);let s=P(F,{width:16,height:16,"stroke-width":2});s.classList.add(`ui-native-select-icon`),this.element=document.createElement(`div`),this.element.className=`ui-native-select-wrap`,this.element.appendChild(this.select),this.element.appendChild(s)}setSelected(e){this.select.value=e}onSelect(e){this.select.addEventListener(`change`,()=>{e(this.select.value)})}},V={fontFamily:{sans:[`Mona Sans`,`ui-sans-serif`,`system-ui`,`sans-serif`,`Apple Color Emoji`,`Segoe UI Emoji`,`Segoe UI Symbol`,`Noto Color Emoji`],mono:[`JetBrains Mono`,`ui-monospace`,`monospace`]},fontSize:{xs:`0.75rem`,sm:`0.875rem`,base:`1rem`,lg:`1.125rem`,xl:`1.25rem`,"2xl":`1.5rem`,"3xl":`1.875rem`,"4xl":`2.25rem`},fontWeight:{normal:`400`,medium:`500`,semibold:`600`,bold:`700`},lineHeight:{tight:`1.25`,normal:`1.5`,relaxed:`1.75`}},sn=V.fontFamily.sans.join(`, `),cn=class{qrLib=null;dialog=null;async show(t){this.hide(),this.qrLib??=await Promise.resolve().then(()=>e.n(require(`./browser-CDLfpTNV.cjs`).default,1));let n=await this.qrLib.toDataURL(t,{width:256,margin:4,errorCorrectionLevel:`M`,color:{dark:z.black,light:z.white}});this.dialog=new rn({onClose:()=>{this.dialog=null}}),Object.assign(this.dialog.card.element.style,{display:`flex`,flexDirection:`column`,alignItems:`center`,gap:B[3],fontFamily:sn}),this.dialog.card.element.appendChild(this.createText(Ue(),{fontSize:V.fontSize.base,fontWeight:V.fontWeight.semibold,color:z.neutral[900]})),this.dialog.card.element.appendChild(this.createText(qe(),{fontSize:V.fontSize.sm,color:z.neutral[600]})),this.dialog.card.element.appendChild(this.createQrImage(n)),this.dialog.card.element.appendChild(this.createText(Ze(),{fontSize:V.fontSize.xs,color:z.neutral[500]}));let r=new R({variant:`outline`,label:tt(),onClick:()=>{this.hide()}});this.dialog.card.element.appendChild(r.element),this.dialog.open()}hide(){this.dialog?.close(),this.dialog=null}createText(e,t){let n=document.createElement(`p`);return n.textContent=e,Object.assign(n.style,{margin:`0`,textAlign:`center`,...t}),n}createQrImage(e){let t=document.createElement(`img`);return t.src=e,t.alt=`QR code`,Object.assign(t.style,{width:B[24],height:B[24],borderRadius:B[1]}),t}},H=V.fontFamily.sans.join(`, `),ln=`
2
+ :root {
3
+ --primary: oklch(5% 0 0);
4
+ --primary-foreground: oklch(100% 0 0);
5
+ --secondary: oklch(92% 0 0);
6
+ --secondary-foreground: oklch(5% 0 0);
7
+ --background: oklch(100% 0 0);
8
+ --foreground: oklch(5% 0 0);
9
+ --border: oklch(92% 0 0);
10
+ --ring: oklch(44% 0 0);
11
+ --radius: 0.625rem;
12
+ --accent: oklch(92% 0 0);
13
+ --accent-foreground: oklch(5% 0 0);
14
+ --muted-foreground: oklch(44% 0 0);
15
+ }
16
+
17
+ /* ── Button ──────────────────────────────────────────────── */
18
+ .ui-btn {
19
+ display: inline-flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ gap: 0.5rem;
23
+ border: 1px solid transparent;
24
+ border-radius: var(--radius);
25
+ font-family: ${H};
26
+ font-size: 0.875rem;
27
+ font-weight: 600;
28
+ white-space: nowrap;
29
+ cursor: pointer;
30
+ transition: all 200ms;
31
+ flex-shrink: 0;
32
+ }
33
+ .ui-btn:active { transform: scale(0.98); }
34
+ .ui-btn:disabled { opacity: 0.5; pointer-events: none; }
35
+ .ui-btn svg { inline-size: 1rem; block-size: 1rem; pointer-events: none; flex-shrink: 0; }
36
+
37
+ .ui-btn--default {
38
+ background: var(--primary);
39
+ color: var(--primary-foreground);
40
+ box-shadow: 0 1px 3px oklch(5% 0 0 / 20%);
41
+ }
42
+ .ui-btn--default:hover { background: oklch(10% 0 0); }
43
+
44
+ .ui-btn--outline {
45
+ background: var(--background);
46
+ color: var(--foreground);
47
+ border-color: var(--border);
48
+ box-shadow: 0 1px 2px oklch(5% 0 0 / 8%);
49
+ }
50
+ .ui-btn--outline:hover { background: var(--accent); border-color: oklch(85% 0 0); }
51
+
52
+ .ui-btn--secondary {
53
+ background: var(--secondary);
54
+ color: var(--secondary-foreground);
55
+ box-shadow: 0 1px 2px oklch(5% 0 0 / 8%);
56
+ }
57
+ .ui-btn--secondary:hover { background: oklch(88% 0 0); }
58
+
59
+ .ui-btn--ghost { background: transparent; color: var(--foreground); }
60
+ .ui-btn--ghost:hover { background: var(--accent); }
61
+
62
+ .ui-btn--size-default { block-size: 2.25rem; padding: 0 1rem; }
63
+ .ui-btn--size-sm { block-size: 2rem; padding: 0 0.75rem; border-radius: calc(var(--radius) - 0.125rem); }
64
+ .ui-btn--size-lg { block-size: 2.5rem; padding: 0 1.5rem; }
65
+ .ui-btn--size-icon { inline-size: 2.25rem; block-size: 2.25rem; padding: 0; }
66
+ .ui-btn--size-icon-sm { inline-size: 2rem; block-size: 2rem; padding: 0; }
67
+ .ui-btn--size-icon-lg { inline-size: 2.5rem; block-size: 2.5rem; padding: 0; }
68
+
69
+ /* ── Toggle group ────────────────────────────────────────── */
70
+ .ui-toggle-group { display: inline-flex; flex-wrap: wrap; gap: 0.25rem; }
71
+
72
+ .ui-toggle-group-item {
73
+ display: inline-flex;
74
+ align-items: center;
75
+ justify-content: center;
76
+ block-size: 2rem;
77
+ padding: 0 0.75rem;
78
+ border: 1px solid var(--border);
79
+ border-radius: var(--radius);
80
+ background: var(--background);
81
+ color: var(--foreground);
82
+ font-family: ${H};
83
+ font-size: 0.875rem;
84
+ font-weight: 600;
85
+ cursor: pointer;
86
+ white-space: nowrap;
87
+ transition: all 200ms;
88
+ box-shadow: 0 1px 2px oklch(5% 0 0 / 8%);
89
+ }
90
+ .ui-toggle-group-item:hover { background: var(--accent); border-color: oklch(85% 0 0); }
91
+ .ui-toggle-group-item:active { transform: scale(0.98); }
92
+ .ui-toggle-group-item[data-state="on"] {
93
+ background: var(--primary);
94
+ color: var(--primary-foreground);
95
+ border-color: var(--primary);
96
+ }
97
+ .ui-toggle-group-item[data-state="on"]:hover { background: oklch(10% 0 0); }
98
+
99
+ /* ── Native select ───────────────────────────────────────── */
100
+ .ui-native-select-wrap {
101
+ position: relative;
102
+ display: inline-flex;
103
+ min-inline-size: 8rem;
104
+ }
105
+
106
+ .ui-native-select {
107
+ display: block;
108
+ inline-size: 100%;
109
+ block-size: 2.25rem;
110
+ padding: 0 2.25rem 0 0.75rem;
111
+ border: 1px solid var(--border);
112
+ border-radius: var(--radius);
113
+ background: var(--background);
114
+ appearance: none;
115
+ color: var(--foreground);
116
+ font-family: ${H};
117
+ font-size: 0.875rem;
118
+ font-weight: 400;
119
+ cursor: pointer;
120
+ transition: color 200ms, box-shadow 200ms, border-color 200ms;
121
+ box-shadow: 0 1px 2px oklch(5% 0 0 / 8%);
122
+ }
123
+ .ui-native-select:hover { border-color: oklch(85% 0 0); }
124
+ .ui-native-select:focus-visible {
125
+ outline: none;
126
+ border-color: var(--ring);
127
+ box-shadow: 0 0 0 3px oklch(5% 0 0 / 12%);
128
+ }
129
+
130
+ .ui-native-select-icon {
131
+ position: absolute;
132
+ inset-block-start: 50%;
133
+ inset-inline-end: 0.625rem;
134
+ transform: translateY(-50%);
135
+ color: var(--muted-foreground);
136
+ pointer-events: none;
137
+ }
138
+
139
+ /* ── Annotation layer ───────────────────────────────────── */
140
+ .vd-annotations-layer {
141
+ position: absolute;
142
+ inset-block-start: 0;
143
+ inset-inline-start: 0;
144
+ inline-size: 100%;
145
+ block-size: 100%;
146
+ pointer-events: none;
147
+ overflow: visible !important; /* override CSS2DRenderer inline style */
148
+ }
149
+
150
+ .vd-annotation-marker {
151
+ display: flex;
152
+ align-items: center;
153
+ justify-content: center;
154
+ inline-size: 1.75rem;
155
+ block-size: 1.75rem;
156
+ border-radius: 50%;
157
+ border: 2px solid oklch(100% 0 0);
158
+ background: var(--primary);
159
+ color: var(--primary-foreground);
160
+ font-family: ${H};
161
+ font-size: 0.8125rem;
162
+ font-weight: 600;
163
+ cursor: pointer;
164
+ pointer-events: auto;
165
+ box-shadow: 0 2px 8px oklch(5% 0 0 / 20%);
166
+ transition: transform 100ms ease;
167
+ position: relative;
168
+ }
169
+ .vd-annotation-marker:hover { transform: scale(1.1); }
170
+
171
+ .vd-annotation-popup {
172
+ position: absolute;
173
+ inset-block-end: calc(100% + 0.5rem);
174
+ inset-inline-start: 50%;
175
+ transform: translateX(-50%);
176
+ background: var(--background);
177
+ color: var(--foreground);
178
+ border: 1px solid var(--border);
179
+ border-radius: var(--radius);
180
+ padding: 0.75rem 1rem;
181
+ max-inline-size: 15rem;
182
+ box-shadow: 0 4px 6px oklch(5% 0 0 / 8%), 0 2px 4px oklch(5% 0 0 / 6%);
183
+ pointer-events: auto;
184
+ white-space: normal;
185
+ }
186
+
187
+ @media (prefers-reduced-motion: no-preference) {
188
+ .vd-annotation-popup {
189
+ animation: vd-popup-in 150ms ease;
190
+ }
191
+ }
192
+
193
+ @keyframes vd-popup-in {
194
+ from { opacity: 0; transform: translateX(-50%) translateY(4px); }
195
+ to { opacity: 1; transform: translateX(-50%) translateY(0); }
196
+ }
197
+
198
+ .vd-annotation-popup-title {
199
+ font-family: ${H};
200
+ font-size: 0.875rem;
201
+ font-weight: 600;
202
+ line-height: 1.25rem;
203
+ }
204
+
205
+ .vd-annotation-popup-description {
206
+ font-family: ${H};
207
+ font-size: 0.8125rem;
208
+ font-weight: 400;
209
+ line-height: 1.125rem;
210
+ color: var(--muted-foreground);
211
+ margin-block-start: 0.25rem;
212
+ }
213
+ `,un=!1;function dn(){if(un||typeof document>`u`)return;un=!0;let e=document.createElement(`style`);e.id=`vd-ui-vanilla`,e.textContent=ln,document.head.appendChild(e)}function fn(e){let t=Math.max(0,Math.min(1,e));return t*t*(3-2*t)}function pn(e,t,n,r,i,a){let[o,s,c]=e,l=Math.cos(t),u=Math.sin(t),d=l*o+u*c,f=-u*o+l*c,p=Math.cos(n),m=Math.sin(n),h=p*s-m*f,g=m*s+p*f,_=.55;return[r+d*a*_,i-h*a*_,g]}function mn(e,t,n){e.beginPath(),e.moveTo(t[0],t[1]),e.lineTo(n[0],n[1]),e.strokeStyle=`#000`,e.lineWidth=2,e.stroke()}function hn(e,t,n,r,i){let a=t(n),o=t(r);mn(e,a,[a[0]+(o[0]-a[0])*i,a[1]+(o[1]-a[1])*i,a[2]])}var U=[-1,-1,1],W=[1,-1,1],G=[1,-1,-1],K=[-1,-1,-1],q=[-1,1,1],J=[1,1,1],Y=[1,1,-1],X=[-1,1,-1],gn=[[U,W],[W,G],[G,K],[K,U],[U,q],[W,J],[G,Y],[K,X],[q,J],[J,Y],[Y,X],[X,q]],_n=400,vn=`-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif`;function yn(){let e=document.createElement(`div`);Object.assign(e.style,{position:`absolute`,inset:`0`,display:`flex`,flexDirection:`column`,alignItems:`center`,justifyContent:`center`,background:`#fff`,zIndex:`20`,opacity:`0`,transition:`opacity 0.3s ease-in-out`});let t=document.createElement(`canvas`);Object.assign(t.style,{width:`100%`,height:`100%`,position:`absolute`,inset:`0`});let n=document.createElement(`div`);Object.assign(n.style,{position:`absolute`,top:`56%`,left:`0`,right:`0`,textAlign:`center`,pointerEvents:`none`});let r=document.createElement(`span`);Object.assign(r.style,{fontSize:`13px`,fontWeight:`400`,color:`#000`,fontVariantNumeric:`tabular-nums`,fontFamily:vn});let i=document.createElement(`span`);return Object.assign(i.style,{fontSize:`13px`,color:`#000`,fontFamily:vn}),i.textContent=M(),n.appendChild(r),n.appendChild(i),e.appendChild(t),e.appendChild(n),{overlay:e,canvas:t,pctEl:r,phaseEl:i}}var bn=class{overlay;canvas;ctx;pctEl;phaseEl;animationId=null;showTimerId=null;startTime;hidden=!1;visible=!1;constructor(e,t={}){this.startTime=performance.now();let n=yn();this.overlay=n.overlay,this.canvas=n.canvas,this.pctEl=n.pctEl,this.phaseEl=n.phaseEl,e.appendChild(this.overlay),this.ctx=this.canvas.getContext(`2d`),this.ctx!==null&&(this.sizeCanvas(),this.tick());let r=t.showDelay??_n;this.showTimerId=setTimeout(()=>{this.reveal()},r)}get loadingTexts(){return{downloading:M(),rendering:ft()}}updateProgress(e,t){this.hidden||(this.pctEl.textContent=`${Math.round(e)}%`,this.phaseEl.textContent=t===``?``:` \u00B7 ${t}`)}showError(e){if(this.hidden=!1,this.animationId!==null&&(cancelAnimationFrame(this.animationId),this.animationId=null),this.ctx!==null){let e=Math.min(devicePixelRatio,2),t=this.canvas.width/e,n=this.canvas.height/e;this.ctx.fillStyle=`#fff`,this.ctx.fillRect(0,0,t*e,n*e)}this.pctEl.textContent=``,this.phaseEl.textContent=e,this.phaseEl.style.color=`#b91c1c`,this.reveal()}hide(){if(!this.hidden){if(this.hidden=!0,this.cancelShowTimer(),!this.visible){this.destroy();return}this.overlay.style.opacity=`0`,this.overlay.addEventListener(`transitionend`,()=>{this.destroy()},{once:!0}),setTimeout(()=>{this.destroy()},500)}}destroy(){this.cancelShowTimer(),this.animationId!==null&&(cancelAnimationFrame(this.animationId),this.animationId=null),this.overlay.remove()}reveal(){this.hidden||this.visible||(this.visible=!0,this.overlay.style.opacity=`1`)}cancelShowTimer(){this.showTimerId!==null&&(clearTimeout(this.showTimerId),this.showTimerId=null)}sizeCanvas(){if(this.ctx===null)return;let e=Math.min(devicePixelRatio,2),t=this.overlay.clientWidth||440,n=this.overlay.clientHeight||360;this.canvas.width=t*e,this.canvas.height=n*e,this.ctx.scale(e,e),this.ctx.lineCap=`round`,this.ctx.lineJoin=`round`}tick=()=>{this.hidden||(this.drawFrame(),this.animationId=requestAnimationFrame(this.tick))};drawFrame(){if(this.ctx===null)return;let e=this.canvas.width/Math.min(devicePixelRatio,2),t=this.canvas.height/Math.min(devicePixelRatio,2),n=(performance.now()-this.startTime)/1e3;this.ctx.fillStyle=`#fff`,this.ctx.fillRect(0,0,e,t);let r=e/2,i=t*.44,a=Math.min(e,t)*.08,o=e=>pn(e,.785,.615,r,i,a),s=n%6/6,c=gn.length,l;l=s<.35?fn(s/.35)*c:s<.55?c:s<.9?(1-fn((s-.55)/.35))*c:0,this.ctx.shadowBlur=5,this.ctx.shadowColor=`rgba(30,30,30,0.08)`;for(let e=0;e<c&&!(e>=l);e++){let t=gn[e];if(t===void 0)continue;let n=Math.min(1,l-e);hn(this.ctx,o,t[0],t[1],n)}this.ctx.shadowBlur=0}},xn=class{element;arBtn=null;fullscreenBtn=null;onFullscreenChange;constructor(e){this.options=e,this.element=document.createElement(`div`),Object.assign(this.element.style,{display:`flex`,gap:`0.375rem`}),this.onFullscreenChange=()=>{this.setFullscreenIcon(document.fullscreenElement!==null)},document.addEventListener(`fullscreenchange`,this.onFullscreenChange)}setFullscreenIcon(e){this.fullscreenBtn!==null&&this.fullscreenBtn.setIcon(e?L.exitFullscreen():L.fullscreen())}syncButton(e,t,n){if(t&&e===null){let e=n();return this.element.appendChild(e.element),e}return!t&&e!==null?(e.element.remove(),null):e}applySettings(e){this.arBtn=this.syncButton(this.arBtn,e.ar!==!1&&this.options.onAr!==void 0,()=>new R({variant:`outline`,size:`icon`,label:ze(),icon:L.ar(),onClick:()=>{this.options.onAr?.()}})),this.fullscreenBtn=this.syncButton(this.fullscreenBtn,e.fullscreen!==!1&&this.options.onFullscreen!==void 0,()=>new R({variant:`outline`,size:`icon`,label:at(),icon:L.fullscreen(),onClick:()=>{this.options.onFullscreen?.()}}))}destroy(){document.removeEventListener(`fullscreenchange`,this.onFullscreenChange)}},Z=.5,Sn=class e{element;constructor(t,n){this.element=Object.assign(document.createElement(`div`),{className:`vd-camera-controls`});let r={targetRotation:n.rotation,targetTilt:n.tilt,targetZoom:n.zoom,thetaOffset:0},i=Cn(t,n,r);n.onChange(e=>{r.targetRotation=e.rotation-r.thetaOffset,r.targetTilt=e.tilt,r.targetZoom=e.zoom,wn(i,n,e)}),this.element.appendChild(e.buildZoom(i.zoomOut,i.zoomIn)),this.element.appendChild(e.buildDpad(i.tiltUp,i.rotateLeft,i.reset,i.rotateRight,i.tiltDown))}static buildZoom(e,t){let n=document.createElement(`div`);return n.className=`vd-zoom`,n.appendChild(e.element),n.appendChild(t.element),n}static buildDpad(e,t,n,r,i){let a=document.createElement(`div`);a.className=`vd-dpad`;for(let[o,s]of[[e,`up`],[t,`left`],[n,`center`],[r,`right`],[i,`down`]])o.element.classList.add(`vd-dpad-${s}`),a.appendChild(o.element);return a}};function Cn(e,t,n){let r=e=>Math.max(t.limits?.minZoom??1,Math.min(t.limits?.maxZoom??1/0,e)),i=e=>{let n=t.limits?.minRotate,r=t.limits?.maxRotate;return n!==void 0||r!==void 0?Math.max(n??-1/0,Math.min(r??1/0,e)):e},a=r=>{let i=t.limits?.minTilt,a=t.limits?.maxTilt;if(i!==void 0||a!==void 0){n.targetTilt=Math.max(i??0,Math.min(a??180,n.targetTilt+r)),e.tilt(n.targetTilt).set();return}let o=n.targetTilt+r;o>180||o<0?(n.targetTilt=o>180?360-o:-o,n.thetaOffset=(n.thetaOffset+180)%360,e.tilt(n.targetTilt).rotate(n.targetRotation+n.thetaOffset).set()):(n.targetTilt=o,e.tilt(n.targetTilt).set())};return{zoomOut:new R({variant:`outline`,size:`icon`,label:Ot(),icon:L.zoomOut(),onClick:()=>{n.targetZoom=r(n.targetZoom-10),e.zoom(n.targetZoom).set()}}),zoomIn:new R({variant:`outline`,size:`icon`,label:wt(),icon:L.zoomIn(),onClick:()=>{n.targetZoom=r(n.targetZoom+10),e.zoom(n.targetZoom).set()}}),tiltUp:new R({variant:`outline`,size:`icon`,label:Bt(),icon:L.tiltUp(),onClick:()=>{a(-15)}}),rotateLeft:new R({variant:`outline`,size:`icon`,label:Mt(),icon:L.rotateLeft(),onClick:()=>{n.targetRotation=i(n.targetRotation-15),e.rotate(n.targetRotation+n.thetaOffset).set()}}),reset:new R({variant:`outline`,size:`icon`,label:bt(),icon:L.reset(),onClick:()=>{n.thetaOffset=0,e.reset()}}),rotateRight:new R({variant:`outline`,size:`icon`,label:It(),icon:L.rotateRight(),onClick:()=>{n.targetRotation=i(n.targetRotation+15),e.rotate(n.targetRotation+n.thetaOffset).set()}}),tiltDown:new R({variant:`outline`,size:`icon`,label:Wt(),icon:L.tiltDown(),onClick:()=>{a(15)}})}}function wn(e,t,n){let r=t.limits;r!==void 0&&(e.zoomOut.element.disabled=r.minZoom!==void 0&&n.zoom<=r.minZoom+Z,e.zoomIn.element.disabled=r.maxZoom!==void 0&&n.zoom>=r.maxZoom-Z,e.tiltUp.element.disabled=r.minTilt!==void 0&&n.tilt<=r.minTilt+Z,e.tiltDown.element.disabled=r.maxTilt!==void 0&&n.tilt>=r.maxTilt-Z,e.rotateLeft.element.disabled=r.minRotate!==void 0&&n.rotation<=r.minRotate+Z,e.rotateRight.element.disabled=r.maxRotate!==void 0&&n.rotation>=r.maxRotate-Z)}var Tn=5;function Q(e){let t=e.replace(/([A-Z])/g,` $1`).trim();return t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()}function En(e,t,n,r,i){let a=document.createElement(`div`);a.className=`vd-attribute`,a.dataset.name=e.name;let o=document.createElement(`span`);o.className=`vd-attribute-label`,o.textContent=Q(e.name),a.appendChild(o);let s=e.values.find(n=>t.getValue(e.name,n)?.isSelected===!0),c=e.values.map(Q),l=e.values.length<=Tn?new an(e.values,s,c):new on(e.name,e.values,Q(e.name),s,c);return l.onSelect(t=>{n.dispatch(`ui:select`,{attribute:e.name,value:t},!0).defaultPrevented||r(e.name,t)}),i(e.name,t=>{l.setSelected(t.value),n.dispatch(`ui:selected`,{attribute:e.name,value:t.value})}),a.appendChild(l.element),a}var Dn=V.fontFamily.sans.join(`, `),$=`
214
+ position: absolute;
215
+ display: flex;
216
+ z-index: 10;
217
+ `,On=`
218
+ /* Override browser's default black fullscreen backdrop */
219
+ .vd-container:fullscreen {
220
+ background: oklch(100% 0 0);
221
+ }
222
+
223
+ /* Layout slots — four corners */
224
+ .vd-slot-top-right {
225
+ ${$}
226
+ inset-block-start: ${B[3]};
227
+ inset-inline-end: ${B[3]};
228
+ flex-direction: column;
229
+ align-items: flex-end;
230
+ gap: ${B[1.5]};
231
+ }
232
+
233
+ .vd-slot-bottom-left {
234
+ ${$}
235
+ inset-block-end: ${B[3]};
236
+ inset-inline-start: ${B[3]};
237
+ flex-direction: column;
238
+ align-items: flex-start;
239
+ gap: ${B[1.5]};
240
+ }
241
+
242
+ .vd-slot-bottom-right {
243
+ ${$}
244
+ inset-block-end: ${B[3]};
245
+ inset-inline-end: ${B[3]};
246
+ flex-direction: row;
247
+ gap: ${B[1.5]};
248
+ }
249
+
250
+ /* Component styles — no positioning */
251
+ .vd-camera-controls {
252
+ display: flex;
253
+ flex-direction: column;
254
+ gap: ${B[1]};
255
+ background: color-mix(in oklch, ${z.white} 85%, transparent);
256
+ backdrop-filter: blur(8px);
257
+ border-radius: ${B[2]};
258
+ padding: ${B[2]};
259
+ }
260
+
261
+ .vd-zoom {
262
+ display: flex;
263
+ gap: ${B[.5]};
264
+ }
265
+
266
+ .vd-dpad {
267
+ display: grid;
268
+ grid-template-columns: repeat(3, ${B[9]});
269
+ grid-template-rows: repeat(3, ${B[9]});
270
+ gap: ${B[.5]};
271
+ }
272
+
273
+ .vd-dpad-up { grid-column: 2; grid-row: 1; }
274
+ .vd-dpad-left { grid-column: 1; grid-row: 2; }
275
+ .vd-dpad-center { grid-column: 2; grid-row: 2; }
276
+ .vd-dpad-right { grid-column: 3; grid-row: 2; }
277
+ .vd-dpad-down { grid-column: 2; grid-row: 3; }
278
+
279
+ .vd-attributes {
280
+ display: flex;
281
+ flex-direction: column;
282
+ gap: ${B[2]};
283
+ background: color-mix(in oklch, ${z.white} 85%, transparent);
284
+ backdrop-filter: blur(8px);
285
+ border-radius: ${B[2]};
286
+ padding: ${B[2]};
287
+ font-family: ${Dn};
288
+ }
289
+
290
+ .vd-attribute {
291
+ display: flex;
292
+ flex-direction: column;
293
+ gap: ${B[1]};
294
+ }
295
+
296
+ .vd-attribute-label {
297
+ font-size: ${V.fontSize.xs};
298
+ font-weight: ${V.fontWeight.medium};
299
+ color: ${z.neutral[900]};
300
+ font-family: ${Dn};
301
+ }
302
+
303
+ `;function kn(){if(dn(),document.getElementById(`vd-styles`)!==null)return;let e=document.createElement(`style`);e.id=`vd-styles`,e.textContent=On,document.head.appendChild(e)}function An(e,t){let n=document.createElement(`a`);n.href=`data:image/png;base64,${e}`,n.download=t,n.click()}var jn=class{options;settings={};container=null;loading=null;slots={topRight:null,bottomLeft:null,bottomRight:null};screenshotBtn=null;actionBar=null;cameraControls=null;attributes=null;constructor(e){this.options=e}attach(e){kn(),this.container=e,this.loading=new bn(e),this.slots.topRight=this.createSlot(e,`vd-slot-top-right`),this.slots.bottomLeft=this.createSlot(e,`vd-slot-bottom-left`),this.slots.bottomRight=this.createSlot(e,`vd-slot-bottom-right`)}onReady(){this.loading?.hide(),this.loading=null,this.mountToolbar(),this.cameraControls!==null&&(this.cameraControls.element.style.display=`flex`),this.attributes!==null&&(this.attributes.style.display=`flex`)}mountToolbar(){if(this.actionBar!==null||this.slots.bottomRight===null||this.container===null)return;let e=typeof this.container.requestFullscreen==`function`;this.actionBar=new xn({onAr:this.options.onAr,onFullscreen:e?()=>{this.toggleFullscreen()}:void 0}),this.actionBar.applySettings(this.settings),this.slots.bottomRight.appendChild(this.actionBar.element),this.syncScreenshotButton(),this.placeScreenshotButton()}toggleFullscreen(){this.container!==null&&(document.fullscreenElement===null?this.container.requestFullscreen():document.exitFullscreen())}updateProgress(e,t){this.loading?.updateProgress(e,t)}showError(e){this.loading?.showError(e)}applyViewerSettings(e){this.settings=e,e.language!==void 0&&O(e.language,{reload:!1}),this.syncScreenshotButton(),this.actionBar?.applySettings(e),this.cameraControls!==null&&(this.cameraControls.element.style.display=e.cameraControls===!0?`flex`:`none`),this.placeScreenshotButton()}renderAttributeControls(e,t){if(!(this.container===null||this.slots.topRight===null)&&(this.cameraControls?.element.remove(),this.cameraControls=null,this.attributes?.remove(),this.attributes=null,this.settings.cameraControls===!0&&(this.cameraControls=new Sn(this.options.cameraApi,this.options.cameraPositionApi),this.cameraControls.element.style.display=`none`,this.slots.topRight.appendChild(this.cameraControls.element)),this.placeScreenshotButton(),!(t.length===0||this.settings.attributeControls===!1))){this.attributes=document.createElement(`div`),this.attributes.className=`vd-attributes`,this.attributes.style.display=`none`;for(let n of t)this.attributes.appendChild(En(n,e,this.options.eventBus,this.options.onSelect,this.options.onSubscribe));this.slots.bottomLeft.appendChild(this.attributes)}}get viewerSettings(){return this.settings}destroy(){this.loading?.destroy(),this.screenshotBtn?.element.remove(),this.actionBar?.destroy(),this.actionBar?.element.remove(),this.cameraControls?.element.remove(),this.attributes?.remove();for(let e of Object.values(this.slots))e?.remove();this.container=null}createSlot(e,t){let n=document.createElement(`div`);return n.className=t,e.appendChild(n),n}syncScreenshotButton(){let e=this.settings.screenshot===!0;e&&this.screenshotBtn===null&&(this.screenshotBtn=new R({variant:`outline`,size:`icon`,label:gt(),icon:L.screenshot(),onClick:()=>{this.options.snapshotApi.take(`snapshot.png`).onDeveloped(({data:e,filename:t})=>{An(e,t)})}})),!e&&this.screenshotBtn!==null&&(this.screenshotBtn.element.remove(),this.screenshotBtn=null)}placeScreenshotButton(){this.screenshotBtn===null||this.slots.topRight===null||(this.cameraControls===null?this.slots.topRight.appendChild(this.screenshotBtn.element):this.cameraControls.element.appendChild(this.screenshotBtn.element))}},Mn=class{attributes;readyStateTracker;messenger;cameraApi;cameraPositionApi;snapshotApi;annotationsApi;eventBus;ui;qrModal;options;iframe;container;readyCallbacks=[];mutationFailedCallbacks=[];constructor(e){this.options=e,this.initializeLogging(),this.messenger=new ge(()=>this.iframe?.contentWindow??null);let t=e=>{this.messenger.send(e)};this.attributes=new ye(t,(e,t)=>{for(let n of this.mutationFailedCallbacks)n({attribute:e,value:t})}),this.snapshotApi=new Ce(t),this.annotationsApi=new S(t),this.cameraApi=new be(t),this.cameraPositionApi=new xe,this.eventBus=new we,this.qrModal=new cn,this.readyStateTracker=new ie(()=>{let e=this.readyCallbacks;this.readyCallbacks=[];for(let t of e)t(this);this.ui.onReady()}),this.ui=new jn({snapshotApi:this.snapshotApi,cameraApi:this.cameraApi,cameraPositionApi:this.cameraPositionApi,eventBus:this.eventBus,onSelect:(e,t)=>this.attributes.select(e,t),onSubscribe:(e,t)=>this.attributes.onChange(e,t),onAr:()=>{this.activateAr()}}),this.registerHandlers(),this.messenger.start(),this.createAndConnectIframe()}registerHandlers(){this.messenger.on(b.HANDSHAKE,e=>{se(e)&&(y.info(`Server handshake received, flushing publisher queue`),this.messenger.markReady())}),this.messenger.on(b.MUTATION,e=>{ce(e)&&this.attributes.handleMutationResult(e)}),this.messenger.on(b.SNAPSHOT,e=>{le(e)&&this.snapshotApi.handleSnapshotResult(e)}),this.messenger.on(b.CAMERA,e=>{ue(e)&&this.cameraPositionApi.handlePositionUpdate(e)}),this.messenger.on(b.LOADING_INDICATOR,e=>{fe(e)&&(e.error===void 0?this.ui.updateProgress(e.progress,e.phase):this.ui.showError(e.error))}),this.messenger.on(b.CONFIG,e=>{pe(e)&&this.handleConfig(e)}),this.messenger.on(b.ANNOTATION_PLACED,e=>{me(e)&&this.annotationsApi.handlePlaced(e.position)}),this.messenger.on(b.MAPPING,e=>{de(e)&&(this.attributes.handleMappingReceived(e),this.ui.renderAttributeControls(this.attributes,e.attributes),this.readyStateTracker.handleMappingReceived())})}handleConfig(e){let t=e.viewerSettings,n=this.options.viewerSettings;if(t!==void 0||n!==void 0){let e=n===void 0?t:{...t??{},...n};if(n!==void 0&&t!==void 0){let e=Object.entries(n).filter(([e,n])=>t[e]!==n).map(([e,n])=>`${e} (metadata: ${t[e]??`undefined`}, override: ${n})`);e.length>0&&y.warn(`Viewer settings override active: ${e.join(`, `)}`)}this.ui.applyViewerSettings(e),this.annotationsApi.setEnabled(e.annotations!==!1)}this.cameraPositionApi.applyLimits(e.cameraLimits)}activateAr(){if(h()){this.messenger.send({type:b.AR_ACTIVATE});return}this.qrModal.show(this.iframe?.src??``)}initializeLogging(){this.options.debug===!0&&ne(),y.info(`Initializing Virtualdisplay client`,{model:this.options.model})}createAndConnectIframe(){let e=new r(this.options).create();this.container=e.container,this.iframe=e.iframe,this.eventBus.attach(this.container),this.ui.attach(this.container);try{let e=new URL(this.iframe.src).origin;this.messenger.setTargetOrigin(e)}catch{}}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)}on(e,t){this.eventBus.on(e,t)}get annotations(){return this.annotationsApi}get camera(){return this.cameraApi}get cameraPosition(){return this.cameraPositionApi}get snapshot(){return this.snapshotApi}get viewerSettings(){return this.ui.viewerSettings}destroy(){this.readyStateTracker.clear(),this.readyCallbacks=[],this.messenger.destroy(),this.qrModal.hide(),this.ui.destroy(),this.container?.parentElement!==null&&this.container?.parentElement!==void 0&&this.container.parentElement.removeChild(this.container),this.container=void 0,this.iframe=void 0}};exports.Annotations=S,exports.Attribute=_e,exports.AttributeValue=C,exports.Camera=be,exports.ERROR_CODES=t,exports.Photo=Se,exports.Snapshot=Ce,exports.VirtualdisplayClient=Mn,exports.VirtualdisplayError=n,exports.enableDebugMode=ne,exports.isDebugMode=re,Object.defineProperty(exports,`logger`,{enumerable:!0,get:function(){return y}});