1import { 2 vZomeViewerCSS 3} from "./chunk-BXRCXLRH.js"; 4import { 5 decodeEntities 6} from "./chunk-J3RXXGCJ.js"; 7import "./chunk-JSBRDJBE.js"; 8
9// src/wc/index-buttons.js 10var debug = false; 11var VZomeViewerIndexButton = class extends HTMLElement { 12 #next; 13 #end; 14 #viewerId; 15 #viewer; 16 #loadCamera; 17 #button; 18 #maxSceneIndex; 19 constructor(next = true, end = false) { 20 super(); 21 this.#next = next; 22 this.#end = end; 23 this.#loadCamera = false; 24 } 25 #disabled(index) { 26 if (this.#next) 27 return index === this.#maxSceneIndex; 28 else 29 return index === 0; 30 } 31 connectedCallback() { 32 if (!!this.#viewerId) { 33 this.#viewer = document.querySelector(`#${this.#viewerId}`); 34 if (!this.#viewer) { 35 console.error(`No vzome-viewer with id "${this.#viewerId}" found.`); 36 } else if (this.#viewer.nextScene === void 0) { 37 console.error(`Element with id "${this.#viewerId}" is not a vzome-viewer.`); 38 return; 39 } 40 } 41 if (!this.#viewer) { 42 this.#viewer = document.querySelector("vzome-viewer"); 43 } 44 if (!this.#viewer) { 45 console.error(`No vzome-viewer found.`); 46 return; 47 } 48 this.#button = document.createElement("button"); 49 this.#button.textContent = this.getAttribute("label"); 50 this.appendChild(this.#button); 51 this.#button.classList.add("vzome-viewer-index-button"); 52 this.#viewer.addEventListener("vzome-design-rendered", (e) => { 53 const { index } = e.detail; 54 if (this.#disabled(index)) 55 this.#button.setAttribute("disabled", "true"); 56 else 57 this.#button.removeAttribute("disabled"); 58 }); 59 this.#viewer.addEventListener("vzome-scenes-discovered", (e) => { 60 const titles = e.detail; 61 this.#maxSceneIndex = titles.length - 1; 62 }); 63 const loadParams = { camera: this.#loadCamera }; 64 const handler = () => { 65 if (this.#end) { 66 if (this.#next) { 67 this.#viewer.selectScene(-1, loadParams); 68 } else { 69 this.#viewer.selectScene(1, loadParams); 70 } 71 } else if (this.#next) { 72 this.#viewer.nextScene(loadParams); 73 } else { 74 this.#viewer.previousScene(loadParams); 75 } 76 }; 77 this.#button.addEventListener("click", handler); 78 } 79 static get observedAttributes() { 80 return ["viewer", "load-camera"]; 81 } 82 attributeChangedCallback(attributeName, _oldValue, _newValue) { 83 debug && console.log("VZomeViewerIndexButton attribute changed"); 84 switch (attributeName) { 85 case "viewer": 86 this.#viewerId = _newValue; 87 break; 88 case "load-camera": 89 this.#loadCamera = _newValue === "true"; 90 break; 91 } 92 } 93}; 94var VZomeViewerNextButton = class extends VZomeViewerIndexButton { 95 constructor() { 96 super(true); 97 } 98}; 99var VZomeViewerPrevButton = class extends VZomeViewerIndexButton { 100 constructor() { 101 super(false); 102 } 103}; 104var VZomeViewerFirstButton = class extends VZomeViewerIndexButton { 105 constructor() { 106 super(false, true); 107 } 108}; 109var VZomeViewerLastButton = class extends VZomeViewerIndexButton { 110 constructor() { 111 super(true, true); 112 } 113}; 114
115// src/wc/vzome-viewer.js 116var debug2 = false; 117var VZomeViewer = class extends HTMLElement { 118 #root; 119 #container; 120 #config; 121 #reactive; 122 #urlChanged; 123 #sceneChanged; 124 #updateCalled; 125 #loadFlags; 126 #indexed; 127 #numScenes; 128 #sceneIndex; 129 // ranges from 1 to #numScenes 130 #sceneTitles; 131 #whenApiReady; 132 #resolveApiReady; 133 #designPromise; 134 constructor() { 135 super(); 136 this.#root = this.attachShadow({ mode: "open" }); 137 this.#root.appendChild(document.createElement("style")).textContent = vZomeViewerCSS; 138 this.#container = document.createElement("div"); 139 this.#root.appendChild(this.#container); 140 this.#config = { 141 preview: true, 142 showScenes: "none", 143 camera: true, 144 lighting: true, 145 design: true, 146 labels: false, 147 showSettings: true, 148 download: true, 149 useSpinner: false 150 }; 151 this.#whenApiReady = new Promise((resolve) => this.#resolveApiReady = resolve); 152 this.#designPromise = null; 153 this.#indexed = false; 154 this.#urlChanged = true; 155 this.#sceneChanged = false; 156 this.#reactive = true; 157 this.#updateCalled = false; 158 this.#loadFlags = {}; 159 debug2 && console.log("custom element constructed"); 160 } 161 #showIndexedScene(index, loadFlags = { camera: true }) { 162 this.#whenApiReady.then((api) => { 163 api.showIndexedScene(index, loadFlags); 164 }); 165 } 166 selectScene(index, loadFlags = { camera: true }) { 167 debug2 && console.log("User called selectScene()"); 168 if (!this.#indexed) { 169 console.log("This selectScene call ignored; the viewer is not indexed. Set indexed to true if you want to use selectScene."); 170 return; 171 } 172 if (this.#numScenes === void 0) { 173 console.log("This selectScene call ignored; no scenes were discovered."); 174 return; 175 } 176 this.#sceneIndex = index < 0 ? this.#numScenes : 1; 177 this.#showIndexedScene(this.#sceneIndex, loadFlags); 178 } 179 previousScene(loadFlags = { camera: true }) { 180 debug2 && console.log("User called previousScene()"); 181 if (!this.#indexed) { 182 console.log("This previousScene call ignored; the viewer is not indexed. Set indexed to true if you want to use previousScene."); 183 return; 184 } 185 if (this.#numScenes === void 0) { 186 console.log("This previousScene call ignored; no scenes were discovered."); 187 return; 188 } 189 this.#sceneIndex = Math.max(this.#sceneIndex - 1, 1); 190 this.#showIndexedScene(this.#sceneIndex, loadFlags); 191 } 192 nextScene(loadFlags = { camera: true }) { 193 debug2 && console.log("User called nextScene()"); 194 this.#loadFlags = loadFlags; 195 if (!this.#indexed) { 196 console.log("This nextScene call ignored; the viewer is not indexed. Set indexed to true if you want to use nextScene."); 197 return; 198 } 199 if (this.#numScenes === void 0) { 200 console.log("This nextScene call ignored; no scenes were discovered."); 201 return; 202 } 203 this.#sceneIndex = Math.min(this.#sceneIndex + 1, this.#numScenes); 204 this.#showIndexedScene(this.#sceneIndex, loadFlags); 205 } 206 update(loadFlags = { camera: true }) { 207 debug2 && console.log("User called update()"); 208 this.#loadFlags = loadFlags; 209 if (this.#reactive) { 210 console.log("This update call ignored; the viewer is reactive to attribute changes. Set reactive to false if you want programmatic control of the viewer."); 211 return; 212 } 213 this.#updateCalled = true; 214 this.#triggerWorker(); 215 } 216 #triggerWorker() { 217 this.#whenApiReady.then((api) => { 218 const { camera = true, lighting = true, design = true } = this.#loadFlags; 219 const load = { camera, lighting, design }; 220 const config = { ...this.#config, load }; 221 if (this.#config.url && this.#urlChanged) { 222 debug2 && console.log("requesting design"); 223 api.requestDesign(this.#config.url, config); 224 this.#urlChanged = false; 225 } else if (this.#sceneChanged) { 226 debug2 && console.log("requesting scene"); 227 api.showTitledScene(this.#config.sceneTitle, load); 228 } 229 }); 230 } 231 async loadFromText(name, contents) { 232 return this.#whenApiReady.then((api) => { 233 if (!!this.#designPromise) { 234 const errorMsg = "loadFromText ignored; Waiting for previous design to load"; 235 console.log(errorMsg); 236 return Promise.reject(new Error(errorMsg)); 237 } 238 return new Promise((resolve, reject) => { 239 this.#designPromise = { resolve, reject }; 240 api.resetScenes(); 241 api.openText(name, contents); 242 }); 243 }); 244 } 245 async captureImage(format, params = {}) { 246 return this.#whenApiReady.then((api) => { 247 return api.captureImage(format, params); 248 }); 249 } 250 async exportText(format, params = {}) { 251 return this.#whenApiReady.then((api) => { 252 return api.exportAs(format, params); 253 }); 254 } 255 connectedCallback() { 256 const callbacks = { 257 setApi: (api) => { 258 this.#resolveApiReady(api); 259 }, 260 onAlert: (error) => { 261 this.dispatchEvent(new CustomEvent("vzome-design-failed")); 262 if (!!this.#designPromise) { 263 this.#designPromise.reject(error); 264 this.#designPromise = null; 265 } 266 }, 267 onSceneRendered: (sceneIndex) => { 268 --sceneIndex; 269 let scene = {}; 270 if (this.#indexed && !!this.#sceneTitles) 271 scene = { index: sceneIndex, title: this.#sceneTitles[sceneIndex] }; 272 this.dispatchEvent(new CustomEvent("vzome-design-rendered", { detail: scene })); 273 if (!!this.#designPromise) { 274 this.#designPromise.resolve(); 275 this.#designPromise = null; 276 } 277 }, 278 onScenesDiscovered: (scenes) => { 279 this.#numScenes = scenes.length - 1; 280 this.#sceneTitles = scenes.map((scene, i) => scene.title ? decodeEntities(scene.title) : `#${i}`); 281 if (this.#indexed) 282 this.#sceneTitles = this.#sceneTitles.slice(1); 283 this.dispatchEvent(new CustomEvent("vzome-scenes-discovered", { detail: this.#sceneTitles })); 284 this.dispatchEvent(new CustomEvent("vzome-scenes", { detail: scenes.slice(1) })); 285 } 286 }; 287 debug2 && console.log("custom element connected"); 288 import("./vzome-viewer-dynamic.js").then((module) => { 289 debug2 && console.log("dynamic module loaded"); 290 module.renderViewer(this.#container, this.#config, callbacks); 291 if (this.#reactive || this.#updateCalled || this.#indexed) 292 this.#triggerWorker(); 293 }); 294 } 295 static get observedAttributes() { 296 return ["src", "show-scenes", "scene", "load-camera", "reactive", "labels", "show-perspective", "show-settings", "tween-duration", "indexed", "download", "progress"]; 297 } 298 // This callback can happen *before* connectedCallback()! 299 attributeChangedCallback(attributeName, _oldValue, _newValue) { 300 debug2 && console.log("custom element attribute changed"); 301 switch (attributeName) { 302 case "src": 303 const newUrl = new URL(_newValue, window.location).toString(); 304 if (newUrl !== this.#config.url) { 305 this.#config.url = newUrl; 306 this.#urlChanged = true; 307 if (this.#reactive) 308 this.#triggerWorker(); 309 } 310 break; 311 case "scene": 312 if (this.#indexed) 313 break; 314 if (_newValue !== this.#config.sceneTitle) { 315 this.#config = { ...this.#config, sceneTitle: _newValue, showScenes: "given" }; 316 this.#sceneChanged = true; 317 if (this.#reactive) 318 this.#triggerWorker(); 319 } 320 break; 321 case "show-scenes": 322 if (this.#indexed) 323 break; 324 const showScenes = _newValue === "true" ? "all" : _newValue === "fal
324se" ? "none" : _newValue === "named" ? "titled" : _newValue; 325 this.#config = { ...this.#config, showScenes }; 326 break; 327 case "labels": 328 const labels = _newValue === "true"; 329 this.#config = { ...this.#config, labels }; 330 break; 331 case "download": 332 const download = _newValue === "true"; 333 this.#config = { ...this.#config, download }; 334 break; 335 case "progress": 336 const useSpinner = _newValue === "true"; 337 this.#config = { ...this.#config, useSpinner }; 338 break; 339 case "show-perspective": 340 case "show-settings": 341 const showSettings = _newValue === "true"; 342 this.#config = { ...this.#config, showSettings }; 343 break; 344 case "tween-duration": 345 const duration = _newValue; 346 this.#config = { ...this.#config, tweening: { duration } }; 347 this.#whenApiReady.then((api) => api.setTweenDuration(duration)); 348 break; 349 case "reactive": 350 if (this.#indexed) 351 break; 352 this.#reactive = _newValue === "true"; 353 break; 354 case "indexed": 355 if (_newValue !== "true") 356 break; 357 this.#indexed = true; 358 this.#reactive = false; 359 this.#sceneIndex = 1; 360 this.#config = { ...this.#config, showScenes: "indexed" }; 361 break; 362 } 363 } 364 set src(newSrc) { 365 if (newSrc === null) { 366 this.removeAttribute("src"); 367 } else { 368 this.setAttribute("src", newSrc); 369 } 370 } 371 get src() { 372 return this.getAttribute("src"); 373 } 374 set scene(newScene) { 375 if (newScene === null) { 376 this.removeAttribute("scene"); 377 } else { 378 this.setAttribute("scene", newScene); 379 } 380 } 381 get scene() { 382 return this.getAttribute("scene"); 383 } 384 set showScenes(newValue) { 385 if (newValue === null) { 386 this.removeAttribute("show-scenes"); 387 } else { 388 this.setAttribute("show-scenes", newValue); 389 } 390 } 391 get showScenes() { 392 return this.getAttribute("show-scenes"); 393 } 394 set labels(newValue) { 395 if (newValue === null) { 396 this.removeAttribute("labels"); 397 } else { 398 this.setAttribute("labels", newValue); 399 } 400 } 401 get labels() { 402 return this.getAttribute("labels"); 403 } 404 set download(newValue) { 405 if (newValue === null) { 406 this.removeAttribute("download"); 407 } else { 408 this.setAttribute("download", newValue); 409 } 410 } 411 get download() { 412 return this.getAttribute("download"); 413 } 414 set progress(newValue) { 415 if (newValue === null) { 416 this.removeAttribute("progress"); 417 } else { 418 this.setAttribute("progress", newValue); 419 } 420 } 421 get progress() { 422 return this.getAttribute("progress"); 423 } 424 set showPerspective(newValue) { 425 if (newValue === null) { 426 this.removeAttribute("show-settings"); 427 } else { 428 this.setAttribute("show-settings", newValue); 429 } 430 } 431 get showPerspective() { 432 return this.getAttribute("show-settings"); 433 } 434 set showSettings(newValue) { 435 if (newValue === null) { 436 this.removeAttribute("show-settings"); 437 } else { 438 this.setAttribute("show-settings", newValue); 439 } 440 } 441 get showSettings() { 442 return this.getAttribute("show-settings"); 443 } 444 set reactive(value) { 445 this.setAttribute("reactive", value); 446 } 447 get reactive() { 448 return this.getAttribute("reactive"); 449 } 450 // These were briefly supported, so I don't want to break anyone's client code. 451 // We don't support the behavior any more. 452 set loadCamera(newValue) { 453 console.log("loadCamera is no longer supported."); 454 } 455 get loadCamera() { 456 console.log("loadCamera is no longer supported."); 457 return void 0; 458 } 459}; 460customElements.define("vzome-viewer", VZomeViewer); 461customElements.define("vzome-viewer-end", VZomeViewerLastButton); 462customElements.define("vzome-viewer-next", VZomeViewerNextButton); 463customElements.define("vzome-viewer-previous", VZomeViewerPrevButton); 464customElements.define("vzome-viewer-start", VZomeViewerFirstButton);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.