@virtualdisplay.io/client 4.0.0-alpha.3 → 4.0.0-alpha.30

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 (47) hide show
  1. package/CHANGELOG.md +218 -1
  2. package/README.md +116 -155
  3. package/dist/browser-DfB_An57.cjs +8 -0
  4. package/dist/browser-ey6Iih3j.js +1540 -0
  5. package/dist/index.d.ts +660 -0
  6. package/dist/virtualdisplay.client.cjs.js +606 -1
  7. package/dist/virtualdisplay.client.es.js +4113 -794
  8. package/dist/virtualdisplay.client.umd.js +613 -1
  9. package/package.json +3 -3
  10. package/dist/src/attributes/attribute.d.ts +0 -38
  11. package/dist/src/attributes/attribute.d.ts.map +0 -1
  12. package/dist/src/attributes/attributes.d.ts +0 -43
  13. package/dist/src/attributes/attributes.d.ts.map +0 -1
  14. package/dist/src/attributes/selections.d.ts +0 -16
  15. package/dist/src/attributes/selections.d.ts.map +0 -1
  16. package/dist/src/attributes/value.d.ts +0 -13
  17. package/dist/src/attributes/value.d.ts.map +0 -1
  18. package/dist/src/camera/camera.d.ts +0 -40
  19. package/dist/src/camera/camera.d.ts.map +0 -1
  20. package/dist/src/camera/index.d.ts +0 -4
  21. package/dist/src/camera/index.d.ts.map +0 -1
  22. package/dist/src/camera/position.d.ts +0 -43
  23. package/dist/src/camera/position.d.ts.map +0 -1
  24. package/dist/src/client/client.d.ts +0 -83
  25. package/dist/src/client/client.d.ts.map +0 -1
  26. package/dist/src/client/error.d.ts +0 -26
  27. package/dist/src/client/error.d.ts.map +0 -1
  28. package/dist/src/client/iframe-builder.d.ts +0 -25
  29. package/dist/src/client/iframe-builder.d.ts.map +0 -1
  30. package/dist/src/client/options.d.ts +0 -17
  31. package/dist/src/client/options.d.ts.map +0 -1
  32. package/dist/src/client/ready-state-tracker.d.ts +0 -26
  33. package/dist/src/client/ready-state-tracker.d.ts.map +0 -1
  34. package/dist/src/client/types.d.ts +0 -5
  35. package/dist/src/client/types.d.ts.map +0 -1
  36. package/dist/src/index.d.ts +0 -11
  37. package/dist/src/index.d.ts.map +0 -1
  38. package/dist/src/snapshot/index.d.ts +0 -3
  39. package/dist/src/snapshot/index.d.ts.map +0 -1
  40. package/dist/src/snapshot/photo.d.ts +0 -47
  41. package/dist/src/snapshot/photo.d.ts.map +0 -1
  42. package/dist/src/snapshot/snapshot.d.ts +0 -30
  43. package/dist/src/snapshot/snapshot.d.ts.map +0 -1
  44. package/dist/src/ui/viewer-config.d.ts +0 -63
  45. package/dist/src/ui/viewer-config.d.ts.map +0 -1
  46. package/dist/src/utils/logger.d.ts +0 -11
  47. package/dist/src/utils/logger.d.ts.map +0 -1
