3dviewer-sdk 1.1.5 → 1.1.7

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 CHANGED
@@ -23,6 +23,7 @@ declare enum ViewerMessageType {
23
23
  WALK_THROUGH = "viewer-walk-through",
24
24
  ZOOM_WINDOW = "viewer-zoom-window",
25
25
  ZOOM_FIT = "viewer-zoom-fit",
26
+ DISPLAY_SET_BACKGROUND = "viewer-display-set-background",
26
27
  TOOLBAR_CONFIG = "viewer-toolbar-config",
27
28
  TOOLBAR_USE = "viewer-toolbar-use",
28
29
  PANEL_OPEN = "viewer-panel-open",
@@ -39,6 +40,8 @@ declare enum ViewerMessageType {
39
40
  STATES_OBJECTS_LIST = "viewer-states-objects-list",
40
41
  TREE_SELECT_NODE = "viewer-tree-select-node",
41
42
  TREE_SET_NODE_VISIBILITY = "viewer-tree-set-node-visibility",
43
+ NODE_SYNC_LOCKED_STATE = "viewer-node-sync-locked-state",
44
+ NODE_GET_LOCKED_STATE = "viewer-node-get-locked-state",
42
45
  TREE_GET_NODE_IDS = "viewer-tree-get-node-ids",
43
46
  TREE_NODE_IDS = "viewer-tree-node-ids",
44
47
  TREE_GET_NODES = "viewer-tree-get-nodes",
@@ -52,6 +55,8 @@ declare enum ViewerMessageType {
52
55
  PDF_CURRENT_PAGE = "viewer-pdf-current-page",
53
56
  HOME_CLICK = "viewer-home-click",
54
57
  NODE_SELECTION_CHANGE = "viewer-node-selection-change",
58
+ NODE_LOCKED_STATE = "viewer-node-locked-state",
59
+ NODE_LOCKED_STATE_CHANGE = "viewer-node-locked-state-change",
55
60
  PAN_CHANGE = "viewer-pan-change"
56
61
  }
57
62
  type LanguageCode = "en" | "vn";
@@ -59,6 +64,19 @@ type NodeSelectionChangePayload = {
59
64
  nodeIds: string[];
60
65
  timestamp: number;
61
66
  };
67
+ type ViewerRgbColor = {
68
+ r: number;
69
+ g: number;
70
+ b: number;
71
+ };
72
+ type ViewerRgbaColor = ViewerRgbColor & {
73
+ a: number;
74
+ };
75
+ type ViewerBackgroundColorInput = ViewerRgbColor | ViewerRgbaColor | string;
76
+ type ViewerBackgroundPayload = {
77
+ top: ViewerRgbColor;
78
+ bottom?: ViewerRgbColor;
79
+ };
62
80
  type CameraZoomPayload = {
63
81
  requestId?: string;
64
82
  percent: number;
@@ -130,6 +148,21 @@ type StateObjectItem = {
130
148
  type: string;
131
149
  };
132
150
  };
151
+ type SyncLockedStatePayload = {
152
+ persistentIds?: string[];
153
+ treeNodeIds?: string[];
154
+ requestId?: string;
155
+ };
156
+ type GetLockedStatePayload = {
157
+ requestId?: string;
158
+ };
159
+ type LockedStatePayload = {
160
+ requestId?: string;
161
+ persistentIds: string[];
162
+ treeNodeIds: string[];
163
+ renderedNodeIds: string[];
164
+ timestamp: number;
165
+ };
133
166
  type TreeNodeItem = {
134
167
  id: string;
135
168
  name: string;
@@ -164,6 +197,8 @@ type ViewerEventMap = {
164
197
  };
165
198
  "camera:zoom": CameraZoomPayload;
166
199
  "node:selection-change": NodeSelectionChangePayload;
200
+ "node:locked-state": LockedStatePayload;
201
+ "node:locked-state-change": LockedStatePayload;
167
202
  "interaction:pan-change": {
168
203
  enabled: boolean;
169
204
  };
@@ -289,6 +324,22 @@ declare class CameraModule {
289
324
  private postCameraGetZoom;
290
325
  }
291
326
 
327
+ type BackgroundOptionsInput = {
328
+ top: ViewerBackgroundColorInput;
329
+ bottom?: ViewerBackgroundColorInput;
330
+ };
331
+ type InitialBackground = ViewerBackgroundColorInput | BackgroundOptionsInput;
332
+
333
+ type SetBackgroundOptions = BackgroundOptionsInput;
334
+ declare class DisplayModule {
335
+ private viewer;
336
+ constructor(viewer: Viewer3D);
337
+ setBackgroundColor(color: ViewerBackgroundColorInput): void;
338
+ setBackgroundGradient(top: ViewerBackgroundColorInput, bottom: ViewerBackgroundColorInput): void;
339
+ setBackground(options: SetBackgroundOptions): void;
340
+ private postBackground;
341
+ }
342
+
292
343
  declare class InteractionModule {
293
344
  private viewer;
294
345
  on: {
@@ -316,6 +367,11 @@ declare class InteractionModule {
316
367
  private setDrawMode;
317
368
  }
318
369
 
370
+ type LockedState = LockedStatePayload;
371
+ type SyncLockedStateInput = Omit<SyncLockedStatePayload, "requestId">;
372
+ type LockedStateRequestOptions = {
373
+ timeoutMs?: number;
374
+ };
319
375
  declare class NodeModule {
320
376
  private viewer;
321
377
  on: {
@@ -323,8 +379,11 @@ declare class NodeModule {
323
379
  nodeIds: string[];
324
380
  timestamp: number;
325
381
  }) => void) => () => void;
382
+ lockedStateChange: (cb: (payload: LockedState) => void) => () => void;
326
383
  };
327
384
  constructor(viewer: Viewer3D);
385
+ syncLockedState(input: SyncLockedStateInput, options?: LockedStateRequestOptions): Promise<LockedState>;
386
+ getLockedState(options?: LockedStateRequestOptions): Promise<LockedState>;
328
387
  }
329
388
 
330
389
  type FilesConfig = {
@@ -647,6 +706,7 @@ type Viewer3DOptions = {
647
706
  uploadPath?: string;
648
707
  file?: File;
649
708
  initialToolbar?: InitialToolbarUse;
709
+ initialBackground?: InitialBackground;
650
710
  ui?: {
651
711
  loadingIndicator?: boolean;
652
712
  };
@@ -666,6 +726,7 @@ declare class Viewer3D {
666
726
  private loadingState;
667
727
  private emitter;
668
728
  camera: CameraModule;
729
+ display: DisplayModule;
669
730
  interaction: InteractionModule;
670
731
  node: NodeModule;
671
732
  files: FilesModule;
@@ -691,6 +752,7 @@ declare class Viewer3D {
691
752
  private ensureInit;
692
753
  private withInitialOptions;
693
754
  private normalizeInitialToolbar;
755
+ private normalizeInitialBackground;
694
756
  _on<K extends SdkEventKey>(event: K, cb: (payload: SdkEventPayload<K>) => void): () => void;
695
757
  _off<K extends SdkEventKey>(event: K, cb: (payload: SdkEventPayload<K>) => void): void;
696
758
  _emit<K extends SdkEventKey>(event: K, payload: SdkEventPayload<K>): void;
@@ -702,4 +764,4 @@ declare class Viewer3D {
702
764
  private handleMessage;
703
765
  }
704
766
 
705
- export { type CameraZoomPayload, type ConvertOptions, type ConvertV2Options, type CreatePipelineOptions, type FileInfoCheckInput, type FileInfoCheckPayloadItem, type FilesConfig, type InitialToolbarUse, type LanguageCode, type LoadStage, type LoadStatePayload, type MarkupAction, type MarkupListItem, type MarkupOperationResultPayload, type ObjectPropertiesGetOptions, type ObjectPropertiesResult, type PreparedViewerData, Viewer3D, type Viewer3DOptions, type ViewerLoadingChangePayload, type ViewerLoadingPhase, type ViewerReadyPayload };
767
+ export { type CameraZoomPayload, type ConvertOptions, type ConvertV2Options, type CreatePipelineOptions, type FileInfoCheckInput, type FileInfoCheckPayloadItem, type FilesConfig, type GetLockedStatePayload, type InitialBackground, type InitialToolbarUse, type LanguageCode, type LoadStage, type LoadStatePayload, type LockedState, type LockedStatePayload, type LockedStateRequestOptions, type MarkupAction, type MarkupListItem, type MarkupOperationResultPayload, type ObjectPropertiesGetOptions, type ObjectPropertiesResult, type PreparedViewerData, type SetBackgroundOptions, type SyncLockedStateInput, type SyncLockedStatePayload, Viewer3D, type Viewer3DOptions, type ViewerBackgroundColorInput, type ViewerBackgroundPayload, type ViewerLoadingChangePayload, type ViewerLoadingPhase, type ViewerReadyPayload, type ViewerRgbColor, type ViewerRgbaColor };
package/dist/index.d.ts CHANGED
@@ -23,6 +23,7 @@ declare enum ViewerMessageType {
23
23
  WALK_THROUGH = "viewer-walk-through",
24
24
  ZOOM_WINDOW = "viewer-zoom-window",
25
25
  ZOOM_FIT = "viewer-zoom-fit",
26
+ DISPLAY_SET_BACKGROUND = "viewer-display-set-background",
26
27
  TOOLBAR_CONFIG = "viewer-toolbar-config",
27
28
  TOOLBAR_USE = "viewer-toolbar-use",
28
29
  PANEL_OPEN = "viewer-panel-open",
@@ -39,6 +40,8 @@ declare enum ViewerMessageType {
39
40
  STATES_OBJECTS_LIST = "viewer-states-objects-list",
40
41
  TREE_SELECT_NODE = "viewer-tree-select-node",
41
42
  TREE_SET_NODE_VISIBILITY = "viewer-tree-set-node-visibility",
43
+ NODE_SYNC_LOCKED_STATE = "viewer-node-sync-locked-state",
44
+ NODE_GET_LOCKED_STATE = "viewer-node-get-locked-state",
42
45
  TREE_GET_NODE_IDS = "viewer-tree-get-node-ids",
43
46
  TREE_NODE_IDS = "viewer-tree-node-ids",
44
47
  TREE_GET_NODES = "viewer-tree-get-nodes",
@@ -52,6 +55,8 @@ declare enum ViewerMessageType {
52
55
  PDF_CURRENT_PAGE = "viewer-pdf-current-page",
53
56
  HOME_CLICK = "viewer-home-click",
54
57
  NODE_SELECTION_CHANGE = "viewer-node-selection-change",
58
+ NODE_LOCKED_STATE = "viewer-node-locked-state",
59
+ NODE_LOCKED_STATE_CHANGE = "viewer-node-locked-state-change",
55
60
  PAN_CHANGE = "viewer-pan-change"
56
61
  }
57
62
  type LanguageCode = "en" | "vn";
@@ -59,6 +64,19 @@ type NodeSelectionChangePayload = {
59
64
  nodeIds: string[];
60
65
  timestamp: number;
61
66
  };
67
+ type ViewerRgbColor = {
68
+ r: number;
69
+ g: number;
70
+ b: number;
71
+ };
72
+ type ViewerRgbaColor = ViewerRgbColor & {
73
+ a: number;
74
+ };
75
+ type ViewerBackgroundColorInput = ViewerRgbColor | ViewerRgbaColor | string;
76
+ type ViewerBackgroundPayload = {
77
+ top: ViewerRgbColor;
78
+ bottom?: ViewerRgbColor;
79
+ };
62
80
  type CameraZoomPayload = {
63
81
  requestId?: string;
64
82
  percent: number;
@@ -130,6 +148,21 @@ type StateObjectItem = {
130
148
  type: string;
131
149
  };
132
150
  };
151
+ type SyncLockedStatePayload = {
152
+ persistentIds?: string[];
153
+ treeNodeIds?: string[];
154
+ requestId?: string;
155
+ };
156
+ type GetLockedStatePayload = {
157
+ requestId?: string;
158
+ };
159
+ type LockedStatePayload = {
160
+ requestId?: string;
161
+ persistentIds: string[];
162
+ treeNodeIds: string[];
163
+ renderedNodeIds: string[];
164
+ timestamp: number;
165
+ };
133
166
  type TreeNodeItem = {
134
167
  id: string;
135
168
  name: string;
@@ -164,6 +197,8 @@ type ViewerEventMap = {
164
197
  };
165
198
  "camera:zoom": CameraZoomPayload;
166
199
  "node:selection-change": NodeSelectionChangePayload;
200
+ "node:locked-state": LockedStatePayload;
201
+ "node:locked-state-change": LockedStatePayload;
167
202
  "interaction:pan-change": {
168
203
  enabled: boolean;
169
204
  };
@@ -289,6 +324,22 @@ declare class CameraModule {
289
324
  private postCameraGetZoom;
290
325
  }
291
326
 
327
+ type BackgroundOptionsInput = {
328
+ top: ViewerBackgroundColorInput;
329
+ bottom?: ViewerBackgroundColorInput;
330
+ };
331
+ type InitialBackground = ViewerBackgroundColorInput | BackgroundOptionsInput;
332
+
333
+ type SetBackgroundOptions = BackgroundOptionsInput;
334
+ declare class DisplayModule {
335
+ private viewer;
336
+ constructor(viewer: Viewer3D);
337
+ setBackgroundColor(color: ViewerBackgroundColorInput): void;
338
+ setBackgroundGradient(top: ViewerBackgroundColorInput, bottom: ViewerBackgroundColorInput): void;
339
+ setBackground(options: SetBackgroundOptions): void;
340
+ private postBackground;
341
+ }
342
+
292
343
  declare class InteractionModule {
293
344
  private viewer;
294
345
  on: {
@@ -316,6 +367,11 @@ declare class InteractionModule {
316
367
  private setDrawMode;
317
368
  }
318
369
 
370
+ type LockedState = LockedStatePayload;
371
+ type SyncLockedStateInput = Omit<SyncLockedStatePayload, "requestId">;
372
+ type LockedStateRequestOptions = {
373
+ timeoutMs?: number;
374
+ };
319
375
  declare class NodeModule {
320
376
  private viewer;
321
377
  on: {
@@ -323,8 +379,11 @@ declare class NodeModule {
323
379
  nodeIds: string[];
324
380
  timestamp: number;
325
381
  }) => void) => () => void;
382
+ lockedStateChange: (cb: (payload: LockedState) => void) => () => void;
326
383
  };
327
384
  constructor(viewer: Viewer3D);
385
+ syncLockedState(input: SyncLockedStateInput, options?: LockedStateRequestOptions): Promise<LockedState>;
386
+ getLockedState(options?: LockedStateRequestOptions): Promise<LockedState>;
328
387
  }
329
388
 
330
389
  type FilesConfig = {
@@ -647,6 +706,7 @@ type Viewer3DOptions = {
647
706
  uploadPath?: string;
648
707
  file?: File;
649
708
  initialToolbar?: InitialToolbarUse;
709
+ initialBackground?: InitialBackground;
650
710
  ui?: {
651
711
  loadingIndicator?: boolean;
652
712
  };
@@ -666,6 +726,7 @@ declare class Viewer3D {
666
726
  private loadingState;
667
727
  private emitter;
668
728
  camera: CameraModule;
729
+ display: DisplayModule;
669
730
  interaction: InteractionModule;
670
731
  node: NodeModule;
671
732
  files: FilesModule;
@@ -691,6 +752,7 @@ declare class Viewer3D {
691
752
  private ensureInit;
692
753
  private withInitialOptions;
693
754
  private normalizeInitialToolbar;
755
+ private normalizeInitialBackground;
694
756
  _on<K extends SdkEventKey>(event: K, cb: (payload: SdkEventPayload<K>) => void): () => void;
695
757
  _off<K extends SdkEventKey>(event: K, cb: (payload: SdkEventPayload<K>) => void): void;
696
758
  _emit<K extends SdkEventKey>(event: K, payload: SdkEventPayload<K>): void;
@@ -702,4 +764,4 @@ declare class Viewer3D {
702
764
  private handleMessage;
703
765
  }
704
766
 
705
- export { type CameraZoomPayload, type ConvertOptions, type ConvertV2Options, type CreatePipelineOptions, type FileInfoCheckInput, type FileInfoCheckPayloadItem, type FilesConfig, type InitialToolbarUse, type LanguageCode, type LoadStage, type LoadStatePayload, type MarkupAction, type MarkupListItem, type MarkupOperationResultPayload, type ObjectPropertiesGetOptions, type ObjectPropertiesResult, type PreparedViewerData, Viewer3D, type Viewer3DOptions, type ViewerLoadingChangePayload, type ViewerLoadingPhase, type ViewerReadyPayload };
767
+ export { type CameraZoomPayload, type ConvertOptions, type ConvertV2Options, type CreatePipelineOptions, type FileInfoCheckInput, type FileInfoCheckPayloadItem, type FilesConfig, type GetLockedStatePayload, type InitialBackground, type InitialToolbarUse, type LanguageCode, type LoadStage, type LoadStatePayload, type LockedState, type LockedStatePayload, type LockedStateRequestOptions, type MarkupAction, type MarkupListItem, type MarkupOperationResultPayload, type ObjectPropertiesGetOptions, type ObjectPropertiesResult, type PreparedViewerData, type SetBackgroundOptions, type SyncLockedStateInput, type SyncLockedStatePayload, Viewer3D, type Viewer3DOptions, type ViewerBackgroundColorInput, type ViewerBackgroundPayload, type ViewerLoadingChangePayload, type ViewerLoadingPhase, type ViewerReadyPayload, type ViewerRgbColor, type ViewerRgbaColor };
package/dist/index.js CHANGED
@@ -99,6 +99,105 @@ var CameraModule = class {
99
99
  }
100
100
  };
101
101
 
102
+ // src/modules/display.shared.ts
103
+ function isBackgroundOptionsInput(value) {
104
+ return typeof value === "object" && value !== null && "top" in value;
105
+ }
106
+ function clampColorChannel(value) {
107
+ if (!Number.isFinite(value)) return 0;
108
+ return Math.min(255, Math.max(0, Math.round(value)));
109
+ }
110
+ function normalizeHexColor(color) {
111
+ const normalized = color.trim();
112
+ const match = normalized.match(/^#?([a-f\d]{3}|[a-f\d]{6})$/i);
113
+ if (!match) {
114
+ throw new Error(
115
+ `Invalid background color "${color}". Use #RGB, #RRGGBB, rgb(...), rgba(...), or { r, g, b }.`
116
+ );
117
+ }
118
+ const hex = match[1].length === 3 ? match[1].split("").map((char) => `${char}${char}`).join("") : match[1];
119
+ return {
120
+ r: Number.parseInt(hex.slice(0, 2), 16),
121
+ g: Number.parseInt(hex.slice(2, 4), 16),
122
+ b: Number.parseInt(hex.slice(4, 6), 16)
123
+ };
124
+ }
125
+ function normalizeFunctionalRgbColor(color) {
126
+ const normalized = color.trim();
127
+ const match = normalized.match(/^rgba?\(\s*([^)]+)\s*\)$/i);
128
+ if (!match) return null;
129
+ const values = match[1].split(",").map((value) => value.trim()).filter((value) => value !== "");
130
+ if (values.length !== 3 && values.length !== 4) {
131
+ throw new Error(
132
+ `Invalid background color "${color}". rgb()/rgba() requires 3 RGB channels and optional alpha.`
133
+ );
134
+ }
135
+ const [r, g, b] = values;
136
+ return {
137
+ r: clampColorChannel(Number(r)),
138
+ g: clampColorChannel(Number(g)),
139
+ b: clampColorChannel(Number(b))
140
+ };
141
+ }
142
+ function normalizeBackgroundColor(color) {
143
+ var _a;
144
+ if (typeof color === "string") {
145
+ return (_a = normalizeFunctionalRgbColor(color)) != null ? _a : normalizeHexColor(color);
146
+ }
147
+ return {
148
+ r: clampColorChannel(color.r),
149
+ g: clampColorChannel(color.g),
150
+ b: clampColorChannel(color.b)
151
+ };
152
+ }
153
+ function normalizeBackgroundOptions(options) {
154
+ return {
155
+ top: normalizeBackgroundColor(options.top),
156
+ bottom: options.bottom === void 0 ? void 0 : normalizeBackgroundColor(options.bottom)
157
+ };
158
+ }
159
+ function normalizeInitialBackground(background) {
160
+ if (isBackgroundOptionsInput(background)) {
161
+ return normalizeBackgroundOptions(background);
162
+ }
163
+ const solidColor = normalizeBackgroundColor(
164
+ background
165
+ );
166
+ return {
167
+ top: solidColor,
168
+ bottom: solidColor
169
+ };
170
+ }
171
+
172
+ // src/modules/display.module.ts
173
+ var DisplayModule = class {
174
+ constructor(viewer) {
175
+ this.viewer = viewer;
176
+ }
177
+ setBackgroundColor(color) {
178
+ const normalizedColor = normalizeBackgroundColor(color);
179
+ this.postBackground({
180
+ top: normalizedColor,
181
+ bottom: normalizedColor
182
+ });
183
+ }
184
+ setBackgroundGradient(top, bottom) {
185
+ this.postBackground({
186
+ top: normalizeBackgroundColor(top),
187
+ bottom: normalizeBackgroundColor(bottom)
188
+ });
189
+ }
190
+ setBackground(options) {
191
+ this.postBackground(normalizeBackgroundOptions(options));
192
+ }
193
+ postBackground(payload) {
194
+ this.viewer.postToViewer(
195
+ "viewer-display-set-background" /* DISPLAY_SET_BACKGROUND */,
196
+ payload
197
+ );
198
+ }
199
+ };
200
+
102
201
  // src/modules/interaction.module.ts
103
202
  var InteractionModule = class {
104
203
  constructor(viewer) {
@@ -161,14 +260,74 @@ var InteractionModule = class {
161
260
  };
162
261
 
163
262
  // src/modules/node.module.ts
263
+ function createRequestId2(prefix) {
264
+ return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
265
+ }
266
+ function normalizeIds(values) {
267
+ if (!values) return void 0;
268
+ const normalized = Array.from(
269
+ new Set(
270
+ values.map((value) => String(value).trim()).filter((value) => value !== "")
271
+ )
272
+ );
273
+ return normalized.length > 0 ? normalized : void 0;
274
+ }
164
275
  var NodeModule = class {
165
276
  constructor(viewer) {
166
277
  this.viewer = viewer;
167
278
  this.on = {
168
279
  // SDK no longer supports first-node-only select events; listen to selectionChange for the full node list.
169
- selectionChange: (cb) => this.viewer._on("node:selection-change", cb)
280
+ selectionChange: (cb) => this.viewer._on("node:selection-change", cb),
281
+ lockedStateChange: (cb) => this.viewer._on("node:locked-state-change", cb)
170
282
  };
171
283
  }
284
+ syncLockedState(input, options) {
285
+ var _a;
286
+ const requestId = createRequestId2("locked_state_sync");
287
+ const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
288
+ return new Promise((resolve, reject) => {
289
+ const timer = setTimeout(() => {
290
+ off();
291
+ reject(new Error("Timeout while syncing locked state with viewer"));
292
+ }, timeoutMs);
293
+ const off = this.viewer._on("node:locked-state", (payload2) => {
294
+ if (payload2.requestId !== requestId) return;
295
+ clearTimeout(timer);
296
+ off();
297
+ resolve(payload2);
298
+ });
299
+ const payload = {
300
+ requestId,
301
+ persistentIds: normalizeIds(input.persistentIds),
302
+ treeNodeIds: normalizeIds(input.treeNodeIds)
303
+ };
304
+ this.viewer.postToViewer(
305
+ "viewer-node-sync-locked-state" /* NODE_SYNC_LOCKED_STATE */,
306
+ payload
307
+ );
308
+ });
309
+ }
310
+ getLockedState(options) {
311
+ var _a;
312
+ const requestId = createRequestId2("locked_state_get");
313
+ const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
314
+ return new Promise((resolve, reject) => {
315
+ const timer = setTimeout(() => {
316
+ off();
317
+ reject(new Error("Timeout while getting locked state from viewer"));
318
+ }, timeoutMs);
319
+ const off = this.viewer._on("node:locked-state", (payload) => {
320
+ if (payload.requestId !== requestId) return;
321
+ clearTimeout(timer);
322
+ off();
323
+ resolve(payload);
324
+ });
325
+ this.viewer.postToViewer(
326
+ "viewer-node-get-locked-state" /* NODE_GET_LOCKED_STATE */,
327
+ { requestId }
328
+ );
329
+ });
330
+ }
172
331
  };
173
332
 
174
333
  // src/modules/files.module.ts
@@ -734,7 +893,7 @@ var FilesModule = class {
734
893
  };
735
894
 
736
895
  // src/modules/toolbar.module.ts
737
- function createRequestId2(prefix) {
896
+ function createRequestId3(prefix) {
738
897
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
739
898
  }
740
899
  var ALL_3D_TOOLBAR_OPERATORS = [
@@ -892,7 +1051,7 @@ var ToolbarModule = class {
892
1051
  }
893
1052
  getSheets(options) {
894
1053
  var _a;
895
- const requestId = createRequestId2("sheets");
1054
+ const requestId = createRequestId3("sheets");
896
1055
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
897
1056
  return new Promise((resolve, reject) => {
898
1057
  const timer = setTimeout(() => {
@@ -910,7 +1069,7 @@ var ToolbarModule = class {
910
1069
  }
911
1070
  getObjectProperties(options) {
912
1071
  var _a;
913
- const requestId = createRequestId2("object_properties");
1072
+ const requestId = createRequestId3("object_properties");
914
1073
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
915
1074
  return new Promise((resolve, reject) => {
916
1075
  var _a2;
@@ -932,7 +1091,7 @@ var ToolbarModule = class {
932
1091
  }
933
1092
  getLinkedObjects(options) {
934
1093
  var _a;
935
- const requestId = createRequestId2("linked_objects");
1094
+ const requestId = createRequestId3("linked_objects");
936
1095
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
937
1096
  return new Promise((resolve, reject) => {
938
1097
  const timer = setTimeout(() => {
@@ -950,7 +1109,7 @@ var ToolbarModule = class {
950
1109
  }
951
1110
  getStatesObjects(options) {
952
1111
  var _a;
953
- const requestId = createRequestId2("states_objects");
1112
+ const requestId = createRequestId3("states_objects");
954
1113
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
955
1114
  return new Promise((resolve, reject) => {
956
1115
  const timer = setTimeout(() => {
@@ -1038,7 +1197,7 @@ var ToolbarModule = class {
1038
1197
  };
1039
1198
 
1040
1199
  // src/modules/model-tree.module.ts
1041
- function createRequestId3(prefix) {
1200
+ function createRequestId4(prefix) {
1042
1201
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
1043
1202
  }
1044
1203
  function buildTree(nodes, rootNodeIds) {
@@ -1112,7 +1271,7 @@ var ModelTreeModule = class {
1112
1271
  this.setNodeVisibility(nodeIds, true);
1113
1272
  }
1114
1273
  getNodeIds(options) {
1115
- const requestId = createRequestId3("tree");
1274
+ const requestId = createRequestId4("tree");
1116
1275
  const timeoutMs = this.resolveTimeoutMs(options);
1117
1276
  return new Promise((resolve, reject) => {
1118
1277
  const timer = setTimeout(() => {
@@ -1138,7 +1297,7 @@ var ModelTreeModule = class {
1138
1297
  return this.requestNodes(options).then((response) => buildTree(response.nodes, response.rootNodeIds));
1139
1298
  }
1140
1299
  requestNodes(options) {
1141
- const requestId = createRequestId3("tree_nodes");
1300
+ const requestId = createRequestId4("tree_nodes");
1142
1301
  const timeoutMs = this.resolveTimeoutMs(options);
1143
1302
  return new Promise((resolve, reject) => {
1144
1303
  const timer = setTimeout(() => {
@@ -1190,7 +1349,7 @@ var ModelTreeModule = class {
1190
1349
  };
1191
1350
 
1192
1351
  // src/modules/markup.module.ts
1193
- function createRequestId4(prefix) {
1352
+ function createRequestId5(prefix) {
1194
1353
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
1195
1354
  }
1196
1355
  var MarkupModule = class {
@@ -1244,7 +1403,7 @@ var MarkupModule = class {
1244
1403
  }
1245
1404
  getList(options) {
1246
1405
  var _a;
1247
- const requestId = createRequestId4("markup-list");
1406
+ const requestId = createRequestId5("markup-list");
1248
1407
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
1249
1408
  return new Promise((resolve, reject) => {
1250
1409
  const timer = setTimeout(() => {
@@ -1262,7 +1421,7 @@ var MarkupModule = class {
1262
1421
  }
1263
1422
  runRequest(prefix, messageType, eventName, options) {
1264
1423
  var _a;
1265
- const requestId = createRequestId4(prefix);
1424
+ const requestId = createRequestId5(prefix);
1266
1425
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
1267
1426
  return new Promise((resolve, reject) => {
1268
1427
  const timer = setTimeout(() => {
@@ -1308,7 +1467,7 @@ function createObjectPropertiesError(message, errorStatus) {
1308
1467
  error.errorStatus = errorStatus;
1309
1468
  return error;
1310
1469
  }
1311
- function createRequestId5(prefix) {
1470
+ function createRequestId6(prefix) {
1312
1471
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
1313
1472
  }
1314
1473
  function normalizeNodeIds(nodeIds) {
@@ -1326,7 +1485,7 @@ var ObjectPropertiesModule = class {
1326
1485
  getByNodeIds(nodeIds, options) {
1327
1486
  var _a;
1328
1487
  const normalizedNodeIds = normalizeNodeIds(nodeIds);
1329
- const requestId = createRequestId5("object_properties");
1488
+ const requestId = createRequestId6("object_properties");
1330
1489
  if (normalizedNodeIds.length === 0) {
1331
1490
  return Promise.resolve({
1332
1491
  requestId,
@@ -1439,6 +1598,30 @@ var Viewer3D = class {
1439
1598
  });
1440
1599
  break;
1441
1600
  }
1601
+ case "viewer-node-locked-state" /* NODE_LOCKED_STATE */: {
1602
+ const payload = data.payload;
1603
+ if (!payload) break;
1604
+ this._emit("node:locked-state", {
1605
+ requestId: payload.requestId ? String(payload.requestId) : void 0,
1606
+ persistentIds: Array.isArray(payload.persistentIds) ? payload.persistentIds.map(String) : [],
1607
+ treeNodeIds: Array.isArray(payload.treeNodeIds) ? payload.treeNodeIds.map(String) : [],
1608
+ renderedNodeIds: Array.isArray(payload.renderedNodeIds) ? payload.renderedNodeIds.map(String) : [],
1609
+ timestamp: Number(payload.timestamp) || Date.now()
1610
+ });
1611
+ break;
1612
+ }
1613
+ case "viewer-node-locked-state-change" /* NODE_LOCKED_STATE_CHANGE */: {
1614
+ const payload = data.payload;
1615
+ if (!payload) break;
1616
+ this._emit("node:locked-state-change", {
1617
+ requestId: payload.requestId ? String(payload.requestId) : void 0,
1618
+ persistentIds: Array.isArray(payload.persistentIds) ? payload.persistentIds.map(String) : [],
1619
+ treeNodeIds: Array.isArray(payload.treeNodeIds) ? payload.treeNodeIds.map(String) : [],
1620
+ renderedNodeIds: Array.isArray(payload.renderedNodeIds) ? payload.renderedNodeIds.map(String) : [],
1621
+ timestamp: Number(payload.timestamp) || Date.now()
1622
+ });
1623
+ break;
1624
+ }
1442
1625
  case "viewer-pan-change" /* PAN_CHANGE */:
1443
1626
  this._emit("interaction:pan-change", {
1444
1627
  enabled: Boolean((_a = data.payload) == null ? void 0 : _a.enabled)
@@ -1662,6 +1845,7 @@ var Viewer3D = class {
1662
1845
  }
1663
1846
  };
1664
1847
  this.camera = new CameraModule(this);
1848
+ this.display = new DisplayModule(this);
1665
1849
  this.interaction = new InteractionModule(this);
1666
1850
  this.node = new NodeModule(this);
1667
1851
  this.files = new FilesModule(this);
@@ -1789,6 +1973,13 @@ var Viewer3D = class {
1789
1973
  if (((_a = this.options.ui) == null ? void 0 : _a.loadingIndicator) === false) {
1790
1974
  parsedUrl.searchParams.set("loadingIndicator", "false");
1791
1975
  }
1976
+ const initialBackground = this.normalizeInitialBackground();
1977
+ if (initialBackground) {
1978
+ parsedUrl.searchParams.set(
1979
+ "initialBackground",
1980
+ JSON.stringify(initialBackground)
1981
+ );
1982
+ }
1792
1983
  return parsedUrl.toString();
1793
1984
  } catch {
1794
1985
  return url;
@@ -1821,6 +2012,11 @@ var Viewer3D = class {
1821
2012
  {}
1822
2013
  );
1823
2014
  }
2015
+ normalizeInitialBackground() {
2016
+ const initialBackground = this.options.initialBackground;
2017
+ if (!initialBackground) return null;
2018
+ return normalizeInitialBackground(initialBackground);
2019
+ }
1824
2020
  // ===== typed internal events used by modules =====
1825
2021
  _on(event, cb) {
1826
2022
  return this.emitter.on(event, cb);
package/dist/index.mjs CHANGED
@@ -73,6 +73,105 @@ var CameraModule = class {
73
73
  }
74
74
  };
75
75
 
76
+ // src/modules/display.shared.ts
77
+ function isBackgroundOptionsInput(value) {
78
+ return typeof value === "object" && value !== null && "top" in value;
79
+ }
80
+ function clampColorChannel(value) {
81
+ if (!Number.isFinite(value)) return 0;
82
+ return Math.min(255, Math.max(0, Math.round(value)));
83
+ }
84
+ function normalizeHexColor(color) {
85
+ const normalized = color.trim();
86
+ const match = normalized.match(/^#?([a-f\d]{3}|[a-f\d]{6})$/i);
87
+ if (!match) {
88
+ throw new Error(
89
+ `Invalid background color "${color}". Use #RGB, #RRGGBB, rgb(...), rgba(...), or { r, g, b }.`
90
+ );
91
+ }
92
+ const hex = match[1].length === 3 ? match[1].split("").map((char) => `${char}${char}`).join("") : match[1];
93
+ return {
94
+ r: Number.parseInt(hex.slice(0, 2), 16),
95
+ g: Number.parseInt(hex.slice(2, 4), 16),
96
+ b: Number.parseInt(hex.slice(4, 6), 16)
97
+ };
98
+ }
99
+ function normalizeFunctionalRgbColor(color) {
100
+ const normalized = color.trim();
101
+ const match = normalized.match(/^rgba?\(\s*([^)]+)\s*\)$/i);
102
+ if (!match) return null;
103
+ const values = match[1].split(",").map((value) => value.trim()).filter((value) => value !== "");
104
+ if (values.length !== 3 && values.length !== 4) {
105
+ throw new Error(
106
+ `Invalid background color "${color}". rgb()/rgba() requires 3 RGB channels and optional alpha.`
107
+ );
108
+ }
109
+ const [r, g, b] = values;
110
+ return {
111
+ r: clampColorChannel(Number(r)),
112
+ g: clampColorChannel(Number(g)),
113
+ b: clampColorChannel(Number(b))
114
+ };
115
+ }
116
+ function normalizeBackgroundColor(color) {
117
+ var _a;
118
+ if (typeof color === "string") {
119
+ return (_a = normalizeFunctionalRgbColor(color)) != null ? _a : normalizeHexColor(color);
120
+ }
121
+ return {
122
+ r: clampColorChannel(color.r),
123
+ g: clampColorChannel(color.g),
124
+ b: clampColorChannel(color.b)
125
+ };
126
+ }
127
+ function normalizeBackgroundOptions(options) {
128
+ return {
129
+ top: normalizeBackgroundColor(options.top),
130
+ bottom: options.bottom === void 0 ? void 0 : normalizeBackgroundColor(options.bottom)
131
+ };
132
+ }
133
+ function normalizeInitialBackground(background) {
134
+ if (isBackgroundOptionsInput(background)) {
135
+ return normalizeBackgroundOptions(background);
136
+ }
137
+ const solidColor = normalizeBackgroundColor(
138
+ background
139
+ );
140
+ return {
141
+ top: solidColor,
142
+ bottom: solidColor
143
+ };
144
+ }
145
+
146
+ // src/modules/display.module.ts
147
+ var DisplayModule = class {
148
+ constructor(viewer) {
149
+ this.viewer = viewer;
150
+ }
151
+ setBackgroundColor(color) {
152
+ const normalizedColor = normalizeBackgroundColor(color);
153
+ this.postBackground({
154
+ top: normalizedColor,
155
+ bottom: normalizedColor
156
+ });
157
+ }
158
+ setBackgroundGradient(top, bottom) {
159
+ this.postBackground({
160
+ top: normalizeBackgroundColor(top),
161
+ bottom: normalizeBackgroundColor(bottom)
162
+ });
163
+ }
164
+ setBackground(options) {
165
+ this.postBackground(normalizeBackgroundOptions(options));
166
+ }
167
+ postBackground(payload) {
168
+ this.viewer.postToViewer(
169
+ "viewer-display-set-background" /* DISPLAY_SET_BACKGROUND */,
170
+ payload
171
+ );
172
+ }
173
+ };
174
+
76
175
  // src/modules/interaction.module.ts
77
176
  var InteractionModule = class {
78
177
  constructor(viewer) {
@@ -135,14 +234,74 @@ var InteractionModule = class {
135
234
  };
136
235
 
137
236
  // src/modules/node.module.ts
237
+ function createRequestId2(prefix) {
238
+ return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
239
+ }
240
+ function normalizeIds(values) {
241
+ if (!values) return void 0;
242
+ const normalized = Array.from(
243
+ new Set(
244
+ values.map((value) => String(value).trim()).filter((value) => value !== "")
245
+ )
246
+ );
247
+ return normalized.length > 0 ? normalized : void 0;
248
+ }
138
249
  var NodeModule = class {
139
250
  constructor(viewer) {
140
251
  this.viewer = viewer;
141
252
  this.on = {
142
253
  // SDK no longer supports first-node-only select events; listen to selectionChange for the full node list.
143
- selectionChange: (cb) => this.viewer._on("node:selection-change", cb)
254
+ selectionChange: (cb) => this.viewer._on("node:selection-change", cb),
255
+ lockedStateChange: (cb) => this.viewer._on("node:locked-state-change", cb)
144
256
  };
145
257
  }
258
+ syncLockedState(input, options) {
259
+ var _a;
260
+ const requestId = createRequestId2("locked_state_sync");
261
+ const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
262
+ return new Promise((resolve, reject) => {
263
+ const timer = setTimeout(() => {
264
+ off();
265
+ reject(new Error("Timeout while syncing locked state with viewer"));
266
+ }, timeoutMs);
267
+ const off = this.viewer._on("node:locked-state", (payload2) => {
268
+ if (payload2.requestId !== requestId) return;
269
+ clearTimeout(timer);
270
+ off();
271
+ resolve(payload2);
272
+ });
273
+ const payload = {
274
+ requestId,
275
+ persistentIds: normalizeIds(input.persistentIds),
276
+ treeNodeIds: normalizeIds(input.treeNodeIds)
277
+ };
278
+ this.viewer.postToViewer(
279
+ "viewer-node-sync-locked-state" /* NODE_SYNC_LOCKED_STATE */,
280
+ payload
281
+ );
282
+ });
283
+ }
284
+ getLockedState(options) {
285
+ var _a;
286
+ const requestId = createRequestId2("locked_state_get");
287
+ const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
288
+ return new Promise((resolve, reject) => {
289
+ const timer = setTimeout(() => {
290
+ off();
291
+ reject(new Error("Timeout while getting locked state from viewer"));
292
+ }, timeoutMs);
293
+ const off = this.viewer._on("node:locked-state", (payload) => {
294
+ if (payload.requestId !== requestId) return;
295
+ clearTimeout(timer);
296
+ off();
297
+ resolve(payload);
298
+ });
299
+ this.viewer.postToViewer(
300
+ "viewer-node-get-locked-state" /* NODE_GET_LOCKED_STATE */,
301
+ { requestId }
302
+ );
303
+ });
304
+ }
146
305
  };
147
306
 
148
307
  // src/modules/files.module.ts
@@ -708,7 +867,7 @@ var FilesModule = class {
708
867
  };
709
868
 
710
869
  // src/modules/toolbar.module.ts
711
- function createRequestId2(prefix) {
870
+ function createRequestId3(prefix) {
712
871
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
713
872
  }
714
873
  var ALL_3D_TOOLBAR_OPERATORS = [
@@ -866,7 +1025,7 @@ var ToolbarModule = class {
866
1025
  }
867
1026
  getSheets(options) {
868
1027
  var _a;
869
- const requestId = createRequestId2("sheets");
1028
+ const requestId = createRequestId3("sheets");
870
1029
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
871
1030
  return new Promise((resolve, reject) => {
872
1031
  const timer = setTimeout(() => {
@@ -884,7 +1043,7 @@ var ToolbarModule = class {
884
1043
  }
885
1044
  getObjectProperties(options) {
886
1045
  var _a;
887
- const requestId = createRequestId2("object_properties");
1046
+ const requestId = createRequestId3("object_properties");
888
1047
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
889
1048
  return new Promise((resolve, reject) => {
890
1049
  var _a2;
@@ -906,7 +1065,7 @@ var ToolbarModule = class {
906
1065
  }
907
1066
  getLinkedObjects(options) {
908
1067
  var _a;
909
- const requestId = createRequestId2("linked_objects");
1068
+ const requestId = createRequestId3("linked_objects");
910
1069
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
911
1070
  return new Promise((resolve, reject) => {
912
1071
  const timer = setTimeout(() => {
@@ -924,7 +1083,7 @@ var ToolbarModule = class {
924
1083
  }
925
1084
  getStatesObjects(options) {
926
1085
  var _a;
927
- const requestId = createRequestId2("states_objects");
1086
+ const requestId = createRequestId3("states_objects");
928
1087
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
929
1088
  return new Promise((resolve, reject) => {
930
1089
  const timer = setTimeout(() => {
@@ -1012,7 +1171,7 @@ var ToolbarModule = class {
1012
1171
  };
1013
1172
 
1014
1173
  // src/modules/model-tree.module.ts
1015
- function createRequestId3(prefix) {
1174
+ function createRequestId4(prefix) {
1016
1175
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
1017
1176
  }
1018
1177
  function buildTree(nodes, rootNodeIds) {
@@ -1086,7 +1245,7 @@ var ModelTreeModule = class {
1086
1245
  this.setNodeVisibility(nodeIds, true);
1087
1246
  }
1088
1247
  getNodeIds(options) {
1089
- const requestId = createRequestId3("tree");
1248
+ const requestId = createRequestId4("tree");
1090
1249
  const timeoutMs = this.resolveTimeoutMs(options);
1091
1250
  return new Promise((resolve, reject) => {
1092
1251
  const timer = setTimeout(() => {
@@ -1112,7 +1271,7 @@ var ModelTreeModule = class {
1112
1271
  return this.requestNodes(options).then((response) => buildTree(response.nodes, response.rootNodeIds));
1113
1272
  }
1114
1273
  requestNodes(options) {
1115
- const requestId = createRequestId3("tree_nodes");
1274
+ const requestId = createRequestId4("tree_nodes");
1116
1275
  const timeoutMs = this.resolveTimeoutMs(options);
1117
1276
  return new Promise((resolve, reject) => {
1118
1277
  const timer = setTimeout(() => {
@@ -1164,7 +1323,7 @@ var ModelTreeModule = class {
1164
1323
  };
1165
1324
 
1166
1325
  // src/modules/markup.module.ts
1167
- function createRequestId4(prefix) {
1326
+ function createRequestId5(prefix) {
1168
1327
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
1169
1328
  }
1170
1329
  var MarkupModule = class {
@@ -1218,7 +1377,7 @@ var MarkupModule = class {
1218
1377
  }
1219
1378
  getList(options) {
1220
1379
  var _a;
1221
- const requestId = createRequestId4("markup-list");
1380
+ const requestId = createRequestId5("markup-list");
1222
1381
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
1223
1382
  return new Promise((resolve, reject) => {
1224
1383
  const timer = setTimeout(() => {
@@ -1236,7 +1395,7 @@ var MarkupModule = class {
1236
1395
  }
1237
1396
  runRequest(prefix, messageType, eventName, options) {
1238
1397
  var _a;
1239
- const requestId = createRequestId4(prefix);
1398
+ const requestId = createRequestId5(prefix);
1240
1399
  const timeoutMs = Math.max(1e3, (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4);
1241
1400
  return new Promise((resolve, reject) => {
1242
1401
  const timer = setTimeout(() => {
@@ -1282,7 +1441,7 @@ function createObjectPropertiesError(message, errorStatus) {
1282
1441
  error.errorStatus = errorStatus;
1283
1442
  return error;
1284
1443
  }
1285
- function createRequestId5(prefix) {
1444
+ function createRequestId6(prefix) {
1286
1445
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
1287
1446
  }
1288
1447
  function normalizeNodeIds(nodeIds) {
@@ -1300,7 +1459,7 @@ var ObjectPropertiesModule = class {
1300
1459
  getByNodeIds(nodeIds, options) {
1301
1460
  var _a;
1302
1461
  const normalizedNodeIds = normalizeNodeIds(nodeIds);
1303
- const requestId = createRequestId5("object_properties");
1462
+ const requestId = createRequestId6("object_properties");
1304
1463
  if (normalizedNodeIds.length === 0) {
1305
1464
  return Promise.resolve({
1306
1465
  requestId,
@@ -1413,6 +1572,30 @@ var Viewer3D = class {
1413
1572
  });
1414
1573
  break;
1415
1574
  }
1575
+ case "viewer-node-locked-state" /* NODE_LOCKED_STATE */: {
1576
+ const payload = data.payload;
1577
+ if (!payload) break;
1578
+ this._emit("node:locked-state", {
1579
+ requestId: payload.requestId ? String(payload.requestId) : void 0,
1580
+ persistentIds: Array.isArray(payload.persistentIds) ? payload.persistentIds.map(String) : [],
1581
+ treeNodeIds: Array.isArray(payload.treeNodeIds) ? payload.treeNodeIds.map(String) : [],
1582
+ renderedNodeIds: Array.isArray(payload.renderedNodeIds) ? payload.renderedNodeIds.map(String) : [],
1583
+ timestamp: Number(payload.timestamp) || Date.now()
1584
+ });
1585
+ break;
1586
+ }
1587
+ case "viewer-node-locked-state-change" /* NODE_LOCKED_STATE_CHANGE */: {
1588
+ const payload = data.payload;
1589
+ if (!payload) break;
1590
+ this._emit("node:locked-state-change", {
1591
+ requestId: payload.requestId ? String(payload.requestId) : void 0,
1592
+ persistentIds: Array.isArray(payload.persistentIds) ? payload.persistentIds.map(String) : [],
1593
+ treeNodeIds: Array.isArray(payload.treeNodeIds) ? payload.treeNodeIds.map(String) : [],
1594
+ renderedNodeIds: Array.isArray(payload.renderedNodeIds) ? payload.renderedNodeIds.map(String) : [],
1595
+ timestamp: Number(payload.timestamp) || Date.now()
1596
+ });
1597
+ break;
1598
+ }
1416
1599
  case "viewer-pan-change" /* PAN_CHANGE */:
1417
1600
  this._emit("interaction:pan-change", {
1418
1601
  enabled: Boolean((_a = data.payload) == null ? void 0 : _a.enabled)
@@ -1636,6 +1819,7 @@ var Viewer3D = class {
1636
1819
  }
1637
1820
  };
1638
1821
  this.camera = new CameraModule(this);
1822
+ this.display = new DisplayModule(this);
1639
1823
  this.interaction = new InteractionModule(this);
1640
1824
  this.node = new NodeModule(this);
1641
1825
  this.files = new FilesModule(this);
@@ -1763,6 +1947,13 @@ var Viewer3D = class {
1763
1947
  if (((_a = this.options.ui) == null ? void 0 : _a.loadingIndicator) === false) {
1764
1948
  parsedUrl.searchParams.set("loadingIndicator", "false");
1765
1949
  }
1950
+ const initialBackground = this.normalizeInitialBackground();
1951
+ if (initialBackground) {
1952
+ parsedUrl.searchParams.set(
1953
+ "initialBackground",
1954
+ JSON.stringify(initialBackground)
1955
+ );
1956
+ }
1766
1957
  return parsedUrl.toString();
1767
1958
  } catch {
1768
1959
  return url;
@@ -1795,6 +1986,11 @@ var Viewer3D = class {
1795
1986
  {}
1796
1987
  );
1797
1988
  }
1989
+ normalizeInitialBackground() {
1990
+ const initialBackground = this.options.initialBackground;
1991
+ if (!initialBackground) return null;
1992
+ return normalizeInitialBackground(initialBackground);
1993
+ }
1798
1994
  // ===== typed internal events used by modules =====
1799
1995
  _on(event, cb) {
1800
1996
  return this.emitter.on(event, cb);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "3dviewer-sdk",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [