3dviewer-sdk 1.0.11 → 1.0.13

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.mjs CHANGED
@@ -121,6 +121,8 @@ var NodeModule = class {
121
121
  // src/modules/files.module.ts
122
122
  var DEFAULT_API_BASE_URL = "https://dev.3dviewer.anybim.vn";
123
123
  var DEFAULT_VIEWER_ORIGIN = "http://localhost:3000";
124
+ var SDK_VIEWER_PATH = "/mainviewer-sdk";
125
+ var LEGACY_VIEWER_PATH = "/mainviewer";
124
126
  var FilesModule = class {
125
127
  constructor(viewer) {
126
128
  this.viewer = viewer;
@@ -270,7 +272,7 @@ var FilesModule = class {
270
272
  const raw = this.config.baseUrl || this.viewer.getOptions().baseUrl || DEFAULT_API_BASE_URL;
271
273
  return this.normalizeBaseUrl(raw);
272
274
  }
273
- // Resolve viewer route path (e.g. /mainviewer).
275
+ // Resolve viewer route path for all SDK flows.
274
276
  resolveViewerPath() {
275
277
  const configuredPath = this.config.viewerPath || this.viewer.getOptions().viewerPath;
276
278
  if (!configuredPath) {
@@ -278,28 +280,32 @@ var FilesModule = class {
278
280
  if (viewerUrl) {
279
281
  try {
280
282
  const pathname = new URL(viewerUrl, window.location.href).pathname;
281
- if (pathname && pathname !== "/") return pathname;
283
+ if (pathname && pathname !== "/") return this.normalizeSdkViewerPath(pathname);
282
284
  } catch {
283
285
  }
284
286
  }
285
287
  }
286
- const p = (configuredPath || "/mainviewer").trim();
287
- if (!p) return "/mainviewer";
288
- return p.startsWith("/") ? p : `/${p}`;
288
+ return this.normalizeSdkViewerPath(configuredPath || SDK_VIEWER_PATH);
289
+ }
290
+ normalizeSdkViewerPath(path) {
291
+ const p = path.trim();
292
+ if (!p || p === LEGACY_VIEWER_PATH) return SDK_VIEWER_PATH;
293
+ const normalized = p.startsWith("/") ? p : `/${p}`;
294
+ return normalized === LEGACY_VIEWER_PATH ? SDK_VIEWER_PATH : normalized;
289
295
  }
290
296
  // Viewer host used to open iframe after conversion completes.
291
297
  resolveViewerOrigin() {
292
- const configuredBaseUrl = this.config.baseUrl || this.viewer.getOptions().baseUrl;
293
- if (configuredBaseUrl) {
298
+ const viewerUrl = this.viewer.getOptions().url;
299
+ if (viewerUrl) {
294
300
  try {
295
- return this.normalizeBaseUrl(new URL(configuredBaseUrl, window.location.href).origin);
301
+ return this.normalizeBaseUrl(new URL(viewerUrl, window.location.href).origin);
296
302
  } catch {
297
303
  }
298
304
  }
299
- const viewerUrl = this.viewer.getOptions().url;
300
- if (viewerUrl) {
305
+ const configuredBaseUrl = this.config.baseUrl || this.viewer.getOptions().baseUrl;
306
+ if (configuredBaseUrl) {
301
307
  try {
302
- return this.normalizeBaseUrl(new URL(viewerUrl, window.location.href).origin);
308
+ return this.normalizeBaseUrl(new URL(configuredBaseUrl, window.location.href).origin);
303
309
  } catch {
304
310
  }
305
311
  }
@@ -308,6 +314,11 @@ var FilesModule = class {
308
314
  // Build conversion service root from API base URL.
309
315
  resolveHostConversion() {
310
316
  const baseUrl = this.resolveBaseUrl();
317
+ try {
318
+ const parsed = new URL(baseUrl, window.location.href);
319
+ if (parsed.hostname.includes("conversion")) return baseUrl;
320
+ } catch {
321
+ }
311
322
  return baseUrl.endsWith("/service/conversion") ? baseUrl : `${baseUrl}/service/conversion`;
312
323
  }
313
324
  // Resolve upload path sent to conversion APIs.
@@ -460,16 +471,16 @@ var FilesModule = class {
460
471
  }
461
472
  // Submit conversion request to the newer downloadUrl-based endpoint.
462
473
  async cacheFileV2(options) {
474
+ var _a;
463
475
  const hostConversion = await this.resolveHostConversion();
464
476
  const params = new URLSearchParams();
465
- if (typeof options.overwrite === "boolean") {
466
- params.set("overwrite", String(options.overwrite));
467
- }
477
+ params.set("overwrite", String((_a = options.overwrite) != null ? _a : true));
478
+ params.set("ignore_line_weight", "1");
468
479
  if (options.project) {
469
480
  params.set("project", options.project);
470
481
  }
471
482
  const query = params.toString();
472
- const url = `${hostConversion}/api/StreamFile/convert${query ? `?${query}` : ""}`;
483
+ const url = `${hostConversion}/api/StreamFile${query ? `?${query}` : ""}`;
473
484
  const payload = this.buildConvertV2Payload(options);
474
485
  const response = await fetch(url, {
475
486
  method: "POST",
@@ -557,8 +568,8 @@ var FilesModule = class {
557
568
  };
558
569
 
559
570
  // src/modules/toolbar.module.ts
560
- function createRequestId() {
561
- return `sheets_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
571
+ function createRequestId(prefix) {
572
+ return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
562
573
  }
563
574
  var ALL_3D_TOOLBAR_OPERATORS = [
564
575
  "home",
@@ -644,90 +655,78 @@ var ToolbarModule = class {
644
655
  enableAllPdf() {
645
656
  this.clearDisabledPdf();
646
657
  }
647
- hideToolbar() {
648
- this.setToolbarVisible(false);
649
- }
650
- showToolbar() {
651
- this.setToolbarVisible(true);
652
- }
653
- setToolbarVisible(visible, target = "all") {
654
- this.postToolbarVisibility({ visible, target });
655
- }
656
- hideLeftToolbar() {
657
- this.setToolbarVisible(false, "left");
658
- }
659
- showLeftToolbar() {
660
- this.setToolbarVisible(true, "left");
658
+ useToolbar(target = "all") {
659
+ this.postToolbarUse({ target });
661
660
  }
662
- hideCenterToolbar() {
663
- this.setToolbarVisible(false, "center");
661
+ useLeftToolbar() {
662
+ this.useToolbar("left");
664
663
  }
665
- showCenterToolbar() {
666
- this.setToolbarVisible(true, "center");
664
+ useCenterToolbar() {
665
+ this.useToolbar("center");
667
666
  }
668
- hideRightToolbar() {
669
- this.setToolbarVisible(false, "right");
667
+ useRightToolbar() {
668
+ this.useToolbar("right");
670
669
  }
671
- showRightToolbar() {
672
- this.setToolbarVisible(true, "right");
670
+ usePanel(panel, format) {
671
+ this.postPanelOpen({ panel, format });
673
672
  }
674
673
  openClippingPlanes() {
675
- this.postPanelOpen({ panel: "clipping-commands", format: "3d" });
674
+ this.usePanel("clipping-commands", "3d");
676
675
  }
677
676
  closeClippingPlanes() {
678
677
  this.postPanelClose({ panel: "clipping-commands", format: "3d" });
679
678
  }
680
679
  openSetting() {
681
- this.postPanelOpen({ panel: "setting" });
680
+ this.usePanel("setting");
682
681
  }
683
682
  closeSetting() {
684
683
  this.postPanelClose({ panel: "setting" });
685
684
  }
686
685
  openSetting3D() {
687
- this.postPanelOpen({ panel: "setting", format: "3d" });
686
+ this.usePanel("setting", "3d");
688
687
  }
689
688
  closeSetting3D() {
690
689
  this.postPanelClose({ panel: "setting", format: "3d" });
691
690
  }
692
691
  openSettingPdf() {
693
- this.postPanelOpen({ panel: "setting", format: "pdf" });
692
+ this.usePanel("setting", "pdf");
694
693
  }
695
694
  closeSettingPdf() {
696
695
  this.postPanelClose({ panel: "setting", format: "pdf" });
697
696
  }
698
697
  openStatesObjects() {
699
- this.postPanelOpen({ panel: "statesObjects", format: "3d" });
698
+ this.usePanel("statesObjects", "3d");
700
699
  }
701
700
  closeStatesObjects() {
702
701
  this.postPanelClose({ panel: "statesObjects", format: "3d" });
703
702
  }
704
703
  openLinkedObjects() {
705
- this.postPanelOpen({ panel: "linkedObjects", format: "3d" });
704
+ this.usePanel("linkedObjects", "3d");
706
705
  }
707
706
  closeLinkedObjects() {
708
707
  this.postPanelClose({ panel: "linkedObjects", format: "3d" });
709
708
  }
710
709
  openModelTree() {
711
- this.postPanelOpen({ panel: "model-tree", format: "3d" });
710
+ this.usePanel("model-tree", "3d");
712
711
  }
713
712
  closeModelTree() {
714
713
  this.postPanelClose({ panel: "model-tree", format: "3d" });
715
714
  }
716
715
  openObjectProperties() {
717
- this.postPanelOpen({ panel: "object-properties", format: "3d" });
716
+ this.usePanel("object-properties", "3d");
718
717
  }
719
718
  closeObjectProperties() {
720
719
  this.postPanelClose({ panel: "object-properties", format: "3d" });
721
720
  }
722
721
  openSheets() {
723
- this.postPanelOpen({ panel: "sheets", format: "3d" });
722
+ this.usePanel("sheets", "3d");
724
723
  }
725
724
  closeSheets() {
726
725
  this.postPanelClose({ panel: "sheets", format: "3d" });
727
726
  }
728
727
  getSheets(options) {
729
728
  var _a;
730
- const requestId = createRequestId();
729
+ const requestId = createRequestId("sheets");
731
730
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
732
731
  return new Promise((resolve, reject) => {
733
732
  const timer = setTimeout(() => {
@@ -743,6 +742,60 @@ var ToolbarModule = class {
743
742
  this.postSheetsGetList({ requestId });
744
743
  });
745
744
  }
745
+ getObjectProperties(options) {
746
+ var _a;
747
+ const requestId = createRequestId("object_properties");
748
+ const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
749
+ return new Promise((resolve, reject) => {
750
+ const timer = setTimeout(() => {
751
+ off();
752
+ reject(new Error("Timeout while getting object properties list from viewer"));
753
+ }, timeoutMs);
754
+ const off = this.viewer._on("object-properties:list", (payload) => {
755
+ if (payload.requestId !== requestId) return;
756
+ clearTimeout(timer);
757
+ off();
758
+ resolve(payload.properties);
759
+ });
760
+ this.postObjectPropertiesGetList({ requestId });
761
+ });
762
+ }
763
+ getLinkedObjects(options) {
764
+ var _a;
765
+ const requestId = createRequestId("linked_objects");
766
+ const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
767
+ return new Promise((resolve, reject) => {
768
+ const timer = setTimeout(() => {
769
+ off();
770
+ reject(new Error("Timeout while getting linked objects list from viewer"));
771
+ }, timeoutMs);
772
+ const off = this.viewer._on("linked-objects:list", (payload) => {
773
+ if (payload.requestId !== requestId) return;
774
+ clearTimeout(timer);
775
+ off();
776
+ resolve(payload.linkedObjects);
777
+ });
778
+ this.postLinkedObjectsGetList({ requestId });
779
+ });
780
+ }
781
+ getStatesObjects(options) {
782
+ var _a;
783
+ const requestId = createRequestId("states_objects");
784
+ const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
785
+ return new Promise((resolve, reject) => {
786
+ const timer = setTimeout(() => {
787
+ off();
788
+ reject(new Error("Timeout while getting states objects list from viewer"));
789
+ }, timeoutMs);
790
+ const off = this.viewer._on("states-objects:list", (payload) => {
791
+ if (payload.requestId !== requestId) return;
792
+ clearTimeout(timer);
793
+ off();
794
+ resolve(payload.statesObjects);
795
+ });
796
+ this.postStatesObjectsGetList({ requestId });
797
+ });
798
+ }
746
799
  applySheet(sheetId) {
747
800
  this.postSheetsApply({ sheetId });
748
801
  }
@@ -785,8 +838,8 @@ var ToolbarModule = class {
785
838
  postConfig(payload) {
786
839
  this.viewer.postToViewer("viewer-toolbar-config" /* TOOLBAR_CONFIG */, payload);
787
840
  }
788
- postToolbarVisibility(payload) {
789
- this.viewer.postToViewer("viewer-toolbar-visibility" /* TOOLBAR_VISIBILITY */, payload);
841
+ postToolbarUse(payload) {
842
+ this.viewer.postToViewer("viewer-toolbar-use" /* TOOLBAR_USE */, payload);
790
843
  }
791
844
  postPanelOpen(payload) {
792
845
  this.viewer.postToViewer("viewer-panel-open" /* PANEL_OPEN */, payload);
@@ -803,6 +856,15 @@ var ToolbarModule = class {
803
856
  postSheetsApply(payload) {
804
857
  this.viewer.postToViewer("viewer-sheets-apply" /* SHEETS_APPLY */, payload);
805
858
  }
859
+ postObjectPropertiesGetList(payload) {
860
+ this.viewer.postToViewer("viewer-object-properties-get-list" /* OBJECT_PROPERTIES_GET_LIST */, payload);
861
+ }
862
+ postLinkedObjectsGetList(payload) {
863
+ this.viewer.postToViewer("viewer-linked-objects-get-list" /* LINKED_OBJECTS_GET_LIST */, payload);
864
+ }
865
+ postStatesObjectsGetList(payload) {
866
+ this.viewer.postToViewer("viewer-states-objects-get-list" /* STATES_OBJECTS_GET_LIST */, payload);
867
+ }
806
868
  };
807
869
 
808
870
  // src/modules/model-tree.module.ts
@@ -959,6 +1021,8 @@ var LanguageModule = class {
959
1021
  };
960
1022
 
961
1023
  // src/viewer.ts
1024
+ var SDK_VIEWER_PATH2 = "/mainviewer-sdk";
1025
+ var LEGACY_VIEWER_PATH2 = "/mainviewer";
962
1026
  var Viewer3D = class {
963
1027
  constructor(options) {
964
1028
  this.options = options;
@@ -1063,6 +1127,54 @@ var Viewer3D = class {
1063
1127
  });
1064
1128
  break;
1065
1129
  }
1130
+ case "viewer-object-properties-list" /* OBJECT_PROPERTIES_LIST */: {
1131
+ const payload = data.payload;
1132
+ if (!payload || !payload.requestId || !Array.isArray(payload.properties)) break;
1133
+ this._emit("object-properties:list", {
1134
+ requestId: String(payload.requestId),
1135
+ properties: payload.properties.filter((item) => item && typeof item === "object").map((item) => ({ ...item })),
1136
+ timestamp: Number(payload.timestamp) || Date.now()
1137
+ });
1138
+ break;
1139
+ }
1140
+ case "viewer-linked-objects-list" /* LINKED_OBJECTS_LIST */: {
1141
+ const payload = data.payload;
1142
+ if (!payload || !payload.requestId || !Array.isArray(payload.linkedObjects)) break;
1143
+ this._emit("linked-objects:list", {
1144
+ requestId: String(payload.requestId),
1145
+ linkedObjects: payload.linkedObjects.filter((item) => item && typeof item === "object").map((item) => ({ ...item })),
1146
+ timestamp: Number(payload.timestamp) || Date.now()
1147
+ });
1148
+ break;
1149
+ }
1150
+ case "viewer-states-objects-list" /* STATES_OBJECTS_LIST */: {
1151
+ const payload = data.payload;
1152
+ if (!payload || !payload.requestId || !Array.isArray(payload.statesObjects)) break;
1153
+ this._emit("states-objects:list", {
1154
+ requestId: String(payload.requestId),
1155
+ statesObjects: payload.statesObjects.map((item) => {
1156
+ var _a2, _b2, _c2, _d2, _e, _f, _g;
1157
+ return {
1158
+ id: String((_a2 = item.id) != null ? _a2 : ""),
1159
+ name: String((_b2 = item.name) != null ? _b2 : ""),
1160
+ char: String((_c2 = item.char) != null ? _c2 : ""),
1161
+ object: Array.isArray(item.object) ? item.object.map((objectItem) => {
1162
+ var _a3;
1163
+ return {
1164
+ name: String((_a3 = objectItem == null ? void 0 : objectItem.name) != null ? _a3 : ""),
1165
+ id: Number(objectItem == null ? void 0 : objectItem.id) || 0
1166
+ };
1167
+ }) : [],
1168
+ states: {
1169
+ color: String((_e = (_d2 = item.states) == null ? void 0 : _d2.color) != null ? _e : ""),
1170
+ type: String((_g = (_f = item.states) == null ? void 0 : _f.type) != null ? _g : "")
1171
+ }
1172
+ };
1173
+ }),
1174
+ timestamp: Number(payload.timestamp) || Date.now()
1175
+ });
1176
+ break;
1177
+ }
1066
1178
  case "viewer-markup-list" /* MARKUP_LIST */: {
1067
1179
  const payload = data.payload;
1068
1180
  if (!payload || !payload.requestId || !Array.isArray(payload.markups)) break;
@@ -1182,18 +1294,39 @@ var Viewer3D = class {
1182
1294
  if (!this.initialized) throw new Error("Call viewer.init() before using viewer");
1183
1295
  }
1184
1296
  withInitialOptions(url) {
1185
- if (!this.options.initialToolbarVisibility) return url;
1186
1297
  try {
1187
1298
  const parsedUrl = new URL(url, window.location.href);
1188
- parsedUrl.searchParams.set(
1189
- "toolbarVisibility",
1190
- JSON.stringify(this.options.initialToolbarVisibility)
1191
- );
1299
+ if (parsedUrl.pathname === LEGACY_VIEWER_PATH2) {
1300
+ parsedUrl.pathname = SDK_VIEWER_PATH2;
1301
+ }
1302
+ const initialToolbar = this.normalizeInitialToolbar();
1303
+ if (initialToolbar) {
1304
+ parsedUrl.searchParams.set("useToolbar", JSON.stringify(initialToolbar));
1305
+ }
1192
1306
  return parsedUrl.toString();
1193
1307
  } catch {
1194
1308
  return url;
1195
1309
  }
1196
1310
  }
1311
+ normalizeInitialToolbar() {
1312
+ const initialToolbar = this.options.initialToolbar;
1313
+ if (!initialToolbar) return null;
1314
+ if (typeof initialToolbar === "string") {
1315
+ return { [initialToolbar]: true };
1316
+ }
1317
+ if (Array.isArray(initialToolbar)) {
1318
+ return initialToolbar.reduce((result, target) => {
1319
+ result[target] = true;
1320
+ return result;
1321
+ }, {});
1322
+ }
1323
+ const entries = Object.entries(initialToolbar).filter(([, enabled]) => enabled === true);
1324
+ if (entries.length === 0) return null;
1325
+ return entries.reduce((result, [target]) => {
1326
+ result[target] = true;
1327
+ return result;
1328
+ }, {});
1329
+ }
1197
1330
  // ===== typed internal events used by modules =====
1198
1331
  _on(event, cb) {
1199
1332
  return this.emitter.on(event, cb);
package/package.json CHANGED
@@ -1,16 +1,21 @@
1
1
  {
2
2
  "name": "3dviewer-sdk",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
7
7
  "dist"
8
8
  ],
9
9
  "scripts": {
10
- "build": "tsup src/index.ts --format cjs,esm --dts --no-splitting"
10
+ "build": "tsup src/index.ts --format cjs,esm --dts --no-splitting",
11
+ "test": "vitest run tests",
12
+ "test:watch": "vitest tests"
11
13
  },
12
14
  "devDependencies": {
15
+ "@vitest/coverage-v8": "^4.1.4",
16
+ "jsdom": "^29.0.2",
13
17
  "tsup": "^8.5.1",
14
- "typescript": "^5.9.3"
18
+ "typescript": "^5.9.3",
19
+ "vitest": "^4.1.4"
15
20
  }
16
21
  }
@@ -1,97 +0,0 @@
1
- import type { MarkupListItem, MarkupOperationResultPayload, PdfCurrentPagePayload, PdfModeEventPayload, PdfToolbarActionEventPayload } from "./messages";
2
- export declare type ViewerEventMap = {
3
- "camera:home": {
4
- timestamp: number;
5
- };
6
- "node:select": {
7
- nodeId: string;
8
- timestamp: number;
9
- };
10
- "interaction:pan-change": {
11
- enabled: boolean;
12
- };
13
- "toolbar:pdf-plan-mode": PdfModeEventPayload;
14
- "toolbar:pdf-document-mode": PdfModeEventPayload;
15
- "toolbar:pdf-first-page": PdfToolbarActionEventPayload;
16
- "toolbar:pdf-previous-page": PdfToolbarActionEventPayload;
17
- "toolbar:pdf-next-page": PdfToolbarActionEventPayload;
18
- "toolbar:pdf-last-page": PdfToolbarActionEventPayload;
19
- "toolbar:pdf-current-page": PdfCurrentPagePayload;
20
- "modelTree:node-ids": {
21
- requestId: string;
22
- nodeIds: string[];
23
- timestamp: number;
24
- };
25
- "sheets:list": {
26
- requestId: string;
27
- sheets: {
28
- id: string | number;
29
- name: string;
30
- is3D?: boolean;
31
- viewId?: string;
32
- }[];
33
- activeSheetId?: string | number | null;
34
- timestamp: number;
35
- };
36
- "markup:list": {
37
- requestId: string;
38
- markups: MarkupListItem[];
39
- timestamp: number;
40
- };
41
- "markup:save": MarkupOperationResultPayload;
42
- "markup:cancel": MarkupOperationResultPayload;
43
- };
44
- export declare type LoadStage = "idle" | "uploading" | "converting" | "rendering" | "completed" | "error";
45
- export declare type LoadStatePayload = {
46
- isLoading: boolean;
47
- stage: LoadStage;
48
- message?: string;
49
- elapsedMs?: number;
50
- };
51
- export declare type PreparedViewerData = {
52
- baseFileId: string;
53
- baseMajorRev: number;
54
- baseMinorRev: number;
55
- fileName: string;
56
- query: string;
57
- url: string;
58
- };
59
- export declare type FilesEventMap = {
60
- "files:state": LoadStatePayload;
61
- "files:upload:start": {
62
- fileName: string;
63
- };
64
- "files:upload:success": {
65
- fileName: string;
66
- baseFileId: string;
67
- };
68
- "files:upload:error": {
69
- fileName: string;
70
- error: string;
71
- };
72
- "files:conversion:start": {
73
- fileName: string;
74
- };
75
- "files:conversion:success": PreparedViewerData;
76
- "files:conversion:error": {
77
- fileName: string;
78
- error: string;
79
- };
80
- "files:render:start": {
81
- url: string;
82
- };
83
- "files:render:success": {
84
- url: string;
85
- };
86
- "files:render:error": {
87
- url?: string;
88
- error: string;
89
- };
90
- "files:load:success": PreparedViewerData;
91
- "files:load:error": {
92
- error: string;
93
- };
94
- };
95
- export declare type SdkEventMap = ViewerEventMap & FilesEventMap;
96
- export declare type SdkEventKey = keyof SdkEventMap;
97
- export declare type SdkEventPayload<K extends SdkEventKey> = SdkEventMap[K];
@@ -1 +0,0 @@
1
- export {};