@@ -1 +1,606 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={NO_MAPPING:`NO_MAPPING`,ATTRIBUTE_NOT_FOUND:`ATTRIBUTE_NOT_FOUND`,VALUE_NOT_FOUND:`VALUE_NOT_FOUND`,PARENT_NOT_FOUND:`PARENT_NOT_FOUND`,INVALID_PARAMETER:`INVALID_PARAMETER`,SNAPSHOT_FAILED:`SNAPSHOT_FAILED`},t=class t extends Error{code;constructor(e,n){super(e),this.name=`VirtualdisplayError`,this.code=n,Error.captureStackTrace?.(this,t)}static noMapping(){return new t(`No attributes available. Waiting for server metadata.`,e.NO_MAPPING)}static attributeNotFound(n){return new t(`Attribute "${n}" not found in mapping`,e.ATTRIBUTE_NOT_FOUND)}static valueNotFound(n,r){return new t(`Value "${r}" not found for attribute "${n}"`,e.VALUE_NOT_FOUND)}static parentNotFound(n){return new t(`Parent element not found: ${n}`,e.PARENT_NOT_FOUND)}static invalidParameter(n){return new t(n,e.INVALID_PARAMETER)}static snapshotFailed(n,r){return new t(`Snapshot failed for "${n}": ${r}`,e.SNAPSHOT_FAILED)}},n=class{defaultServer=`https://server.virtualdisplay.io`;options;constructor(e){this.options=e}create(){let e=this.createIframe();return this.attachToParent(e),e}createIframe(){let e=document.createElement(`iframe`);return e.src=this.buildUrl(),Object.assign(e.style,{width:`100%`,height:`100%`,border:`none`}),e.setAttribute(`allow`,`xr-spatial-tracking; fullscreen`),e}attachToParent(e){this.getParentElement().appendChild(e)}buildUrl(){let e=this.getServerUrl(),t=new URL(e);return t.searchParams.set(`license`,this.options.license),t.searchParams.set(`model`,this.options.model),this.options.debug===!0&&t.searchParams.set(`debug`,`true`),this.options.language!==void 0&&t.searchParams.set(`language`,this.options.language),t.toString()}getServerUrl(){return this.defaultServer}getParentElement(){if(typeof this.options.parent!=`string`)return this.options.parent;let e=document.querySelector(this.options.parent);if(e===null)throw t.parentNotFound(this.options.parent);return e}};function r(e){let t=new Date(e.timestamp).toLocaleTimeString(`en-GB`,{hour12:!1}),n=e.level.toUpperCase().padEnd(5),r=e.trace_id?.slice(0,8)??`--------`,i=e.msg,a=[`timestamp`,`level`,`msg`,`service`,`trace_id`,`span_id`],o=Object.entries(e).filter(([e])=>!a.includes(e)).map(([e,t])=>`${e}=${JSON.stringify(t)}`).join(` `);return`${t} ${n} [${r}] ${i}${o?` `+o:``}`}function i(e){return JSON.stringify(e)}function a(e,t){let n=t?r(e):i(e);e.level===`error`?console.error(n):e.level===`warn`?console.warn(n):console.log(n)}function o(){return new Date}function s(e){return e.toISOString()}var c=class e{constructor(e){this.config=e}log(e,t,n={}){let r=this.config.traceProvider?.()??{};a({timestamp:s(o()),level:e,msg:t,service:this.config.service,...r,...n},this.config.isDev)}debug(e,t){this.config.isDev&&this.log(`debug`,e,t)}info(e,t){this.log(`info`,e,t)}warn(e,t){this.log(`warn`,e,t)}error(e,t){this.log(`error`,e,t)}with(t){let n=new e(this.config);return n.log=((e,n,r={})=>{this.log(e,n,{...t,...r})}).bind(this),n}};function l(e,t){return new c({service:e,isDev:t?.isDev===void 0?typeof process<`u`?process.env.NODE_ENV!==`production`:!0:t.isDev,traceProvider:t?.traceProvider})}function u(e){if(e!==void 0)return typeof e==`object`&&e&&!Array.isArray(e)&&!(e instanceof Error)?e:e instanceof Error?{error:e.message}:{value:e}}function d(e){return{debug:(t,n)=>e.debug(t,u(n)),info:(t,n)=>e.info(t,u(n)),warn:(t,n)=>e.warn(t,u(n)),error:(t,n)=>e.error(t,u(n))}}var f=!1,p=d(l(`client`,{isDev:!1}));function m(){f=!0,p=d(l(`client`,{isDev:!0}))}function h(){return f}var g=class{ready=!1;onReady;constructor(e){this.onReady=e}handleMappingReceived(){this.markReady(`Mapping received from server`)}handleMutationResult(e){e.isInitial&&this.markReady(`Initial mutations processed`)}get isReady(){return this.ready}clear(){this.ready=!1}markReady(e){this.ready||(this.ready=!0,p.info(`${e} - client is now ready`),this.onReady?.())}},_=class{isSelectedValue=!1;constructor(e,t){this.value=e,this.attribute=t}get isSelected(){return this.isSelectedValue}setSelected(e){this.isSelectedValue=e}},v=class{name;defaultValue;values;onSelect;onChangeCallback;constructor(e){this.name=e.name,this.defaultValue=e.defaultValue,this.onSelect=e.onSelect,this.values=this.createValues(e.values)}select(e){if(!this.values.has(e))throw t.valueNotFound(this.name,e);this.onSelect(this.name,e)}getValues(){return Array.from(this.values.values())}getValue(e){return this.values.get(e)}onChange(e){this.onChangeCallback=e}handleResult(e){let t;for(let n of this.values.values()){let r=n.value===e;n.setSelected(r),r&&(t=n)}t!==void 0&&this.onChangeCallback!==void 0&&this.onChangeCallback(t)}createValues(e){let t=new Map;for(let n of e){let e=new _(n,this.name);n===this.defaultValue&&e.setSelected(!0),t.set(n,e)}return t}},y=class{attributes=new Map;constructor(e,t,n){for(let n of e){let e=this.buildOptions(n,t);this.attributes.set(n.name,new v(e))}this.onMutationFailed=n}onMutationFailed;get(e){return this.attributes.get(e)}defaults(){let e=[];for(let t of this.attributes.values())t.defaultValue!==void 0&&e.push({name:t.name,value:t.defaultValue});return e}handleResults(e){for(let t of e){if(!t.success){this.onMutationFailed?.(t.name,t.value);continue}this.get(t.name)?.handleResult(t.value)}}buildOptions(e,t){let n={name:e.name,values:e.values,onSelect:(e,n)=>{t([{name:e,value:n}],!1)}};return e.defaultValue===void 0?n:{...n,defaultValue:e.defaultValue}}},b={READY:`ready`,MUTATION:`mutation`,STATE:`state`,CONFIG:`config`,CAMERA:`camera`,SNAPSHOT:`snapshot`,MAPPING:`mapping`},x=new Set(Object.values(b));function S(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.target==`string`?!1:typeof t.type==`string`&&x.has(t.type)}function C(e){let t=O(e);return t!==null&&t.type===b.READY}function w(e){let t=O(e);return t!==null&&t.type===b.MUTATION&&Array.isArray(t.results)}function T(e){let t=O(e);return t!==null&&t.type===b.SNAPSHOT&&(`data`in t||`error`in t)}function E(e){let t=O(e);return t!==null&&t.type===b.CAMERA&&Array.isArray(t.transforms)}function D(e){let t=O(e);return t!==null&&t.type===b.MAPPING&&Array.isArray(t.attributes)}function O(e){return typeof e!=`object`||!e?null:e}var k=class{pending=[];isReady=!1;constructor(e){this.processor=e}enqueue(e){if(this.isReady){this.processor(e);return}this.pending.push(e)}markReady(){if(this.isReady||(this.isReady=!0,this.pending.length===0))return;let e=[...this.pending];this.pending.length=0;for(let t of e)this.processor(t)}get ready(){return this.isReady}get pendingCount(){return this.pending.length}hasPending(e){return this.pending.some(t=>t.type===e)}clear(){this.pending.length=0}},A=class{handlers=new Map;publisher;consumer;shouldBuffer;listener=null;sourceId;constructor(e,t){this.getTarget=e,this.sourceId=`vd-${Math.random().toString(36).slice(2,8)}`,this.publisher=new k(e=>this.post(e)),this.consumer=new k(e=>this.routeToHandler(e)),this.shouldBuffer=t?.shouldBuffer??null,t?.bufferIncoming!==!0&&this.consumer.markReady()}on(e,t){this.handlers.set(e,t)}off(e){this.handlers.delete(e)}send(e){this.publisher.enqueue(e)}markReady(){this.publisher.markReady()}markConsumerReady(){this.consumer.markReady()}consumerHasPending(e){return this.consumer.hasPending(e)}start(){this.listener===null&&(this.listener=e=>{let{data:t}=e;if(!S(t)||t._source===this.sourceId)return;let n=t;if(this.shouldBuffer!==null&&!this.shouldBuffer(n)){this.routeToHandler(n);return}this.consumer.enqueue(n)},window.addEventListener(`message`,this.listener))}destroy(){this.listener!==null&&(window.removeEventListener(`message`,this.listener),this.listener=null),this.publisher.clear(),this.consumer.clear(),this.handlers.clear()}get ready(){return this.publisher.ready}get pendingCount(){return this.publisher.pendingCount}post(e){let t=this.getTarget();t!==null&&t.postMessage({...e,_source:this.sourceId},`*`)}routeToHandler(e){let t=this.handlers.get(e.type);if(t===void 0)return;let n=t(e);n instanceof Promise&&n.catch(t=>{let n=t instanceof Error?t.message:String(t);console.error(`Virtualdisplay: error handling ${e.type}: ${n}`)})}};new Set([b.CAMERA]);var j=class{registry;pendingCallbacks=[];constructor(e,t){this.send=e,this.onMutationFailed=t}handleMappingReceived(e){p.debug(`Initializing from server mapping`,{attributeCount:e.attributes.length}),this.registry=new y(e.attributes,(e,t)=>this.sendMutation(e,t),this.onMutationFailed);let t=this.registry.defaults();t.length>0&&this.sendMutation(t,!0),this.replayPendingCallbacks()}handleMutationResult(e){this.registry?.handleResults(e.results)}select(e,t){this.sendMutation([{name:e,value:t}],!1)}getValues(e){return this.registry?.get(e)?.getValues()??[]}getValue(e,t){return this.registry?.get(e)?.getValue(t)}onChange(e,t){if(this.registry===void 0){this.pendingCallbacks.push({name:e,callback:t});return}let n=this.registry.get(e);if(n===void 0){p.warn(`onChange: attribute "${e}" not found — callback will not fire`);return}n.onChange(t)}getAttribute(e){return this.registry?.get(e)}get hasMapping(){return this.registry!==void 0}sendMutation(e,t){let n={type:b.MUTATION,mutations:e,isInitial:t};this.send(n)}replayPendingCallbacks(){for(let{name:e,callback:t}of this.pendingCallbacks){let n=this.registry?.get(e);n===void 0&&p.warn(`onChange: attribute "${e}" not found — buffered callback will not fire`),n?.onChange(t)}this.pendingCallbacks.length=0}},M=class{commands=[];constructor(e){this.send=e}rotate(e){return this.validateFiniteNumber(e,`rotate`),this.commands.push({action:`rotate`,value:e}),this}tilt(e){return this.validateFiniteNumber(e,`tilt`),this.commands.push({action:`tilt`,value:e}),this}zoom(e){return this.validateFiniteNumber(e,`zoom`),this.commands.push({action:`zoom`,value:e}),this}set(){if(this.commands.length===0)throw t.invalidParameter(`No camera commands to execute. Call rotate(), tilt(), or zoom() before set().`);let e={type:b.CAMERA,commands:this.commands};this.send(e),this.commands=[]}validateFiniteNumber(e,n){if(!Number.isFinite(e))throw t.invalidParameter(`${n}() requires a finite number, got ${String(e)}`)}reset(){let e={type:b.CAMERA,commands:[{action:`reset`}]};this.send(e)}},N=class{state;changeCallbacks=[];constructor(){this.state={rotation:0,tilt:0,zoom:0}}get rotation(){return this.state.rotation}get tilt(){return this.state.tilt}get zoom(){return this.state.zoom}onChange(e){this.changeCallbacks.push(e)}handlePositionUpdate(e){this.update(e.transforms)}update(e){let t=!1;for(let n of e)switch(n.type){case`rotation`:this.state.rotation=n.value,t=!0;break;case`tilt`:this.state.tilt=n.value,t=!0;break;case`zoom`:this.state.zoom=n.value,t=!0;break;default:break}if(t){let e={rotation:this.rotation,tilt:this.tilt,zoom:this.zoom};for(let t of this.changeCallbacks)t(e)}}},P=class{developedCallbacks=new Set;errorCallbacks=new Set;developed=!1;failed=!1;photoData=null;constructor(e){this.filename=e}onDeveloped(e){return this.developed&&this.photoData!==null?(e(this.photoData),this):(this.developedCallbacks.add(e),this)}onError(e){return this.errorCallbacks.add(e),this}getFilename(){return this.filename}develop(e){this.developed||this.failed||(this.photoData=e,this.developed=!0,this.developedCallbacks.forEach(e=>{e(this.photoData)}),this.developedCallbacks.clear(),this.errorCallbacks.clear())}fail(e){this.developed||this.failed||(this.failed=!0,this.errorCallbacks.forEach(t=>{t(e)}),this.developedCallbacks.clear(),this.errorCallbacks.clear())}},F=class{validExtensions=[`.png`];pendingPhotos=new Map;constructor(e){this.send=e}take(e){this.validateFilename(e),p.debug(`Taking snapshot`,{filename:e});let t=new P(e);return this.pendingPhotos.set(t.getFilename(),t),this.send({type:b.SNAPSHOT,filename:e}),t}handleSnapshotResult(n){let r=this.pendingPhotos.get(n.filename);if(r===void 0){p.warn(`No pending photo found for filename`,{filename:n.filename,pendingFilenames:Array.from(this.pendingPhotos.keys())});return}if(this.pendingPhotos.delete(n.filename),n.error!==void 0){r.fail(new t(n.error,e.SNAPSHOT_FAILED));return}n.data!==void 0&&r.develop({filename:n.filename,data:n.data})}validateFilename(n){if(n===``||typeof n!=`string`)throw new t(`Filename must be a non-empty string`,e.INVALID_PARAMETER);if(!this.validExtensions.some(e=>n.toLowerCase().endsWith(e)))throw new t(`Invalid filename: "${n}". Filename must end with one of: ${this.validExtensions.join(`, `)}`,e.INVALID_PARAMETER);if(n.includes(`..`)||n.includes(`/`)||n.includes(`\\`))throw new t(`Filename cannot contain path separators or ".."`,e.INVALID_PARAMETER)}},I=class{send;constructor(e){this.send=e}sendInitialConfig(e){let t=this.buildUIConfig(e),n=this.buildViewerConfig(t,e.camera);n!==void 0&&this.sendConfig(n)}buildUIConfig(e){let t=this.extractUIValues(e);if(Object.values(t).some(e=>e!==void 0))return{...t.arEnabled!==void 0&&{arEnabled:t.arEnabled},...t.fullscreenEnabled!==void 0&&{fullscreenEnabled:t.fullscreenEnabled},...t.loadingIndicatorEnabled!==void 0&&{loadingIndicatorEnabled:t.loadingIndicatorEnabled}}}extractUIValues(e){return{arEnabled:e.arEnabled??e.ui?.arEnabled,fullscreenEnabled:e.fullscreenEnabled??e.ui?.fullscreenEnabled,loadingIndicatorEnabled:e.loadingIndicatorEnabled??e.ui?.loadingIndicatorEnabled}}buildViewerConfig(e,t){if(!(e===void 0&&t===void 0))return{...e!==void 0&&{ui:e},...t!==void 0&&{camera:t}}}setArEnabled(e){p.debug(`Setting AR button enabled: ${e}`),this.updateUIConfig({arEnabled:e})}setFullscreenEnabled(e){p.debug(`Setting fullscreen button enabled: ${e}`),this.updateUIConfig({fullscreenEnabled:e})}setLoadingIndicatorEnabled(e){p.debug(`Setting loading indicator enabled: ${e}`),this.updateUIConfig({loadingIndicatorEnabled:e})}updateUIConfig(e){p.debug(`Updating UI configuration`,e),Object.keys(e).length>0&&this.sendConfig({ui:e})}hideAllUI(){p.debug(`Hiding all UI elements`),this.sendUIConfig({arEnabled:!1,fullscreenEnabled:!1,loadingIndicatorEnabled:!1})}showAllUI(){p.debug(`Showing all UI elements`),this.sendUIConfig({arEnabled:!0,fullscreenEnabled:!0,loadingIndicatorEnabled:!0})}sendUIConfig(e){this.sendConfig({ui:e})}sendConfig(e){let t={type:b.CONFIG,config:e};p.debug(`Sending config`,t),this.send(t)}},L=class{attributes;readyStateTracker;messenger;viewerService;cameraApi;cameraPositionApi;snapshotApi;options;iframe;readyCallbacks=[];mutationFailedCallbacks=[];constructor(e){this.options=e,this.initializeLogging(),this.messenger=new A(()=>this.iframe?.contentWindow??null);let t=e=>{this.messenger.send(e)};this.attributes=new j(t,(e,t)=>{for(let n of this.mutationFailedCallbacks)n({attribute:e,value:t})}),this.readyStateTracker=new g(()=>{let e=this.readyCallbacks;this.readyCallbacks=[];for(let t of e)t(this)}),this.viewerService=new I(t),this.cameraApi=new M(t),this.cameraPositionApi=new N,this.snapshotApi=new F(t),this.registerHandlers(),this.messenger.start(),this.createAndConnectIframe()}registerHandlers(){this.messenger.on(b.READY,e=>{C(e)&&(p.info(`Server ready — flushing publisher queue`),this.messenger.markReady(),this.viewerService.sendInitialConfig(this.options))}),this.messenger.on(b.MUTATION,e=>{w(e)&&(this.attributes.handleMutationResult(e),this.readyStateTracker.handleMutationResult(e))}),this.messenger.on(b.SNAPSHOT,e=>{T(e)&&this.snapshotApi.handleSnapshotResult(e)}),this.messenger.on(b.CAMERA,e=>{E(e)&&this.cameraPositionApi.handlePositionUpdate(e)}),this.messenger.on(b.MAPPING,e=>{D(e)&&(this.attributes.handleMappingReceived(e),this.readyStateTracker.handleMappingReceived())})}initializeLogging(){this.options.debug===!0&&m(),p.info(`Initializing Virtualdisplay client`,{model:this.options.model,debug:this.options.debug,language:this.options.language})}createAndConnectIframe(){p.debug(`Creating iframe for Virtualdisplay viewer`),this.iframe=new n(this.options).create(),p.debug(`Iframe created, waiting for server READY`)}select(e,t){this.attributes.select(e,t)}getValues(e){return this.attributes.getValues(e)}getValue(e,t){return this.attributes.getValue(e,t)}onChange(e,t){this.attributes.onChange(e,t)}getAttribute(e){return this.attributes.getAttribute(e)}get isReady(){return this.readyStateTracker.isReady}onReady(e){if(this.readyStateTracker.isReady){e(this);return}this.readyCallbacks.push(e)}onMutationFailed(e){this.mutationFailedCallbacks.push(e)}get viewer(){return this.viewerService}get camera(){return this.cameraApi}get cameraPosition(){return this.cameraPositionApi}get snapshot(){return this.snapshotApi}destroy(){p.info(`Destroying Virtualdisplay client`),this.readyStateTracker.clear(),this.readyCallbacks=[],this.messenger.destroy(),this.iframe?.parentElement!==null&&this.iframe?.parentElement!==void 0&&this.iframe.parentElement.removeChild(this.iframe),this.iframe=void 0,p.debug(`Virtualdisplay client destroyed`)}};exports.Attribute=v,exports.AttributeValue=_,exports.Camera=M,exports.ERROR_CODES=e,exports.Photo=P,exports.Snapshot=F,exports.VirtualdisplayClient=L,exports.VirtualdisplayError=t,exports.VirtualdisplayViewerService=I,exports.enableDebugMode=m,exports.isDebugMode=h,Object.defineProperty(exports,`logger`,{enumerable:!0,get:function(){return p}});
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c={HANDSHAKE:"handshake",SESSION:"session",MUTATION:"mutation",STATE:"state",LOADING_INDICATOR:"loading_indicator",CAMERA:"camera",SNAPSHOT:"snapshot",MAPPING:"mapping",AR_ACTIVATE:"ar_activate",FULLSCREEN:"fullscreen",CONFIG:"config",ANNOTATION_TOGGLE:"annotation_toggle",FOCUS:"focus",PRICING:"pricing",QR_SHOWN:"qr_shown",SYNC:"sync",SELECTABLE:"selectable",APP_RESOLVED:"app_resolved"},O="main",tt={FOCUS:"focus",UNFOCUS:"unfocus"},Bt={FOCUSED:"focused"},mt={AVAILABLE:"available",VIEW_ONLY:"view_only",HIDDEN:"hidden"},Ut=new Set(Object.values(c));function Vt(n){if(typeof n!="object"||n===null)return!1;const t=n;return typeof t.target=="string"?!1:typeof t.type=="string"&&Ut.has(t.type)}function Ht(n){const t=w(n);return t!==null&&t.type===c.HANDSHAKE}function jt(n){const t=w(n);return t!==null&&t.type===c.SESSION&&typeof t.sessionId=="string"}function qt(n){const t=w(n);return t!==null&&t.type===c.APP_RESOLVED&&typeof t.appType=="string"&&t.appType!==""&&typeof t.name=="string"}function Gt(n){const t=w(n);return t!==null&&t.type===c.MUTATION&&typeof t.instance=="string"&&t.instance!==""&&Array.isArray(t.results)}function Zt(n){const t=w(n);return t!==null&&t.type===c.SNAPSHOT&&("data"in t||"error"in t)}function Wt(n){const t=w(n);return t!==null&&t.type===c.CAMERA&&Array.isArray(t.transforms)}function Yt(n){const t=w(n);return t!==null&&t.type===c.MAPPING&&typeof t.instance=="string"&&t.instance!==""&&Array.isArray(t.attributes)}function Qt(n){const t=w(n);return t!==null&&t.type===c.LOADING_INDICATOR&&typeof t.progress=="number"}function Kt(n){const t=w(n);return t!==null&&t.type===c.SYNC&&typeof t.connected=="boolean"}function Xt(n){const t=w(n);return t!==null&&t.type===c.SELECTABLE&&typeof t.instance=="string"&&t.instance!==""&&Array.isArray(t.attributes)}function Jt(n){const t=w(n);return t!==null&&t.type===c.CONFIG&&typeof t.viewerSettings=="object"}function te(n){const t=w(n);return t!==null&&t.type===c.FOCUS&&typeof t.instance=="string"&&t.instance!==""&&typeof t.state=="string"}function ee(n){const t=w(n);return t!==null&&t.type===c.PRICING&&typeof t.instance=="string"&&t.instance!==""&&typeof t.pricing=="object"&&t.pricing!==null}function w(n){return typeof n!="object"||n===null?null:n}class et{constructor(t){this.processor=t}processor;pending=[];isReady=!1;enqueue(t){if(this.isReady){this.processor(t);return}this.pending.push(t)}markReady(){if(this.isReady||(this.isReady=!0,this.pending.length===0))return;const t=[...this.pending];this.pending.length=0;for(const e of t)this.processor(e)}get ready(){return this.isReady}get pendingCount(){return this.pending.length}hasPending(t){return this.pending.some(e=>e.type===t)}clear(){this.pending.length=0}}class ne{constructor(t,e){this.getTarget=t,this.sourceId=`vd-${Math.random().toString(36).slice(2,8)}`,this.targetOrigin="*",this.isValid=e?.isValid??Vt,this.onHandlerError=e?.onHandlerError??ie,this.publisher=new et(i=>this.post(i)),this.consumer=new et(i=>this.routeToHandler(i)),e?.bufferIncoming!==!0&&this.consumer.markReady()}getTarget;handlers=new Map;publisher;consumer;listener=null;sourceId;targetOrigin;isValid;onHandlerError;on(t,e){this.handlers.set(t,e)}setTargetOrigin(t){this.targetOrigin=t}send(t){this.publisher.enqueue(t)}receive(t){this.isValid(t)&&this.consumer.enqueue(t)}markReady(){this.publisher.markReady()}markConsumerReady(){this.consumer.markReady()}consumerHasPending(t){return this.consumer.hasPending(t)}start(){this.listener===null&&(this.listener=t=>{const{data:e}=t;if(!this.isValid(e)||e._source===this.sourceId)return;const i=this.getTarget();if(i!==null&&t.source!==null&&t.source!==i)return;const o=e;this.consumer.enqueue(o)},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()}post(t){const e=this.getTarget();e!==null&&e.postMessage({...t,_source:this.sourceId},this.targetOrigin)}routeToHandler(t){const e=this.handlers.get(t.type);if(e===void 0)return;const i=e(t);i instanceof Promise&&i.catch(o=>{this.onHandlerError(t,o)})}}function ie(n,t){const e=t instanceof Error?t.message:String(t);console.error(`Virtualdisplay: error handling ${n.type}: ${e}`)}class ft{constructor(t,e){this.send=t,this.instance=e}send;instance;setEnabled(t){this.send({type:c.ANNOTATION_TOGGLE,instance:this.instance,enabled:t})}}class gt{constructor(t,e){this.value=t,this.attribute=e}value;attribute;isSelectedValue=!1;get isSelected(){return this.isSelectedValue}setSelected(t){this.isSelectedValue=t}}const _={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 b extends Error{code;constructor(t,e){super(t),this.name="VirtualdisplayError",this.code=e}static valueNotFound(t,e){return new b(`Value "${e}" not found for attribute "${t}"`,_.VALUE_NOT_FOUND)}static parentNotFound(t){return new b(`Parent element not found: ${t}`,_.PARENT_NOT_FOUND)}static invalidParameter(t){return new b(t,_.INVALID_PARAMETER)}}class bt{name;defaultValue;values;onSelect;onChangeCallback;constructor(t){this.name=t.name,this.defaultValue=t.defaultValue,this.onSelect=t.onSelect,this.values=this.createValues(t.values)}select(t){if(!this.values.has(t))throw b.valueNotFound(this.name,t);this.onSelect(this.name,t)}getValues(){return Array.from(this.values.values())}getValue(t){return this.values.get(t)}get selected(){for(const t of this.values.values())if(t.isSelected)return t.value}onChange(t){this.onChangeCallback=t}handleResult(t){let e;for(const i of this.values.values()){const o=i.value===t;i.setSelected(o),o&&(e=i)}e!==void 0&&this.onChangeCallback!==void 0&&this.onChangeCallback(e)}createValues(t){const e=new Map;for(const i of t){const o=new gt(i,this.name);i===this.defaultValue&&o.setSelected(!0),e.set(i,o)}return e}}class oe{attributes=new Map;constructor(t,e,i){for(const o of t){const s=this.buildOptions(o,e);this.attributes.set(o.name,new bt(s))}this.onMutationFailed=i}onMutationFailed;get(t){return this.attributes.get(t)}getSelection(){const t={};for(const[e,i]of this.attributes){const o=i.selected;o!==void 0&&(t[e]=o)}return t}handleResults(t){for(const e of t){if(!e.success){this.onMutationFailed?.(e.name,e.value);continue}this.get(e.name)?.handleResult(e.value)}}buildOptions(t,e){const i={name:t.name,values:t.values,onSelect:(o,s)=>{e([{name:o,value:s}],!1)}};return t.defaultValue!==void 0?{...i,defaultValue:t.defaultValue}:i}}const M=4096,F=16384,se=[1024,256,64],re=20,W=["timestamp","level","msg","service","trace_id","span_id"];function ae(n){const t=new Date(n.timestamp).toLocaleTimeString("en-GB",{hour12:!1}),e=n.level.toUpperCase().padEnd(5),i=n.trace_id?.slice(0,8)??"--------",o=n.msg,s=Object.entries(n).filter(([r])=>!W.includes(r)).map(([r,a])=>`${r}=${I(a,M).line}`).join(" ");return`${t} ${e} [${i}] ${o}${s?" "+s:""}`}function le(n){for(const o of[M,...se]){const{line:s,truncated:r}=I(n,o);if(!r){if(s.length<=F)return s;continue}const{line:a}=I({...n,log_truncated:!0},o);if(a.length<=F)return a}const t=Object.keys(n).filter(o=>!W.includes(o)),e={...ue(n,W),log_truncated:!0,log_dropped_count:t.length},i=I({...e,log_dropped_attrs:t.slice(0,re)},M);return i.line.length<=F?i.line:I(e,M).line}function I(n,t){const e=[];let i=!1;return{line:JSON.stringify(n,function(r,a){if(typeof a=="string")return a.length>t&&(i=!0),ce(a,t);if(typeof a=="bigint")return a.toString();if(typeof a!="object"||a===null)return a;for(;e.length>0&&e.at(-1)!==this;)e.pop();return e.includes(a)?"[Circular]":(e.push(a),a)}),truncated:i}}function ce(n,t){return n.length<=t?n:`${n.slice(0,t)}...[truncated ${n.length-t} chars]`}function ue(n,t){const e={};for(const i of t)n[i]!==void 0&&(e[i]=n[i]);return e}function de(n,t){const e=t?ae(n):le(n);n.level==="error"?console.error(e):n.level==="warn"?console.warn(e):console.log(e)}function vt(n,t=0){const e={name:n.name,message:n.message};n.stack!==void 0&&(e.stack=n.stack);for(const i of Object.getOwnPropertyNames(n)){if(i==="name"||i==="message"||i==="stack"||i==="cause")continue;const o=n[i];o!==void 0&&(e[i]=o)}return n.cause!==void 0&&n.cause!==null&&(e.cause=n.cause instanceof Error&&t<5?vt(n.cause,t+1):String(n.cause)),e}function he(n){const t={};for(const[e,i]of Object.entries(n))t[e]=i instanceof Error?vt(i):i;return t}function pe(){return new Date}function me(n){return n.toISOString()}function yt(){return typeof navigator>"u"?"":navigator.userAgent}function fe(){return typeof navigator>"u"?!1:navigator.platform==="MacIntel"&&navigator.maxTouchPoints>1}function ge(){return/iPhone|iPad|iPod/i.test(yt())||fe()}function be(){return/Android/i.test(yt())}function ve(){return ge()||be()}class ye{constructor(t){this.config=t}config;log(t,e,i={}){const o=this.config.traceProvider?.()??{},s={timestamp:me(pe()),level:t,msg:e,service:this.config.service,...o,...he(i)};de(s,this.config.isDev)}debug(t,e){this.config.isDev&&this.log("debug",t,e)}info(t,e){this.log("info",t,e)}warn(t,e){this.log("warn",t,e)}error(t,e){this.log("error",t,e)}}function wt(n,t){const e=t?.isDev!==void 0?t.isDev:typeof process<"u"?process.env.NODE_ENV!=="production":!0;return new ye({service:n,isDev:e,traceProvider:t?.traceProvider})}function L(n){if(n!==void 0)return typeof n=="object"&&n!==null&&!Array.isArray(n)&&!(n instanceof Error)?n:n instanceof Error?{error:n.message}:{value:n}}function St(n){return{debug:(t,e)=>n.debug(t,L(e)),info:(t,e)=>n.info(t,L(e)),warn:(t,e)=>n.warn(t,L(e)),error:(t,e)=>n.error(t,L(e))}}let Ct=!1;exports.logger=St(wt("client",{isDev:!1}));function _t(){Ct=!0,exports.logger=St(wt("client",{isDev:!0}))}function we(){return Ct}class Se{constructor(t,e,i){this.send=t,this.instance=e,this.onMutationFailed=i}send;instance;onMutationFailed;registry;pendingCallbacks=[];handleMappingReceived(t){exports.logger.debug("Initializing from server mapping",{attributeCount:t.attributes.length}),this.registry=new oe(t.attributes,(e,i)=>this.sendMutation(e,i),this.onMutationFailed),this.replayPendingCallbacks()}handleMutationResult(t){this.registry?.handleResults(t.results)}select(t,e){this.sendMutation([{name:t,value:e}],!1)}selectTransient(t,e){this.sendMutation([{name:t,value:e}],!1,!0)}getValues(t){return this.registry?.get(t)?.getValues()??[]}getValue(t,e){return this.registry?.get(t)?.getValue(e)}onChange(t,e){if(this.registry===void 0){this.pendingCallbacks.push({name:t,callback:e});return}const i=this.registry.get(t);if(i===void 0){exports.logger.warn(`onChange: attribute "${t}" not found — callback will not fire`);return}i.onChange(e)}getAttribute(t){return this.registry?.get(t)}getSelection(){return this.registry?.getSelection()??{}}sendMutation(t,e,i=!1){const o={type:c.MUTATION,instance:this.instance,mutations:t,isInitial:e,...i&&{transient:!0}};this.send(o)}replayPendingCallbacks(){for(const{name:t,callback:e}of this.pendingCallbacks){const i=this.registry?.get(t);i===void 0&&exports.logger.warn(`onChange: attribute "${t}" not found — buffered callback will not fire`),i?.onChange(e)}this.pendingCallbacks.length=0}}class Ce{snapshot;callbacks=[];handleSnapshot(t){this.snapshot=t.attributes;for(const e of this.callbacks)e(t.attributes)}onChange(t){this.callbacks.push(t),this.snapshot!==void 0&&t(this.snapshot)}selectableFor(t){return this.snapshot?.find(i=>i.name===t)?.selectable??null}get current(){return this.snapshot??[]}}let kt=class{constructor(t){this.send=t}send;commands=[];rotate(t){return this.validateFiniteNumber(t,"rotate"),this.commands.push({action:"rotate",value:t}),this}tilt(t){return this.validateFiniteNumber(t,"tilt"),this.commands.push({action:"tilt",value:t}),this}zoom(t){return this.validateFiniteNumber(t,"zoom"),this.commands.push({action:"zoom",value:t}),this}set(){if(this.commands.length===0)throw b.invalidParameter("No camera commands to execute. Call rotate(), tilt(), or zoom() before set().");const t={type:c.CAMERA,commands:this.commands};this.send(t),this.commands=[]}validateFiniteNumber(t,e){if(!Number.isFinite(t))throw b.invalidParameter(`${e}() requires a finite number, got ${String(t)}`)}reset(){const t={type:c.CAMERA,commands:[{action:"reset"}]};this.send(t)}};class At{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(t){this.changeCallbacks.push(t)}get limits(){return this.limitsState}applyLimits(t){this.limitsState=t;const e={rotation:this.rotation,tilt:this.tilt,zoom:this.zoom};for(const i of this.changeCallbacks)i(e)}handlePositionUpdate(t){this.update(t.transforms)}update(t){let e=!1;for(const i of t)switch(i.type){case"rotation":this.state.rotation=i.value,e=!0;break;case"tilt":this.state.tilt=i.value,e=!0;break;case"zoom":this.state.zoom=i.value,e=!0;break}if(e){const i={rotation:this.rotation,tilt:this.tilt,zoom:this.zoom};for(const o of this.changeCallbacks)o(i)}}}function _e(n,t){const e=n.filter(s=>ke(s,t));if(e.length===0)return;const i=Math.max(...e.map(nt)),o=e.filter(s=>nt(s)===i);return o.length===1?o[0]:void 0}function ke(n,t){return Object.entries(n.attributes).every(([e,i])=>t[e]===i)}function nt(n){return Object.keys(n.attributes).length}class Et{constructor(t,e){this.dispatchChange=t,this.dispatchSubmit=e}dispatchChange;dispatchSubmit;pricing;selection={};resolved;changeCallbacks=[];renderCallbacks=[];submitCallback;submitDefaultLabel;get current(){return this.resolved}get vatDisplay(){return this.pricing?.vatDisplay}get buttonLabel(){const t=this.pricing?.buttonLabel;if(t!=null&&t!=="")return t;if(this.submitDefaultLabel!==void 0&&this.submitDefaultLabel!=="")return this.submitDefaultLabel}get submittable(){return this.submitCallback===void 0?!1:this.pricing===void 0?!0:this.resolved?.availability==="available"}get submitEnabled(){return this.submittable&&this.buttonLabel!==void 0}onChange(t){this.changeCallbacks.push(t)}onSubmit(t,e){this.submitCallback=t,this.submitDefaultLabel=e?.defaultLabel,this.notifyRender()}onRender(t){return this.renderCallbacks.push(t),()=>{const e=this.renderCallbacks.indexOf(t);e!==-1&&this.renderCallbacks.splice(e,1)}}async submit(){if(!this.submittable)return;const t=this.resolved!==void 0?{attributes:this.resolved.attributes,reference:this.resolved.reference}:{attributes:{...this.selection},reference:""};this.dispatchSubmit(t),await this.submitCallback?.(t)}handlePricingReceived(t){this.pricing=t,this.recompute()}handleSelectionChanged(t){this.selection=t,this.recompute()}recompute(){this.resolved=this.resolve();for(const t of this.changeCallbacks)t(this.resolved);this.dispatchChange(this.resolved),this.notifyRender()}notifyRender(){for(const t of this.renderCallbacks)t()}resolve(){if(this.pricing===void 0)return;const t=_e(this.pricing.rules,this.selection);if(!(t===void 0||t.availability===mt.HIDDEN))return{attributes:{...this.selection},reference:t.reference,price:t.priceCents,currency:this.pricing.currency,availability:t.availability}}}class xt{constructor(t,e,i){this.send=t,this.dispatch=e,this.instance=i}send;dispatch;instance;focused=null;attributes=[];changeCallbacks=[];get current(){return this.focused}set(t){if(typeof t!="string"||t.length===0)throw b.invalidParameter(`set() requires a non-empty component name, got ${String(t)}`);this.send({type:c.FOCUS,instance:this.instance,action:tt.FOCUS,component:t})}clear(){this.send({type:c.FOCUS,instance:this.instance,action:tt.UNFOCUS})}onChange(t){this.changeCallbacks.push(t)}handleStateReceived(t){t.state===Bt.FOCUSED&&t.component!==void 0?(this.focused=t.component,this.attributes=t.attributes??[]):(this.focused=null,this.attributes=[]);const e=this.focused!==null?{component:this.focused,attributes:this.attributes}:null;for(const i of this.changeCallbacks)i(e);this.dispatch(e)}}class Tt{constructor(t){this.filename=t}filename;developedCallbacks=new Set;errorCallbacks=new Set;developed=!1;failed=!1;photoData=null;onDeveloped(t){return this.developed&&this.photoData!==null?(t(this.photoData),this):(this.developedCallbacks.add(t),this)}onError(t){return this.errorCallbacks.add(t),this}getFilename(){return this.filename}develop(t){this.developed||this.failed||(this.photoData=t,this.developed=!0,this.developedCallbacks.forEach(e=>{e(this.photoData)}),this.developedCallbacks.clear(),this.errorCallbacks.clear())}fail(t){this.developed||this.failed||(this.failed=!0,this.errorCallbacks.forEach(e=>{e(t)}),this.developedCallbacks.clear(),this.errorCallbacks.clear())}}const it=3e4;class Rt{constructor(t){this.send=t}send;validExtensions=[".png"];pendingPhotos=new Map;take(t){this.validateFilename(t),exports.logger.debug("Taking snapshot",{filename:t});const e=new Tt(t),i=setTimeout(()=>{this.pendingPhotos.delete(t),exports.logger.warn("Snapshot timed out",{filename:t}),e.fail(new b(`Snapshot timed out: the viewer did not respond within ${it}ms`,_.SNAPSHOT_FAILED))},it);return this.pendingPhotos.set(t,{photo:e,timeout:i}),this.send({type:c.SNAPSHOT,filename:t}),e}handleSnapshotResult(t){const e=this.pendingPhotos.get(t.filename);if(e===void 0){exports.logger.warn("No pending photo found for filename",{filename:t.filename,pendingFilenames:Array.from(this.pendingPhotos.keys())});return}clearTimeout(e.timeout),this.pendingPhotos.delete(t.filename);const{photo:i}=e;if(t.error!==void 0){i.fail(new b(t.error,_.SNAPSHOT_FAILED));return}t.data!==void 0&&i.develop({filename:t.filename,data:t.data})}clear(){if(this.pendingPhotos.size===0)return;const t=new b("Client destroyed before snapshot completed",_.SNAPSHOT_FAILED);for(const{photo:e,timeout:i}of this.pendingPhotos.values())clearTimeout(i),e.fail(t);this.pendingPhotos.clear()}validateFilename(t){if(t===""||typeof t!="string")throw new b("Filename must be a non-empty string",_.INVALID_PARAMETER);if(!this.validExtensions.some(i=>t.toLowerCase().endsWith(i)))throw new b(`Invalid filename: "${t}". Filename must end with one of: ${this.validExtensions.join(", ")}`,_.INVALID_PARAMETER);if(t.includes("..")||t.includes("/")||t.includes("\\"))throw new b('Filename cannot contain path separators or ".."',_.INVALID_PARAMETER)}}class Ae{container=null;attach(t){this.container=t}dispatch(t,e,i=!1){const o=new CustomEvent(t,{detail:e,cancelable:i});return this.container?.dispatchEvent(o),o}on(t,e){const i=o=>{const s=o,r={...s.detail,preventDefault:()=>{s.preventDefault()}};e(r)};return this.container?.addEventListener(t,i),()=>{this.container?.removeEventListener(t,i)}}}const Ee={},xe="en",It=["en","nl","de"],K=["baseLocale"],ot=[],Y=typeof window>"u";globalThis.__paraglide=globalThis.__paraglide??{};globalThis.__paraglide.ssr=globalThis.__paraglide.ssr??{};let st=!1,p=()=>{let n=K;!Y&&typeof window<"u"&&window.location?.href&&(n=Lt(window.location.href));const t=Te(n);if(t)return st||(st=!0,Ot(t,{reload:!1})),t;throw new Error("No locale found. Read the docs https://paraglidejs.com/errors#no-locale-found")};function Te(n,t){let e;for(const i of n){if(i==="baseLocale")e=xe;else if(Mt(i)&&N.has(i)){const s=N.get(i);if(s){const r=s.getLocale();if(r instanceof Promise)continue;if(r!==void 0)return Oe(r)}}const o=X(e);if(o)return o}}const Re=n=>{window.location.reload()};let Ot=(n,t)=>{const e={reload:!0,...t};let i;try{i=p()}catch{}const o=[];let s=K;!Y&&typeof window<"u"&&window.location?.href&&(s=Lt(window.location.href));for(const a of s)if(a!=="baseLocale"&&Mt(a)&&N.has(a)){const u=N.get(a);if(u){let d=u.setLocale(n);d instanceof Promise&&(d=d.catch(f=>{throw new Error(`Custom strategy "${a}" setLocale failed.`,{cause:f})}),o.push(d))}}const r=()=>{!Y&&e.reload&&window.location&&n!==i&&Re()};if(o.length)return Promise.all(o).then(()=>{r()});r()},Ie=()=>typeof window<"u"?window.location.origin:"http://fallback.com";function X(n){if(typeof n!="string")return;const t=n.toLowerCase();for(const e of It)if(e.toLowerCase()===t)return e}function Oe(n){const t=X(n);if(t)return t;throw new Error(`Invalid locale: ${n}. Expected one of: ${It.join(", ")}`)}function Le(n,t){return n.exec(t.href)}function Me(n){return Ne(n)}function Ne(n){const t=typeof n=="string"?new URL(n,Ie()):new URL(n),e=t.pathname.split("/").filter(Boolean);return e.length>0&&X(e[0])&&(t.pathname="/"+e.slice(1).join("/")),t}let rt,at;function ze(n){if(ot.length===0)return;const t=typeof n=="string"?n:n.href;if(rt===t)return at;const e=new URL(t,"http://example.com"),i=Me(e),o=i.href===e.href?[e]:[e,i];let s;for(const r of o){for(const a of ot){const u=new Ee(a.match,r.href);if(Le(u,r)){s=a;break}}if(s)break}return rt=t,at=s,s}function Lt(n){const t=ze(n);return t&&t.exclude!==!0&&Array.isArray(t.strategy)?t.strategy:K}const N=new Map;function Mt(n){return typeof n=="string"&&/^custom-[A-Za-z0-9_-]+$/.test(n)}const Pe=()=>"Working…",Fe=()=>"Bezig…",De=()=>"Läuft…",$e=((n={},t={})=>{const e=t.locale??p();return e==="nl"?Fe():e==="de"?De():Pe()}),Be=()=>"Failed",Ue=()=>"Mislukt",Ve=()=>"Fehlgeschlagen",He=((n={},t={})=>{const e=t.locale??p();return e==="nl"?Ue():e==="de"?Ve():Be()}),je=()=>"Done",qe=()=>"Gelukt",Ge=()=>"Fertig",Ze=((n={},t={})=>{const e=t.locale??p();return e==="nl"?qe():e==="de"?Ge():je()}),We=()=>"Annotations",Ye=()=>"Annotaties",Qe=()=>"Anmerkungen",Ke=((n={},t={})=>{const e=t.locale??p();return e==="nl"?Ye():e==="de"?Qe():We()}),Xe=()=>"Activate AR",Je=()=>"AR activeren",tn=()=>"AR aktivieren",en=((n={},t={})=>{const e=t.locale??p();return e==="nl"?Je():e==="de"?tn():Xe()}),nn=()=>"Reset camera",on=()=>"Camera resetten",sn=()=>"Kamera zurücksetzen",rn=((n={},t={})=>{const e=t.locale??p();return e==="nl"?on():e==="de"?sn():nn()}),an=()=>"Rotate left",ln=()=>"Naar links draaien",cn=()=>"Nach links drehen",un=((n={},t={})=>{const e=t.locale??p();return e==="nl"?ln():e==="de"?cn():an()}),dn=()=>"Rotate right",hn=()=>"Naar rechts draaien",pn=()=>"Nach rechts drehen",mn=((n={},t={})=>{const e=t.locale??p();return e==="nl"?hn():e==="de"?pn():dn()}),fn=()=>"Tilt down",gn=()=>"Omlaag kantelen",bn=()=>"Nach unten kippen",vn=((n={},t={})=>{const e=t.locale??p();return e==="nl"?gn():e==="de"?bn():fn()}),yn=()=>"Tilt up",wn=()=>"Omhoog kantelen",Sn=()=>"Nach oben kippen",Cn=((n={},t={})=>{const e=t.locale??p();return e==="nl"?wn():e==="de"?Sn():yn()}),_n=()=>"Zoom in",kn=()=>"Inzoomen",An=()=>"Hineinzoomen",En=((n={},t={})=>{const e=t.locale??p();return e==="nl"?kn():e==="de"?An():_n()}),xn=()=>"Zoom out",Tn=()=>"Uitzoomen",Rn=()=>"Herauszoomen",In=((n={},t={})=>{const e=t.locale??p();return e==="nl"?Tn():e==="de"?Rn():xn()}),On=()=>"Close",Ln=()=>"Sluiten",Mn=()=>"Schließen",Nn=((n={},t={})=>{const e=t.locale??p();return e==="nl"?Ln():e==="de"?Mn():On()}),zn=()=>"Configure",Pn=()=>"Configureren",Fn=()=>"Konfigurieren",Dn=((n={},t={})=>{const e=t.locale??p();return e==="nl"?Pn():e==="de"?Fn():zn()}),$n=()=>"Fullscreen",Bn=()=>"Volledig scherm",Un=()=>"Vollbild",Vn=((n={},t={})=>{const e=t.locale??p();return e==="nl"?Bn():e==="de"?Un():$n()}),Hn=()=>"Close",jn=()=>"Sluiten",qn=()=>"Schließen",Gn=((n={},t={})=>{const e=t.locale??p();return e==="nl"?jn():e==="de"?qn():Hn()}),Zn=()=>"Use your smartphone camera to scan this QR code",Wn=()=>"Gebruik de camera van je smartphone om deze QR-code te scannen",Yn=()=>"Verwende die Kamera deines Smartphones, um diesen QR-Code zu scannen",Qn=((n={},t={})=>{const e=t.locale??p();return e==="nl"?Wn():e==="de"?Yn():Zn()}),Kn=()=>"Your phone will open the 3D model in AR mode.",Xn=()=>"Je telefoon opent het 3D-model in AR-modus.",Jn=()=>"Dein Telefon öffnet das 3D-Modell im AR-Modus.",ti=((n={},t={})=>{const e=t.locale??p();return e==="nl"?Xn():e==="de"?Jn():Kn()}),ei=()=>"Scan to view in AR",ni=()=>"Scan om in AR te bekijken",ii=()=>"Scannen für AR-Ansicht",oi=((n={},t={})=>{const e=t.locale??p();return e==="nl"?ni():e==="de"?ii():ei()}),si=()=>"Screenshot",ri=()=>"Screenshot",ai=()=>"Screenshot",li=((n={},t={})=>{const e=t.locale??p();return e==="nl"?ri():e==="de"?ai():si()}),ci=()=>"Downloading",ui=()=>"Downloaden",di=()=>"Herunterladen",hi=((n={},t={})=>{const e=t.locale??p();return e==="nl"?ui():e==="de"?di():ci()});const pi={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"};const Nt=([n,t,e])=>{const i=document.createElementNS("http://www.w3.org/2000/svg",n);return Object.keys(t).forEach(o=>{i.setAttribute(o,String(t[o]))}),e?.length&&e.forEach(o=>{const s=Nt(o);i.appendChild(s)}),i},zt=(n,t={})=>{const i={...pi,...t};return Nt(["svg",i,n])};const mi=[["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"}]];const fi=[["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"}]];const Pt=[["path",{d:"m6 9 6 6 6-6"}]];const gi=[["path",{d:"m15 18-6-6 6-6"}]];const bi=[["path",{d:"m9 18 6-6-6-6"}]];const vi=[["path",{d:"m18 15-6-6-6 6"}]];const yi=[["path",{d:"M12.75 7.09a3 3 0 0 1 2.16 2.16"}],["path",{d:"M17.072 17.072c-1.634 2.17-3.527 3.912-4.471 4.727a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 1.432-4.568"}],["path",{d:"m2 2 20 20"}],["path",{d:"M8.475 2.818A8 8 0 0 1 20 10c0 1.183-.31 2.377-.81 3.533"}],["path",{d:"M9.13 9.13a3 3 0 0 0 3.74 3.74"}]];const wi=[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"}],["circle",{cx:"12",cy:"10",r:"3"}]];const Si=[["path",{d:"M15 3h6v6"}],["path",{d:"m21 3-7 7"}],["path",{d:"m3 21 7-7"}],["path",{d:"M9 21H3v-6"}]];const Ci=[["path",{d:"m14 10 7-7"}],["path",{d:"M20 10h-6V4"}],["path",{d:"m3 21 7-7"}],["path",{d:"M4 14h6v6"}]];const _i=[["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"}]];const ki=[["path",{d:"M10 5H3"}],["path",{d:"M12 19H3"}],["path",{d:"M14 3v4"}],["path",{d:"M16 17v4"}],["path",{d:"M21 12h-9"}],["path",{d:"M21 19h-5"}],["path",{d:"M21 5h-7"}],["path",{d:"M8 10v4"}],["path",{d:"M8 12H3"}]];const Ai=[["path",{d:"M18 6 6 18"}],["path",{d:"m6 6 12 12"}]];const Ei=[["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"}]];const xi=[["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 v(n,{size:t=20,strokeWidth:e=1.75}={}){return zt(n,{width:t,height:t,"stroke-width":e})}const g={ar:n=>v(mi,n),annotations:n=>v(wi,n),annotationsOff:n=>v(yi,n),fullscreen:n=>v(Si,n),exitFullscreen:n=>v(Ci,n),screenshot:n=>v(fi,n),tiltUp:n=>v(vi,n),tiltDown:n=>v(Pt,n),rotateLeft:n=>v(gi,n),rotateRight:n=>v(bi,n),zoomIn:n=>v(Ei,n),zoomOut:n=>v(xi,n),reset:n=>v(_i,n),configurator:n=>v(ki,n),close:n=>v(Ai,n)};class y{element;constructor({variant:t="default",size:e="default",label:i,icon:o,onClick:s,disabled:r=!1}={}){this.element=document.createElement("button"),this.element.className=`ui-btn ui-btn--${t} ui-btn--size-${e}`,i!==void 0&&(this.element.setAttribute("aria-label",i),this.element.title=i),o!==void 0?this.element.appendChild(o):i!==void 0&&(this.element.textContent=i),s&&this.element.addEventListener("click",s),this.element.disabled=r}setIcon(t){const e=this.element.querySelector("svg");e!==null?e.replaceWith(t):this.element.appendChild(t)}}const m={semantic:{error:"#dc2626"},neutral:{500:"#737373",600:"#525252",900:"#171717"},white:"#ffffff",black:"#000000"},l={0:"0",.5:"0.125rem",1:"0.25rem",1.5:"0.375rem",2:"0.5rem",3:"0.75rem",4:"1rem",5:"1.25rem",6:"1.5rem",8:"2rem",9:"2.25rem"};class Ti{element;constructor(){this.element=document.createElement("div"),Object.assign(this.element.style,{background:m.white,borderRadius:l[3],padding:l[6],boxShadow:`0 ${l[2]} ${l[8]} oklch(0% 0 0 / 20%)`,maxWidth:"20rem",width:"100%"})}}class Ri{constructor(t={}){this.options=t,this.card=new Ti,this.backdrop=this.createBackdrop(),this.backdrop.appendChild(this.card.element)}options;card;backdrop;keyHandler=null;open(){document.body.appendChild(this.backdrop),this.keyHandler=t=>{t.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(){const t=document.createElement("div");return Object.assign(t.style,{position:"fixed",inset:l[0],background:"oklch(0% 0 0 / 50%)",zIndex:"9999",display:"flex",alignItems:"center",justifyContent:"center"}),t.addEventListener("click",e=>{e.target===t&&this.close()}),t}}class Ii{element;selectCallback=null;constructor(t,e,i){this.element=document.createElement("div"),this.element.className="ui-toggle-group";for(let o=0;o<t.length;o++){const s=t[o],r=document.createElement("button");r.className="ui-toggle-group-item",r.dataset.value=s,r.textContent=i?.[o]??s,r.dataset.state=s===e?"on":"off",r.setAttribute("aria-pressed",s===e?"true":"false"),r.addEventListener("click",()=>{this.selectCallback?.(s)}),this.element.appendChild(r)}}setSelected(t){for(const e of this.element.querySelectorAll(".ui-toggle-group-item")){const i=e.dataset.value===t;e.dataset.state=i?"on":"off",e.setAttribute("aria-pressed",i?"true":"false")}}onSelect(t){this.selectCallback=t}setEnabled(t){for(const e of this.element.querySelectorAll(".ui-toggle-group-item")){const i=t===null||t.includes(e.dataset.value??"");e.disabled=!i,e.setAttribute("aria-disabled",i?"false":"true")}}}class Oi{element;select;constructor(t,e,i,o,s){this.select=document.createElement("select"),this.select.className="ui-native-select",this.select.dataset.name=t,this.select.setAttribute("aria-label",i);const r=document.createElement("option");r.value="",r.disabled=!0,r.textContent=i,this.select.appendChild(r);let a=!1;for(let d=0;d<e.length;d++){const f=e[d],h=document.createElement("option");h.value=f,h.textContent=s?.[d]??f,f===o&&(h.selected=!0,a=!0),this.select.appendChild(h)}a||(r.selected=!0);const u=zt(Pt,{width:16,height:16,"stroke-width":2});u.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(u)}setSelected(t){this.select.value=t}onSelect(t){this.select.addEventListener("change",()=>{t(this.select.value)})}setEnabled(t){for(const e of this.select.options)e.value!==""&&(e.disabled=t!==null&&!t.includes(e.value))}}class Li{element;input;valueText;values;options;selectCallback=null;settleCallback=null;constructor(t,e){if(t.length===0)throw new Error("Virtualdisplay: Slider needs at least one value");this.values=t,this.options=e,this.input=document.createElement("input"),this.input.type="range",this.input.className="ui-slider-input",this.input.min="0",this.input.max=String(t.length-1),this.input.step="1",this.input.setAttribute("aria-label",e.label),this.valueText=document.createElement("span"),this.valueText.className="ui-slider-value",this.valueText.setAttribute("aria-hidden","true");const i=document.createElement("div");i.className="ui-slider-track",i.appendChild(this.input),i.appendChild(this.buildEnds()),this.element=document.createElement("div"),this.element.className="ui-slider",this.element.appendChild(i),this.element.appendChild(this.valueText);const o=e.initialSelected===void 0?0:t.indexOf(e.initialSelected);this.applyIndex(o===-1?0:o),this.listen()}setSelected(t){const e=this.values.indexOf(t);e!==-1&&this.applyIndex(e)}onSelect(t){this.selectCallback=t}onSettle(t){this.settleCallback=t}listen(){this.input.addEventListener("input",()=>{const t=this.values[this.currentIndex];t!==void 0&&(this.applyIndex(this.currentIndex),this.selectCallback?.(t))}),this.input.addEventListener("change",()=>{const t=this.values[this.currentIndex];t!==void 0&&this.settleCallback?.(t)})}get currentIndex(){return Number(this.input.value)}applyIndex(t){this.input.value=String(t);const e=this.displayAt(t);this.valueText.textContent=e,this.input.setAttribute("aria-valuetext",e);const i=this.values.length===1?100:t/(this.values.length-1)*100;this.element.style.setProperty("--ui-slider-pct",`${i}%`)}buildEnds(){const t=document.createElement("div");t.className="ui-slider-ends",t.setAttribute("aria-hidden","true");for(const e of[0,this.values.length-1]){const i=document.createElement("span");i.textContent=this.labelAt(e),t.appendChild(i)}return t}labelAt(t){return this.options.labels?.[t]??this.values[t]??""}displayAt(t){const e=this.labelAt(t);return this.options.unit===void 0?e:`${e} ${this.options.unit}`}}const S={fontFamily:{sans:["Mona Sans","ui-sans-serif","system-ui","sans-serif","Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"]},fontSize:{xs:"0.75rem",sm:"0.875rem",base:"1rem",lg:"1.125rem"},fontWeight:{medium:"500",semibold:"600"}},E=S.fontFamily.sans.join(", "),Mi=`
2
+ --primary: oklch(5% 0 0);
3
+ --primary-foreground: oklch(100% 0 0);
4
+ --secondary: oklch(92% 0 0);
5
+ --secondary-foreground: oklch(5% 0 0);
6
+ --background: oklch(100% 0 0);
7
+ --foreground: oklch(5% 0 0);
8
+ --border: oklch(92% 0 0);
9
+ --ring: oklch(44% 0 0);
10
+ --radius: 0.625rem;
11
+ --accent: oklch(92% 0 0);
12
+ --accent-foreground: oklch(5% 0 0);
13
+ --muted-foreground: oklch(44% 0 0);
14
+ `,Ni=`
15
+ :root { ${Mi} }
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: ${E};
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: ${E};
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:disabled { opacity: 0.4; cursor: not-allowed; }
92
+ .ui-toggle-group-item:disabled:hover { background: var(--background); border-color: var(--border); }
93
+ .ui-toggle-group-item:active { transform: scale(0.98); }
94
+ .ui-toggle-group-item:focus-visible {
95
+ outline: none;
96
+ border-color: var(--ring);
97
+ box-shadow: 0 0 0 3px oklch(5% 0 0 / 12%);
98
+ }
99
+ .ui-toggle-group-item[data-state="on"] {
100
+ background: var(--primary);
101
+ color: var(--primary-foreground);
102
+ border-color: var(--primary);
103
+ }
104
+ .ui-toggle-group-item[data-state="on"]:hover { background: oklch(10% 0 0); }
105
+
106
+ /* ── Native select ───────────────────────────────────────── */
107
+ .ui-native-select-wrap {
108
+ position: relative;
109
+ display: inline-flex;
110
+ min-inline-size: 8rem;
111
+ }
112
+
113
+ .ui-native-select {
114
+ display: block;
115
+ inline-size: 100%;
116
+ block-size: 2.25rem;
117
+ padding: 0 2.25rem 0 0.75rem;
118
+ border: 1px solid var(--border);
119
+ border-radius: var(--radius);
120
+ background: var(--background);
121
+ appearance: none;
122
+ color: var(--foreground);
123
+ font-family: ${E};
124
+ font-size: 0.875rem;
125
+ font-weight: 400;
126
+ cursor: pointer;
127
+ transition: color 200ms, box-shadow 200ms, border-color 200ms;
128
+ box-shadow: 0 1px 2px oklch(5% 0 0 / 8%);
129
+ }
130
+ .ui-native-select:hover { border-color: oklch(85% 0 0); }
131
+ .ui-native-select:focus-visible {
132
+ outline: none;
133
+ border-color: var(--ring);
134
+ box-shadow: 0 0 0 3px oklch(5% 0 0 / 12%);
135
+ }
136
+
137
+ .ui-native-select-icon {
138
+ position: absolute;
139
+ inset-block-start: 50%;
140
+ inset-inline-end: 0.625rem;
141
+ transform: translateY(-50%);
142
+ color: var(--muted-foreground);
143
+ pointer-events: none;
144
+ }
145
+
146
+ /* ── Slider ──────────────────────────────────────────────── */
147
+ .ui-slider {
148
+ display: flex;
149
+ align-items: center;
150
+ gap: 0.75rem;
151
+ inline-size: 100%;
152
+ }
153
+
154
+ .ui-slider-track {
155
+ flex: 1;
156
+ min-inline-size: 0;
157
+ }
158
+
159
+ /* Tabular figures keep the readout and layout steady mid-drag. */
160
+ .ui-slider-value {
161
+ font-family: ${E};
162
+ font-size: 0.875rem;
163
+ font-weight: 600;
164
+ color: var(--foreground);
165
+ font-variant-numeric: tabular-nums;
166
+ white-space: nowrap;
167
+ }
168
+
169
+ .ui-slider-ends {
170
+ display: flex;
171
+ justify-content: space-between;
172
+ font-family: ${E};
173
+ font-size: 0.75rem;
174
+ color: var(--muted-foreground);
175
+ font-variant-numeric: tabular-nums;
176
+ }
177
+
178
+ /* 2.75rem tall: the whole input is the touch target (44px). */
179
+ .ui-slider-input {
180
+ appearance: none;
181
+ display: block;
182
+ inline-size: 100%;
183
+ block-size: 2.75rem;
184
+ margin: 0;
185
+ padding: 0;
186
+ background: transparent;
187
+ cursor: pointer;
188
+ }
189
+ .ui-slider-input:focus-visible { outline: none; }
190
+
191
+ /* --ui-slider-pct is set by the component; it fills the track up to the thumb. */
192
+ .ui-slider-input::-webkit-slider-runnable-track {
193
+ block-size: 0.375rem;
194
+ border-radius: 9999px;
195
+ background: linear-gradient(to right, var(--primary) var(--ui-slider-pct, 0%), var(--secondary) var(--ui-slider-pct, 0%));
196
+ }
197
+ .ui-slider-input::-webkit-slider-thumb {
198
+ appearance: none;
199
+ inline-size: 1.25rem;
200
+ block-size: 1.25rem;
201
+ margin-block-start: -0.4375rem; /* centre the 1.25rem thumb on the 0.375rem track */
202
+ border-radius: 50%;
203
+ border: 2px solid var(--primary);
204
+ background: var(--background);
205
+ box-shadow: 0 1px 3px oklch(5% 0 0 / 20%);
206
+ transition: box-shadow 200ms, border-color 200ms;
207
+ }
208
+ .ui-slider-input:focus-visible::-webkit-slider-thumb {
209
+ border-color: var(--ring);
210
+ box-shadow: 0 0 0 3px oklch(5% 0 0 / 12%);
211
+ }
212
+
213
+ .ui-slider-input::-moz-range-track {
214
+ block-size: 0.375rem;
215
+ border-radius: 9999px;
216
+ background: var(--secondary);
217
+ }
218
+ .ui-slider-input::-moz-range-progress {
219
+ block-size: 0.375rem;
220
+ border-radius: 9999px;
221
+ background: var(--primary);
222
+ }
223
+ .ui-slider-input::-moz-range-thumb {
224
+ inline-size: 1.25rem;
225
+ block-size: 1.25rem;
226
+ border-radius: 50%;
227
+ border: 2px solid var(--primary);
228
+ background: var(--background);
229
+ box-shadow: 0 1px 3px oklch(5% 0 0 / 20%);
230
+ transition: box-shadow 200ms, border-color 200ms;
231
+ }
232
+ .ui-slider-input:focus-visible::-moz-range-thumb {
233
+ border-color: var(--ring);
234
+ box-shadow: 0 0 0 3px oklch(5% 0 0 / 12%);
235
+ }
236
+
237
+ /* ── Annotation layer ───────────────────────────────────── */
238
+ .vd-annotations-layer {
239
+ position: absolute;
240
+ inset-block-start: 0;
241
+ inset-inline-start: 0;
242
+ inline-size: 100%;
243
+ block-size: 100%;
244
+ pointer-events: none;
245
+ overflow: visible !important; /* override CSS2DRenderer inline style */
246
+ }
247
+
248
+ .vd-annotation-anchor {
249
+ position: relative;
250
+ }
251
+
252
+ .vd-annotation-marker {
253
+ display: flex;
254
+ align-items: center;
255
+ justify-content: center;
256
+ inline-size: 1.75rem;
257
+ block-size: 1.75rem;
258
+ border-radius: 50%;
259
+ border: 2px solid oklch(100% 0 0);
260
+ background: var(--primary);
261
+ color: var(--primary-foreground);
262
+ font-family: ${E};
263
+ font-size: 0.8125rem;
264
+ font-weight: 600;
265
+ cursor: pointer;
266
+ pointer-events: auto;
267
+ box-shadow: 0 2px 8px oklch(5% 0 0 / 20%);
268
+ transition: transform 100ms ease;
269
+ position: relative;
270
+ }
271
+ .vd-annotation-marker:hover { transform: scale(1.1); }
272
+ .vd-annotation-marker:focus-visible {
273
+ outline: 2px solid var(--ring);
274
+ outline-offset: 2px;
275
+ }
276
+
277
+ .vd-annotation-popup {
278
+ position: absolute;
279
+ inset-block-end: calc(100% + 0.5rem);
280
+ inset-inline-start: 50%;
281
+ transform: translateX(-50%);
282
+ background: var(--background);
283
+ color: var(--foreground);
284
+ border: 1px solid var(--border);
285
+ border-radius: var(--radius);
286
+ padding: 0.75rem 1rem;
287
+ /* The popup is absolutely positioned inside the ~28px marker anchor, so
288
+ without an explicit width it shrink-to-fits against that anchor and
289
+ collapses to one word per line. max-content sizes it by its own text,
290
+ capped below. */
291
+ inline-size: max-content;
292
+ max-inline-size: 15rem;
293
+ box-shadow: 0 4px 6px oklch(5% 0 0 / 8%), 0 2px 4px oklch(5% 0 0 / 6%);
294
+ pointer-events: auto;
295
+ white-space: normal;
296
+ }
297
+ .vd-annotation-popup:focus { outline: none; }
298
+
299
+ /* Flipped below the marker when the popup would clip the container's top
300
+ edge; the layer positions it at open time and on the render cadence. */
301
+ .vd-annotation-popup--below {
302
+ inset-block-end: auto;
303
+ inset-block-start: calc(100% + 0.5rem);
304
+ }
305
+
306
+ .vd-annotation-popup-close {
307
+ position: absolute;
308
+ inset-block-start: 0.375rem;
309
+ inset-inline-end: 0.375rem;
310
+ display: flex;
311
+ align-items: center;
312
+ justify-content: center;
313
+ inline-size: 1.25rem;
314
+ block-size: 1.25rem;
315
+ padding: 0;
316
+ border: none;
317
+ border-radius: calc(var(--radius) - 4px);
318
+ background: transparent;
319
+ color: var(--muted-foreground);
320
+ cursor: pointer;
321
+ pointer-events: auto;
322
+ }
323
+ .vd-annotation-popup-close:hover {
324
+ color: var(--foreground);
325
+ background: var(--secondary);
326
+ }
327
+ .vd-annotation-popup-close:focus-visible {
328
+ outline: 2px solid var(--ring);
329
+ outline-offset: 1px;
330
+ }
331
+ .vd-annotation-popup-close svg {
332
+ inline-size: 0.875rem;
333
+ block-size: 0.875rem;
334
+ }
335
+
336
+ @media (prefers-reduced-motion: no-preference) {
337
+ .vd-annotation-popup {
338
+ animation: vd-popup-in 150ms ease;
339
+ }
340
+ }
341
+
342
+ /* Opacity only: the layer sets the popup's transform inline to clamp it
343
+ inside the container, and a keyframe animating transform would override
344
+ that for its duration and make the popup jump at the end. */
345
+ @keyframes vd-popup-in {
346
+ from { opacity: 0; }
347
+ to { opacity: 1; }
348
+ }
349
+
350
+ .vd-annotation-popup-title {
351
+ font-family: ${E};
352
+ font-size: 0.875rem;
353
+ font-weight: 600;
354
+ line-height: 1.25rem;
355
+ /* Keep the title clear of the absolutely positioned close button. */
356
+ padding-inline-end: 1.5rem;
357
+ }
358
+
359
+ .vd-annotation-popup-description {
360
+ font-family: ${E};
361
+ font-size: 0.8125rem;
362
+ font-weight: 400;
363
+ line-height: 1.125rem;
364
+ color: var(--muted-foreground);
365
+ margin-block-start: 0.25rem;
366
+ }
367
+
368
+ /* ── QR modal ────────────────────────────────────────────── */
369
+ /* The slot the QR renders into. While loading it is a calm pulsing
370
+ placeholder of the same size, so the modal opens instantly and the QR
371
+ swaps in without any layout shift. */
372
+ .ui-qr-slot {
373
+ inline-size: 6rem;
374
+ block-size: 6rem;
375
+ border-radius: 0.25rem;
376
+ overflow: hidden;
377
+ }
378
+
379
+ .ui-qr-slot img {
380
+ inline-size: 100%;
381
+ block-size: 100%;
382
+ display: block;
383
+ }
384
+
385
+ .ui-qr-slot--loading {
386
+ background: var(--secondary);
387
+ }
388
+
389
+ @media (prefers-reduced-motion: no-preference) {
390
+ .ui-qr-slot--loading {
391
+ animation: vd-qr-pulse 1.6s ease-in-out infinite;
392
+ }
393
+ }
394
+
395
+ @keyframes vd-qr-pulse {
396
+ 0%, 100% { opacity: 1; }
397
+ 50% { opacity: 0.55; }
398
+ }
399
+ `;let lt=!1;function Ft(){if(lt||typeof document>"u")return;lt=!0;const n=document.createElement("style");n.id="vd-ui-vanilla",n.textContent=Ni,document.head.appendChild(n)}const zi=S.fontFamily.sans.join(", ");class Pi{qrLib=null;dialog=null;qrSlot=null;show(){this.hide(),Ft(),this.dialog=new Ri({onClose:()=>{this.dialog=null,this.qrSlot=null}}),Object.assign(this.dialog.card.element.style,{display:"flex",flexDirection:"column",alignItems:"center",gap:l[3],fontFamily:zi}),this.dialog.card.element.appendChild(this.createText(oi(),{fontSize:S.fontSize.base,fontWeight:S.fontWeight.semibold,color:m.neutral[900]})),this.dialog.card.element.appendChild(this.createText(Qn(),{fontSize:S.fontSize.sm,color:m.neutral[600]})),this.qrSlot=this.createQrSlot(),this.dialog.card.element.appendChild(this.qrSlot),this.dialog.card.element.appendChild(this.createText(ti(),{fontSize:S.fontSize.xs,color:m.neutral[500]}));const t=new y({variant:"outline",label:Gn(),onClick:()=>{this.hide()}});this.dialog.card.element.appendChild(t.element),this.dialog.open()}async update(t){this.qrLib??=await Promise.resolve().then(()=>require("./browser-DfB_An57.cjs")).then(i=>i.browser);const e=await this.qrLib.toDataURL(t,{width:256,margin:4,errorCorrectionLevel:"M",color:{dark:m.black,light:m.white}});return this.qrSlot===null?!1:(this.qrSlot.classList.remove("ui-qr-slot--loading"),this.qrSlot.replaceChildren(this.createQrImage(e)),!0)}hide(){this.dialog?.close(),this.dialog=null,this.qrSlot=null}createText(t,e){const i=document.createElement("p");return i.textContent=t,Object.assign(i.style,{margin:"0",textAlign:"center",...e}),i}createQrSlot(){const t=document.createElement("div");return t.className="ui-qr-slot ui-qr-slot--loading",t}createQrImage(t){const e=document.createElement("img");return e.src=t,e.alt="QR code",e}}function ct(n){const t=Math.max(0,Math.min(1,n));return t*t*(3-2*t)}function Fi(n,t,e,i,o,s){const[r,a,u]=n,d=Math.cos(t),f=Math.sin(t),h=d*r+f*u,A=-f*r+d*u,k=Math.cos(e),C=Math.sin(e),R=k*a-C*A,P=C*a+k*A,J=.55;return[i+h*s*J,o-R*s*J,P]}function Di(n,t,e){n.beginPath(),n.moveTo(t[0],t[1]),n.lineTo(e[0],e[1]),n.strokeStyle="#000",n.lineWidth=2,n.stroke()}function $i(n,t,e,i,o){const s=t(e),r=t(i),a=[s[0]+(r[0]-s[0])*o,s[1]+(r[1]-s[1])*o,s[2]];Di(n,s,a)}const D=[-1,-1,1],$=[1,-1,1],B=[1,-1,-1],U=[-1,-1,-1],V=[-1,1,1],H=[1,1,1],j=[1,1,-1],q=[-1,1,-1],ut=[[D,$],[$,B],[B,U],[U,D],[D,V],[$,H],[B,j],[U,q],[V,H],[H,j],[j,q],[q,V]],Bi=400,dt='-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif';function Ui(){const n=document.createElement("div");Object.assign(n.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"});const t=document.createElement("canvas");Object.assign(t.style,{width:"100%",height:"100%",position:"absolute",inset:"0"});const e=document.createElement("div");Object.assign(e.style,{position:"absolute",top:"56%",left:"0",right:"0",textAlign:"center",pointerEvents:"none"});const i=document.createElement("span");Object.assign(i.style,{fontSize:"13px",fontWeight:"400",color:"#000",fontVariantNumeric:"tabular-nums",fontFamily:dt});const o=document.createElement("span");return Object.assign(o.style,{fontSize:"13px",color:"#000",fontFamily:dt}),o.textContent=hi(),e.appendChild(i),e.appendChild(o),n.appendChild(t),n.appendChild(e),{overlay:n,canvas:t,pctEl:i,phaseEl:o}}class Vi{overlay;canvas;ctx;pctEl;phaseEl;animationId=null;showTimerId=null;startTime;hidden=!1;visible=!1;constructor(t,e={}){this.startTime=performance.now();const i=Ui();this.overlay=i.overlay,this.canvas=i.canvas,this.pctEl=i.pctEl,this.phaseEl=i.phaseEl,t.appendChild(this.overlay),this.ctx=this.canvas.getContext("2d"),this.ctx!==null&&(this.sizeCanvas(),this.tick());const o=e.showDelay??Bi;this.showTimerId=setTimeout(()=>{this.reveal()},o)}updateProgress(t,e){this.hidden||(this.pctEl.textContent=`${Math.round(t)}%`,this.phaseEl.textContent=e!==""?` · ${e}`:"")}showError(t){if(this.hidden=!1,this.animationId!==null&&(cancelAnimationFrame(this.animationId),this.animationId=null),this.ctx!==null){const e=Math.min(devicePixelRatio,2),i=this.canvas.width/e,o=this.canvas.height/e;this.ctx.fillStyle="#fff",this.ctx.fillRect(0,0,i*e,o*e)}this.pctEl.textContent="",this.phaseEl.textContent=t,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;const t=Math.min(devicePixelRatio,2),e=this.overlay.clientWidth||440,i=this.overlay.clientHeight||360;this.canvas.width=e*t,this.canvas.height=i*t,this.ctx.scale(t,t),this.ctx.lineCap="round",this.ctx.lineJoin="round"}tick=()=>{this.hidden||(this.drawFrame(),this.animationId=requestAnimationFrame(this.tick))};drawFrame(){if(this.ctx===null)return;const t=this.canvas.width/Math.min(devicePixelRatio,2),e=this.canvas.height/Math.min(devicePixelRatio,2),i=(performance.now()-this.startTime)/1e3;this.ctx.fillStyle="#fff",this.ctx.fillRect(0,0,t,e);const o=t/2,s=e*.44,r=Math.min(t,e)*.08,a=.785,u=.615,d=C=>Fi(C,a,u,o,s,r),f=6,h=i%f/f,A=ut.length;let k;h<.35?k=ct(h/.35)*A:h<.55?k=A:h<.9?k=(1-ct((h-.55)/.35))*A:k=0,this.ctx.shadowBlur=5,this.ctx.shadowColor="rgba(30,30,30,0.08)";for(let C=0;C<A&&!(C>=k);C++){const R=ut[C];if(R===void 0)continue;const P=Math.min(1,k-C);$i(this.ctx,d,R[0],R[1],P)}this.ctx.shadowBlur=0}}class Hi{constructor(t){this.options=t,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)}options;element;arBtn=null;fullscreenBtn=null;annotationsBtn=null;annotationsShown=!1;onFullscreenChange;setFullscreenIcon(t){this.fullscreenBtn!==null&&this.fullscreenBtn.setIcon(t?g.exitFullscreen():g.fullscreen())}syncButton(t,e,i){if(e&&t===null){const o=i();return this.element.appendChild(o.element),o}return!e&&t!==null?(t.element.remove(),null):t}applySettings(t){this.arBtn=this.syncButton(this.arBtn,t.ar!==!1&&this.options.onAr!==void 0,()=>new y({variant:"outline",size:"icon",label:en(),icon:g.ar(),onClick:()=>{this.options.onAr?.()}})),this.fullscreenBtn=this.syncButton(this.fullscreenBtn,t.fullscreen!==!1&&this.options.onFullscreen!==void 0,()=>new y({variant:"outline",size:"icon",label:Vn(),icon:g.fullscreen(),onClick:()=>{this.options.onFullscreen?.()}}));const e=t.annotations==="toggle-shown"||t.annotations==="toggle-hidden";this.annotationsBtn=this.syncButton(this.annotationsBtn,e&&this.options.onAnnotationsToggle!==void 0,()=>{this.annotationsShown=t.annotations==="toggle-shown";const i=new y({variant:"outline",size:"icon",label:Ke(),icon:this.annotationsShown?g.annotations():g.annotationsOff(),onClick:()=>{this.flipAnnotations()}});return i.element.setAttribute("aria-pressed",String(this.annotationsShown)),i})}flipAnnotations(){this.annotationsShown=!this.annotationsShown,this.annotationsBtn?.element.setAttribute("aria-pressed",String(this.annotationsShown)),this.annotationsBtn?.setIcon(this.annotationsShown?g.annotations():g.annotationsOff()),this.options.onAnnotationsToggle?.(this.annotationsShown)}destroy(){document.removeEventListener("fullscreenchange",this.onFullscreenChange)}}const T=.5;class z{element;constructor(t,e){this.element=Object.assign(document.createElement("div"),{className:"vd-camera-controls"});const i={targetRotation:e.rotation,targetTilt:e.tilt,targetZoom:e.zoom,thetaOffset:0},o=ji(t,e,i);e.onChange(s=>{i.targetRotation=s.rotation-i.thetaOffset,i.targetTilt=s.tilt,i.targetZoom=s.zoom,qi(o,e,s)}),this.element.appendChild(z.buildZoom(o.zoomOut,o.zoomIn)),this.element.appendChild(z.buildDpad(o.tiltUp,o.rotateLeft,o.reset,o.rotateRight,o.tiltDown))}static buildZoom(t,e){const i=document.createElement("div");return i.className="vd-zoom",i.appendChild(t.element),i.appendChild(e.element),i}static buildDpad(t,e,i,o,s){const r=document.createElement("div");r.className="vd-dpad";for(const[a,u]of[[t,"up"],[e,"left"],[i,"center"],[o,"right"],[s,"down"]])a.element.classList.add(`vd-dpad-${u}`),r.appendChild(a.element);return r}}function ji(n,t,e){const i=r=>Math.max(t.limits?.minZoom??1,Math.min(t.limits?.maxZoom??1/0,r)),o=r=>{const a=t.limits?.minRotate,u=t.limits?.maxRotate;return a!==void 0||u!==void 0?Math.max(a??-1/0,Math.min(u??1/0,r)):r},s=r=>{const a=t.limits?.minTilt,u=t.limits?.maxTilt;if(a!==void 0||u!==void 0){e.targetTilt=Math.max(a??0,Math.min(u??180,e.targetTilt+r)),n.tilt(e.targetTilt).set();return}const d=e.targetTilt+r;d>180||d<0?(e.targetTilt=d>180?360-d:-d,e.thetaOffset=(e.thetaOffset+180)%360,n.tilt(e.targetTilt).rotate(e.targetRotation+e.thetaOffset).set()):(e.targetTilt=d,n.tilt(e.targetTilt).set())};return{zoomOut:new y({variant:"outline",size:"icon",label:In(),icon:g.zoomOut(),onClick:()=>{e.targetZoom=i(e.targetZoom-10),n.zoom(e.targetZoom).set()}}),zoomIn:new y({variant:"outline",size:"icon",label:En(),icon:g.zoomIn(),onClick:()=>{e.targetZoom=i(e.targetZoom+10),n.zoom(e.targetZoom).set()}}),tiltUp:new y({variant:"outline",size:"icon",label:Cn(),icon:g.tiltUp(),onClick:()=>{s(-15)}}),rotateLeft:new y({variant:"outline",size:"icon",label:un(),icon:g.rotateLeft(),onClick:()=>{e.targetRotation=o(e.targetRotation-15),n.rotate(e.targetRotation+e.thetaOffset).set()}}),reset:new y({variant:"outline",size:"icon",label:rn(),icon:g.reset(),onClick:()=>{e.thetaOffset=0,n.reset()}}),rotateRight:new y({variant:"outline",size:"icon",label:mn(),icon:g.rotateRight(),onClick:()=>{e.targetRotation=o(e.targetRotation+15),n.rotate(e.targetRotation+e.thetaOffset).set()}}),tiltDown:new y({variant:"outline",size:"icon",label:vn(),icon:g.tiltDown(),onClick:()=>{s(15)}})}}function qi(n,t,e){const i=t.limits;i!==void 0&&(n.zoomOut.element.disabled=i.minZoom!==void 0&&e.zoom<=i.minZoom+T,n.zoomIn.element.disabled=i.maxZoom!==void 0&&e.zoom>=i.maxZoom-T,n.tiltUp.element.disabled=i.minTilt!==void 0&&e.tilt<=i.minTilt+T,n.tiltDown.element.disabled=i.maxTilt!==void 0&&e.tilt>=i.maxTilt-T,n.rotateLeft.element.disabled=i.minRotate!==void 0&&e.rotation<=i.minRotate+T,n.rotateRight.element.disabled=i.maxRotate!==void 0&&e.rotation>=i.maxRotate-T)}const x={SELECT:"vd:select",SELECTED:"vd:selected",FOCUS_CHANGE:"vd:focus-change",CONFIGURATION_CHANGE:"vd:configuration-change",CONFIGURATION_SUBMIT:"vd:configuration-submit"},Dt={mm:1,cm:10,m:1e3,in:25.4},ht=3;function Gi(n){const t=n.stepMm/Dt[n.displayUnit];for(let e=0;e<=ht;e++){const i=t*10**e;if(Math.abs(i-Math.round(i))<1e-9)return e}return ht}function Zi(n,t,e){const i=Gi(t),o=n/Dt[t.displayUnit];return new Intl.NumberFormat(e,{minimumFractionDigits:i,maximumFractionDigits:i}).format(o)}function Wi(n,t,e,i,o,s,r){const a=p(),u=n.values.map(h=>Zi(Number(h),t,a)),d=n.values.find(h=>e.getValue(n.name,h)?.isSelected===!0)??n.defaultValue,f=new Li(n.values,{label:n.name,labels:u,unit:t.displayUnit,...d!==void 0&&{initialSelected:d}});return f.onSelect(h=>{o(n.name,h)}),f.onSettle(h=>{i.dispatch(x.SELECT,{attribute:n.name,value:h},!0).defaultPrevented||s(n.name,h)}),r(n.name,h=>{f.setSelected(h.value),i.dispatch(x.SELECTED,{attribute:n.name,value:h.value})}),{element:f.element,setSelectable:()=>{}}}const Yi=5;let Qi=0;function Q(n){const t=n.replace(/([A-Z])/g," $1").trim();return t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()}function Ki(n,t,e,i,o,s){const r=document.createElement("div");r.className="vd-attribute",r.dataset.name=n.name;const a=document.createElement("span");a.className="vd-attribute-label",a.textContent=Q(n.name),a.id=`vd-attribute-label-${Qi++}`,r.appendChild(a),r.setAttribute("role","group"),r.setAttribute("aria-labelledby",a.id);const u=f=>{r.style.display=f?"none":""},d=n.dimension!==void 0?Wi(n,n.dimension,t,e,o,i,s):Xi(n,t,e,i,s);return r.appendChild(d.element),{element:r,setSelectable:d.setSelectable,setHidden:u}}function Xi(n,t,e,i,o){const s=n.values.find(u=>t.getValue(n.name,u)?.isSelected===!0),r=n.values.map(Q),a=n.values.length<=Yi?new Ii(n.values,s,r):new Oi(n.name,n.values,Q(n.name),s,r);return a.onSelect(u=>{e.dispatch(x.SELECT,{attribute:n.name,value:u},!0).defaultPrevented||i(n.name,u)}),o(n.name,u=>{a.setSelected(u.value),e.dispatch(x.SELECTED,{attribute:n.name,value:u.value})}),{element:a.element,setSelectable:u=>{a.setEnabled(u)}}}const Ji=80,to=2500;class eo{constructor(t,e=to){this.configuration=t,this.resetMs=e,this.element=document.createElement("div"),this.element.className="vd-commerce vd-hidden";const i=document.createElement("div");i.className="vd-commerce-price",this.priceEl=document.createElement("span"),this.priceEl.className="vd-price",this.vatEl=document.createElement("span"),this.vatEl.className="vd-vat",i.append(this.priceEl,this.vatEl),this.button=new y({variant:"default",onClick:()=>{this.handleSubmit()}}),this.button.element.classList.add("vd-cta","vd-hidden"),this.element.append(i,this.button.element),this.unsubscribe=this.configuration.onRender(()=>{this.update()}),this.update()}configuration;resetMs;element;priceEl;vatEl;button;unsubscribe;state="idle";resetTimer;update(){this.renderPrice(this.configuration.current),this.renderButton();const t=this.configuration.current!==void 0||this.configuration.submitEnabled;this.element.classList.toggle("vd-hidden",!t)}destroy(){this.unsubscribe(),this.resetTimer!==void 0&&clearTimeout(this.resetTimer),this.element.remove()}renderPrice(t){if(t===void 0){this.priceEl.textContent="",this.vatEl.textContent="";return}this.priceEl.textContent=no(t.price,t.currency),this.vatEl.textContent=pt(this.configuration.vatDisplay)}renderButton(){const t=this.configuration.submitEnabled;this.button.element.classList.toggle("vd-hidden",!t),t&&this.state==="idle"&&this.setButtonText(pt(this.configuration.buttonLabel))}async handleSubmit(){if(this.state!=="busy"){this.setState("busy",$e());try{await this.configuration.submit(),this.setState("success",Ze())}catch{this.setState("failed",He())}this.scheduleReset()}}scheduleReset(){this.resetTimer!==void 0&&clearTimeout(this.resetTimer),this.resetTimer=setTimeout(()=>{this.state="idle",this.update()},this.resetMs)}setState(t,e){this.state=t,this.element.dataset.submit=t,this.button.element.disabled=t==="busy",this.setButtonText(e)}setButtonText(t){this.button.element.textContent=t,this.button.element.setAttribute("aria-label",t)}}function pt(n){return(n??"").slice(0,Ji)}function no(n,t){try{const e=new Intl.NumberFormat(p(),{style:"currency",currency:t}),i=e.resolvedOptions().maximumFractionDigits??2;return e.format(n/10**i)}catch{return`${t} ${(n/100).toFixed(2)}`}}class $t{slot=null;panel=null;attach(t,e){this.panel=e,e.style.display="none",this.slot=document.createElement("div"),this.slot.className="vd-slot-bottom-left",this.slot.appendChild(e),t.appendChild(this.slot)}setVisible(t){this.panel!==null&&(this.panel.style.display=t?"flex":"none")}destroy(){this.slot?.remove(),this.slot=null,this.panel=null}}const io=572;class oo{constructor(t){this.actionBarSlot=t}actionBarSlot;element=null;body=null;openButton=null;closeButton=null;container=null;observer=null;collapsible=!1;expanded=!0;visible=!1;attach(t,e){this.container=t,e.classList.add("vd-attributes-sidebar"),this.closeButton=new y({variant:"ghost",size:"icon-sm",label:Nn(),icon:g.close({size:18}),onClick:()=>{this.expanded=!1,this.render()}});const i=document.createElement("div");i.className="vd-sidebar-header",i.appendChild(this.closeButton.element),this.body=document.createElement("div"),this.body.className="vd-sidebar-body",this.body.appendChild(e),this.element=document.createElement("div"),this.element.className="vd-sidebar vd-hidden",this.element.append(i,this.body),t.appendChild(this.element),this.openButton=new y({variant:"outline",size:"icon",label:Dn(),icon:g.configurator({size:18}),onClick:()=>{this.expanded=!0,this.render()}}),this.openButton.element.classList.add("vd-configurator-toggle","vd-hidden"),this.actionBarSlot.appendChild(this.openButton.element),this.observe()}setVisible(t){this.visible=t,this.render()}destroy(){this.observer?.disconnect(),this.observer=null,this.openButton?.element.remove(),this.element?.remove(),this.container?.classList.remove("vd-layout-sidebar-right","vd-layout-sidebar-permanent"),this.container=null}observe(){typeof ResizeObserver>"u"||this.container===null||(this.observer=new ResizeObserver(t=>{const e=t[0]?.contentRect.width??0;this.setCollapsible(e>0&&e<io)}),this.observer.observe(this.container))}setCollapsible(t){t!==this.collapsible&&(this.collapsible=t,this.expanded=!t,this.render())}render(){if(this.element===null||this.openButton===null||this.closeButton===null||this.container===null)return;const t=this.visible&&this.expanded,e=this.visible&&!this.expanded;this.element.classList.toggle("vd-hidden",!this.visible),this.element.classList.toggle("vd-sidebar-collapsed",e),this.openButton.element.classList.toggle("vd-hidden",!e),this.closeButton.element.style.display=this.collapsible?"":"none",this.container.classList.toggle("vd-layout-sidebar-right",t),this.container.classList.toggle("vd-layout-sidebar-permanent",t&&!this.collapsible)}}class so{attach(t,e){}setVisible(t){}destroy(){}}const ro={"inframe-bottom-left":()=>new $t,"sidebar-right":n=>new oo(n),hidden:()=>new so};function ao(n,t){return(ro[n??""]??(()=>new $t))(t)}const G=S.fontFamily.sans.join(", "),Z=`
400
+ position: absolute;
401
+ display: flex;
402
+ z-index: 10;
403
+ transition: inset-inline-end 0.18s ease;
404
+ `,lo=`
405
+ /* Override browser's default black fullscreen backdrop */
406
+ .vd-container:fullscreen {
407
+ background: oklch(100% 0 0);
408
+ }
409
+
410
+ /* Layout slots — four corners */
411
+ .vd-slot-top-right {
412
+ ${Z}
413
+ inset-block-start: ${l[3]};
414
+ inset-inline-end: ${l[3]};
415
+ flex-direction: column;
416
+ align-items: flex-end;
417
+ gap: ${l[1.5]};
418
+ }
419
+
420
+ .vd-slot-bottom-left {
421
+ ${Z}
422
+ inset-block-end: ${l[3]};
423
+ inset-inline-start: ${l[3]};
424
+ flex-direction: column;
425
+ align-items: flex-start;
426
+ gap: ${l[1.5]};
427
+ }
428
+
429
+ .vd-slot-bottom-right {
430
+ ${Z}
431
+ inset-block-end: ${l[3]};
432
+ inset-inline-end: ${l[3]};
433
+ flex-direction: row;
434
+ gap: ${l[1.5]};
435
+ }
436
+
437
+ /* Component styles — no positioning */
438
+ .vd-camera-controls {
439
+ display: flex;
440
+ flex-direction: column;
441
+ gap: ${l[1]};
442
+ background: color-mix(in oklch, ${m.white} 85%, transparent);
443
+ backdrop-filter: blur(8px);
444
+ border-radius: ${l[2]};
445
+ padding: ${l[2]};
446
+ }
447
+
448
+ .vd-zoom {
449
+ display: flex;
450
+ gap: ${l[.5]};
451
+ }
452
+
453
+ .vd-dpad {
454
+ display: grid;
455
+ grid-template-columns: repeat(3, ${l[9]});
456
+ grid-template-rows: repeat(3, ${l[9]});
457
+ gap: ${l[.5]};
458
+ }
459
+
460
+ .vd-dpad-up { grid-column: 2; grid-row: 1; }
461
+ .vd-dpad-left { grid-column: 1; grid-row: 2; }
462
+ .vd-dpad-center { grid-column: 2; grid-row: 2; }
463
+ .vd-dpad-right { grid-column: 3; grid-row: 2; }
464
+ .vd-dpad-down { grid-column: 2; grid-row: 3; }
465
+
466
+ .vd-attributes {
467
+ display: flex;
468
+ flex-direction: column;
469
+ gap: ${l[3]};
470
+ background: color-mix(in oklch, ${m.white} 85%, transparent);
471
+ backdrop-filter: blur(8px);
472
+ border: 1px solid color-mix(in oklch, ${m.neutral[900]} 8%, transparent);
473
+ border-radius: ${l[3]};
474
+ padding: ${l[3]};
475
+ box-shadow: 0 ${l[1]} ${l[4]} color-mix(in oklch, ${m.neutral[900]} 6%, transparent);
476
+ font-family: ${G};
477
+ }
478
+
479
+ .vd-attribute {
480
+ display: flex;
481
+ flex-direction: column;
482
+ gap: ${l[1.5]};
483
+ }
484
+
485
+ /* Micro-label: recedes so the controls lead. */
486
+ .vd-attribute-label {
487
+ font-size: ${S.fontSize.xs};
488
+ font-weight: ${S.fontWeight.medium};
489
+ color: ${m.neutral[500]};
490
+ text-transform: uppercase;
491
+ letter-spacing: 0.05em;
492
+ font-family: ${G};
493
+ }
494
+
495
+ /* sidebar-right layout — a docked, full-height right panel */
496
+ .vd-container { --vd-sidebar-width: 300px; }
497
+
498
+ .vd-container > iframe {
499
+ width: 100%;
500
+ height: 100%;
501
+ border: none;
502
+ display: block;
503
+ }
504
+
505
+ /* Permanently docked panel (wide embeds, not collapsible): the viewer fills the
506
+ remaining width instead of the panel floating over it. On narrow embeds the
507
+ panel is a temporary tap-to-reveal overlay instead (vd-layout-sidebar-right
508
+ without -permanent), where covering part of the model briefly is expected. */
509
+ .vd-container.vd-layout-sidebar-permanent > iframe {
510
+ width: calc(100% - var(--vd-sidebar-width));
511
+ }
512
+
513
+ .vd-hidden { display: none !important; }
514
+
515
+ /* the "open configurator" toggle joins the shared bottom-right slot as a flex child;
516
+ order pins it after AR/fullscreen regardless of DOM insertion order (MAPPING data,
517
+ which mounts this button, always arrives before the toolbar mounts on ready). */
518
+ .vd-configurator-toggle { order: 1; }
519
+
520
+ .vd-sidebar {
521
+ position: absolute;
522
+ inset-block: 0;
523
+ inset-inline-end: 0;
524
+ inline-size: var(--vd-sidebar-width);
525
+ z-index: 11;
526
+ display: flex;
527
+ flex-direction: column;
528
+ background: color-mix(in oklch, ${m.white} 90%, transparent);
529
+ backdrop-filter: blur(10px);
530
+ border-inline-start: 1px solid color-mix(in oklch, ${m.neutral[900]} 8%, transparent);
531
+ box-shadow: -${l[1]} 0 ${l[4]} color-mix(in oklch, ${m.neutral[900]} 5%, transparent);
532
+ }
533
+
534
+ @media (prefers-reduced-motion: no-preference) {
535
+ .vd-sidebar { transition: transform 0.18s ease; }
536
+ }
537
+
538
+ .vd-sidebar-collapsed { transform: translateX(100%); }
539
+
540
+ .vd-sidebar-header {
541
+ display: flex;
542
+ justify-content: flex-end;
543
+ padding: ${l[1.5]} ${l[1.5]} 0;
544
+ }
545
+
546
+ .vd-sidebar-body {
547
+ flex: 1;
548
+ overflow-y: auto;
549
+ padding: ${l[4]};
550
+ }
551
+
552
+ /* attributes inside the sidebar: flat and full-width — the panel provides the frosting */
553
+ .vd-attributes.vd-attributes-sidebar {
554
+ background: transparent;
555
+ backdrop-filter: none;
556
+ border: none;
557
+ border-radius: 0;
558
+ padding: 0;
559
+ box-shadow: none;
560
+ gap: ${l[5]};
561
+ }
562
+
563
+ /* while the panel is open, keep the corner controls clear of it */
564
+ .vd-layout-sidebar-right .vd-slot-top-right { inset-inline-end: calc(var(--vd-sidebar-width) + ${l[3]}); }
565
+ .vd-layout-sidebar-right .vd-slot-bottom-right { inset-inline-end: calc(var(--vd-sidebar-width) + ${l[3]}); }
566
+
567
+ /* Price + CTA — sit under the attribute controls, separated by a hairline */
568
+ .vd-commerce {
569
+ display: flex;
570
+ flex-direction: column;
571
+ gap: ${l[2]};
572
+ padding-block-start: ${l[3]};
573
+ border-block-start: 1px solid color-mix(in oklch, ${m.neutral[900]} 8%, transparent);
574
+ font-family: ${G};
575
+ }
576
+
577
+ .vd-commerce-price {
578
+ display: flex;
579
+ align-items: baseline;
580
+ gap: ${l[1.5]};
581
+ }
582
+
583
+ .vd-price {
584
+ font-size: ${S.fontSize.lg};
585
+ font-weight: ${S.fontWeight.semibold};
586
+ color: ${m.neutral[900]};
587
+ }
588
+
589
+ .vd-vat {
590
+ font-size: ${S.fontSize.xs};
591
+ color: ${m.neutral[500]};
592
+ }
593
+
594
+ .vd-cta {
595
+ inline-size: 100%;
596
+ justify-content: center;
597
+ }
598
+
599
+ /* Failed submit is the one place red belongs: a clear, recoverable error state. */
600
+ .vd-commerce[data-submit="failed"] .vd-cta {
601
+ background: ${m.semantic.error};
602
+ border-color: ${m.semantic.error};
603
+ color: ${m.white};
604
+ }
605
+
606
+ `;function co(){if(Ft(),document.getElementById("vd-styles")!==null)return;const n=document.createElement("style");n.id="vd-styles",n.textContent=lo,document.head.appendChild(n)}function uo(n,t){const e=document.createElement("a");e.href=`data:image/png;base64,${n}`,e.download=t,e.click()}class ho{options;settings={};container=null;loading=null;slots={topRight:null,bottomRight:null};screenshotBtn=null;actionBar=null;cameraControls=null;attributes=null;groupHandles=new Map;lastSelectable=null;layout=null;commerce=null;constructor(t){this.options=t}attach(t){co(),this.container=t,this.loading=new Vi(t),this.slots.topRight=this.createSlot(t,"vd-slot-top-right"),this.slots.bottomRight=this.createSlot(t,"vd-slot-bottom-right")}onReady(){this.loading?.hide(),this.loading=null,this.mountToolbar(),this.cameraControls!==null&&(this.cameraControls.element.style.display="flex"),this.layout?.setVisible(!0)}mountToolbar(){if(this.actionBar!==null||this.slots.bottomRight===null||this.container===null)return;const t=typeof this.container.requestFullscreen=="function";this.actionBar=new Hi({onAr:this.options.onAr,onFullscreen:t?()=>{this.toggleFullscreen()}:void 0,onAnnotationsToggle:this.options.onAnnotationsToggle}),this.actionBar.applySettings(this.settings),this.slots.bottomRight.appendChild(this.actionBar.element),this.syncScreenshotButton(),this.placeScreenshotButton()}toggleFullscreen(){this.container!==null&&(document.fullscreenElement!==null?document.exitFullscreen():(this.options.onFullscreenEnter?.(),this.container.requestFullscreen()))}updateProgress(t,e){this.loading?.updateProgress(t,e)}showError(t){this.loading?.showError(t)}applyViewerSettings(t){this.settings=t,t.language!==void 0&&Ot(t.language,{reload:!1}),this.syncScreenshotButton(),this.actionBar?.applySettings(t),this.cameraControls!==null&&(this.cameraControls.element.style.display=t.cameraControls===!0?"flex":"none"),this.placeScreenshotButton()}renderAttributeControls(t,e){if(!(this.container===null||this.slots.topRight===null||this.slots.bottomRight===null)&&(this.cameraControls?.element.remove(),this.cameraControls=null,this.teardownConfigurator(),this.settings.cameraControls===!0&&(this.cameraControls=new z(this.options.cameraApi,this.options.cameraPositionApi),this.cameraControls.element.style.display="none",this.slots.topRight.appendChild(this.cameraControls.element)),this.placeScreenshotButton(),e.length!==0)){this.attributes=document.createElement("div"),this.attributes.className="vd-attributes",this.groupHandles=new Map;for(const i of e){const o=Ki(i,t,this.options.eventBus,this.options.onSelect,this.options.onSelectTransient,this.options.onSubscribe);this.groupHandles.set(i.name,o),this.attributes.appendChild(o.element)}this.commerce=new eo(this.options.configuration),this.attributes.appendChild(this.commerce.element),this.layout=ao(this.settings.configuratorLayout,this.slots.bottomRight),this.layout.attach(this.container,this.attributes),this.lastSelectable!==null&&this.applySelectable(this.lastSelectable)}}applySelectable(t){this.lastSelectable=t;for(const[e,i]of this.groupHandles){const o=t.find(s=>s.name===e);i.setSelectable(o?.selectable??null),i.setHidden(o?.hidden===!0)}}get viewerSettings(){return this.settings}teardownConfigurator(){this.commerce?.destroy(),this.commerce=null,this.attributes?.remove(),this.attributes=null,this.groupHandles=new Map,this.layout?.destroy(),this.layout=null}destroy(){this.loading?.destroy(),this.screenshotBtn?.element.remove(),this.actionBar?.destroy(),this.actionBar?.element.remove(),this.cameraControls?.element.remove(),this.teardownConfigurator();for(const t of Object.values(this.slots))t?.remove();this.container=null}createSlot(t,e){const i=document.createElement("div");return i.className=e,t.appendChild(i),i}syncScreenshotButton(){const t=this.settings.screenshot===!0;t&&this.screenshotBtn===null&&(this.screenshotBtn=new y({variant:"outline",size:"icon",label:li(),icon:g.screenshot(),onClick:()=>{this.options.snapshotApi.take("snapshot.png").onDeveloped(({data:e,filename:i})=>{uo(e,i)})}})),!t&&this.screenshotBtn!==null&&(this.screenshotBtn.element.remove(),this.screenshotBtn=null)}placeScreenshotButton(){this.screenshotBtn===null||this.slots.topRight===null||(this.cameraControls!==null?this.cameraControls.element.appendChild(this.screenshotBtn.element):this.slots.topRight.appendChild(this.screenshotBtn.element))}}const po={};class mo{defaultServer="https://server.virtualdisplay.io";options;serverHost;extraParams;constructor(t,e,i){this.options=t,this.serverHost=e,this.extraParams=i}create(){const t=this.createContainer(),e=this.createIframe();return t.appendChild(e),this.attachToParent(t),{container:t,iframe:e}}createContainer(){const t=document.createElement("div");return t.className="vd-container",Object.assign(t.style,{position:"relative",width:"100%",height:"100%",overflow:"hidden"}),t}createIframe(){const t=document.createElement("iframe");return t.src=this.buildUrl(),t.setAttribute("allow","xr-spatial-tracking; fullscreen"),t}attachToParent(t){this.getParentElement().appendChild(t)}buildUrl(){const t=this.getServerUrl(),e=new URL(t);this.setAddressParams(e),this.options.language!==void 0&&e.searchParams.set("language",this.options.language),this.options.session!==void 0&&e.searchParams.set("session",this.options.session),this.options.debug===!0&&e.searchParams.set("debug","true"),this.options.traceparent!==void 0&&e.searchParams.set("traceparent",this.options.traceparent);for(const[i,o]of Object.entries(this.extraParams??{}))e.searchParams.set(i,o);return e.toString()}setAddressParams(t){if(this.options.app===void 0){t.searchParams.set("license",this.options.license),t.searchParams.set("model",this.options.model);return}t.searchParams.set("app",this.options.app),(this.options.license!==void 0||this.options.model!==void 0)&&exports.logger.warn("Both `app` and `license`/`model` were supplied: `app` wins, the pair was ignored")}getServerUrl(){if(this.serverHost!==void 0)return this.serverHost;if(po?.VITE_VIRTUALDISPLAY_SERVER_HOST===void 0)return this.defaultServer}getParentElement(){if(typeof this.options.parent!="string")return this.options.parent;const t=document.querySelector(this.options.parent);if(t===null)throw b.parentNotFound(this.options.parent);return t}}function fo(n){const{messenger:t}=n;t.on(c.HANDSHAKE,e=>{Ht(e)&&(exports.logger.info("Server handshake received, flushing publisher queue"),t.markReady())}),t.on(c.SESSION,e=>{jt(e)&&n.onSession(e.sessionId)}),t.on(c.MUTATION,e=>{Gt(e)&&(n.attributes.handleMutationResult(e),n.configuration.handleSelectionChanged(n.attributes.getSelection()))}),t.on(c.SNAPSHOT,e=>{Zt(e)&&n.snapshot.handleSnapshotResult(e)}),t.on(c.CAMERA,e=>{Wt(e)&&n.cameraPosition.handlePositionUpdate(e)}),t.on(c.LOADING_INDICATOR,e=>{Qt(e)&&(e.error!==void 0?n.ui.showError(e.error):n.ui.updateProgress(e.progress,e.phase))}),t.on(c.CONFIG,e=>{Jt(e)&&n.applyConfig(e)}),t.on(c.MAPPING,e=>{Yt(e)&&(n.attributes.handleMappingReceived(e),n.configuration.handleSelectionChanged(n.attributes.getSelection()),n.ui.renderAttributeControls(n.attributes,e.attributes),n.readyStateTracker.handleMappingReceived())}),go(n)}function go(n){const{messenger:t}=n;t.on(c.FOCUS,e=>{te(e)&&n.focus.handleStateReceived(e)}),t.on(c.PRICING,e=>{ee(e)&&n.configuration.handlePricingReceived(e.pricing)}),t.on(c.SYNC,e=>{Kt(e)&&n.onSync(e.connected)}),t.on(c.SELECTABLE,e=>{Xt(e)&&(n.selectable.handleSnapshot(e),n.ui.applySelectable(e.attributes))}),t.on(c.APP_RESOLVED,e=>{qt(e)&&n.onAppResolved(e)})}class bo{ready=!1;onReady;constructor(t){this.onReady=t}handleMappingReceived(){this.ready||(this.ready=!0,exports.logger.info("Mapping received from server, client is now ready"),this.onReady?.())}get isReady(){return this.ready}clear(){this.ready=!1}}function vo(n){if(n===void 0)return;const{annotations:t,...e}=n;return t===void 0?e:t===!0?{...e,annotations:"show"}:t===!1?{...e,annotations:"hide"}:{...e,annotations:t}}class yo{attributes;selectableState;readyStateTracker;messenger;cameraApi;cameraPositionApi;focusApi;configurationApi;snapshotApi;annotationsApi;eventBus;ui;options;serverHost;iframeParams;arActivation;syncTracker;iframe;container;readyCallbacks=[];mutationFailedCallbacks=[];viewerSessionId;resolvedApp;appResolvedCallbacks=[];constructor(t,e){this.options=t;const i=e??{};this.serverHost=i.serverHost,this.iframeParams=i.iframeParams,this.initializeLogging(),this.messenger=new ne(()=>this.iframe?.contentWindow??null,{onHandlerError:(s,r)=>exports.logger.error(`Error handling ${s.type}`,r),...i.messengerOptions});const o=s=>{this.messenger.send(s)};this.attributes=new Se(o,O,(s,r)=>{this.notifyMutationFailed(s,r)}),this.selectableState=new Ce,this.snapshotApi=new Rt(o),this.annotationsApi=new ft(o,O),this.cameraApi=new kt(o),this.cameraPositionApi=new At,this.focusApi=new xt(o,s=>{this.dispatchFocusChange(s)},O),this.configurationApi=new Et(s=>{this.dispatchConfigurationChange(s)},s=>{this.dispatchConfigurationSubmit(s)}),this.eventBus=new Ae,this.arActivation=i.createArActivation?.(o),this.syncTracker=i.createSyncTracker?.(),this.readyStateTracker=new bo(()=>{this.notifyReady()}),this.ui=this.createStandardInterface(),this.wireIncomingMessages(),i.registerHandlers?.(this.messenger,o),this.messenger.start(),this.createAndConnectIframe()}createStandardInterface(){const t=this.arActivation;return new ho({snapshotApi:this.snapshotApi,cameraApi:this.cameraApi,cameraPositionApi:this.cameraPositionApi,eventBus:this.eventBus,configuration:this.configurationApi,onSelect:(e,i)=>this.attributes.select(e,i),onSelectTransient:(e,i)=>this.attributes.selectTransient(e,i),onSubscribe:(e,i)=>this.attributes.onChange(e,i),...t!==void 0&&{onAr:()=>{t.activate()}},onFullscreenEnter:()=>{this.trackFullscreen()},onAnnotationsToggle:e=>{this.sendControlAnnotationToggle(e)}})}sendControlAnnotationToggle(t){this.messenger.send({type:c.ANNOTATION_TOGGLE,instance:O,enabled:t,origin:"control"})}wireIncomingMessages(){fo({messenger:this.messenger,attributes:this.attributes,selectable:this.selectableState,configuration:this.configurationApi,snapshot:this.snapshotApi,cameraPosition:this.cameraPositionApi,focus:this.focusApi,ui:this.ui,readyStateTracker:this.readyStateTracker,applyConfig:t=>{this.handleConfig(t)},onSession:t=>{this.handleSession(t)},onSync:t=>{this.syncTracker?.handleSync(t)},onAppResolved:t=>{this.handleAppResolved({appType:t.appType,name:t.name,...t.slug!==void 0&&{slug:t.slug},...t.submit!==void 0&&{submit:t.submit}})}})}handleAppResolved(t){this.resolvedApp=t;for(const e of this.appResolvedCallbacks)e(t)}handleSession(t){this.viewerSessionId=t,this.arActivation?.onSession(t)}notifyMutationFailed(t,e){for(const i of this.mutationFailedCallbacks)i({attribute:t,value:e})}notifyReady(){const t=this.readyCallbacks;this.readyCallbacks=[];for(const e of t)e(this);this.ui.onReady()}dispatchFocusChange(t){this.container?.dispatchEvent(new CustomEvent(x.FOCUS_CHANGE,{detail:t,bubbles:!0}))}dispatchConfigurationChange(t){this.container?.dispatchEvent(new CustomEvent(x.CONFIGURATION_CHANGE,{detail:t??null,bubbles:!0}))}dispatchConfigurationSubmit(t){this.container?.dispatchEvent(new CustomEvent(x.CONFIGURATION_SUBMIT,{detail:t,bubbles:!0}))}handleConfig(t){const e=t.viewerSettings,i=vo(this.options.viewerSettings);if(e!==void 0||i!==void 0){const o=i!==void 0?{...e??{},...i}:e;if(i!==void 0&&e!==void 0){const s=Object.entries(i).filter(([r,a])=>e[r]!==a).map(([r,a])=>`${r} (metadata: ${e[r]??"undefined"}, override: ${a})`);s.length>0&&exports.logger.warn(`Viewer settings override active: ${s.join(", ")}`)}this.ui.applyViewerSettings(o),this.echoAnnotationsDifference(e?.annotations,o.annotations)}this.cameraPositionApi.applyLimits(t.cameraLimits)}echoAnnotationsDifference(t,e){e===void 0||e===t||this.annotationsApi.setEnabled(e==="show"||e==="toggle-shown")}trackFullscreen(){this.messenger.send({type:c.FULLSCREEN})}initializeLogging(){this.options.debug===!0&&_t(),exports.logger.info("Initializing Virtualdisplay client",{...this.options.app===void 0?{model:this.options.model}:{app:this.options.app}})}createAndConnectIframe(){const e=new mo(this.options,this.serverHost,this.iframeParams).create();this.container=e.container,this.iframe=e.iframe,this.eventBus.attach(this.container),this.ui.attach(this.container);try{const i=new URL(this.iframe.src).origin;this.messenger.setTargetOrigin(i)}catch{}}select(t,e){this.attributes.select(t,e)}getValues(t){return this.attributes.getValues(t)}getValue(t,e){return this.attributes.getValue(t,e)}onChange(t,e){this.attributes.onChange(t,e)}getAttribute(t){return this.attributes.getAttribute(t)}get isReady(){return this.readyStateTracker.isReady}onReady(t){if(this.readyStateTracker.isReady){t(this);return}this.readyCallbacks.push(t)}onMutationFailed(t){this.mutationFailedCallbacks.push(t)}onSelectableChange(t){this.selectableState.onChange(t)}onAppResolved(t){this.appResolvedCallbacks.push(t),this.resolvedApp!==void 0&&t(this.resolvedApp)}getSelectable(t){return this.selectableState.selectableFor(t)}activateAr(){this.arActivation?.activate()}on(t,e){this.eventBus.on(t,e)}get annotations(){return this.annotationsApi}get camera(){return this.cameraApi}get focus(){return this.focusApi}get configuration(){return this.configurationApi}get cameraPosition(){return this.cameraPositionApi}get snapshot(){return this.snapshotApi}get sessionId(){return this.viewerSessionId}get viewerSettings(){return this.ui.viewerSettings}destroy(){this.readyStateTracker.clear(),this.readyCallbacks=[],this.mutationFailedCallbacks.length=0,this.snapshotApi.clear(),this.messenger.destroy(),this.arActivation?.destroy(),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}}const wo="ar.virtualdisplay.io";function So(n){const t=new URL(`https://${wo}/go`);return n.sessionId!==void 0?t.searchParams.set("session",n.sessionId):n.app!==void 0?t.searchParams.set("app",n.app):n.license!==void 0&&n.model!==void 0&&(t.searchParams.set("license",n.license),t.searchParams.set("model",n.model)),t.toString()}const Co=1500;class _o{options;qrModal=new Pi;sessionId;waiters=[];pendingTimers=new Set;destroyed=!1;constructor(t){this.options=t}onSession(t){this.sessionId=t;const e=this.waiters;this.waiters=[];for(const i of e)i(t)}activate(){if(ve()){this.options.send({type:c.AR_ACTIVATE});return}this.showQrCode()}destroy(){this.destroyed=!0;for(const t of this.pendingTimers)clearTimeout(t);this.pendingTimers.clear(),this.waiters=[],this.qrModal.hide()}async showQrCode(){this.qrModal.show();const t=await this.waitForSessionId();if(this.destroyed)return;const e=So({sessionId:t,app:this.options.app,license:this.options.license,model:this.options.model}),i=await this.qrModal.update(e);if(this.destroyed){this.qrModal.hide();return}i&&this.options.send({type:c.QR_SHOWN})}waitForSessionId(){return this.sessionId!==void 0?Promise.resolve(this.sessionId):new Promise(t=>{const e=setTimeout(()=>{this.pendingTimers.delete(e),t(void 0)},Co);this.pendingTimers.add(e),this.waiters.push(i=>{this.pendingTimers.delete(e),clearTimeout(e),t(i)})})}}class ko{callbacks=[];lastKnown;handleSync(t){this.lastKnown=t;for(const e of this.callbacks)e(t)}onChange(t){this.callbacks.push(t),this.lastKnown!==void 0&&t(this.lastKnown)}}class Ao extends yo{syncStatusTracker;constructor(t){const e=new ko;super(t,{createArActivation:i=>new _o({app:t.app,license:t.license,model:t.model,send:i}),createSyncTracker:()=>e}),this.syncStatusTracker=e}onSyncChange(t){this.syncStatusTracker.onChange(t)}}exports.AVAILABILITY=mt;exports.Annotations=ft;exports.Attribute=bt;exports.AttributeValue=gt;exports.Camera=kt;exports.CameraPosition=At;exports.Configuration=Et;exports.ERROR_CODES=_;exports.Focus=xt;exports.Photo=Tt;exports.Snapshot=Rt;exports.VD_EVENTS=x;exports.VirtualdisplayClient=Ao;exports.VirtualdisplayError=b;exports.enableDebugMode=_t;exports.isDebugMode=we;