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.mjs
CHANGED
|
@@ -139,7 +139,7 @@ var NodeModule = class {
|
|
|
139
139
|
constructor(viewer) {
|
|
140
140
|
this.viewer = viewer;
|
|
141
141
|
this.on = {
|
|
142
|
-
|
|
142
|
+
// SDK no longer supports first-node-only select events; listen to selectionChange for the full node list.
|
|
143
143
|
selectionChange: (cb) => this.viewer._on("node:selection-change", cb)
|
|
144
144
|
};
|
|
145
145
|
}
|
|
@@ -186,52 +186,75 @@ var FilesModule = class {
|
|
|
186
186
|
// Upload file to conversion server and keep generated baseFileId in session.
|
|
187
187
|
async upload(file) {
|
|
188
188
|
const target = this.resolveFile(file);
|
|
189
|
-
return this.withOperation(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
189
|
+
return this.withOperation(
|
|
190
|
+
{ stage: "uploading", message: "Uploading file..." },
|
|
191
|
+
async () => {
|
|
192
|
+
var _a;
|
|
193
|
+
this.viewer._emit("files:upload:start", { fileName: target.name });
|
|
194
|
+
await this.uploadInternal(target);
|
|
195
|
+
const baseFileId = ((_a = this.getUploadSessionForFile(target)) == null ? void 0 : _a.baseFileId) || "";
|
|
196
|
+
this.viewer._emit("files:upload:success", {
|
|
197
|
+
fileName: target.name,
|
|
198
|
+
baseFileId
|
|
199
|
+
});
|
|
200
|
+
return { fileName: target.name, baseFileId };
|
|
201
|
+
}
|
|
202
|
+
);
|
|
197
203
|
}
|
|
198
204
|
// Trigger conversion flow and resolve final viewer metadata.
|
|
199
205
|
async convert(file, options = {}) {
|
|
200
206
|
const target = this.resolveFile(file);
|
|
201
|
-
return this.withOperation(
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
207
|
+
return this.withOperation(
|
|
208
|
+
{ stage: "converting", message: "Converting file..." },
|
|
209
|
+
async () => {
|
|
210
|
+
this.viewer._emit("files:conversion:start", { fileName: target.name });
|
|
211
|
+
try {
|
|
212
|
+
const prepared = await this.convertInternal(target, options);
|
|
213
|
+
this.viewer._emit("files:conversion:success", prepared);
|
|
214
|
+
return prepared;
|
|
215
|
+
} catch (e) {
|
|
216
|
+
this.viewer._emit("files:conversion:error", {
|
|
217
|
+
fileName: target.name,
|
|
218
|
+
error: this.toErrorMessage(e)
|
|
219
|
+
});
|
|
220
|
+
throw e;
|
|
221
|
+
}
|
|
210
222
|
}
|
|
211
|
-
|
|
223
|
+
);
|
|
212
224
|
}
|
|
213
225
|
// Convenience API: upload first, then convert in one call.
|
|
214
226
|
async prepare(file, options = {}) {
|
|
215
227
|
const target = this.resolveFile(file);
|
|
216
|
-
return this.withOperation(
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
228
|
+
return this.withOperation(
|
|
229
|
+
{ stage: "uploading", message: "Preparing file..." },
|
|
230
|
+
async () => {
|
|
231
|
+
await this.uploadInternal(target);
|
|
232
|
+
const prepared = await this.convertInternal(target, options);
|
|
233
|
+
return prepared;
|
|
234
|
+
}
|
|
235
|
+
);
|
|
221
236
|
}
|
|
222
237
|
// Trigger the newer downloadUrl-based conversion flow.
|
|
223
238
|
async convertV2(options) {
|
|
224
|
-
return this.withOperation(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
239
|
+
return this.withOperation(
|
|
240
|
+
{ stage: "converting", message: "Converting file..." },
|
|
241
|
+
async () => {
|
|
242
|
+
this.viewer._emit("files:conversion:start", {
|
|
243
|
+
fileName: options.filename
|
|
244
|
+
});
|
|
245
|
+
try {
|
|
246
|
+
const prepared = await this.convertV2Internal(options);
|
|
247
|
+
this.viewer._emit("files:conversion:success", prepared);
|
|
248
|
+
return prepared;
|
|
249
|
+
} catch (e) {
|
|
250
|
+
this.viewer._emit("files:conversion:error", {
|
|
251
|
+
fileName: options.filename,
|
|
252
|
+
error: this.toErrorMessage(e)
|
|
253
|
+
});
|
|
254
|
+
throw e;
|
|
255
|
+
}
|
|
233
256
|
}
|
|
234
|
-
|
|
257
|
+
);
|
|
235
258
|
}
|
|
236
259
|
// Check stream file info by one or more baseFileId values.
|
|
237
260
|
async checkFileInfo(baseFileIds) {
|
|
@@ -247,7 +270,9 @@ var FilesModule = class {
|
|
|
247
270
|
body: JSON.stringify(payload)
|
|
248
271
|
});
|
|
249
272
|
if (!response.ok) {
|
|
250
|
-
throw new Error(
|
|
273
|
+
throw new Error(
|
|
274
|
+
`Check file info failed (${response.status} ${response.statusText})`
|
|
275
|
+
);
|
|
251
276
|
}
|
|
252
277
|
const text = await response.text();
|
|
253
278
|
if (!text) return null;
|
|
@@ -265,27 +290,34 @@ var FilesModule = class {
|
|
|
265
290
|
this.viewer.open(url);
|
|
266
291
|
this.viewer._emit("files:render:success", { url });
|
|
267
292
|
} catch (e) {
|
|
268
|
-
this.viewer._emit("files:render:error", {
|
|
293
|
+
this.viewer._emit("files:render:error", {
|
|
294
|
+
url,
|
|
295
|
+
error: this.toErrorMessage(e)
|
|
296
|
+
});
|
|
269
297
|
throw e;
|
|
270
298
|
}
|
|
271
299
|
}
|
|
272
300
|
// Full pipeline: upload + convert + open iframe.
|
|
273
301
|
async render(file, options = {}) {
|
|
274
302
|
const target = this.resolveFile(file);
|
|
275
|
-
return this.withOperation(
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
303
|
+
return this.withOperation(
|
|
304
|
+
{ stage: "uploading", message: "Uploading + converting + opening..." },
|
|
305
|
+
async () => {
|
|
306
|
+
await this.upload(target);
|
|
307
|
+
const prepared = await this.convert(target, options);
|
|
308
|
+
this.updateState({ stage: "rendering", message: "Opening viewer..." });
|
|
309
|
+
this.open(prepared);
|
|
310
|
+
this.viewer._emit("files:load:success", prepared);
|
|
311
|
+
return prepared;
|
|
312
|
+
}
|
|
313
|
+
);
|
|
283
314
|
}
|
|
284
315
|
// Resolve file argument, fallback to options.file, and persist it back.
|
|
285
316
|
resolveFile(file) {
|
|
286
317
|
const optFile = this.viewer.getOptions().file;
|
|
287
318
|
const target = file || optFile;
|
|
288
|
-
if (!target)
|
|
319
|
+
if (!target)
|
|
320
|
+
throw new Error("No file provided. Pass a File or set options.file");
|
|
289
321
|
this.viewer.patchOptions({ file: target });
|
|
290
322
|
return target;
|
|
291
323
|
}
|
|
@@ -306,7 +338,8 @@ var FilesModule = class {
|
|
|
306
338
|
if (viewerUrl) {
|
|
307
339
|
try {
|
|
308
340
|
const pathname = new URL(viewerUrl, window.location.href).pathname;
|
|
309
|
-
if (pathname && pathname !== "/")
|
|
341
|
+
if (pathname && pathname !== "/")
|
|
342
|
+
return this.normalizeViewerPath(pathname);
|
|
310
343
|
} catch {
|
|
311
344
|
}
|
|
312
345
|
}
|
|
@@ -323,14 +356,18 @@ var FilesModule = class {
|
|
|
323
356
|
const configuredViewerBaseUrl = this.config.baseUrl || this.viewer.getOptions().baseUrl;
|
|
324
357
|
if (configuredViewerBaseUrl) {
|
|
325
358
|
try {
|
|
326
|
-
return this.normalizeBaseUrl(
|
|
359
|
+
return this.normalizeBaseUrl(
|
|
360
|
+
new URL(configuredViewerBaseUrl, window.location.href).origin
|
|
361
|
+
);
|
|
327
362
|
} catch {
|
|
328
363
|
}
|
|
329
364
|
}
|
|
330
365
|
const viewerUrl = this.viewer.getOptions().url;
|
|
331
366
|
if (viewerUrl) {
|
|
332
367
|
try {
|
|
333
|
-
return this.normalizeBaseUrl(
|
|
368
|
+
return this.normalizeBaseUrl(
|
|
369
|
+
new URL(viewerUrl, window.location.href).origin
|
|
370
|
+
);
|
|
334
371
|
} catch {
|
|
335
372
|
}
|
|
336
373
|
}
|
|
@@ -351,7 +388,8 @@ var FilesModule = class {
|
|
|
351
388
|
}
|
|
352
389
|
// Create a UUID-like baseFileId when caller does not provide one.
|
|
353
390
|
createBaseFileId() {
|
|
354
|
-
if (typeof crypto !== "undefined" && "randomUUID" in crypto)
|
|
391
|
+
if (typeof crypto !== "undefined" && "randomUUID" in crypto)
|
|
392
|
+
return crypto.randomUUID();
|
|
355
393
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
356
394
|
const r = Math.floor(Math.random() * 16);
|
|
357
395
|
const v = c === "x" ? r : r & 3 | 8;
|
|
@@ -382,15 +420,25 @@ var FilesModule = class {
|
|
|
382
420
|
const session = existing || this.createUploadSession(file);
|
|
383
421
|
const hostConversion = this.resolveHostConversion();
|
|
384
422
|
const path = this.getUploadPath();
|
|
385
|
-
const url = `${hostConversion}/api/File/upload?path=${encodeURIComponent(
|
|
423
|
+
const url = `${hostConversion}/api/File/upload?path=${encodeURIComponent(
|
|
424
|
+
path
|
|
425
|
+
)}`;
|
|
386
426
|
const formData = new FormData();
|
|
387
427
|
formData.append("file", file, file.name);
|
|
388
|
-
const res = await fetch(url, {
|
|
389
|
-
|
|
428
|
+
const res = await fetch(url, {
|
|
429
|
+
method: "POST",
|
|
430
|
+
body: formData,
|
|
431
|
+
headers: { Accept: "text/plain" }
|
|
432
|
+
});
|
|
433
|
+
if (!res.ok)
|
|
434
|
+
throw new Error(`Upload failed (${res.status} ${res.statusText})`);
|
|
390
435
|
this.lastUploadSession = session;
|
|
391
436
|
} catch (e) {
|
|
392
437
|
const msg = this.toErrorMessage(e);
|
|
393
|
-
this.viewer._emit("files:upload:error", {
|
|
438
|
+
this.viewer._emit("files:upload:error", {
|
|
439
|
+
fileName: file.name,
|
|
440
|
+
error: msg
|
|
441
|
+
});
|
|
394
442
|
throw e;
|
|
395
443
|
}
|
|
396
444
|
}
|
|
@@ -544,11 +592,20 @@ var FilesModule = class {
|
|
|
544
592
|
const baseMajorRev = (_b = cacheResult.baseMajorRev) != null ? _b : 0;
|
|
545
593
|
const baseMinorRev = (_c = cacheResult.baseMinorRev) != null ? _c : 0;
|
|
546
594
|
const fileName = cacheResult.filename || cacheResult.fileName || file.name;
|
|
547
|
-
const cacheListItem = {
|
|
595
|
+
const cacheListItem = {
|
|
596
|
+
baseFileId,
|
|
597
|
+
baseMajorRev,
|
|
598
|
+
baseMinorRev,
|
|
599
|
+
fileName
|
|
600
|
+
};
|
|
548
601
|
if (cacheResult.cacheStatus !== 2) {
|
|
549
|
-
throw new Error(
|
|
602
|
+
throw new Error(
|
|
603
|
+
`Conversion not ready after first request (cacheStatus=${(_d = cacheResult.cacheStatus) != null ? _d : "unknown"})`
|
|
604
|
+
);
|
|
550
605
|
}
|
|
551
|
-
const query = new URLSearchParams({
|
|
606
|
+
const query = new URLSearchParams({
|
|
607
|
+
fileList: JSON.stringify([cacheListItem])
|
|
608
|
+
}).toString();
|
|
552
609
|
const viewerBase = this.resolveViewerOrigin();
|
|
553
610
|
const viewerPath = this.resolveViewerPath();
|
|
554
611
|
const url = `${viewerBase}${viewerPath}?${query}`;
|
|
@@ -563,10 +620,19 @@ var FilesModule = class {
|
|
|
563
620
|
const baseMinorRev = (_e = (_d = cacheResult.baseMinorRev) != null ? _d : options.baseMinorRev) != null ? _e : 0;
|
|
564
621
|
const fileName = cacheResult.filename || cacheResult.fileName || options.filename;
|
|
565
622
|
if (cacheResult.cacheStatus !== void 0 && cacheResult.cacheStatus !== 2) {
|
|
566
|
-
throw new Error(
|
|
623
|
+
throw new Error(
|
|
624
|
+
`Conversion not ready after v2 request (cacheStatus=${cacheResult.cacheStatus})`
|
|
625
|
+
);
|
|
567
626
|
}
|
|
568
|
-
const cacheListItem = {
|
|
569
|
-
|
|
627
|
+
const cacheListItem = {
|
|
628
|
+
baseFileId,
|
|
629
|
+
baseMajorRev,
|
|
630
|
+
baseMinorRev,
|
|
631
|
+
fileName
|
|
632
|
+
};
|
|
633
|
+
const query = new URLSearchParams({
|
|
634
|
+
fileList: JSON.stringify([cacheListItem])
|
|
635
|
+
}).toString();
|
|
570
636
|
const viewerBase = this.resolveViewerOrigin();
|
|
571
637
|
const viewerPath = this.resolveViewerPath();
|
|
572
638
|
const url = `${viewerBase}${viewerPath}?${query}`;
|
|
@@ -577,6 +643,15 @@ var FilesModule = class {
|
|
|
577
643
|
const elapsedMs = this.operationStartTime > 0 ? Date.now() - this.operationStartTime : 0;
|
|
578
644
|
this.state = { ...this.state, ...next, elapsedMs };
|
|
579
645
|
this.viewer._emit("files:state", this.state);
|
|
646
|
+
this.viewer._emit("loading:change", {
|
|
647
|
+
loading: this.state.isLoading,
|
|
648
|
+
phase: this.toViewerLoadingPhase(this.state.stage)
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
toViewerLoadingPhase(stage) {
|
|
652
|
+
if (stage === "error") return "error";
|
|
653
|
+
if (stage === "idle" || stage === "completed") return "ready";
|
|
654
|
+
return "loading";
|
|
580
655
|
}
|
|
581
656
|
// Shared wrapper to handle loading state lifecycle and top-level errors.
|
|
582
657
|
async withOperation(initial, run) {
|
|
@@ -588,7 +663,11 @@ var FilesModule = class {
|
|
|
588
663
|
});
|
|
589
664
|
try {
|
|
590
665
|
const result = await run();
|
|
591
|
-
this.updateState({
|
|
666
|
+
this.updateState({
|
|
667
|
+
isLoading: false,
|
|
668
|
+
stage: "completed",
|
|
669
|
+
message: "Completed"
|
|
670
|
+
});
|
|
592
671
|
return result;
|
|
593
672
|
} catch (e) {
|
|
594
673
|
const msg = this.toErrorMessage(e);
|
|
@@ -1241,12 +1320,50 @@ var Viewer3D = class {
|
|
|
1241
1320
|
this.containerEl = null;
|
|
1242
1321
|
this.iframeEl = null;
|
|
1243
1322
|
this.initialized = false;
|
|
1323
|
+
this.viewerReady = false;
|
|
1324
|
+
this.readyPayload = null;
|
|
1325
|
+
this.readyWaiters = [];
|
|
1326
|
+
this.loadingState = {
|
|
1327
|
+
loading: false,
|
|
1328
|
+
phase: "ready"
|
|
1329
|
+
};
|
|
1244
1330
|
this.emitter = new Emitter();
|
|
1245
1331
|
this.handleMessage = (event) => {
|
|
1246
|
-
var _a, _b, _c
|
|
1332
|
+
var _a, _b, _c;
|
|
1247
1333
|
const data = event.data;
|
|
1248
1334
|
if (!data || typeof data !== "object") return;
|
|
1249
1335
|
switch (data.type) {
|
|
1336
|
+
case "viewer-loading-change" /* LOADING_CHANGE */: {
|
|
1337
|
+
const payload = data.payload;
|
|
1338
|
+
if (!payload) break;
|
|
1339
|
+
this.setLoadingState({
|
|
1340
|
+
loading: Boolean(payload.loading),
|
|
1341
|
+
phase: payload.phase,
|
|
1342
|
+
viewId: payload.viewId ? String(payload.viewId) : void 0,
|
|
1343
|
+
modelFileId: payload.modelFileId ? String(payload.modelFileId) : void 0,
|
|
1344
|
+
timestamp: payload.timestamp ? Number(payload.timestamp) : void 0
|
|
1345
|
+
});
|
|
1346
|
+
break;
|
|
1347
|
+
}
|
|
1348
|
+
case "viewer-ready" /* READY */: {
|
|
1349
|
+
const payload = data.payload;
|
|
1350
|
+
const readyPayload = {
|
|
1351
|
+
ready: true,
|
|
1352
|
+
viewId: (payload == null ? void 0 : payload.viewId) ? String(payload.viewId) : void 0,
|
|
1353
|
+
modelFileId: (payload == null ? void 0 : payload.modelFileId) ? String(payload.modelFileId) : void 0,
|
|
1354
|
+
timestamp: Number(payload == null ? void 0 : payload.timestamp) || Date.now()
|
|
1355
|
+
};
|
|
1356
|
+
this.setLoadingState({
|
|
1357
|
+
loading: false,
|
|
1358
|
+
phase: "ready",
|
|
1359
|
+
viewId: readyPayload.viewId,
|
|
1360
|
+
modelFileId: readyPayload.modelFileId,
|
|
1361
|
+
timestamp: readyPayload.timestamp
|
|
1362
|
+
});
|
|
1363
|
+
this.resolveReady(readyPayload);
|
|
1364
|
+
this._emit("viewer:ready", readyPayload);
|
|
1365
|
+
break;
|
|
1366
|
+
}
|
|
1250
1367
|
case "viewer-home-click" /* HOME_CLICK */:
|
|
1251
1368
|
this._emit("camera:home", { timestamp: Date.now() });
|
|
1252
1369
|
break;
|
|
@@ -1261,9 +1378,6 @@ var Viewer3D = class {
|
|
|
1261
1378
|
});
|
|
1262
1379
|
break;
|
|
1263
1380
|
}
|
|
1264
|
-
case "viewer-node-select" /* NODE_SELECT */:
|
|
1265
|
-
this._emit("node:select", { nodeId: String((_b = (_a = data.payload) == null ? void 0 : _a.nodeId) != null ? _b : ""), timestamp: Date.now() });
|
|
1266
|
-
break;
|
|
1267
1381
|
case "viewer-node-selection-change" /* NODE_SELECTION_CHANGE */: {
|
|
1268
1382
|
const payload = data.payload;
|
|
1269
1383
|
const rawNodeIds = payload == null ? void 0 : payload.nodeIds;
|
|
@@ -1275,7 +1389,9 @@ var Viewer3D = class {
|
|
|
1275
1389
|
break;
|
|
1276
1390
|
}
|
|
1277
1391
|
case "viewer-pan-change" /* PAN_CHANGE */:
|
|
1278
|
-
this._emit("interaction:pan-change", {
|
|
1392
|
+
this._emit("interaction:pan-change", {
|
|
1393
|
+
enabled: Boolean((_a = data.payload) == null ? void 0 : _a.enabled)
|
|
1394
|
+
});
|
|
1279
1395
|
break;
|
|
1280
1396
|
case "viewer-pdf-plan-mode" /* PDF_PLAN_MODE */: {
|
|
1281
1397
|
const payload = data.payload;
|
|
@@ -1333,7 +1449,8 @@ var Viewer3D = class {
|
|
|
1333
1449
|
}
|
|
1334
1450
|
case "viewer-tree-node-ids" /* TREE_NODE_IDS */: {
|
|
1335
1451
|
const payload = data.payload;
|
|
1336
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.nodeIds))
|
|
1452
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.nodeIds))
|
|
1453
|
+
break;
|
|
1337
1454
|
this._emit("modelTree:node-ids", {
|
|
1338
1455
|
requestId: String(payload.requestId),
|
|
1339
1456
|
nodeIds: payload.nodeIds.map(String),
|
|
@@ -1343,7 +1460,8 @@ var Viewer3D = class {
|
|
|
1343
1460
|
}
|
|
1344
1461
|
case "viewer-tree-nodes" /* TREE_NODES */: {
|
|
1345
1462
|
const payload = data.payload;
|
|
1346
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.nodes))
|
|
1463
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.nodes))
|
|
1464
|
+
break;
|
|
1347
1465
|
this._emit("modelTree:nodes", {
|
|
1348
1466
|
requestId: String(payload.requestId),
|
|
1349
1467
|
nodes: payload.nodes.filter((node) => node && typeof node === "object").map((node) => {
|
|
@@ -1369,7 +1487,8 @@ var Viewer3D = class {
|
|
|
1369
1487
|
}
|
|
1370
1488
|
case "viewer-sheets-list" /* SHEETS_LIST */: {
|
|
1371
1489
|
const payload = data.payload;
|
|
1372
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.sheets))
|
|
1490
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.sheets))
|
|
1491
|
+
break;
|
|
1373
1492
|
this._emit("sheets:list", {
|
|
1374
1493
|
requestId: String(payload.requestId),
|
|
1375
1494
|
sheets: payload.sheets.map((sheet) => {
|
|
@@ -1381,17 +1500,18 @@ var Viewer3D = class {
|
|
|
1381
1500
|
viewId: sheet.viewId ? String(sheet.viewId) : void 0
|
|
1382
1501
|
};
|
|
1383
1502
|
}),
|
|
1384
|
-
activeSheetId: (
|
|
1503
|
+
activeSheetId: (_b = payload.activeSheetId) != null ? _b : null,
|
|
1385
1504
|
timestamp: Number(payload.timestamp) || Date.now()
|
|
1386
1505
|
});
|
|
1387
1506
|
break;
|
|
1388
1507
|
}
|
|
1389
1508
|
case "viewer-object-properties-list" /* OBJECT_PROPERTIES_LIST */: {
|
|
1390
1509
|
const payload = data.payload;
|
|
1391
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.properties))
|
|
1510
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.properties))
|
|
1511
|
+
break;
|
|
1392
1512
|
this._emit("object-properties:list", {
|
|
1393
1513
|
requestId: String(payload.requestId),
|
|
1394
|
-
selectionKey: String((
|
|
1514
|
+
selectionKey: String((_c = payload.selectionKey) != null ? _c : ""),
|
|
1395
1515
|
nodeIds: Array.isArray(payload.nodeIds) ? payload.nodeIds.map(String) : [],
|
|
1396
1516
|
persistentIds: Array.isArray(payload.persistentIds) ? payload.persistentIds.map(String) : [],
|
|
1397
1517
|
properties: payload.properties.filter((item) => item && typeof item === "object").map((item) => ({ ...item })),
|
|
@@ -1401,7 +1521,8 @@ var Viewer3D = class {
|
|
|
1401
1521
|
}
|
|
1402
1522
|
case "viewer-linked-objects-list" /* LINKED_OBJECTS_LIST */: {
|
|
1403
1523
|
const payload = data.payload;
|
|
1404
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.linkedObjects))
|
|
1524
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.linkedObjects))
|
|
1525
|
+
break;
|
|
1405
1526
|
this._emit("linked-objects:list", {
|
|
1406
1527
|
requestId: String(payload.requestId),
|
|
1407
1528
|
linkedObjects: payload.linkedObjects.filter((item) => item && typeof item === "object").map((item) => ({ ...item })),
|
|
@@ -1411,11 +1532,12 @@ var Viewer3D = class {
|
|
|
1411
1532
|
}
|
|
1412
1533
|
case "viewer-states-objects-list" /* STATES_OBJECTS_LIST */: {
|
|
1413
1534
|
const payload = data.payload;
|
|
1414
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.statesObjects))
|
|
1535
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.statesObjects))
|
|
1536
|
+
break;
|
|
1415
1537
|
this._emit("states-objects:list", {
|
|
1416
1538
|
requestId: String(payload.requestId),
|
|
1417
1539
|
statesObjects: payload.statesObjects.map((item) => {
|
|
1418
|
-
var _a2, _b2, _c2,
|
|
1540
|
+
var _a2, _b2, _c2, _d, _e, _f, _g;
|
|
1419
1541
|
return {
|
|
1420
1542
|
id: String((_a2 = item.id) != null ? _a2 : ""),
|
|
1421
1543
|
name: String((_b2 = item.name) != null ? _b2 : ""),
|
|
@@ -1428,7 +1550,7 @@ var Viewer3D = class {
|
|
|
1428
1550
|
};
|
|
1429
1551
|
}) : [],
|
|
1430
1552
|
states: {
|
|
1431
|
-
color: String((
|
|
1553
|
+
color: String((_e = (_d = item.states) == null ? void 0 : _d.color) != null ? _e : ""),
|
|
1432
1554
|
type: String((_g = (_f = item.states) == null ? void 0 : _f.type) != null ? _g : "")
|
|
1433
1555
|
}
|
|
1434
1556
|
};
|
|
@@ -1439,7 +1561,8 @@ var Viewer3D = class {
|
|
|
1439
1561
|
}
|
|
1440
1562
|
case "viewer-markup-list" /* MARKUP_LIST */: {
|
|
1441
1563
|
const payload = data.payload;
|
|
1442
|
-
if (!payload || !payload.requestId || !Array.isArray(payload.markups))
|
|
1564
|
+
if (!payload || !payload.requestId || !Array.isArray(payload.markups))
|
|
1565
|
+
break;
|
|
1443
1566
|
this._emit("markup:list", {
|
|
1444
1567
|
requestId: String(payload.requestId),
|
|
1445
1568
|
markups: payload.markups.map((markup) => {
|
|
@@ -1508,6 +1631,36 @@ var Viewer3D = class {
|
|
|
1508
1631
|
var _a;
|
|
1509
1632
|
return (_a = this.options.url) != null ? _a : null;
|
|
1510
1633
|
}
|
|
1634
|
+
on(event, cb) {
|
|
1635
|
+
return this._on(event, cb);
|
|
1636
|
+
}
|
|
1637
|
+
off(event, cb) {
|
|
1638
|
+
this._off(event, cb);
|
|
1639
|
+
}
|
|
1640
|
+
getLoadingState() {
|
|
1641
|
+
return { ...this.loadingState };
|
|
1642
|
+
}
|
|
1643
|
+
ready(options) {
|
|
1644
|
+
if (this.viewerReady && this.readyPayload) {
|
|
1645
|
+
return Promise.resolve({ ...this.readyPayload });
|
|
1646
|
+
}
|
|
1647
|
+
const timeoutMs = options == null ? void 0 : options.timeoutMs;
|
|
1648
|
+
return new Promise((resolve, reject) => {
|
|
1649
|
+
const waiter = {
|
|
1650
|
+
resolve: (payload) => resolve({ ...payload }),
|
|
1651
|
+
reject
|
|
1652
|
+
};
|
|
1653
|
+
if (typeof timeoutMs === "number" && timeoutMs > 0) {
|
|
1654
|
+
waiter.timer = setTimeout(() => {
|
|
1655
|
+
this.readyWaiters = this.readyWaiters.filter(
|
|
1656
|
+
(item) => item !== waiter
|
|
1657
|
+
);
|
|
1658
|
+
reject(new Error("Timeout while waiting for viewer to be ready"));
|
|
1659
|
+
}, timeoutMs);
|
|
1660
|
+
}
|
|
1661
|
+
this.readyWaiters.push(waiter);
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1511
1664
|
// ===== lifecycle =====
|
|
1512
1665
|
init() {
|
|
1513
1666
|
if (this.initialized) return;
|
|
@@ -1519,7 +1672,12 @@ var Viewer3D = class {
|
|
|
1519
1672
|
async render(file) {
|
|
1520
1673
|
this.ensureInit();
|
|
1521
1674
|
if (this.iframeEl) return;
|
|
1675
|
+
this.resetReadyState();
|
|
1522
1676
|
if (!this.options.url) return this.files.render(file);
|
|
1677
|
+
this.setLoadingState({
|
|
1678
|
+
loading: true,
|
|
1679
|
+
phase: "loading"
|
|
1680
|
+
});
|
|
1523
1681
|
const iframe = document.createElement("iframe");
|
|
1524
1682
|
iframe.src = this.withInitialOptions(this.options.url);
|
|
1525
1683
|
iframe.style.border = "none";
|
|
@@ -1527,13 +1685,19 @@ var Viewer3D = class {
|
|
|
1527
1685
|
iframe.style.height = this.options.height || "100%";
|
|
1528
1686
|
iframe.width = this.options.width || "100%";
|
|
1529
1687
|
iframe.height = this.options.height || "100%";
|
|
1530
|
-
if (this.options.sandbox)
|
|
1688
|
+
if (this.options.sandbox)
|
|
1689
|
+
iframe.setAttribute("sandbox", this.options.sandbox);
|
|
1531
1690
|
this.containerEl.appendChild(iframe);
|
|
1532
1691
|
this.iframeEl = iframe;
|
|
1533
1692
|
}
|
|
1534
1693
|
open(url) {
|
|
1535
1694
|
this.ensureInit();
|
|
1536
1695
|
this.options.url = url;
|
|
1696
|
+
this.resetReadyState();
|
|
1697
|
+
this.setLoadingState({
|
|
1698
|
+
loading: true,
|
|
1699
|
+
phase: "loading"
|
|
1700
|
+
});
|
|
1537
1701
|
const finalUrl = this.withInitialOptions(url);
|
|
1538
1702
|
if (!this.iframeEl) {
|
|
1539
1703
|
this.render();
|
|
@@ -1552,16 +1716,27 @@ var Viewer3D = class {
|
|
|
1552
1716
|
this.iframeEl = null;
|
|
1553
1717
|
this.containerEl = null;
|
|
1554
1718
|
this.initialized = false;
|
|
1719
|
+
this.rejectReadyWaiters(
|
|
1720
|
+
new Error("Viewer was destroyed before becoming ready")
|
|
1721
|
+
);
|
|
1555
1722
|
}
|
|
1556
1723
|
ensureInit() {
|
|
1557
|
-
if (!this.initialized)
|
|
1724
|
+
if (!this.initialized)
|
|
1725
|
+
throw new Error("Call viewer.init() before using viewer");
|
|
1558
1726
|
}
|
|
1559
1727
|
withInitialOptions(url) {
|
|
1728
|
+
var _a;
|
|
1560
1729
|
try {
|
|
1561
1730
|
const parsedUrl = new URL(url, window.location.href);
|
|
1562
1731
|
const initialToolbar = this.normalizeInitialToolbar();
|
|
1563
1732
|
if (initialToolbar) {
|
|
1564
|
-
parsedUrl.searchParams.set(
|
|
1733
|
+
parsedUrl.searchParams.set(
|
|
1734
|
+
"useToolbar",
|
|
1735
|
+
JSON.stringify(initialToolbar)
|
|
1736
|
+
);
|
|
1737
|
+
}
|
|
1738
|
+
if (((_a = this.options.ui) == null ? void 0 : _a.loadingIndicator) === false) {
|
|
1739
|
+
parsedUrl.searchParams.set("loadingIndicator", "false");
|
|
1565
1740
|
}
|
|
1566
1741
|
return parsedUrl.toString();
|
|
1567
1742
|
} catch {
|
|
@@ -1575,17 +1750,25 @@ var Viewer3D = class {
|
|
|
1575
1750
|
return { [initialToolbar]: true };
|
|
1576
1751
|
}
|
|
1577
1752
|
if (Array.isArray(initialToolbar)) {
|
|
1578
|
-
return initialToolbar.reduce(
|
|
1579
|
-
result
|
|
1580
|
-
|
|
1581
|
-
|
|
1753
|
+
return initialToolbar.reduce(
|
|
1754
|
+
(result, target) => {
|
|
1755
|
+
result[target] = true;
|
|
1756
|
+
return result;
|
|
1757
|
+
},
|
|
1758
|
+
{}
|
|
1759
|
+
);
|
|
1582
1760
|
}
|
|
1583
|
-
const entries = Object.entries(initialToolbar).filter(
|
|
1761
|
+
const entries = Object.entries(initialToolbar).filter(
|
|
1762
|
+
([, enabled]) => enabled === true
|
|
1763
|
+
);
|
|
1584
1764
|
if (entries.length === 0) return null;
|
|
1585
|
-
return entries.reduce(
|
|
1586
|
-
result[target]
|
|
1587
|
-
|
|
1588
|
-
|
|
1765
|
+
return entries.reduce(
|
|
1766
|
+
(result, [target]) => {
|
|
1767
|
+
result[target] = true;
|
|
1768
|
+
return result;
|
|
1769
|
+
},
|
|
1770
|
+
{}
|
|
1771
|
+
);
|
|
1589
1772
|
}
|
|
1590
1773
|
// ===== typed internal events used by modules =====
|
|
1591
1774
|
_on(event, cb) {
|
|
@@ -1597,6 +1780,30 @@ var Viewer3D = class {
|
|
|
1597
1780
|
_emit(event, payload) {
|
|
1598
1781
|
this.emitter.emit(event, payload);
|
|
1599
1782
|
}
|
|
1783
|
+
resetReadyState() {
|
|
1784
|
+
this.viewerReady = false;
|
|
1785
|
+
this.readyPayload = null;
|
|
1786
|
+
}
|
|
1787
|
+
setLoadingState(payload) {
|
|
1788
|
+
this.loadingState = { ...payload };
|
|
1789
|
+
this._emit("loading:change", this.loadingState);
|
|
1790
|
+
}
|
|
1791
|
+
resolveReady(payload) {
|
|
1792
|
+
this.viewerReady = true;
|
|
1793
|
+
this.readyPayload = { ...payload };
|
|
1794
|
+
this.readyWaiters.forEach((waiter) => {
|
|
1795
|
+
if (waiter.timer) clearTimeout(waiter.timer);
|
|
1796
|
+
waiter.resolve(payload);
|
|
1797
|
+
});
|
|
1798
|
+
this.readyWaiters = [];
|
|
1799
|
+
}
|
|
1800
|
+
rejectReadyWaiters(error) {
|
|
1801
|
+
this.readyWaiters.forEach((waiter) => {
|
|
1802
|
+
if (waiter.timer) clearTimeout(waiter.timer);
|
|
1803
|
+
waiter.reject(error);
|
|
1804
|
+
});
|
|
1805
|
+
this.readyWaiters = [];
|
|
1806
|
+
}
|
|
1600
1807
|
// ===== postMessage bridge =====
|
|
1601
1808
|
postToViewer(type, payload) {
|
|
1602
1809
|
var _a;
|