3dviewer-sdk 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +37 -10
- package/dist/index.d.ts +37 -10
- package/dist/index.js +295 -88
- package/dist/index.mjs +295 -88
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -165,7 +165,7 @@ var NodeModule = class {
|
|
|
165
165
|
constructor(viewer) {
|
|
166
166
|
this.viewer = viewer;
|
|
167
167
|
this.on = {
|
|
168
|
-
|
|
168
|
+
// SDK no longer supports first-node-only select events; listen to selectionChange for the full node list.
|
|
169
169
|
selectionChange: (cb) => this.viewer._on("node:selection-change", cb)
|
|
170
170
|
};
|
|
171
171
|
}
|
|
@@ -212,52 +212,75 @@ var FilesModule = class {
|
|
|
212
212
|
// Upload file to conversion server and keep generated baseFileId in session.
|
|
213
213
|
async upload(file) {
|
|
214
214
|
const target = this.resolveFile(file);
|
|
215
|
-
return this.withOperation(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
215
|
+
return this.withOperation(
|
|
216
|
+
{ stage: "uploading", message: "Uploading file..." },
|
|
217
|
+
async () => {
|
|
218
|
+
var _a;
|
|
219
|
+
this.viewer._emit("files:upload:start", { fileName: target.name });
|
|
220
|
+
await this.uploadInternal(target);
|
|
221
|
+
const baseFileId = ((_a = this.getUploadSessionForFile(target)) == null ? void 0 : _a.baseFileId) || "";
|
|
222
|
+
this.viewer._emit("files:upload:success", {
|
|
223
|
+
fileName: target.name,
|
|
224
|
+
baseFileId
|
|
225
|
+
});
|
|
226
|
+
return { fileName: target.name, baseFileId };
|
|
227
|
+
}
|
|
228
|
+
);
|
|
223
229
|
}
|
|
224
230
|
// Trigger conversion flow and resolve final viewer metadata.
|
|
225
231
|
async convert(file, options = {}) {
|
|
226
232
|
const target = this.resolveFile(file);
|
|
227
|
-
return this.withOperation(
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
return this.withOperation(
|
|
234
|
+
{ stage: "converting", message: "Converting file..." },
|
|
235
|
+
async () => {
|
|
236
|
+
this.viewer._emit("files:conversion:start", { fileName: target.name });
|
|
237
|
+
try {
|
|
238
|
+
const prepared = await this.convertInternal(target, options);
|
|
239
|
+
this.viewer._emit("files:conversion:success", prepared);
|
|
240
|
+
return prepared;
|
|
241
|
+
} catch (e) {
|
|
242
|
+
this.viewer._emit("files:conversion:error", {
|
|
243
|
+
fileName: target.name,
|
|
244
|
+
error: this.toErrorMessage(e)
|
|
245
|
+
});
|
|
246
|
+
throw e;
|
|
247
|
+
}
|
|
236
248
|
}
|
|
237
|
-
|
|
249
|
+
);
|
|
238
250
|
}
|
|
239
251
|
// Convenience API: upload first, then convert in one call.
|
|
240
252
|
async prepare(file, options = {}) {
|
|
241
253
|
const target = this.resolveFile(file);
|
|
242
|
-
return this.withOperation(
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
254
|
+
return this.withOperation(
|
|
255
|
+
{ stage: "uploading", message: "Preparing file..." },
|
|
256
|
+
async () => {
|
|
257
|
+
await this.uploadInternal(target);
|
|
258
|
+
const prepared = await this.convertInternal(target, options);
|
|
259
|
+
return prepared;
|
|
260
|
+
}
|
|
261
|
+
);
|
|
247
262
|
}
|
|
248
263
|
// Trigger the newer downloadUrl-based conversion flow.
|
|
249
264
|
async convertV2(options) {
|
|
250
|
-
return this.withOperation(
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
265
|
+
return this.withOperation(
|
|
266
|
+
{ stage: "converting", message: "Converting file..." },
|
|
267
|
+
async () => {
|
|
268
|
+
this.viewer._emit("files:conversion:start", {
|
|
269
|
+
fileName: options.filename
|
|
270
|
+
});
|
|
271
|
+
try {
|
|
272
|
+
const prepared = await this.convertV2Internal(options);
|
|
273
|
+
this.viewer._emit("files:conversion:success", prepared);
|
|
274
|
+
return prepared;
|
|
275
|
+
} catch (e) {
|
|
276
|
+
this.viewer._emit("files:conversion:error", {
|
|
277
|
+
fileName: options.filename,
|
|
278
|
+
error: this.toErrorMessage(e)
|
|
279
|
+
});
|
|
280
|
+
throw e;
|
|
281
|
+
}
|
|
259
282
|
}
|
|
260
|
-
|
|
283
|
+
);
|
|
261
284
|
}
|
|
262
285
|
// Check stream file info by one or more baseFileId values.
|
|
263
286
|
async checkFileInfo(baseFileIds) {
|
|
@@ -273,7 +296,9 @@ var FilesModule = class {
|
|
|
273
296
|
body: JSON.stringify(payload)
|
|
274
297
|
});
|
|
275
298
|
if (!response.ok) {
|
|
276
|
-
throw new Error(
|
|
299
|
+
throw new Error(
|
|
300
|
+
`Check file info failed (${response.status} ${response.statusText})`
|
|
301
|
+
);
|
|
277
302
|
}
|
|
278
303
|
const text = await response.text();
|
|
279
304
|
if (!text) return null;
|
|
@@ -291,27 +316,34 @@ var FilesModule = class {
|
|
|
291
316
|
this.viewer.open(url);
|
|
292
317
|
this.viewer._emit("files:render:success", { url });
|
|
293
318
|
} catch (e) {
|
|
294
|
-
this.viewer._emit("files:render:error", {
|
|
319
|
+
this.viewer._emit("files:render:error", {
|
|
320
|
+
url,
|
|
321
|
+
error: this.toErrorMessage(e)
|
|
322
|
+
});
|
|
295
323
|
throw e;
|
|
296
324
|
}
|
|
297
325
|
}
|
|
298
326
|
// Full pipeline: upload + convert + open iframe.
|
|
299
327
|
async render(file, options = {}) {
|
|
300
328
|
const target = this.resolveFile(file);
|
|
301
|
-
return this.withOperation(
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
329
|
+
return this.withOperation(
|
|
330
|
+
{ stage: "uploading", message: "Uploading + converting + opening..." },
|
|
331
|
+
async () => {
|
|
332
|
+
await this.upload(target);
|
|
333
|
+
const prepared = await this.convert(target, options);
|
|
334
|
+
this.updateState({ stage: "rendering", message: "Opening viewer..." });
|
|
335
|
+
this.open(prepared);
|
|
336
|
+
this.viewer._emit("files:load:success", prepared);
|
|
337
|
+
return prepared;
|
|
338
|
+
}
|
|
339
|
+
);
|
|
309
340
|
}
|
|
310
341
|
// Resolve file argument, fallback to options.file, and persist it back.
|
|
311
342
|
resolveFile(file) {
|
|
312
343
|
const optFile = this.viewer.getOptions().file;
|
|
313
344
|
const target = file || optFile;
|
|
314
|
-
if (!target)
|
|
345
|
+
if (!target)
|
|
346
|
+
throw new Error("No file provided. Pass a File or set options.file");
|
|
315
347
|
this.viewer.patchOptions({ file: target });
|
|
316
348
|
return target;
|
|
317
349
|
}
|
|
@@ -332,7 +364,8 @@ var FilesModule = class {
|
|
|
332
364
|
if (viewerUrl) {
|
|
333
365
|
try {
|
|
334
366
|
const pathname = new URL(viewerUrl, window.location.href).pathname;
|
|
335
|
-
if (pathname && pathname !== "/")
|
|
367
|
+
if (pathname && pathname !== "/")
|
|
368
|
+
return this.normalizeViewerPath(pathname);
|
|
336
369
|
} catch {
|
|
337
370
|
}
|
|
338
371
|
}
|
|
@@ -349,14 +382,18 @@ var FilesModule = class {
|
|
|
349
382
|
const configuredViewerBaseUrl = this.config.baseUrl || this.viewer.getOptions().baseUrl;
|
|
350
383
|
if (configuredViewerBaseUrl) {
|
|
351
384
|
try {
|
|
352
|
-
return this.normalizeBaseUrl(
|
|
385
|
+
return this.normalizeBaseUrl(
|
|
386
|
+
new URL(configuredViewerBaseUrl, window.location.href).origin
|
|
387
|
+
);
|
|
353
388
|
} catch {
|
|
354
389
|
}
|
|
355
390
|
}
|
|
356
391
|
const viewerUrl = this.viewer.getOptions().url;
|
|
357
392
|
if (viewerUrl) {
|
|
358
393
|
try {
|
|
359
|
-
return this.normalizeBaseUrl(
|
|
394
|
+
return this.normalizeBaseUrl(
|
|
395
|
+
new URL(viewerUrl, window.location.href).origin
|
|
396
|
+
);
|
|
360
397
|
} catch {
|
|
361
398
|
}
|
|
362
399
|
}
|
|
@@ -377,7 +414,8 @@ var FilesModule = class {
|
|
|
377
414
|
}
|
|
378
415
|
// Create a UUID-like baseFileId when caller does not provide one.
|
|
379
416
|
createBaseFileId() {
|
|
380
|
-
if (typeof crypto !== "undefined" && "randomUUID" in crypto)
|
|
417
|
+
if (typeof crypto !== "undefined" && "randomUUID" in crypto)
|
|
418
|
+
return crypto.randomUUID();
|
|
381
419
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
382
420
|
const r = Math.floor(Math.random() * 16);
|
|
383
421
|
const v = c === "x" ? r : r & 3 | 8;
|
|
@@ -408,15 +446,25 @@ var FilesModule = class {
|
|
|
408
446
|
const session = existing || this.createUploadSession(file);
|
|
409
447
|
const hostConversion = this.resolveHostConversion();
|
|
410
448
|
const path = this.getUploadPath();
|
|
411
|
-
const url = `${hostConversion}/api/File/upload?path=${encodeURIComponent(
|
|
449
|
+
const url = `${hostConversion}/api/File/upload?path=${encodeURIComponent(
|
|
450
|
+
path
|
|
451
|
+
)}`;
|
|
412
452
|
const formData = new FormData();
|
|
413
453
|
formData.append("file", file, file.name);
|
|
414
|
-
const res = await fetch(url, {
|
|
415
|
-
|
|
454
|
+
const res = await fetch(url, {
|
|
455
|
+
method: "POST",
|
|
456
|
+
body: formData,
|
|
457
|
+
headers: { Accept: "text/plain" }
|
|
458
|
+
});
|
|
459
|
+
if (!res.ok)
|
|
460
|
+
throw new Error(`Upload failed (${res.status} ${res.statusText})`);
|
|
416
461
|
this.lastUploadSession = session;
|
|
417
462
|
} catch (e) {
|
|
418
463
|
const msg = this.toErrorMessage(e);
|
|
419
|
-
this.viewer._emit("files:upload:error", {
|
|
464
|
+
this.viewer._emit("files:upload:error", {
|
|
465
|
+
fileName: file.name,
|
|
466
|
+
error: msg
|
|
467
|
+
});
|
|
420
468
|
throw e;
|
|
421
469
|
}
|
|
422
470
|
}
|
|
@@ -570,11 +618,20 @@ var FilesModule = class {
|
|
|
570
618
|
const baseMajorRev = (_b = cacheResult.baseMajorRev) != null ? _b : 0;
|
|
571
619
|
const baseMinorRev = (_c = cacheResult.baseMinorRev) != null ? _c : 0;
|
|
572
620
|
const fileName = cacheResult.filename || cacheResult.fileName || file.name;
|
|
573
|
-
const cacheListItem = {
|
|
621
|
+
const cacheListItem = {
|
|
622
|
+
baseFileId,
|
|
623
|
+
baseMajorRev,
|
|
624
|
+
baseMinorRev,
|
|
625
|
+
fileName
|
|
626
|
+
};
|
|
574
627
|
if (cacheResult.cacheStatus !== 2) {
|
|
575
|
-
throw new Error(
|
|
628
|
+
throw new Error(
|
|
629
|
+
`Conversion not ready after first request (cacheStatus=${(_d = cacheResult.cacheStatus) != null ? _d : "unknown"})`
|
|
630
|
+
);
|
|
576
631
|
}
|
|
577
|
-
const query = new URLSearchParams({
|
|
632
|
+
const query = new URLSearchParams({
|
|
633
|
+
fileList: JSON.stringify([cacheListItem])
|
|
634
|
+
}).toString();
|
|
578
635
|
const viewerBase = this.resolveViewerOrigin();
|
|
579
636
|
const viewerPath = this.resolveViewerPath();
|
|
580
637
|
const url = `${viewerBase}${viewerPath}?${query}`;
|
|
@@ -589,10 +646,19 @@ var FilesModule = class {
|
|
|
589
646
|
const baseMinorRev = (_e = (_d = cacheResult.baseMinorRev) != null ? _d : options.baseMinorRev) != null ? _e : 0;
|
|
590
647
|
const fileName = cacheResult.filename || cacheResult.fileName || options.filename;
|
|
591
648
|
if (cacheResult.cacheStatus !== void 0 && cacheResult.cacheStatus !== 2) {
|
|
592
|
-
throw new Error(
|
|
649
|
+
throw new Error(
|
|
650
|
+
`Conversion not ready after v2 request (cacheStatus=${cacheResult.cacheStatus})`
|
|
651
|
+
);
|
|
593
652
|
}
|
|
594
|
-
const cacheListItem = {
|
|
595
|
-
|
|
653
|
+
const cacheListItem = {
|
|
654
|
+
baseFileId,
|
|
655
|
+
baseMajorRev,
|
|
656
|
+
baseMinorRev,
|
|
657
|
+
fileName
|
|
658
|
+
};
|
|
659
|
+
const query = new URLSearchParams({
|
|
660
|
+
fileList: JSON.stringify([cacheListItem])
|
|
661
|
+
}).toString();
|
|
596
662
|
const viewerBase = this.resolveViewerOrigin();
|
|
597
663
|
const viewerPath = this.resolveViewerPath();
|
|
598
664
|
const url = `${viewerBase}${viewerPath}?${query}`;
|
|
@@ -603,6 +669,15 @@ var FilesModule = class {
|
|
|
603
669
|
const elapsedMs = this.operationStartTime > 0 ? Date.now() - this.operationStartTime : 0;
|
|
604
670
|
this.state = { ...this.state, ...next, elapsedMs };
|
|
605
671
|
this.viewer._emit("files:state", this.state);
|
|
672
|
+
this.viewer._emit("loading:change", {
|
|
673
|
+
loading: this.state.isLoading,
|
|
674
|
+
phase: this.toViewerLoadingPhase(this.state.stage)
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
toViewerLoadingPhase(stage) {
|
|
678
|
+
if (stage === "error") return "error";
|
|
679
|
+
if (stage === "idle" || stage === "completed") return "ready";
|
|
680
|
+
return "loading";
|
|
606
681
|
}
|
|
607
682
|
// Shared wrapper to handle loading state lifecycle and top-level errors.
|
|
608
683
|
async withOperation(initial, run) {
|
|
@@ -614,7 +689,11 @@ var FilesModule = class {
|
|
|
614
689
|
});
|
|
615
690
|
try {
|
|
616
691
|
const result = await run();
|
|
617
|
-
this.updateState({
|
|
692
|
+
this.updateState({
|
|
693
|
+
isLoading: false,
|
|
694
|
+
stage: "completed",
|
|
695
|
+
message: "Completed"
|
|
696
|
+
});
|
|
618
697
|
return result;
|
|
619
698
|
} catch (e) {
|
|
620
699
|
const msg = this.toErrorMessage(e);
|
|
@@ -1267,12 +1346,50 @@ var Viewer3D = class {
|
|
|
1267
1346
|
this.containerEl = null;
|
|
1268
1347
|
this.iframeEl = null;
|
|
1269
1348
|
this.initialized = false;
|
|
1349
|
+
this.viewerReady = false;
|
|
1350
|
+
this.readyPayload = null;
|
|
1351
|
+
this.readyWaiters = [];
|
|
1352
|
+
this.loadingState = {
|
|
1353
|
+
loading: false,
|
|
1354
|
+
phase: "ready"
|
|
1355
|
+
};
|
|
1270
1356
|
this.emitter = new Emitter();
|
|
1271
1357
|
this.handleMessage = (event) => {
|
|
1272
|
-
var _a, _b, _c
|
|
1358
|
+
var _a, _b, _c;
|
|
1273
1359
|
const data = event.data;
|
|
1274
1360
|
if (!data || typeof data !== "object") return;
|
|
1275
1361
|
switch (data.type) {
|
|
1362
|
+
case "viewer-loading-change" /* LOADING_CHANGE */: {
|
|
1363
|
+
const payload = data.payload;
|
|
1364
|
+
if (!payload) break;
|
|
1365
|
+
this.setLoadingState({
|
|
1366
|
+
loading: Boolean(payload.loading),
|
|
1367
|
+
phase: payload.phase,
|
|
1368
|
+
viewId: payload.viewId ? String(payload.viewId) : void 0,
|
|
1369
|
+
modelFileId: payload.modelFileId ? String(payload.modelFileId) : void 0,
|
|
1370
|
+
timestamp: payload.timestamp ? Number(payload.timestamp) : void 0
|
|
1371
|
+
});
|
|
1372
|
+
break;
|
|
1373
|
+
}
|
|
1374
|
+
case "viewer-ready" /* READY */: {
|
|
1375
|
+
const payload = data.payload;
|
|
1376
|
+
const readyPayload = {
|
|
1377
|
+
ready: true,
|
|
1378
|
+
viewId: (payload == null ? void 0 : payload.viewId) ? String(payload.viewId) : void 0,
|
|
1379
|
+
modelFileId: (payload == null ? void 0 : payload.modelFileId) ? String(payload.modelFileId) : void 0,
|
|
1380
|
+
timestamp: Number(payload == null ? void 0 : payload.timestamp) || Date.now()
|
|
1381
|
+
};
|
|
1382
|
+
this.setLoadingState({
|
|
1383
|
+
loading: false,
|
|
1384
|
+
phase: "ready",
|
|
1385
|
+
viewId: readyPayload.viewId,
|
|
1386
|
+
modelFileId: readyPayload.modelFileId,
|
|
1387
|
+
timestamp: readyPayload.timestamp
|
|
1388
|
+
});
|
|
1389
|
+
this.resolveReady(readyPayload);
|
|
1390
|
+
this._emit("viewer:ready", readyPayload);
|
|
1391
|
+
break;
|
|
1392
|
+
}
|
|
1276
1393
|
case "viewer-home-click" /* HOME_CLICK */:
|
|
1277
1394
|
this._emit("camera:home", { timestamp: Date.now() });
|
|
1278
1395
|
break;
|
|
@@ -1287,9 +1404,6 @@ var Viewer3D = class {
|
|
|
1287
1404
|
});
|
|
1288
1405
|
break;
|
|
1289
1406
|
}
|
|
1290
|
-
case "viewer-node-select" /* NODE_SELECT */:
|
|
1291
|
-
this._emit("node:select", { nodeId: String((_b = (_a = data.payload) == null ? void 0 : _a.nodeId) != null ? _b : ""), timestamp: Date.now() });
|
|
1292
|
-
break;
|
|
1293
1407
|
case "viewer-node-selection-change" /* NODE_SELECTION_CHANGE */: {
|
|
1294
1408
|
const payload = data.payload;
|
|
1295
1409
|
const rawNodeIds = payload == null ? void 0 : payload.nodeIds;
|
|
@@ -1301,7 +1415,9 @@ var Viewer3D = class {
|
|
|
1301
1415
|
break;
|
|
1302
1416
|
}
|
|
1303
1417
|
case "viewer-pan-change" /* PAN_CHANGE */:
|
|
1304
|
-
this._emit("interaction:pan-change", {
|
|
1418
|
+
this._emit("interaction:pan-change", {
|
|
1419
|
+
enabled: Boolean((_a = data.payload) == null ? void 0 : _a.enabled)
|
|
1420
|
+
});
|
|
1305
1421
|
break;
|
|
1306
1422
|
case "viewer-pdf-plan-mode" /* PDF_PLAN_MODE */: {
|
|
1307
1423
|
const payload = data.payload;
|
|
@@ -1359,7 +1475,8 @@ var Viewer3D = class {
|
|
|
1359
1475
|
}
|
|
1360
1476
|
case "viewer-tree-node-ids" /* TREE_NODE_IDS */: {
|
|
1361
1477
|
const payload = data.payload;
|
|
1362
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.nodeIds))
|
|
1478
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.nodeIds))
|
|
1479
|
+
break;
|
|
1363
1480
|
this._emit("modelTree:node-ids", {
|
|
1364
1481
|
requestId: String(payload.requestId),
|
|
1365
1482
|
nodeIds: payload.nodeIds.map(String),
|
|
@@ -1369,7 +1486,8 @@ var Viewer3D = class {
|
|
|
1369
1486
|
}
|
|
1370
1487
|
case "viewer-tree-nodes" /* TREE_NODES */: {
|
|
1371
1488
|
const payload = data.payload;
|
|
1372
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.nodes))
|
|
1489
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.nodes))
|
|
1490
|
+
break;
|
|
1373
1491
|
this._emit("modelTree:nodes", {
|
|
1374
1492
|
requestId: String(payload.requestId),
|
|
1375
1493
|
nodes: payload.nodes.filter((node) => node && typeof node === "object").map((node) => {
|
|
@@ -1395,7 +1513,8 @@ var Viewer3D = class {
|
|
|
1395
1513
|
}
|
|
1396
1514
|
case "viewer-sheets-list" /* SHEETS_LIST */: {
|
|
1397
1515
|
const payload = data.payload;
|
|
1398
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.sheets))
|
|
1516
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.sheets))
|
|
1517
|
+
break;
|
|
1399
1518
|
this._emit("sheets:list", {
|
|
1400
1519
|
requestId: String(payload.requestId),
|
|
1401
1520
|
sheets: payload.sheets.map((sheet) => {
|
|
@@ -1407,17 +1526,18 @@ var Viewer3D = class {
|
|
|
1407
1526
|
viewId: sheet.viewId ? String(sheet.viewId) : void 0
|
|
1408
1527
|
};
|
|
1409
1528
|
}),
|
|
1410
|
-
activeSheetId: (
|
|
1529
|
+
activeSheetId: (_b = payload.activeSheetId) != null ? _b : null,
|
|
1411
1530
|
timestamp: Number(payload.timestamp) || Date.now()
|
|
1412
1531
|
});
|
|
1413
1532
|
break;
|
|
1414
1533
|
}
|
|
1415
1534
|
case "viewer-object-properties-list" /* OBJECT_PROPERTIES_LIST */: {
|
|
1416
1535
|
const payload = data.payload;
|
|
1417
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.properties))
|
|
1536
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.properties))
|
|
1537
|
+
break;
|
|
1418
1538
|
this._emit("object-properties:list", {
|
|
1419
1539
|
requestId: String(payload.requestId),
|
|
1420
|
-
selectionKey: String((
|
|
1540
|
+
selectionKey: String((_c = payload.selectionKey) != null ? _c : ""),
|
|
1421
1541
|
nodeIds: Array.isArray(payload.nodeIds) ? payload.nodeIds.map(String) : [],
|
|
1422
1542
|
persistentIds: Array.isArray(payload.persistentIds) ? payload.persistentIds.map(String) : [],
|
|
1423
1543
|
properties: payload.properties.filter((item) => item && typeof item === "object").map((item) => ({ ...item })),
|
|
@@ -1427,7 +1547,8 @@ var Viewer3D = class {
|
|
|
1427
1547
|
}
|
|
1428
1548
|
case "viewer-linked-objects-list" /* LINKED_OBJECTS_LIST */: {
|
|
1429
1549
|
const payload = data.payload;
|
|
1430
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.linkedObjects))
|
|
1550
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.linkedObjects))
|
|
1551
|
+
break;
|
|
1431
1552
|
this._emit("linked-objects:list", {
|
|
1432
1553
|
requestId: String(payload.requestId),
|
|
1433
1554
|
linkedObjects: payload.linkedObjects.filter((item) => item && typeof item === "object").map((item) => ({ ...item })),
|
|
@@ -1437,11 +1558,12 @@ var Viewer3D = class {
|
|
|
1437
1558
|
}
|
|
1438
1559
|
case "viewer-states-objects-list" /* STATES_OBJECTS_LIST */: {
|
|
1439
1560
|
const payload = data.payload;
|
|
1440
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.statesObjects))
|
|
1561
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.statesObjects))
|
|
1562
|
+
break;
|
|
1441
1563
|
this._emit("states-objects:list", {
|
|
1442
1564
|
requestId: String(payload.requestId),
|
|
1443
1565
|
statesObjects: payload.statesObjects.map((item) => {
|
|
1444
|
-
var _a2, _b2, _c2,
|
|
1566
|
+
var _a2, _b2, _c2, _d, _e, _f, _g;
|
|
1445
1567
|
return {
|
|
1446
1568
|
id: String((_a2 = item.id) != null ? _a2 : ""),
|
|
1447
1569
|
name: String((_b2 = item.name) != null ? _b2 : ""),
|
|
@@ -1454,7 +1576,7 @@ var Viewer3D = class {
|
|
|
1454
1576
|
};
|
|
1455
1577
|
}) : [],
|
|
1456
1578
|
states: {
|
|
1457
|
-
color: String((
|
|
1579
|
+
color: String((_e = (_d = item.states) == null ? void 0 : _d.color) != null ? _e : ""),
|
|
1458
1580
|
type: String((_g = (_f = item.states) == null ? void 0 : _f.type) != null ? _g : "")
|
|
1459
1581
|
}
|
|
1460
1582
|
};
|
|
@@ -1465,7 +1587,8 @@ var Viewer3D = class {
|
|
|
1465
1587
|
}
|
|
1466
1588
|
case "viewer-markup-list" /* MARKUP_LIST */: {
|
|
1467
1589
|
const payload = data.payload;
|
|
1468
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.markups))
|
|
1590
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.markups))
|
|
1591
|
+
break;
|
|
1469
1592
|
this._emit("markup:list", {
|
|
1470
1593
|
requestId: String(payload.requestId),
|
|
1471
1594
|
markups: payload.markups.map((markup) => {
|
|
@@ -1534,6 +1657,36 @@ var Viewer3D = class {
|
|
|
1534
1657
|
var _a;
|
|
1535
1658
|
return (_a = this.options.url) != null ? _a : null;
|
|
1536
1659
|
}
|
|
1660
|
+
on(event, cb) {
|
|
1661
|
+
return this._on(event, cb);
|
|
1662
|
+
}
|
|
1663
|
+
off(event, cb) {
|
|
1664
|
+
this._off(event, cb);
|
|
1665
|
+
}
|
|
1666
|
+
getLoadingState() {
|
|
1667
|
+
return { ...this.loadingState };
|
|
1668
|
+
}
|
|
1669
|
+
ready(options) {
|
|
1670
|
+
if (this.viewerReady && this.readyPayload) {
|
|
1671
|
+
return Promise.resolve({ ...this.readyPayload });
|
|
1672
|
+
}
|
|
1673
|
+
const timeoutMs = options == null ? void 0 : options.timeoutMs;
|
|
1674
|
+
return new Promise((resolve, reject) => {
|
|
1675
|
+
const waiter = {
|
|
1676
|
+
resolve: (payload) => resolve({ ...payload }),
|
|
1677
|
+
reject
|
|
1678
|
+
};
|
|
1679
|
+
if (typeof timeoutMs === "number" && timeoutMs > 0) {
|
|
1680
|
+
waiter.timer = setTimeout(() => {
|
|
1681
|
+
this.readyWaiters = this.readyWaiters.filter(
|
|
1682
|
+
(item) => item !== waiter
|
|
1683
|
+
);
|
|
1684
|
+
reject(new Error("Timeout while waiting for viewer to be ready"));
|
|
1685
|
+
}, timeoutMs);
|
|
1686
|
+
}
|
|
1687
|
+
this.readyWaiters.push(waiter);
|
|
1688
|
+
});
|
|
1689
|
+
}
|
|
1537
1690
|
// ===== lifecycle =====
|
|
1538
1691
|
init() {
|
|
1539
1692
|
if (this.initialized) return;
|
|
@@ -1545,7 +1698,12 @@ var Viewer3D = class {
|
|
|
1545
1698
|
async render(file) {
|
|
1546
1699
|
this.ensureInit();
|
|
1547
1700
|
if (this.iframeEl) return;
|
|
1701
|
+
this.resetReadyState();
|
|
1548
1702
|
if (!this.options.url) return this.files.render(file);
|
|
1703
|
+
this.setLoadingState({
|
|
1704
|
+
loading: true,
|
|
1705
|
+
phase: "loading"
|
|
1706
|
+
});
|
|
1549
1707
|
const iframe = document.createElement("iframe");
|
|
1550
1708
|
iframe.src = this.withInitialOptions(this.options.url);
|
|
1551
1709
|
iframe.style.border = "none";
|
|
@@ -1553,13 +1711,19 @@ var Viewer3D = class {
|
|
|
1553
1711
|
iframe.style.height = this.options.height || "100%";
|
|
1554
1712
|
iframe.width = this.options.width || "100%";
|
|
1555
1713
|
iframe.height = this.options.height || "100%";
|
|
1556
|
-
if (this.options.sandbox)
|
|
1714
|
+
if (this.options.sandbox)
|
|
1715
|
+
iframe.setAttribute("sandbox", this.options.sandbox);
|
|
1557
1716
|
this.containerEl.appendChild(iframe);
|
|
1558
1717
|
this.iframeEl = iframe;
|
|
1559
1718
|
}
|
|
1560
1719
|
open(url) {
|
|
1561
1720
|
this.ensureInit();
|
|
1562
1721
|
this.options.url = url;
|
|
1722
|
+
this.resetReadyState();
|
|
1723
|
+
this.setLoadingState({
|
|
1724
|
+
loading: true,
|
|
1725
|
+
phase: "loading"
|
|
1726
|
+
});
|
|
1563
1727
|
const finalUrl = this.withInitialOptions(url);
|
|
1564
1728
|
if (!this.iframeEl) {
|
|
1565
1729
|
this.render();
|
|
@@ -1578,16 +1742,27 @@ var Viewer3D = class {
|
|
|
1578
1742
|
this.iframeEl = null;
|
|
1579
1743
|
this.containerEl = null;
|
|
1580
1744
|
this.initialized = false;
|
|
1745
|
+
this.rejectReadyWaiters(
|
|
1746
|
+
new Error("Viewer was destroyed before becoming ready")
|
|
1747
|
+
);
|
|
1581
1748
|
}
|
|
1582
1749
|
ensureInit() {
|
|
1583
|
-
if (!this.initialized)
|
|
1750
|
+
if (!this.initialized)
|
|
1751
|
+
throw new Error("Call viewer.init() before using viewer");
|
|
1584
1752
|
}
|
|
1585
1753
|
withInitialOptions(url) {
|
|
1754
|
+
var _a;
|
|
1586
1755
|
try {
|
|
1587
1756
|
const parsedUrl = new URL(url, window.location.href);
|
|
1588
1757
|
const initialToolbar = this.normalizeInitialToolbar();
|
|
1589
1758
|
if (initialToolbar) {
|
|
1590
|
-
parsedUrl.searchParams.set(
|
|
1759
|
+
parsedUrl.searchParams.set(
|
|
1760
|
+
"useToolbar",
|
|
1761
|
+
JSON.stringify(initialToolbar)
|
|
1762
|
+
);
|
|
1763
|
+
}
|
|
1764
|
+
if (((_a = this.options.ui) == null ? void 0 : _a.loadingIndicator) === false) {
|
|
1765
|
+
parsedUrl.searchParams.set("loadingIndicator", "false");
|
|
1591
1766
|
}
|
|
1592
1767
|
return parsedUrl.toString();
|
|
1593
1768
|
} catch {
|
|
@@ -1601,17 +1776,25 @@ var Viewer3D = class {
|
|
|
1601
1776
|
return { [initialToolbar]: true };
|
|
1602
1777
|
}
|
|
1603
1778
|
if (Array.isArray(initialToolbar)) {
|
|
1604
|
-
return initialToolbar.reduce(
|
|
1605
|
-
result
|
|
1606
|
-
|
|
1607
|
-
|
|
1779
|
+
return initialToolbar.reduce(
|
|
1780
|
+
(result, target) => {
|
|
1781
|
+
result[target] = true;
|
|
1782
|
+
return result;
|
|
1783
|
+
},
|
|
1784
|
+
{}
|
|
1785
|
+
);
|
|
1608
1786
|
}
|
|
1609
|
-
const entries = Object.entries(initialToolbar).filter(
|
|
1787
|
+
const entries = Object.entries(initialToolbar).filter(
|
|
1788
|
+
([, enabled]) => enabled === true
|
|
1789
|
+
);
|
|
1610
1790
|
if (entries.length === 0) return null;
|
|
1611
|
-
return entries.reduce(
|
|
1612
|
-
result[target]
|
|
1613
|
-
|
|
1614
|
-
|
|
1791
|
+
return entries.reduce(
|
|
1792
|
+
(result, [target]) => {
|
|
1793
|
+
result[target] = true;
|
|
1794
|
+
return result;
|
|
1795
|
+
},
|
|
1796
|
+
{}
|
|
1797
|
+
);
|
|
1615
1798
|
}
|
|
1616
1799
|
// ===== typed internal events used by modules =====
|
|
1617
1800
|
_on(event, cb) {
|
|
@@ -1623,6 +1806,30 @@ var Viewer3D = class {
|
|
|
1623
1806
|
_emit(event, payload) {
|
|
1624
1807
|
this.emitter.emit(event, payload);
|
|
1625
1808
|
}
|
|
1809
|
+
resetReadyState() {
|
|
1810
|
+
this.viewerReady = false;
|
|
1811
|
+
this.readyPayload = null;
|
|
1812
|
+
}
|
|
1813
|
+
setLoadingState(payload) {
|
|
1814
|
+
this.loadingState = { ...payload };
|
|
1815
|
+
this._emit("loading:change", this.loadingState);
|
|
1816
|
+
}
|
|
1817
|
+
resolveReady(payload) {
|
|
1818
|
+
this.viewerReady = true;
|
|
1819
|
+
this.readyPayload = { ...payload };
|
|
1820
|
+
this.readyWaiters.forEach((waiter) => {
|
|
1821
|
+
if (waiter.timer) clearTimeout(waiter.timer);
|
|
1822
|
+
waiter.resolve(payload);
|
|
1823
|
+
});
|
|
1824
|
+
this.readyWaiters = [];
|
|
1825
|
+
}
|
|
1826
|
+
rejectReadyWaiters(error) {
|
|
1827
|
+
this.readyWaiters.forEach((waiter) => {
|
|
1828
|
+
if (waiter.timer) clearTimeout(waiter.timer);
|
|
1829
|
+
waiter.reject(error);
|
|
1830
|
+
});
|
|
1831
|
+
this.readyWaiters = [];
|
|
1832
|
+
}
|
|
1626
1833
|
// ===== postMessage bridge =====
|
|
1627
1834
|
postToViewer(type, payload) {
|
|
1628
1835
|
var _a;
|