@preference-sl/pref-viewer 2.16.2 → 2.17.0-beta.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/README.md +184 -22
- package/index.d.ts +11 -1
- package/package.json +1 -1
- package/src/babylonjs-animation-controller.js +12 -163
- package/src/babylonjs-animation-opening-menu.js +8 -1
- package/src/babylonjs-animation-opening.js +21 -1
- package/src/babylonjs-animation-overlay-controller.js +145 -0
- package/src/babylonjs-camera-framing.js +171 -0
- package/src/babylonjs-camera-zoom-controller.js +272 -0
- package/src/babylonjs-controller.js +640 -378
- package/src/babylonjs-selection-controller.js +215 -0
- package/src/babylonjs-view-cube-controller.js +810 -0
- package/src/file-storage.js +13 -0
- package/src/gltf-storage.js +97 -0
- package/src/localization/i18n.js +147 -74
- package/src/localization/translations.js +18 -0
- package/src/material-utils.js +67 -60
- package/src/panzoom-controller.js +14 -1
- package/src/pref-viewer-2d.js +16 -4
- package/src/pref-viewer-3d-data.js +166 -0
- package/src/pref-viewer-3d.js +40 -5
- package/src/pref-viewer-dialog.js +7 -1
- package/src/pref-viewer-menu-3d.js +57 -37
- package/src/pref-viewer.js +155 -44
- package/src/render-math.js +130 -117
- package/src/styles.js +94 -3
- package/src/svg-resolver.js +5 -4
package/src/pref-viewer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import PrefViewerTask from "./pref-viewer-task.js";
|
|
2
2
|
import { PREF_VIEWER_STYLES_STORAGE_KEY, PrefViewerStyles, PrefViewerStyleVariables } from "./styles.js";
|
|
3
|
-
import
|
|
3
|
+
import I18n from "./localization/i18n.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* PrefViewer - Custom Web Component for immersive 2D/3D product visualization with localization, persistence, and download tooling.
|
|
@@ -23,13 +23,14 @@ import { DEFAULT_LOCALE, resolveLocale, setLocale, SUPPORTED_LOCALES } from "./l
|
|
|
23
23
|
* - Listen for `pref-viewer-initialized`, `pref-viewer-loading`, `pref-viewer-loaded`, `pref-viewer-error`, `pref-viewer-3d-loaded`, `pref-viewer-2d-loaded`, and `pref-viewer-2d-viewport-changed` to integrate with surrounding UX.
|
|
24
24
|
*
|
|
25
25
|
* Reactive Attributes:
|
|
26
|
-
* - config: Configuration descriptor
|
|
26
|
+
* - config: Configuration descriptor with assets, culture/styles and optional boolean showRenderMenu/showViewCube flags.
|
|
27
27
|
* - model / scene / materials / drawing: Independent asset entry points (URLs, Base64, indexed data) for each subsystem.
|
|
28
28
|
* - options: JSON describing render toggles (AA, SSAO, IBL, shadows), animation menu, highlight, lighting, and misc viewer knobs.
|
|
29
|
-
* - culture: Locale identifier (RFC-5646 style) that resolves against `SUPPORTED_LOCALES` before applying.
|
|
29
|
+
* - culture: Locale identifier (RFC-5646 style) that resolves against `I18n.SUPPORTED_LOCALES` before applying.
|
|
30
30
|
* - mode: Switches between `2d` and `3d`, automatically hiding/showing the relevant subcomponents and menu states.
|
|
31
31
|
* - show-model / show-scene: Boolean flags to toggle visibility without reloading the underlying resources.
|
|
32
32
|
* - show-render-menu: Boolean flag to show or hide the render-settings menu (default: true).
|
|
33
|
+
* - show-view-cube: Enables the 3D orientation overlay unless "false"; visible cubes position the render menu below their measured height.
|
|
33
34
|
* - styles: JSON style overrides. Currently supports `colorPrimary`, persisted in localStorage and exposed as `--pref-viewer-color-primary`.
|
|
34
35
|
*
|
|
35
36
|
* Public Methods (selection):
|
|
@@ -66,6 +67,7 @@ import { DEFAULT_LOCALE, resolveLocale, setLocale, SUPPORTED_LOCALES } from "./l
|
|
|
66
67
|
* - Legacy `scene-*` and `drawing-*` aliases are still emitted alongside their modern equivalents for backward compatibility.
|
|
67
68
|
*
|
|
68
69
|
* Notes:
|
|
70
|
+
* - Stores the cube layout handler and subscribes only for active 3D cube layout; open dialogs render above viewer overlays.
|
|
69
71
|
* - Internally wires PrefViewerMenu3D hover/apply events to PrefViewer3D render settings, ensuring persisted toggles stay in sync with BabylonJSController.
|
|
70
72
|
* - Cleans up dialogs, listeners, and subcomponents on disconnect to prevent leaks when frameworks mount/unmount the custom element.
|
|
71
73
|
* - Uses localStorage-backed culture persistence and attribute reflection safeguards to keep templates, menu, and global i18n aligned.
|
|
@@ -93,8 +95,8 @@ export default class PrefViewer extends HTMLElement {
|
|
|
93
95
|
|
|
94
96
|
// Localization/culture management
|
|
95
97
|
#CULTURE_STORAGE_KEY = "pref-viewer/culture";
|
|
96
|
-
#cultureInitial = DEFAULT_LOCALE;
|
|
97
|
-
#cultureList = SUPPORTED_LOCALES;
|
|
98
|
+
#cultureInitial = I18n.DEFAULT_LOCALE;
|
|
99
|
+
#cultureList = I18n.SUPPORTED_LOCALES;
|
|
98
100
|
#culture = "";
|
|
99
101
|
#cultureSuppressAttribute = false;
|
|
100
102
|
|
|
@@ -115,11 +117,13 @@ export default class PrefViewer extends HTMLElement {
|
|
|
115
117
|
#handlers = {
|
|
116
118
|
on2DZoomChanged: null,
|
|
117
119
|
on2DElementClick: null,
|
|
120
|
+
on3DElementClick: null,
|
|
118
121
|
onMenuApply: null,
|
|
119
122
|
onViewerHoverStart: null,
|
|
120
123
|
onViewerHoverEnd: null,
|
|
121
124
|
on3DSceneLoaded: null,
|
|
122
125
|
on3DSceneError: null,
|
|
126
|
+
onViewCubeLayout: null,
|
|
123
127
|
};
|
|
124
128
|
|
|
125
129
|
/**
|
|
@@ -132,9 +136,9 @@ export default class PrefViewer extends HTMLElement {
|
|
|
132
136
|
this.attachShadow({ mode: "open" });
|
|
133
137
|
const storedCulture = this.#cultureReadPersisted();
|
|
134
138
|
if (storedCulture) {
|
|
135
|
-
this.#culture = resolveLocale(storedCulture);
|
|
139
|
+
this.#culture = I18n.resolveLocale(storedCulture);
|
|
136
140
|
} else {
|
|
137
|
-
this.#culture = setLocale(this.#cultureInitial);
|
|
141
|
+
this.#culture = I18n.setLocale(this.#cultureInitial);
|
|
138
142
|
}
|
|
139
143
|
|
|
140
144
|
this.#applyStyles(this.#stylesReadPersisted(), { persist: false, applyCssVariables: false });
|
|
@@ -146,21 +150,26 @@ export default class PrefViewer extends HTMLElement {
|
|
|
146
150
|
* @returns {string[]} Array of attribute names to observe.
|
|
147
151
|
*/
|
|
148
152
|
static get observedAttributes() {
|
|
149
|
-
return ["config", "culture", "drawing", "materials", "mode", "model", "scene", "options", "show-model", "show-scene", "show-render-menu", "styles"];
|
|
153
|
+
return ["config", "culture", "drawing", "materials", "mode", "model", "scene", "options", "show-model", "show-scene", "show-render-menu", "show-view-cube", "styles"];
|
|
150
154
|
}
|
|
151
155
|
|
|
152
156
|
/**
|
|
153
157
|
* Observes changes to specific attributes and triggers corresponding actions.
|
|
154
158
|
* Loads configuration, drawing, model, scene, materials, or options when their attributes change.
|
|
155
159
|
* Toggles model or scene visibility when "show-model" or "show-scene" attributes change, recreates the 3D menu when "show-render-menu" changes, and queues style overrides when "styles" changes.
|
|
160
|
+
* "show-view-cube" synchronizes lazy cube activation and conditional layout subscription before forwarding the attribute.
|
|
156
161
|
* @public
|
|
157
162
|
* @param {string} name - The name of the changed attribute.
|
|
158
|
-
* @param {
|
|
159
|
-
* @param {
|
|
163
|
+
* @param {string|null} _old - The previous attribute value.
|
|
164
|
+
* @param {string|null} value - The new attribute value; null when removed.
|
|
160
165
|
* @returns {void}
|
|
161
166
|
*/
|
|
162
167
|
attributeChangedCallback(name, _old, value) {
|
|
163
168
|
switch (name) {
|
|
169
|
+
case "show-view-cube":
|
|
170
|
+
this.#setViewCubeLayoutSubscription(this.#mode === "3d" && value !== "false");
|
|
171
|
+
this.#component3D?.setAttribute("show-view-cube", value === "false" ? "false" : "true");
|
|
172
|
+
break;
|
|
164
173
|
case "config":
|
|
165
174
|
this.loadConfig(value);
|
|
166
175
|
break;
|
|
@@ -227,6 +236,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
227
236
|
/**
|
|
228
237
|
* Called when the element is inserted into the DOM.
|
|
229
238
|
* Initializes the 3D and 2D viewer components and starts processing tasks.
|
|
239
|
+
* Restores the primary animation-highlight color after creating the 3D component and menu.
|
|
230
240
|
* @public
|
|
231
241
|
* @returns {void|boolean} Returns false if initialization fails; otherwise void.
|
|
232
242
|
*/
|
|
@@ -236,6 +246,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
236
246
|
this.#createComponent3D();
|
|
237
247
|
this.#createComponent2D();
|
|
238
248
|
this.#createMenu3D();
|
|
249
|
+
this.#applyRenderSettings({ highlightColor: this.#styles.colorPrimary, persist: false });
|
|
239
250
|
|
|
240
251
|
this.setMode(this.getAttribute("mode") ?? this.#mode);
|
|
241
252
|
|
|
@@ -252,7 +263,8 @@ export default class PrefViewer extends HTMLElement {
|
|
|
252
263
|
}
|
|
253
264
|
|
|
254
265
|
/**
|
|
255
|
-
*
|
|
266
|
+
* Removes stored child/menu/dialog listeners and subcomponents when detached.
|
|
267
|
+
* Unsubscribes the cube layout handler before the 3D component and its overlay are torn down.
|
|
256
268
|
* @public
|
|
257
269
|
* @returns {void}
|
|
258
270
|
*/
|
|
@@ -270,8 +282,10 @@ export default class PrefViewer extends HTMLElement {
|
|
|
270
282
|
this.#component2D.remove();
|
|
271
283
|
}
|
|
272
284
|
if (this.#component3D) {
|
|
285
|
+
this.#component3D.removeEventListener("pref-viewer-3d-element-click", this.#handlers.on3DElementClick);
|
|
273
286
|
this.#component3D.removeEventListener("pref-viewer-3d-loaded", this.#handlers.on3DSceneLoaded);
|
|
274
287
|
this.#component3D.removeEventListener("pref-viewer-3d-error", this.#handlers.on3DSceneError);
|
|
288
|
+
this.#component3D.removeEventListener("view-cube-layout", this.#handlers.onViewCubeLayout);
|
|
275
289
|
this.#component3D.remove();
|
|
276
290
|
}
|
|
277
291
|
if (this.#menu3D) {
|
|
@@ -302,8 +316,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
302
316
|
}
|
|
303
317
|
|
|
304
318
|
/**
|
|
305
|
-
* Creates and appends the 2D viewer component to the shadow DOM.
|
|
306
|
-
* Sets the "visible" attribute to true by default.
|
|
319
|
+
* Creates and appends the 2D viewer component, initially hidden, to the shadow DOM.
|
|
307
320
|
* @private
|
|
308
321
|
* @returns {void}
|
|
309
322
|
*/
|
|
@@ -318,14 +331,45 @@ export default class PrefViewer extends HTMLElement {
|
|
|
318
331
|
}
|
|
319
332
|
|
|
320
333
|
/**
|
|
321
|
-
*
|
|
322
|
-
*
|
|
334
|
+
* Subscribes before cube activation so its first layout is received.
|
|
335
|
+
* Removes the subscription and menu overrides when the cube is inactive or the mode is 2D.
|
|
336
|
+
* @private
|
|
337
|
+
* @param {boolean} enabled - Whether cube layout updates are needed.
|
|
338
|
+
* @returns {void}
|
|
339
|
+
*/
|
|
340
|
+
#setViewCubeLayoutSubscription(enabled) {
|
|
341
|
+
if (!this.#component3D || !this.#handlers.onViewCubeLayout) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
this.#component3D.removeEventListener("view-cube-layout", this.#handlers.onViewCubeLayout);
|
|
345
|
+
if (enabled) {
|
|
346
|
+
this.#component3D.addEventListener("view-cube-layout", this.#handlers.onViewCubeLayout);
|
|
347
|
+
} else {
|
|
348
|
+
this.#wrapper?.style.removeProperty("--pref-viewer-render-menu-top");
|
|
349
|
+
this.#wrapper?.style.removeProperty("--pref-viewer-viewport-height");
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Creates and appends the 3D viewer component to the shadow DOM, initially hidden.
|
|
354
|
+
* Forwards show-view-cube, stores its layout handler in #handlers and subscribes before activation
|
|
355
|
+
* so the first measured layout positions the render menu correctly.
|
|
323
356
|
* @private
|
|
324
357
|
* @returns {void}
|
|
325
358
|
*/
|
|
326
359
|
#createComponent3D() {
|
|
360
|
+
this.#handlers.on3DElementClick = this.#on3DElementClick.bind(this);
|
|
327
361
|
this.#component3D = document.createElement("pref-viewer-3d");
|
|
328
362
|
this.#component3D.setAttribute("visible", "false");
|
|
363
|
+
this.#component3D.setAttribute("show-view-cube", this.getAttribute("show-view-cube") === "false" ? "false" : "true");
|
|
364
|
+
this.#handlers.onViewCubeLayout = (event) => {
|
|
365
|
+
if (event.detail.offset > 0) {
|
|
366
|
+
this.#wrapper.style.setProperty("--pref-viewer-render-menu-top", `${event.detail.offset}px`);
|
|
367
|
+
} else {
|
|
368
|
+
this.#wrapper.style.removeProperty("--pref-viewer-render-menu-top");
|
|
369
|
+
}
|
|
370
|
+
this.#wrapper.style.setProperty("--pref-viewer-viewport-height", `${event.detail.height}px`);
|
|
371
|
+
};
|
|
372
|
+
this.#setViewCubeLayoutSubscription(this.getAttribute("show-view-cube") !== "false" && (this.getAttribute("mode") ?? this.#mode) === "3d");
|
|
329
373
|
|
|
330
374
|
this.#handlers.on3DSceneLoaded = () => {
|
|
331
375
|
this.#menu3DSyncSettings();
|
|
@@ -334,6 +378,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
334
378
|
this.#handlers.on3DSceneError = () => {
|
|
335
379
|
this.#menu3D?.setApplying(false, true);
|
|
336
380
|
};
|
|
381
|
+
this.#component3D.addEventListener("pref-viewer-3d-element-click", this.#handlers.on3DElementClick);
|
|
337
382
|
this.#component3D.addEventListener("pref-viewer-3d-loaded", this.#handlers.on3DSceneLoaded);
|
|
338
383
|
this.#component3D.addEventListener("pref-viewer-3d-error", this.#handlers.on3DSceneError);
|
|
339
384
|
this.#wrapper.appendChild(this.#component3D);
|
|
@@ -609,7 +654,8 @@ export default class PrefViewer extends HTMLElement {
|
|
|
609
654
|
}
|
|
610
655
|
|
|
611
656
|
/**
|
|
612
|
-
* Resolves
|
|
657
|
+
* Resolves culture, updates internal/global state and menu/cube labels, and persists the selection.
|
|
658
|
+
* Refreshes only an existing cube; a culture change does not activate an inactive overlay.
|
|
613
659
|
* @private
|
|
614
660
|
* @param {string} [cultureId] - Desired locale to activate.
|
|
615
661
|
* @param {object} [options] - Extra flags for the update.
|
|
@@ -626,15 +672,16 @@ export default class PrefViewer extends HTMLElement {
|
|
|
626
672
|
return changed;
|
|
627
673
|
}
|
|
628
674
|
const { reflectAttribute = false } = options;
|
|
629
|
-
const resolved = resolveLocale(cultureId);
|
|
675
|
+
const resolved = I18n.resolveLocale(cultureId);
|
|
630
676
|
changed = resolved !== this.#culture;
|
|
631
677
|
if (reflectAttribute) {
|
|
632
678
|
this.#cultureReflectAttribute(resolved);
|
|
633
679
|
}
|
|
634
680
|
if (changed) {
|
|
635
681
|
this.#culture = resolved;
|
|
636
|
-
setLocale(resolved);
|
|
682
|
+
I18n.setLocale(resolved);
|
|
637
683
|
this.#menu3D?.setCulture?.(resolved);
|
|
684
|
+
this.#component3D?.refreshViewCube?.();
|
|
638
685
|
this.#culturePersist(resolved);
|
|
639
686
|
}
|
|
640
687
|
return changed;
|
|
@@ -739,6 +786,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
739
786
|
|
|
740
787
|
this.removeAttribute("loading-3d");
|
|
741
788
|
this.setAttribute("loaded-3d", "");
|
|
789
|
+
this.#applySelectionStateTo3D();
|
|
742
790
|
|
|
743
791
|
this.#dispatchPrefViewerEvent("pref-viewer-3d-loaded", detail ?? {});
|
|
744
792
|
this.#dispatchPrefViewerEvent("scene-loaded", detail ?? {}); // Legacy event for backward compatibility
|
|
@@ -850,12 +898,23 @@ export default class PrefViewer extends HTMLElement {
|
|
|
850
898
|
this.notifyElementClick(event.detail?.ids ?? []);
|
|
851
899
|
}
|
|
852
900
|
|
|
901
|
+
/**
|
|
902
|
+
* Forwards semantic click ids from the encapsulated 3D component through the root event contract.
|
|
903
|
+
* @private
|
|
904
|
+
* @param {CustomEvent<{ids: string[]}>} event - Internal 3D model click event.
|
|
905
|
+
* @returns {void}
|
|
906
|
+
*/
|
|
907
|
+
#on3DElementClick(event) {
|
|
908
|
+
event.stopPropagation();
|
|
909
|
+
this.notifyElementClick(event.detail?.ids ?? []);
|
|
910
|
+
}
|
|
911
|
+
|
|
853
912
|
/**
|
|
854
913
|
* Handles the custom "pref-viewer-3d-render-settings-change-requested" event emitted by the menu component.
|
|
855
914
|
* Forwards the requested settings to the render-application pipeline.
|
|
856
915
|
* @private
|
|
857
916
|
* @param {CustomEvent} event - Menu event containing the `settings` payload.
|
|
858
|
-
* @returns {void}
|
|
917
|
+
* @returns {Promise<void>}
|
|
859
918
|
*/
|
|
860
919
|
async #onMenuApply(event) {
|
|
861
920
|
event.stopPropagation();
|
|
@@ -867,13 +926,24 @@ export default class PrefViewer extends HTMLElement {
|
|
|
867
926
|
}
|
|
868
927
|
|
|
869
928
|
/**
|
|
870
|
-
*
|
|
929
|
+
* Applies optional boolean overlay flags through their attributes, then loads the queued 3D configuration.
|
|
930
|
+
* Explicit flags override the current attributes; omitted/non-boolean values preserve their state.
|
|
871
931
|
* Dispatches loading events and processes the next task when finished.
|
|
872
932
|
* @private
|
|
873
933
|
* @param {object} config - The configuration object to process.
|
|
874
|
-
* @
|
|
934
|
+
* @param {boolean} [config.showRenderMenu] - Reflects render-menu visibility before loading assets; non-booleans are ignored.
|
|
935
|
+
* @param {boolean} [config.showViewCube] - Reflects cube activation before loading assets; non-booleans are ignored.
|
|
936
|
+
* @returns {Promise<void>} Resolves after the load attempt and advances the task queue.
|
|
875
937
|
*/
|
|
876
938
|
async #processConfig(config) {
|
|
939
|
+
for (const [property, attribute] of [["showRenderMenu", "show-render-menu"], ["showViewCube", "show-view-cube"]]) {
|
|
940
|
+
if (typeof config[property] === "boolean") {
|
|
941
|
+
const value = String(config[property]);
|
|
942
|
+
if (this.getAttribute(attribute) !== value) {
|
|
943
|
+
this.setAttribute(attribute, value);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}
|
|
877
947
|
if (!this.#component3D) {
|
|
878
948
|
this.#processNextTask();
|
|
879
949
|
return;
|
|
@@ -912,7 +982,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
912
982
|
* Processes the next task when finished.
|
|
913
983
|
* @private
|
|
914
984
|
* @param {object} drawing - The drawing object to process.
|
|
915
|
-
* @returns {void}
|
|
985
|
+
* @returns {Promise<void>}
|
|
916
986
|
*/
|
|
917
987
|
async #processDrawing(drawing) {
|
|
918
988
|
if (!this.#component2D) {
|
|
@@ -974,7 +1044,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
974
1044
|
* Dispatches loading events and processes the next task.
|
|
975
1045
|
* @private
|
|
976
1046
|
* @param {object} options - The options object to process.
|
|
977
|
-
* @returns {void}
|
|
1047
|
+
* @returns {Promise<void>}
|
|
978
1048
|
*/
|
|
979
1049
|
async #processOptions(options) {
|
|
980
1050
|
if (!this.#component3D) {
|
|
@@ -996,14 +1066,20 @@ export default class PrefViewer extends HTMLElement {
|
|
|
996
1066
|
}
|
|
997
1067
|
|
|
998
1068
|
/**
|
|
999
|
-
*
|
|
1069
|
+
* Applies queued styles and synchronizes animation-opening highlight color without reloading assets.
|
|
1070
|
+
* Waits for render settings/menu synchronization before advancing the task queue.
|
|
1000
1071
|
* @private
|
|
1001
1072
|
* @param {object} styles - Style overrides to apply.
|
|
1002
|
-
* @returns {void}
|
|
1073
|
+
* @returns {Promise<void>} Resolves after style/highlight synchronization and queue advancement.
|
|
1003
1074
|
*/
|
|
1004
|
-
#processStyles(styles) {
|
|
1005
|
-
|
|
1006
|
-
|
|
1075
|
+
async #processStyles(styles) {
|
|
1076
|
+
try {
|
|
1077
|
+
if (this.#applyStyles(styles)) {
|
|
1078
|
+
await this.#applyRenderSettings({ highlightColor: this.#styles.colorPrimary });
|
|
1079
|
+
}
|
|
1080
|
+
} finally {
|
|
1081
|
+
this.#processNextTask();
|
|
1082
|
+
}
|
|
1007
1083
|
}
|
|
1008
1084
|
|
|
1009
1085
|
/**
|
|
@@ -1069,7 +1145,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1069
1145
|
* Non-string and empty-string results are filtered out.
|
|
1070
1146
|
* @private
|
|
1071
1147
|
* @param {Array<string|{id?: string, Id?: string}>} value - Array of id-like items to normalize.
|
|
1072
|
-
* @returns {string[]}
|
|
1148
|
+
* @returns {string[]} Non-empty string ids, preserving input order and duplicate occurrences.
|
|
1073
1149
|
*/
|
|
1074
1150
|
#normalizeIdList(value) {
|
|
1075
1151
|
if (!Array.isArray(value)) {
|
|
@@ -1120,11 +1196,31 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1120
1196
|
this.#dispatchPrefViewerEvent("pref-viewer-selection-state-changed", this.getSelectionState());
|
|
1121
1197
|
}
|
|
1122
1198
|
|
|
1123
|
-
/** Apply the current semantic snapshot to the 2D renderer when available.
|
|
1199
|
+
/** Apply the current semantic snapshot to the 2D renderer when available. * @returns {void}
|
|
1200
|
+
*/
|
|
1124
1201
|
#applySelectionStateTo2D() {
|
|
1125
1202
|
this.#component2D?.applySelectionState?.(this.getSelectionState());
|
|
1126
1203
|
}
|
|
1127
1204
|
|
|
1205
|
+
/**
|
|
1206
|
+
* Applies the current semantic snapshot to the 3D renderer when available.
|
|
1207
|
+
* @private
|
|
1208
|
+
* @returns {void}
|
|
1209
|
+
*/
|
|
1210
|
+
#applySelectionStateTo3D() {
|
|
1211
|
+
this.#component3D?.applySelectionState?.(this.getSelectionState());
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
/**
|
|
1215
|
+
* Synchronizes the current semantic selection snapshot with both renderers.
|
|
1216
|
+
* @private
|
|
1217
|
+
* @returns {void}
|
|
1218
|
+
*/
|
|
1219
|
+
#applySelectionState() {
|
|
1220
|
+
this.#applySelectionStateTo2D();
|
|
1221
|
+
this.#applySelectionStateTo3D();
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1128
1224
|
/**
|
|
1129
1225
|
* Dispatches a `pref-viewer-3d-turnable-changed` event carrying the current turnable snapshot.
|
|
1130
1226
|
* Called after `startTurnable`, `stopTurnable`, or `toggleTurnable` mutates the internal state.
|
|
@@ -1259,10 +1355,15 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1259
1355
|
|
|
1260
1356
|
/**
|
|
1261
1357
|
* Loads a configuration object or JSON string and adds it to the task queue.
|
|
1262
|
-
*
|
|
1358
|
+
* Queues supplied styles/culture before the configuration and a supplied drawing afterward.
|
|
1359
|
+
* Boolean showRenderMenu/showViewCube flags apply when that config task is processed, before its 3D load.
|
|
1360
|
+
* Omitted/non-boolean flags preserve current attributes; equal values do not recreate the menu.
|
|
1263
1361
|
* @public
|
|
1264
|
-
* @param {object|string} config - Configuration object or JSON string.
|
|
1265
|
-
* @
|
|
1362
|
+
* @param {object|string} config - Configuration object or JSON string; overlay flags apply in queue order.
|
|
1363
|
+
* @param {boolean} [config.showRenderMenu] - Sets show-render-menu when explicitly boolean.
|
|
1364
|
+
* @param {boolean} [config.showViewCube] - Sets show-view-cube when explicitly boolean.
|
|
1365
|
+
* @returns {false|void} Returns false for an absent/falsy payload; otherwise queues the configuration.
|
|
1366
|
+
* @throws {SyntaxError} If a supplied JSON string cannot be parsed.
|
|
1266
1367
|
*/
|
|
1267
1368
|
loadConfig(config) {
|
|
1268
1369
|
config = typeof config === "string" ? JSON.parse(config) : config;
|
|
@@ -1357,7 +1458,8 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1357
1458
|
}
|
|
1358
1459
|
|
|
1359
1460
|
/**
|
|
1360
|
-
* Sets the viewer mode
|
|
1461
|
+
* Sets the viewer mode and component/menu visibility; updates the conditional cube layout subscription
|
|
1462
|
+
* before showing 3D or releasing its overlay in 2D.
|
|
1361
1463
|
* @public
|
|
1362
1464
|
* @param {string} [mode=this.#mode] - The mode to set ("2d" or "3d").
|
|
1363
1465
|
* @returns {void}
|
|
@@ -1369,6 +1471,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1369
1471
|
mode = this.#mode;
|
|
1370
1472
|
}
|
|
1371
1473
|
this.#mode = mode;
|
|
1474
|
+
this.#setViewCubeLayoutSubscription(mode === "3d" && this.getAttribute("show-view-cube") !== "false");
|
|
1372
1475
|
if (mode === "2d") {
|
|
1373
1476
|
this.#component3D?.hide();
|
|
1374
1477
|
this.#component2D?.show();
|
|
@@ -1401,7 +1504,8 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1401
1504
|
|
|
1402
1505
|
/**
|
|
1403
1506
|
* Sets supported PrefViewer style variables from an object or JSON string and adds them to the task queue.
|
|
1404
|
-
* Currently supports `colorPrimary`, which updates `PrefViewerStyleVariables.colorPrimary`, applies the host CSS custom property,
|
|
1507
|
+
* Currently supports `colorPrimary`, which updates `PrefViewerStyleVariables.colorPrimary`, applies the host CSS custom property,
|
|
1508
|
+
* synchronizes animation-opening highlight color (including active highlights), and persists the value in localStorage.
|
|
1405
1509
|
* @public
|
|
1406
1510
|
* @param {object|string} styles - Style overrides object or JSON string.
|
|
1407
1511
|
* @returns {boolean|void} Returns false if styles are invalid; otherwise void.
|
|
@@ -1437,7 +1541,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1437
1541
|
*/
|
|
1438
1542
|
setSelectableElements(elements = []) {
|
|
1439
1543
|
this.#selectionState.selectableIds = this.#normalizeIdList(elements);
|
|
1440
|
-
this.#
|
|
1544
|
+
this.#applySelectionState();
|
|
1441
1545
|
this.#emitSelectionStateChanged();
|
|
1442
1546
|
return this.getSelectionState();
|
|
1443
1547
|
}
|
|
@@ -1452,7 +1556,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1452
1556
|
const selectedItems = this.#normalizeSelectionItems(elements);
|
|
1453
1557
|
this.#selectionState.selectedItems = selectedItems;
|
|
1454
1558
|
this.#selectionState.selectedIds = selectedItems.map((item) => item.id);
|
|
1455
|
-
this.#
|
|
1559
|
+
this.#applySelectionState();
|
|
1456
1560
|
this.#emitSelectionStateChanged();
|
|
1457
1561
|
return this.getSelectionState();
|
|
1458
1562
|
}
|
|
@@ -1468,7 +1572,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1468
1572
|
const selectedItems = this.#normalizeSelectionItems(state.selectedItems ?? state.selectedIds ?? state.selected ?? []);
|
|
1469
1573
|
this.#selectionState.selectedItems = selectedItems;
|
|
1470
1574
|
this.#selectionState.selectedIds = selectedItems.map((item) => item.id);
|
|
1471
|
-
this.#
|
|
1575
|
+
this.#applySelectionState();
|
|
1472
1576
|
this.#emitSelectionStateChanged();
|
|
1473
1577
|
return this.getSelectionState();
|
|
1474
1578
|
}
|
|
@@ -1481,7 +1585,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1481
1585
|
clearSelectedElements() {
|
|
1482
1586
|
this.#selectionState.selectedIds = [];
|
|
1483
1587
|
this.#selectionState.selectedItems = [];
|
|
1484
|
-
this.#
|
|
1588
|
+
this.#applySelectionState();
|
|
1485
1589
|
this.#emitSelectionStateChanged();
|
|
1486
1590
|
return this.getSelectionState();
|
|
1487
1591
|
}
|
|
@@ -1493,7 +1597,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1493
1597
|
*/
|
|
1494
1598
|
clearSelectableElements() {
|
|
1495
1599
|
this.#selectionState.selectableIds = [];
|
|
1496
|
-
this.#
|
|
1600
|
+
this.#applySelectionState();
|
|
1497
1601
|
this.#emitSelectionStateChanged();
|
|
1498
1602
|
return this.getSelectionState();
|
|
1499
1603
|
}
|
|
@@ -1509,7 +1613,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1509
1613
|
selectedIds: [],
|
|
1510
1614
|
selectedItems: [],
|
|
1511
1615
|
};
|
|
1512
|
-
this.#
|
|
1616
|
+
this.#applySelectionState();
|
|
1513
1617
|
this.#emitSelectionStateChanged();
|
|
1514
1618
|
return this.getSelectionState();
|
|
1515
1619
|
}
|
|
@@ -1575,7 +1679,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1575
1679
|
* Remove every SVG node previously added through appendSvgNode.
|
|
1576
1680
|
* @public
|
|
1577
1681
|
* @returns {void}
|
|
1578
|
-
|
|
1682
|
+
*/
|
|
1579
1683
|
removeAppendedSvgNodes() {
|
|
1580
1684
|
this.#component2D?.removeAppendedSvgNodes?.();
|
|
1581
1685
|
}
|
|
@@ -1635,10 +1739,12 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1635
1739
|
* @param {string} title - The dialog title to display in the header.
|
|
1636
1740
|
* @param {string} content - The HTML content to display in the dialog body.
|
|
1637
1741
|
* @param {string} footer - The HTML content to display in the dialog footer (e.g., action buttons).
|
|
1638
|
-
* @returns {HTMLElement} The
|
|
1742
|
+
* @returns {HTMLElement|null} The dialog element if opening succeeds; otherwise null.
|
|
1639
1743
|
* @description
|
|
1640
1744
|
* If a dialog is already open, it is closed before opening the new one.
|
|
1641
1745
|
* The dialog is appended to the viewer's shadow DOM and returned for further manipulation.
|
|
1746
|
+
* Shared dialog styles place its modal backdrop above the render menu and ViewCube.
|
|
1747
|
+
* Background pointer input is intercepted; backdrop dismissal does not also activate a covered control.
|
|
1642
1748
|
*/
|
|
1643
1749
|
openDialog(title, content, footer) {
|
|
1644
1750
|
if (this.#dialog && this.#dialog.hasAttribute("open")) {
|
|
@@ -1811,9 +1917,14 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1811
1917
|
*/
|
|
1812
1918
|
|
|
1813
1919
|
/**
|
|
1814
|
-
* Accepts a config object or JSON string and forwards it to `loadConfig()
|
|
1920
|
+
* Accepts a config object or JSON string and forwards it to `loadConfig()` in the existing task queue.
|
|
1921
|
+
* Includes optional boolean showRenderMenu/showViewCube flags with the same precedence and omission rules.
|
|
1922
|
+
* Supplied styles/culture and drawing retain the loadConfig ordering.
|
|
1815
1923
|
* @public
|
|
1816
1924
|
* @param {object|string} value - Configuration payload or serialized JSON.
|
|
1925
|
+
* @param {boolean} [value.showRenderMenu] - Optional render-menu visibility for an object payload.
|
|
1926
|
+
* @param {boolean} [value.showViewCube] - Optional cube visibility for an object payload.
|
|
1927
|
+
* @throws {SyntaxError} If a supplied JSON string cannot be parsed.
|
|
1817
1928
|
*/
|
|
1818
1929
|
set config(value) {
|
|
1819
1930
|
this.loadConfig(value);
|