3dviewer-sdk 1.0.2 → 1.0.3

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.
@@ -0,0 +1,97 @@
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];
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,153 @@
1
+ export declare enum ViewerMessageType {
2
+ LANGUAGE_CHANGE = "viewer-language-change",
3
+ ZOOM = "viewer-zoom",
4
+ DRAW_MODE = "viewer-draw-mode",
5
+ EXPLODE = "viewer-explode",
6
+ MARKUP_ACTION = "viewer-markup-action",
7
+ MARKUP_SAVE = "viewer-markup-save",
8
+ MARKUP_CANCEL = "viewer-markup-cancel",
9
+ MARKUP_GET_LIST = "viewer-markup-get-list",
10
+ MARKUP_SAVE_RESULT = "viewer-markup-save-result",
11
+ MARKUP_CANCEL_RESULT = "viewer-markup-cancel-result",
12
+ MARKUP_LIST = "viewer-markup-list",
13
+ HOME = "viewer-home",
14
+ PAN_TOGGLE = "viewer-pan-toggle",
15
+ SELECT = "viewer-select",
16
+ AREA_SELECT = "viewer-area-select",
17
+ ORBIT = "viewer-orbit",
18
+ ROTATE_Z = "viewer-rotate-z",
19
+ WALK_THROUGH = "viewer-walk-through",
20
+ ZOOM_WINDOW = "viewer-zoom-window",
21
+ ZOOM_FIT = "viewer-zoom-fit",
22
+ TOOLBAR_CONFIG = "viewer-toolbar-config",
23
+ PANEL_OPEN = "viewer-panel-open",
24
+ PANEL_CLOSE = "viewer-panel-close",
25
+ CUTTING_PLANE_ACTION = "viewer-cutting-plane-action",
26
+ SHEETS_GET_LIST = "viewer-sheets-get-list",
27
+ SHEETS_LIST = "viewer-sheets-list",
28
+ SHEETS_APPLY = "viewer-sheets-apply",
29
+ TREE_SELECT_NODE = "viewer-tree-select-node",
30
+ TREE_GET_NODE_IDS = "viewer-tree-get-node-ids",
31
+ TREE_NODE_IDS = "viewer-tree-node-ids",
32
+ PDF_PLAN_MODE = "viewer-pdf-plan-mode",
33
+ PDF_DOCUMENT_MODE = "viewer-pdf-document-mode",
34
+ PDF_FIRST_PAGE = "viewer-pdf-first-page",
35
+ PDF_PREVIOUS_PAGE = "viewer-pdf-previous-page",
36
+ PDF_NEXT_PAGE = "viewer-pdf-next-page",
37
+ PDF_LAST_PAGE = "viewer-pdf-last-page",
38
+ PDF_CURRENT_PAGE = "viewer-pdf-current-page",
39
+ HOME_CLICK = "viewer-home-click",
40
+ NODE_SELECT = "viewer-node-select",
41
+ PAN_CHANGE = "viewer-pan-change"
42
+ }
43
+ export declare enum ViewerMessageSource {
44
+ SDK = "HC_SDK",
45
+ VIEWER = "HC_VIEWER"
46
+ }
47
+ export declare type OutgoingMessage<T = unknown> = {
48
+ source: ViewerMessageSource.SDK;
49
+ type: ViewerMessageType;
50
+ payload?: T;
51
+ };
52
+ export declare type IncomingMessage<T = any> = {
53
+ source?: ViewerMessageSource | string;
54
+ type: ViewerMessageType;
55
+ payload?: T;
56
+ };
57
+ export declare type LanguageCode = "en" | "vn";
58
+ export declare type LanguageChangePayload = {
59
+ language: LanguageCode;
60
+ timestamp?: number;
61
+ };
62
+ export declare type DrawModeValue = "shaded" | "wireframe" | "hidden-line" | "shaded-wire" | "xray" | "ghosting";
63
+ export declare type DrawModePayload = {
64
+ mode: DrawModeValue;
65
+ };
66
+ export declare type ExplodePayload = {
67
+ magnitude: number;
68
+ };
69
+ export declare type MarkupAction = "line" | "arrow" | "circle" | "ellipse" | "rectangle" | "polygon" | "polyline" | "textbox" | "note" | "callout" | "cloud" | "freehand";
70
+ export declare type MarkupActionPayload = {
71
+ action: MarkupAction;
72
+ };
73
+ export declare type MarkupRequestPayload = {
74
+ requestId: string;
75
+ };
76
+ export declare type MarkupOperationResultPayload = {
77
+ requestId: string;
78
+ success: boolean;
79
+ timestamp: number;
80
+ error?: string;
81
+ };
82
+ export declare type MarkupListItem = {
83
+ id: string;
84
+ viewId: string;
85
+ viewName?: string;
86
+ title: string;
87
+ type: string;
88
+ shapeName?: string;
89
+ createdDate?: string;
90
+ modifiedDate?: string;
91
+ createdBy?: string;
92
+ lastModifiedBy?: string;
93
+ };
94
+ export declare type MarkupListPayload = {
95
+ requestId: string;
96
+ markups: MarkupListItem[];
97
+ timestamp: number;
98
+ };
99
+ export declare type PanelTarget = "clipping-commands" | "setting" | "statesObjects" | "linkedObjects" | "model-tree" | "sheets" | "object-properties";
100
+ export declare type PanelOpenPayload = {
101
+ panel: PanelTarget;
102
+ format?: "3d" | "pdf";
103
+ };
104
+ export declare type PanelClosePayload = {
105
+ panel: PanelTarget;
106
+ format?: "3d" | "pdf";
107
+ };
108
+ export declare type CuttingPlaneAction = "close" | "multi" | "toggle-section" | "toggle-plane" | "plane-x" | "plane-y" | "plane-z" | "plane-box" | "rotate-box" | "reverse-plane-x" | "reverse-plane-y" | "reverse-plane-z";
109
+ export declare type CuttingPlaneActionPayload = {
110
+ action: CuttingPlaneAction;
111
+ };
112
+ export declare type SheetsGetListPayload = {
113
+ requestId: string;
114
+ };
115
+ export declare type SheetListItem = {
116
+ id: string | number;
117
+ name: string;
118
+ is3D?: boolean;
119
+ viewId?: string;
120
+ };
121
+ export declare type SheetsListPayload = {
122
+ requestId: string;
123
+ sheets: SheetListItem[];
124
+ activeSheetId?: string | number | null;
125
+ timestamp: number;
126
+ };
127
+ export declare type SheetsApplyPayload = {
128
+ sheetId: string | number;
129
+ };
130
+ export declare type TreeSelectNodePayload = {
131
+ nodeId: string;
132
+ };
133
+ export declare type TreeGetNodeIdsPayload = {
134
+ requestId: string;
135
+ onlyRealNodes?: boolean;
136
+ };
137
+ export declare type TreeNodeIdsPayload = {
138
+ requestId: string;
139
+ nodeIds: string[];
140
+ timestamp: number;
141
+ };
142
+ export declare type PdfModeEventPayload = {
143
+ mode: "plan" | "document";
144
+ timestamp: number;
145
+ };
146
+ export declare type PdfToolbarActionEventPayload = {
147
+ timestamp: number;
148
+ };
149
+ export declare type PdfCurrentPagePayload = {
150
+ pageIndex: number;
151
+ pageNumber: number;
152
+ timestamp: number;
153
+ };
@@ -0,0 +1,49 @@
1
+ // sdk/src/contracts/messages.ts
2
+ export var ViewerMessageType;
3
+ (function (ViewerMessageType) {
4
+ ViewerMessageType["LANGUAGE_CHANGE"] = "viewer-language-change";
5
+ ViewerMessageType["ZOOM"] = "viewer-zoom";
6
+ ViewerMessageType["DRAW_MODE"] = "viewer-draw-mode";
7
+ ViewerMessageType["EXPLODE"] = "viewer-explode";
8
+ ViewerMessageType["MARKUP_ACTION"] = "viewer-markup-action";
9
+ ViewerMessageType["MARKUP_SAVE"] = "viewer-markup-save";
10
+ ViewerMessageType["MARKUP_CANCEL"] = "viewer-markup-cancel";
11
+ ViewerMessageType["MARKUP_GET_LIST"] = "viewer-markup-get-list";
12
+ ViewerMessageType["MARKUP_SAVE_RESULT"] = "viewer-markup-save-result";
13
+ ViewerMessageType["MARKUP_CANCEL_RESULT"] = "viewer-markup-cancel-result";
14
+ ViewerMessageType["MARKUP_LIST"] = "viewer-markup-list";
15
+ ViewerMessageType["HOME"] = "viewer-home";
16
+ ViewerMessageType["PAN_TOGGLE"] = "viewer-pan-toggle";
17
+ ViewerMessageType["SELECT"] = "viewer-select";
18
+ ViewerMessageType["AREA_SELECT"] = "viewer-area-select";
19
+ ViewerMessageType["ORBIT"] = "viewer-orbit";
20
+ ViewerMessageType["ROTATE_Z"] = "viewer-rotate-z";
21
+ ViewerMessageType["WALK_THROUGH"] = "viewer-walk-through";
22
+ ViewerMessageType["ZOOM_WINDOW"] = "viewer-zoom-window";
23
+ ViewerMessageType["ZOOM_FIT"] = "viewer-zoom-fit";
24
+ ViewerMessageType["TOOLBAR_CONFIG"] = "viewer-toolbar-config";
25
+ ViewerMessageType["PANEL_OPEN"] = "viewer-panel-open";
26
+ ViewerMessageType["PANEL_CLOSE"] = "viewer-panel-close";
27
+ ViewerMessageType["CUTTING_PLANE_ACTION"] = "viewer-cutting-plane-action";
28
+ ViewerMessageType["SHEETS_GET_LIST"] = "viewer-sheets-get-list";
29
+ ViewerMessageType["SHEETS_LIST"] = "viewer-sheets-list";
30
+ ViewerMessageType["SHEETS_APPLY"] = "viewer-sheets-apply";
31
+ ViewerMessageType["TREE_SELECT_NODE"] = "viewer-tree-select-node";
32
+ ViewerMessageType["TREE_GET_NODE_IDS"] = "viewer-tree-get-node-ids";
33
+ ViewerMessageType["TREE_NODE_IDS"] = "viewer-tree-node-ids";
34
+ ViewerMessageType["PDF_PLAN_MODE"] = "viewer-pdf-plan-mode";
35
+ ViewerMessageType["PDF_DOCUMENT_MODE"] = "viewer-pdf-document-mode";
36
+ ViewerMessageType["PDF_FIRST_PAGE"] = "viewer-pdf-first-page";
37
+ ViewerMessageType["PDF_PREVIOUS_PAGE"] = "viewer-pdf-previous-page";
38
+ ViewerMessageType["PDF_NEXT_PAGE"] = "viewer-pdf-next-page";
39
+ ViewerMessageType["PDF_LAST_PAGE"] = "viewer-pdf-last-page";
40
+ ViewerMessageType["PDF_CURRENT_PAGE"] = "viewer-pdf-current-page";
41
+ ViewerMessageType["HOME_CLICK"] = "viewer-home-click";
42
+ ViewerMessageType["NODE_SELECT"] = "viewer-node-select";
43
+ ViewerMessageType["PAN_CHANGE"] = "viewer-pan-change";
44
+ })(ViewerMessageType || (ViewerMessageType = {}));
45
+ export var ViewerMessageSource;
46
+ (function (ViewerMessageSource) {
47
+ ViewerMessageSource["SDK"] = "HC_SDK";
48
+ ViewerMessageSource["VIEWER"] = "HC_VIEWER";
49
+ })(ViewerMessageSource || (ViewerMessageSource = {}));
@@ -0,0 +1,7 @@
1
+ export declare class Emitter<EventMap extends Record<string, any>> {
2
+ private listeners;
3
+ on<K extends keyof EventMap>(event: K, cb: (payload: EventMap[K]) => void): () => void;
4
+ off<K extends keyof EventMap>(event: K, cb: (payload: EventMap[K]) => void): void;
5
+ emit<K extends keyof EventMap>(event: K, payload: EventMap[K]): void;
6
+ clear(): void;
7
+ }
@@ -0,0 +1,31 @@
1
+ // sdk/src/core/emitter.ts
2
+ export class Emitter {
3
+ constructor() {
4
+ this.listeners = {};
5
+ }
6
+ on(event, cb) {
7
+ if (!this.listeners[event]) {
8
+ this.listeners[event] = [];
9
+ }
10
+ const arr = this.listeners[event];
11
+ arr.push(cb);
12
+ return () => this.off(event, cb);
13
+ }
14
+ off(event, cb) {
15
+ const arr = this.listeners[event];
16
+ if (!arr)
17
+ return;
18
+ const idx = arr.indexOf(cb);
19
+ if (idx >= 0)
20
+ arr.splice(idx, 1);
21
+ if (arr.length === 0)
22
+ delete this.listeners[event];
23
+ }
24
+ emit(event, payload) {
25
+ var _a;
26
+ (_a = this.listeners[event]) === null || _a === void 0 ? void 0 : _a.forEach((cb) => cb(payload));
27
+ }
28
+ clear() {
29
+ this.listeners = {};
30
+ }
31
+ }
package/dist/index.d.mts CHANGED
@@ -233,6 +233,9 @@ type FilesConfig = {
233
233
  viewerPath?: string;
234
234
  uploadPath?: string;
235
235
  };
236
+ type ConvertOptions = {
237
+ downloadUrl?: string;
238
+ };
236
239
  declare class FilesModule {
237
240
  private viewer;
238
241
  on: {
@@ -282,12 +285,12 @@ declare class FilesModule {
282
285
  fileName: string;
283
286
  baseFileId: string;
284
287
  }>;
285
- convert(file?: File): Promise<PreparedViewerData>;
286
- prepare(file?: File): Promise<PreparedViewerData>;
288
+ convert(file?: File, options?: ConvertOptions): Promise<PreparedViewerData>;
289
+ prepare(file?: File, options?: ConvertOptions): Promise<PreparedViewerData>;
287
290
  open(input: PreparedViewerData | {
288
291
  url: string;
289
292
  }): void;
290
- render(file?: File): Promise<PreparedViewerData>;
293
+ render(file?: File, options?: ConvertOptions): Promise<PreparedViewerData>;
291
294
  private resolveFile;
292
295
  private normalizeBaseUrl;
293
296
  private resolveBaseUrl;
@@ -475,4 +478,4 @@ declare class Viewer3D {
475
478
  private handleMessage;
476
479
  }
477
480
 
478
- export { type FilesConfig, type LanguageCode, type LoadStage, type LoadStatePayload, type MarkupAction, type MarkupListItem, type MarkupOperationResultPayload, type PreparedViewerData, Viewer3D };
481
+ export { type ConvertOptions, type FilesConfig, type LanguageCode, type LoadStage, type LoadStatePayload, type MarkupAction, type MarkupListItem, type MarkupOperationResultPayload, type PreparedViewerData, Viewer3D };
package/dist/index.d.ts CHANGED
@@ -233,6 +233,9 @@ type FilesConfig = {
233
233
  viewerPath?: string;
234
234
  uploadPath?: string;
235
235
  };
236
+ type ConvertOptions = {
237
+ downloadUrl?: string;
238
+ };
236
239
  declare class FilesModule {
237
240
  private viewer;
238
241
  on: {
@@ -282,12 +285,12 @@ declare class FilesModule {
282
285
  fileName: string;
283
286
  baseFileId: string;
284
287
  }>;
285
- convert(file?: File): Promise<PreparedViewerData>;
286
- prepare(file?: File): Promise<PreparedViewerData>;
288
+ convert(file?: File, options?: ConvertOptions): Promise<PreparedViewerData>;
289
+ prepare(file?: File, options?: ConvertOptions): Promise<PreparedViewerData>;
287
290
  open(input: PreparedViewerData | {
288
291
  url: string;
289
292
  }): void;
290
- render(file?: File): Promise<PreparedViewerData>;
293
+ render(file?: File, options?: ConvertOptions): Promise<PreparedViewerData>;
291
294
  private resolveFile;
292
295
  private normalizeBaseUrl;
293
296
  private resolveBaseUrl;
@@ -475,4 +478,4 @@ declare class Viewer3D {
475
478
  private handleMessage;
476
479
  }
477
480
 
478
- export { type FilesConfig, type LanguageCode, type LoadStage, type LoadStatePayload, type MarkupAction, type MarkupListItem, type MarkupOperationResultPayload, type PreparedViewerData, Viewer3D };
481
+ export { type ConvertOptions, type FilesConfig, type LanguageCode, type LoadStage, type LoadStatePayload, type MarkupAction, type MarkupListItem, type MarkupOperationResultPayload, type PreparedViewerData, Viewer3D };
package/dist/index.js CHANGED
@@ -146,7 +146,7 @@ var NodeModule = class {
146
146
 
147
147
  // src/modules/files.module.ts
148
148
  var DEFAULT_API_BASE_URL = "https://dev.3dviewer.anybim.vn";
149
- var DEFAULT_VIEWER_ORIGIN = "https://dev.3dviewer.anybim.vn";
149
+ var DEFAULT_VIEWER_ORIGIN = "http://localhost:3000";
150
150
  var FilesModule = class {
151
151
  constructor(viewer) {
152
152
  this.viewer = viewer;
@@ -194,12 +194,12 @@ var FilesModule = class {
194
194
  });
195
195
  }
196
196
  // Trigger conversion flow and resolve final viewer metadata.
197
- async convert(file) {
197
+ async convert(file, options = {}) {
198
198
  const target = this.resolveFile(file);
199
199
  return this.withOperation({ stage: "converting", message: "Converting file..." }, async () => {
200
200
  this.viewer._emit("files:conversion:start", { fileName: target.name });
201
201
  try {
202
- const prepared = await this.convertInternal(target);
202
+ const prepared = await this.convertInternal(target, options);
203
203
  this.viewer._emit("files:conversion:success", prepared);
204
204
  return prepared;
205
205
  } catch (e) {
@@ -209,11 +209,11 @@ var FilesModule = class {
209
209
  });
210
210
  }
211
211
  // Convenience API: upload first, then convert in one call.
212
- async prepare(file) {
212
+ async prepare(file, options = {}) {
213
213
  const target = this.resolveFile(file);
214
214
  return this.withOperation({ stage: "uploading", message: "Preparing file..." }, async () => {
215
215
  await this.uploadInternal(target);
216
- const prepared = await this.convertInternal(target);
216
+ const prepared = await this.convertInternal(target, options);
217
217
  return prepared;
218
218
  });
219
219
  }
@@ -230,11 +230,11 @@ var FilesModule = class {
230
230
  }
231
231
  }
232
232
  // Full pipeline: upload + convert + open iframe.
233
- async render(file) {
233
+ async render(file, options = {}) {
234
234
  const target = this.resolveFile(file);
235
235
  return this.withOperation({ stage: "uploading", message: "Uploading + converting + opening..." }, async () => {
236
236
  await this.upload(target);
237
- const prepared = await this.convert(target);
237
+ const prepared = await this.convert(target, options);
238
238
  this.updateState({ stage: "rendering", message: "Opening viewer..." });
239
239
  this.open(prepared);
240
240
  this.viewer._emit("files:load:success", prepared);
@@ -327,10 +327,11 @@ var FilesModule = class {
327
327
  }
328
328
  }
329
329
  // Build StreamFile payload compatible with conversion service.
330
- buildCachePayload(file, baseFileId) {
330
+ buildCachePayload(file, baseFileId, options = {}) {
331
331
  const createdDate = (/* @__PURE__ */ new Date()).toISOString();
332
332
  return {
333
333
  filename: file.name,
334
+ ...options.downloadUrl ? { downloadUrl: options.downloadUrl } : {},
334
335
  baseFileId,
335
336
  baseMajorRev: 0,
336
337
  baseMinorRev: 0,
@@ -374,10 +375,10 @@ var FilesModule = class {
374
375
  };
375
376
  }
376
377
  // Submit conversion/caching request and return service response.
377
- async cacheFile(file, baseFileId) {
378
+ async cacheFile(file, baseFileId, options = {}) {
378
379
  const hostConversion = await this.resolveHostConversion();
379
380
  const url = `${hostConversion}/api/StreamFile?overwrite=true&ignore_line_weight=1`;
380
- const payload = this.buildCachePayload(file, baseFileId);
381
+ const payload = this.buildCachePayload(file, baseFileId, options);
381
382
  const response = await fetch(url, {
382
383
  method: "POST",
383
384
  headers: {
@@ -394,12 +395,12 @@ var FilesModule = class {
394
395
  return await response.json();
395
396
  }
396
397
  // Convert file and generate final iframe URL with query string.
397
- async convertInternal(file) {
398
+ async convertInternal(file, options = {}) {
398
399
  var _a, _b, _c, _d;
399
400
  this.updateState({ stage: "converting", message: "Converting file..." });
400
401
  const uploadSession = this.getUploadSessionForFile(file) || this.createUploadSession(file);
401
402
  const seedBaseFileId = uploadSession.baseFileId;
402
- const cacheResult = await this.cacheFile(file, seedBaseFileId);
403
+ const cacheResult = await this.cacheFile(file, seedBaseFileId, options);
403
404
  const baseFileId = (_a = cacheResult.baseFileId) != null ? _a : seedBaseFileId;
404
405
  const baseMajorRev = (_b = cacheResult.baseMajorRev) != null ? _b : 0;
405
406
  const baseMinorRev = (_c = cacheResult.baseMinorRev) != null ? _c : 0;
package/dist/index.mjs CHANGED
@@ -120,7 +120,7 @@ var NodeModule = class {
120
120
 
121
121
  // src/modules/files.module.ts
122
122
  var DEFAULT_API_BASE_URL = "https://dev.3dviewer.anybim.vn";
123
- var DEFAULT_VIEWER_ORIGIN = "https://dev.3dviewer.anybim.vn";
123
+ var DEFAULT_VIEWER_ORIGIN = "http://localhost:3000";
124
124
  var FilesModule = class {
125
125
  constructor(viewer) {
126
126
  this.viewer = viewer;
@@ -168,12 +168,12 @@ var FilesModule = class {
168
168
  });
169
169
  }
170
170
  // Trigger conversion flow and resolve final viewer metadata.
171
- async convert(file) {
171
+ async convert(file, options = {}) {
172
172
  const target = this.resolveFile(file);
173
173
  return this.withOperation({ stage: "converting", message: "Converting file..." }, async () => {
174
174
  this.viewer._emit("files:conversion:start", { fileName: target.name });
175
175
  try {
176
- const prepared = await this.convertInternal(target);
176
+ const prepared = await this.convertInternal(target, options);
177
177
  this.viewer._emit("files:conversion:success", prepared);
178
178
  return prepared;
179
179
  } catch (e) {
@@ -183,11 +183,11 @@ var FilesModule = class {
183
183
  });
184
184
  }
185
185
  // Convenience API: upload first, then convert in one call.
186
- async prepare(file) {
186
+ async prepare(file, options = {}) {
187
187
  const target = this.resolveFile(file);
188
188
  return this.withOperation({ stage: "uploading", message: "Preparing file..." }, async () => {
189
189
  await this.uploadInternal(target);
190
- const prepared = await this.convertInternal(target);
190
+ const prepared = await this.convertInternal(target, options);
191
191
  return prepared;
192
192
  });
193
193
  }
@@ -204,11 +204,11 @@ var FilesModule = class {
204
204
  }
205
205
  }
206
206
  // Full pipeline: upload + convert + open iframe.
207
- async render(file) {
207
+ async render(file, options = {}) {
208
208
  const target = this.resolveFile(file);
209
209
  return this.withOperation({ stage: "uploading", message: "Uploading + converting + opening..." }, async () => {
210
210
  await this.upload(target);
211
- const prepared = await this.convert(target);
211
+ const prepared = await this.convert(target, options);
212
212
  this.updateState({ stage: "rendering", message: "Opening viewer..." });
213
213
  this.open(prepared);
214
214
  this.viewer._emit("files:load:success", prepared);
@@ -301,10 +301,11 @@ var FilesModule = class {
301
301
  }
302
302
  }
303
303
  // Build StreamFile payload compatible with conversion service.
304
- buildCachePayload(file, baseFileId) {
304
+ buildCachePayload(file, baseFileId, options = {}) {
305
305
  const createdDate = (/* @__PURE__ */ new Date()).toISOString();
306
306
  return {
307
307
  filename: file.name,
308
+ ...options.downloadUrl ? { downloadUrl: options.downloadUrl } : {},
308
309
  baseFileId,
309
310
  baseMajorRev: 0,
310
311
  baseMinorRev: 0,
@@ -348,10 +349,10 @@ var FilesModule = class {
348
349
  };
349
350
  }
350
351
  // Submit conversion/caching request and return service response.
351
- async cacheFile(file, baseFileId) {
352
+ async cacheFile(file, baseFileId, options = {}) {
352
353
  const hostConversion = await this.resolveHostConversion();
353
354
  const url = `${hostConversion}/api/StreamFile?overwrite=true&ignore_line_weight=1`;
354
- const payload = this.buildCachePayload(file, baseFileId);
355
+ const payload = this.buildCachePayload(file, baseFileId, options);
355
356
  const response = await fetch(url, {
356
357
  method: "POST",
357
358
  headers: {
@@ -368,12 +369,12 @@ var FilesModule = class {
368
369
  return await response.json();
369
370
  }
370
371
  // Convert file and generate final iframe URL with query string.
371
- async convertInternal(file) {
372
+ async convertInternal(file, options = {}) {
372
373
  var _a, _b, _c, _d;
373
374
  this.updateState({ stage: "converting", message: "Converting file..." });
374
375
  const uploadSession = this.getUploadSessionForFile(file) || this.createUploadSession(file);
375
376
  const seedBaseFileId = uploadSession.baseFileId;
376
- const cacheResult = await this.cacheFile(file, seedBaseFileId);
377
+ const cacheResult = await this.cacheFile(file, seedBaseFileId, options);
377
378
  const baseFileId = (_a = cacheResult.baseFileId) != null ? _a : seedBaseFileId;
378
379
  const baseMajorRev = (_b = cacheResult.baseMajorRev) != null ? _b : 0;
379
380
  const baseMinorRev = (_c = cacheResult.baseMinorRev) != null ? _c : 0;
@@ -0,0 +1,13 @@
1
+ import { Viewer3D } from "../viewer";
2
+ export declare class CameraModule {
3
+ private viewer;
4
+ on: {
5
+ home: (cb: (payload: {
6
+ timestamp: number;
7
+ }) => void) => () => void;
8
+ };
9
+ constructor(viewer: Viewer3D);
10
+ zoomIn(percent: number): void;
11
+ zoomOut(percent: number): void;
12
+ home(): void;
13
+ }
@@ -0,0 +1,18 @@
1
+ import { ViewerMessageType } from "../contracts/messages";
2
+ export class CameraModule {
3
+ constructor(viewer) {
4
+ this.viewer = viewer;
5
+ this.on = {
6
+ home: (cb) => this.viewer._on("camera:home", cb),
7
+ };
8
+ }
9
+ zoomIn(percent) {
10
+ this.viewer.postToViewer(ViewerMessageType.ZOOM, { action: "in", percent });
11
+ }
12
+ zoomOut(percent) {
13
+ this.viewer.postToViewer(ViewerMessageType.ZOOM, { action: "out", percent });
14
+ }
15
+ home() {
16
+ this.viewer.postToViewer(ViewerMessageType.HOME, {});
17
+ }
18
+ }