@preference-sl/pref-viewer 2.16.2-beta.1 → 2.17.0-beta.0
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 +137 -7
- package/index.d.ts +9 -0
- package/package.json +1 -1
- package/src/babylonjs-camera-framing.js +171 -0
- package/src/babylonjs-camera-zoom-controller.js +272 -0
- package/src/babylonjs-controller.js +312 -205
- package/src/babylonjs-view-cube-controller.js +718 -0
- package/src/localization/translations.js +18 -0
- package/src/pref-viewer-3d.js +29 -5
- package/src/pref-viewer-menu-3d.js +2 -2
- package/src/pref-viewer.js +99 -24
- package/src/styles.js +94 -3
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
export const translations = {
|
|
2
2
|
"en-EN": {
|
|
3
3
|
prefViewer: {
|
|
4
|
+
viewCube: {
|
|
5
|
+
title: "View orientation",
|
|
6
|
+
front: "Inner",
|
|
7
|
+
back: "Outer",
|
|
8
|
+
top: "Top",
|
|
9
|
+
bottom: "Bottom",
|
|
10
|
+
left: "Left",
|
|
11
|
+
right: "Right"
|
|
12
|
+
},
|
|
4
13
|
menu3d: {
|
|
5
14
|
title: "3D render settings",
|
|
6
15
|
subtitle: "Modify the visual effects.",
|
|
@@ -62,6 +71,15 @@ export const translations = {
|
|
|
62
71
|
},
|
|
63
72
|
"es-ES": {
|
|
64
73
|
prefViewer: {
|
|
74
|
+
viewCube: {
|
|
75
|
+
title: "Orientación de vista",
|
|
76
|
+
front: "Interior",
|
|
77
|
+
back: "Exterior",
|
|
78
|
+
top: "Arriba",
|
|
79
|
+
bottom: "Abajo",
|
|
80
|
+
left: "Izquierda",
|
|
81
|
+
right: "Derecha"
|
|
82
|
+
},
|
|
65
83
|
menu3d: {
|
|
66
84
|
title: "Ajustes de render 3D",
|
|
67
85
|
subtitle: "Modifica los efectos visuales.",
|
package/src/pref-viewer-3d.js
CHANGED
|
@@ -25,6 +25,7 @@ import FileStorage from "./file-storage.js";
|
|
|
25
25
|
* - show-model: Show or hide the 3D model ("true"/"false").
|
|
26
26
|
* - show-scene: Show or hide the 3D environment ("true"/"false").
|
|
27
27
|
* - visible: Show or hide the entire viewer ("true"/"false").
|
|
28
|
+
* - show-view-cube: Enable the orientation overlay while visible; only "false" disables it (default: enabled).
|
|
28
29
|
*
|
|
29
30
|
* Public Methods:
|
|
30
31
|
* - show(): Shows the 3D viewer component.
|
|
@@ -39,6 +40,7 @@ import FileStorage from "./file-storage.js";
|
|
|
39
40
|
* - hideEnvironment(): Hides the 3D environment/scene.
|
|
40
41
|
* - isIBLAvailable(): Reports whether a valid IBL environment map is currently available.
|
|
41
42
|
* - isAnimationMenuEnabled(): Reports whether the animation control menu is currently enabled.
|
|
43
|
+
* - refreshViewCube(): Internally synchronizes an existing cube after a host culture change.
|
|
42
44
|
* - getDebugInfo(): Returns a diagnostic snapshot of the underlying Babylon.js runtime.
|
|
43
45
|
* - getAnimations(): Returns a snapshot of all available animations and their current state.
|
|
44
46
|
* - playAnimation(name, action): Controls a named animation by applying the specified action.
|
|
@@ -69,6 +71,7 @@ import FileStorage from "./file-storage.js";
|
|
|
69
71
|
* - #onLoading/#onLoaded/#onSettingOptions/#onSetOptions(): Dispatch lifecycle events and synchronize attributes.
|
|
70
72
|
*
|
|
71
73
|
* Events:
|
|
74
|
+
* - "view-cube-layout": Internal, non-bubbling event with {offset, height} in CSS pixels for host menu layout; disposal clears both.
|
|
72
75
|
* - "pref-viewer-3d-loading": Dispatched when a loading operation starts. Legacy alias: "scene-loading".
|
|
73
76
|
* - "pref-viewer-3d-loaded": Dispatched when a loading operation completes. Legacy alias: "scene-loaded".
|
|
74
77
|
* - "pref-viewer-3d-options-applying": Dispatched when viewer options are being set. Legacy alias: "scene-setting-options".
|
|
@@ -107,7 +110,7 @@ export default class PrefViewer3D extends HTMLElement {
|
|
|
107
110
|
* @returns {string[]} Array of attribute names that trigger attributeChangedCallback.
|
|
108
111
|
*/
|
|
109
112
|
static get observedAttributes() {
|
|
110
|
-
return ["show-model", "show-scene", "visible"];
|
|
113
|
+
return ["show-model", "show-scene", "visible", "show-view-cube"];
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
/**
|
|
@@ -120,9 +123,13 @@ export default class PrefViewer3D extends HTMLElement {
|
|
|
120
123
|
* - "show-model": shows or hides the model according to the attribute value ("true"/"false").
|
|
121
124
|
* - "show-scene": shows or hides the scene according to the attribute value ("true"/"false").
|
|
122
125
|
* - "visible": shows or hides the component according to the attribute value ("true"/"false").
|
|
126
|
+
* - "show-view-cube": activates the cube only while visible and the attribute is not "false".
|
|
123
127
|
*/
|
|
124
128
|
attributeChangedCallback(name, _old, value) {
|
|
125
129
|
switch (name) {
|
|
130
|
+
case "show-view-cube":
|
|
131
|
+
this.#babylonJSController?.setViewCubeEnabled(this.#isVisible && value !== "false");
|
|
132
|
+
break;
|
|
126
133
|
case "show-model":
|
|
127
134
|
if (_old === value) {
|
|
128
135
|
return;
|
|
@@ -237,12 +244,18 @@ export default class PrefViewer3D extends HTMLElement {
|
|
|
237
244
|
}
|
|
238
245
|
|
|
239
246
|
/**
|
|
240
|
-
* Initializes the
|
|
247
|
+
* Initializes the Babylon controller with asset/option state and the visibility-aware cube contract.
|
|
248
|
+
* Supplies current host culture and dispatches measured view-cube-layout events for render-menu positioning.
|
|
249
|
+
* Starts asynchronous engine initialization without waiting for asset loading.
|
|
241
250
|
* @private
|
|
242
251
|
* @returns {void}
|
|
243
252
|
*/
|
|
244
253
|
#initializeBabylonJS() {
|
|
245
|
-
this.#babylonJSController = new BabylonJSController(this.#canvas, this.#data.containers, this.#data.options
|
|
254
|
+
this.#babylonJSController = new BabylonJSController(this.#canvas, this.#data.containers, this.#data.options, {
|
|
255
|
+
enabled: this.#isVisible && this.getAttribute("show-view-cube") !== "false",
|
|
256
|
+
getCulture: () => this.getRootNode().host?.culture,
|
|
257
|
+
onLayout: (offset, height) => this.dispatchEvent(new CustomEvent("view-cube-layout", { detail: { offset, height } })),
|
|
258
|
+
});
|
|
246
259
|
this.#babylonJSController.enable();
|
|
247
260
|
|
|
248
261
|
}
|
|
@@ -608,22 +621,24 @@ export default class PrefViewer3D extends HTMLElement {
|
|
|
608
621
|
*/
|
|
609
622
|
|
|
610
623
|
/**
|
|
611
|
-
* Hides the 3D viewer
|
|
624
|
+
* Hides the 3D viewer and releases its cube resources while retaining the requested show-view-cube attribute.
|
|
612
625
|
* @public
|
|
613
626
|
* @returns {void}
|
|
614
627
|
*/
|
|
615
628
|
hide() {
|
|
616
629
|
this.#isVisible = false;
|
|
630
|
+
this.#babylonJSController?.setViewCubeEnabled(false);
|
|
617
631
|
this.setAttribute("visible", "false");
|
|
618
632
|
}
|
|
619
633
|
|
|
620
634
|
/**
|
|
621
|
-
* Shows the 3D viewer
|
|
635
|
+
* Shows/focuses the 3D viewer and lazily recreates its cube when show-view-cube is not "false".
|
|
622
636
|
* @public
|
|
623
637
|
* @returns {void}
|
|
624
638
|
*/
|
|
625
639
|
show() {
|
|
626
640
|
this.#isVisible = true;
|
|
641
|
+
this.#babylonJSController?.setViewCubeEnabled(this.getAttribute("show-view-cube") !== "false");
|
|
627
642
|
this.setAttribute("visible", "true");
|
|
628
643
|
this.#canvas.focus();
|
|
629
644
|
}
|
|
@@ -900,6 +915,15 @@ export default class PrefViewer3D extends HTMLElement {
|
|
|
900
915
|
return this.#babylonJSController.getRenderSettings();
|
|
901
916
|
}
|
|
902
917
|
|
|
918
|
+
/**
|
|
919
|
+
* Forwards an internal culture/camera refresh to the existing overlay without activating a disabled cube.
|
|
920
|
+
* @public
|
|
921
|
+
* @returns {void}
|
|
922
|
+
*/
|
|
923
|
+
refreshViewCube() {
|
|
924
|
+
this.#babylonJSController?.refreshViewCube();
|
|
925
|
+
}
|
|
926
|
+
|
|
903
927
|
/**
|
|
904
928
|
* Returns a snapshot of all available animations and their current state.
|
|
905
929
|
* @public
|
|
@@ -61,7 +61,7 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
61
61
|
onToggleEnter: null,
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
#DEFAULT_RENDER_SETTINGS = { ...BabylonJSController.
|
|
64
|
+
#DEFAULT_RENDER_SETTINGS = { ...BabylonJSController.config.render.defaultSettings };
|
|
65
65
|
// Only include boolean settings as switches; scalar settings are handled by sliders.
|
|
66
66
|
#MENU_SWITCHES = Object.keys(this.#DEFAULT_RENDER_SETTINGS).filter(key =>
|
|
67
67
|
typeof this.#DEFAULT_RENDER_SETTINGS[key] === "boolean"
|
|
@@ -194,7 +194,7 @@ export default class PrefViewerMenu3D extends HTMLElement {
|
|
|
194
194
|
/**
|
|
195
195
|
* Generates the HTML fragment for a single boolean render-setting switch.
|
|
196
196
|
* @private
|
|
197
|
-
* @param {string} key - Render setting key from BabylonJSController.
|
|
197
|
+
* @param {string} key - Render setting key from BabylonJSController.config.render.defaultSettings.
|
|
198
198
|
* @param {Record<string, {label?: string, helper?: string}>} copy - Locale-aware feature copy used for labels.
|
|
199
199
|
* @returns {string} HTML string representing the switch row.
|
|
200
200
|
*/
|
package/src/pref-viewer.js
CHANGED
|
@@ -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
29
|
* - culture: Locale identifier (RFC-5646 style) that resolves against `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.
|
|
@@ -120,6 +122,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
120
122
|
onViewerHoverEnd: null,
|
|
121
123
|
on3DSceneLoaded: null,
|
|
122
124
|
on3DSceneError: null,
|
|
125
|
+
onViewCubeLayout: null,
|
|
123
126
|
};
|
|
124
127
|
|
|
125
128
|
/**
|
|
@@ -146,21 +149,26 @@ export default class PrefViewer extends HTMLElement {
|
|
|
146
149
|
* @returns {string[]} Array of attribute names to observe.
|
|
147
150
|
*/
|
|
148
151
|
static get observedAttributes() {
|
|
149
|
-
return ["config", "culture", "drawing", "materials", "mode", "model", "scene", "options", "show-model", "show-scene", "show-render-menu", "styles"];
|
|
152
|
+
return ["config", "culture", "drawing", "materials", "mode", "model", "scene", "options", "show-model", "show-scene", "show-render-menu", "show-view-cube", "styles"];
|
|
150
153
|
}
|
|
151
154
|
|
|
152
155
|
/**
|
|
153
156
|
* Observes changes to specific attributes and triggers corresponding actions.
|
|
154
157
|
* Loads configuration, drawing, model, scene, materials, or options when their attributes change.
|
|
155
158
|
* 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.
|
|
159
|
+
* "show-view-cube" synchronizes lazy cube activation and conditional layout subscription before forwarding the attribute.
|
|
156
160
|
* @public
|
|
157
161
|
* @param {string} name - The name of the changed attribute.
|
|
158
|
-
* @param {
|
|
159
|
-
* @param {
|
|
162
|
+
* @param {string|null} _old - The previous attribute value.
|
|
163
|
+
* @param {string|null} value - The new attribute value; null when removed.
|
|
160
164
|
* @returns {void}
|
|
161
165
|
*/
|
|
162
166
|
attributeChangedCallback(name, _old, value) {
|
|
163
167
|
switch (name) {
|
|
168
|
+
case "show-view-cube":
|
|
169
|
+
this.#setViewCubeLayoutSubscription(this.#mode === "3d" && value !== "false");
|
|
170
|
+
this.#component3D?.setAttribute("show-view-cube", value === "false" ? "false" : "true");
|
|
171
|
+
break;
|
|
164
172
|
case "config":
|
|
165
173
|
this.loadConfig(value);
|
|
166
174
|
break;
|
|
@@ -227,6 +235,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
227
235
|
/**
|
|
228
236
|
* Called when the element is inserted into the DOM.
|
|
229
237
|
* Initializes the 3D and 2D viewer components and starts processing tasks.
|
|
238
|
+
* Restores the primary animation-highlight color after creating the 3D component and menu.
|
|
230
239
|
* @public
|
|
231
240
|
* @returns {void|boolean} Returns false if initialization fails; otherwise void.
|
|
232
241
|
*/
|
|
@@ -236,6 +245,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
236
245
|
this.#createComponent3D();
|
|
237
246
|
this.#createComponent2D();
|
|
238
247
|
this.#createMenu3D();
|
|
248
|
+
this.#applyRenderSettings({ highlightColor: this.#styles.colorPrimary, persist: false });
|
|
239
249
|
|
|
240
250
|
this.setMode(this.getAttribute("mode") ?? this.#mode);
|
|
241
251
|
|
|
@@ -252,7 +262,8 @@ export default class PrefViewer extends HTMLElement {
|
|
|
252
262
|
}
|
|
253
263
|
|
|
254
264
|
/**
|
|
255
|
-
*
|
|
265
|
+
* Removes stored child/menu/dialog listeners and subcomponents when detached.
|
|
266
|
+
* Unsubscribes the cube layout handler before the 3D component and its overlay are torn down.
|
|
256
267
|
* @public
|
|
257
268
|
* @returns {void}
|
|
258
269
|
*/
|
|
@@ -272,6 +283,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
272
283
|
if (this.#component3D) {
|
|
273
284
|
this.#component3D.removeEventListener("pref-viewer-3d-loaded", this.#handlers.on3DSceneLoaded);
|
|
274
285
|
this.#component3D.removeEventListener("pref-viewer-3d-error", this.#handlers.on3DSceneError);
|
|
286
|
+
this.#component3D.removeEventListener("view-cube-layout", this.#handlers.onViewCubeLayout);
|
|
275
287
|
this.#component3D.remove();
|
|
276
288
|
}
|
|
277
289
|
if (this.#menu3D) {
|
|
@@ -302,8 +314,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
302
314
|
}
|
|
303
315
|
|
|
304
316
|
/**
|
|
305
|
-
* Creates and appends the 2D viewer component to the shadow DOM.
|
|
306
|
-
* Sets the "visible" attribute to true by default.
|
|
317
|
+
* Creates and appends the 2D viewer component, initially hidden, to the shadow DOM.
|
|
307
318
|
* @private
|
|
308
319
|
* @returns {void}
|
|
309
320
|
*/
|
|
@@ -318,14 +329,44 @@ export default class PrefViewer extends HTMLElement {
|
|
|
318
329
|
}
|
|
319
330
|
|
|
320
331
|
/**
|
|
321
|
-
*
|
|
322
|
-
*
|
|
332
|
+
* Subscribes before cube activation so its first layout is received.
|
|
333
|
+
* Removes the subscription and menu overrides when the cube is inactive or the mode is 2D.
|
|
334
|
+
* @private
|
|
335
|
+
* @param {boolean} enabled - Whether cube layout updates are needed.
|
|
336
|
+
* @returns {void}
|
|
337
|
+
*/
|
|
338
|
+
#setViewCubeLayoutSubscription(enabled) {
|
|
339
|
+
if (!this.#component3D || !this.#handlers.onViewCubeLayout) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
this.#component3D.removeEventListener("view-cube-layout", this.#handlers.onViewCubeLayout);
|
|
343
|
+
if (enabled) {
|
|
344
|
+
this.#component3D.addEventListener("view-cube-layout", this.#handlers.onViewCubeLayout);
|
|
345
|
+
} else {
|
|
346
|
+
this.#wrapper?.style.removeProperty("--pref-viewer-render-menu-top");
|
|
347
|
+
this.#wrapper?.style.removeProperty("--pref-viewer-viewport-height");
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Creates and appends the 3D viewer component to the shadow DOM, initially hidden.
|
|
352
|
+
* Forwards show-view-cube, stores its layout handler in #handlers and subscribes before activation
|
|
353
|
+
* so the first measured layout positions the render menu correctly.
|
|
323
354
|
* @private
|
|
324
355
|
* @returns {void}
|
|
325
356
|
*/
|
|
326
357
|
#createComponent3D() {
|
|
327
358
|
this.#component3D = document.createElement("pref-viewer-3d");
|
|
328
359
|
this.#component3D.setAttribute("visible", "false");
|
|
360
|
+
this.#component3D.setAttribute("show-view-cube", this.getAttribute("show-view-cube") === "false" ? "false" : "true");
|
|
361
|
+
this.#handlers.onViewCubeLayout = (event) => {
|
|
362
|
+
if (event.detail.offset > 0) {
|
|
363
|
+
this.#wrapper.style.setProperty("--pref-viewer-render-menu-top", `${event.detail.offset}px`);
|
|
364
|
+
} else {
|
|
365
|
+
this.#wrapper.style.removeProperty("--pref-viewer-render-menu-top");
|
|
366
|
+
}
|
|
367
|
+
this.#wrapper.style.setProperty("--pref-viewer-viewport-height", `${event.detail.height}px`);
|
|
368
|
+
};
|
|
369
|
+
this.#setViewCubeLayoutSubscription(this.getAttribute("show-view-cube") !== "false" && (this.getAttribute("mode") ?? this.#mode) === "3d");
|
|
329
370
|
|
|
330
371
|
this.#handlers.on3DSceneLoaded = () => {
|
|
331
372
|
this.#menu3DSyncSettings();
|
|
@@ -609,7 +650,8 @@ export default class PrefViewer extends HTMLElement {
|
|
|
609
650
|
}
|
|
610
651
|
|
|
611
652
|
/**
|
|
612
|
-
* Resolves
|
|
653
|
+
* Resolves culture, updates internal/global state and menu/cube labels, and persists the selection.
|
|
654
|
+
* Refreshes only an existing cube; a culture change does not activate an inactive overlay.
|
|
613
655
|
* @private
|
|
614
656
|
* @param {string} [cultureId] - Desired locale to activate.
|
|
615
657
|
* @param {object} [options] - Extra flags for the update.
|
|
@@ -635,6 +677,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
635
677
|
this.#culture = resolved;
|
|
636
678
|
setLocale(resolved);
|
|
637
679
|
this.#menu3D?.setCulture?.(resolved);
|
|
680
|
+
this.#component3D?.refreshViewCube?.();
|
|
638
681
|
this.#culturePersist(resolved);
|
|
639
682
|
}
|
|
640
683
|
return changed;
|
|
@@ -867,13 +910,24 @@ export default class PrefViewer extends HTMLElement {
|
|
|
867
910
|
}
|
|
868
911
|
|
|
869
912
|
/**
|
|
870
|
-
*
|
|
913
|
+
* Applies optional boolean overlay flags through their attributes, then loads the queued 3D configuration.
|
|
914
|
+
* Explicit flags override the current attributes; omitted/non-boolean values preserve their state.
|
|
871
915
|
* Dispatches loading events and processes the next task when finished.
|
|
872
916
|
* @private
|
|
873
917
|
* @param {object} config - The configuration object to process.
|
|
874
|
-
* @
|
|
918
|
+
* @param {boolean} [config.showRenderMenu] - Reflects render-menu visibility before loading assets; non-booleans are ignored.
|
|
919
|
+
* @param {boolean} [config.showViewCube] - Reflects cube activation before loading assets; non-booleans are ignored.
|
|
920
|
+
* @returns {Promise<void>} Resolves after the load attempt and advances the task queue.
|
|
875
921
|
*/
|
|
876
922
|
async #processConfig(config) {
|
|
923
|
+
for (const [property, attribute] of [["showRenderMenu", "show-render-menu"], ["showViewCube", "show-view-cube"]]) {
|
|
924
|
+
if (typeof config[property] === "boolean") {
|
|
925
|
+
const value = String(config[property]);
|
|
926
|
+
if (this.getAttribute(attribute) !== value) {
|
|
927
|
+
this.setAttribute(attribute, value);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
877
931
|
if (!this.#component3D) {
|
|
878
932
|
this.#processNextTask();
|
|
879
933
|
return;
|
|
@@ -996,14 +1050,20 @@ export default class PrefViewer extends HTMLElement {
|
|
|
996
1050
|
}
|
|
997
1051
|
|
|
998
1052
|
/**
|
|
999
|
-
*
|
|
1053
|
+
* Applies queued styles and synchronizes animation-opening highlight color without reloading assets.
|
|
1054
|
+
* Waits for render settings/menu synchronization before advancing the task queue.
|
|
1000
1055
|
* @private
|
|
1001
1056
|
* @param {object} styles - Style overrides to apply.
|
|
1002
|
-
* @returns {void}
|
|
1057
|
+
* @returns {Promise<void>} Resolves after style/highlight synchronization and queue advancement.
|
|
1003
1058
|
*/
|
|
1004
|
-
#processStyles(styles) {
|
|
1005
|
-
|
|
1006
|
-
|
|
1059
|
+
async #processStyles(styles) {
|
|
1060
|
+
try {
|
|
1061
|
+
if (this.#applyStyles(styles)) {
|
|
1062
|
+
await this.#applyRenderSettings({ highlightColor: this.#styles.colorPrimary });
|
|
1063
|
+
}
|
|
1064
|
+
} finally {
|
|
1065
|
+
this.#processNextTask();
|
|
1066
|
+
}
|
|
1007
1067
|
}
|
|
1008
1068
|
|
|
1009
1069
|
/**
|
|
@@ -1259,10 +1319,15 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1259
1319
|
|
|
1260
1320
|
/**
|
|
1261
1321
|
* Loads a configuration object or JSON string and adds it to the task queue.
|
|
1262
|
-
*
|
|
1322
|
+
* Queues supplied styles/culture before the configuration and a supplied drawing afterward.
|
|
1323
|
+
* Boolean showRenderMenu/showViewCube flags apply when that config task is processed, before its 3D load.
|
|
1324
|
+
* Omitted/non-boolean flags preserve current attributes; equal values do not recreate the menu.
|
|
1263
1325
|
* @public
|
|
1264
|
-
* @param {object|string} config - Configuration object or JSON string.
|
|
1265
|
-
* @
|
|
1326
|
+
* @param {object|string} config - Configuration object or JSON string; overlay flags apply in queue order.
|
|
1327
|
+
* @param {boolean} [config.showRenderMenu] - Sets show-render-menu when explicitly boolean.
|
|
1328
|
+
* @param {boolean} [config.showViewCube] - Sets show-view-cube when explicitly boolean.
|
|
1329
|
+
* @returns {false|void} Returns false for an absent/falsy payload; otherwise queues the configuration.
|
|
1330
|
+
* @throws {SyntaxError} If a supplied JSON string cannot be parsed.
|
|
1266
1331
|
*/
|
|
1267
1332
|
loadConfig(config) {
|
|
1268
1333
|
config = typeof config === "string" ? JSON.parse(config) : config;
|
|
@@ -1357,7 +1422,8 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1357
1422
|
}
|
|
1358
1423
|
|
|
1359
1424
|
/**
|
|
1360
|
-
* Sets the viewer mode
|
|
1425
|
+
* Sets the viewer mode and component/menu visibility; updates the conditional cube layout subscription
|
|
1426
|
+
* before showing 3D or releasing its overlay in 2D.
|
|
1361
1427
|
* @public
|
|
1362
1428
|
* @param {string} [mode=this.#mode] - The mode to set ("2d" or "3d").
|
|
1363
1429
|
* @returns {void}
|
|
@@ -1369,6 +1435,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1369
1435
|
mode = this.#mode;
|
|
1370
1436
|
}
|
|
1371
1437
|
this.#mode = mode;
|
|
1438
|
+
this.#setViewCubeLayoutSubscription(mode === "3d" && this.getAttribute("show-view-cube") !== "false");
|
|
1372
1439
|
if (mode === "2d") {
|
|
1373
1440
|
this.#component3D?.hide();
|
|
1374
1441
|
this.#component2D?.show();
|
|
@@ -1401,7 +1468,8 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1401
1468
|
|
|
1402
1469
|
/**
|
|
1403
1470
|
* 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,
|
|
1471
|
+
* Currently supports `colorPrimary`, which updates `PrefViewerStyleVariables.colorPrimary`, applies the host CSS custom property,
|
|
1472
|
+
* synchronizes animation-opening highlight color (including active highlights), and persists the value in localStorage.
|
|
1405
1473
|
* @public
|
|
1406
1474
|
* @param {object|string} styles - Style overrides object or JSON string.
|
|
1407
1475
|
* @returns {boolean|void} Returns false if styles are invalid; otherwise void.
|
|
@@ -1635,10 +1703,12 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1635
1703
|
* @param {string} title - The dialog title to display in the header.
|
|
1636
1704
|
* @param {string} content - The HTML content to display in the dialog body.
|
|
1637
1705
|
* @param {string} footer - The HTML content to display in the dialog footer (e.g., action buttons).
|
|
1638
|
-
* @returns {HTMLElement} The
|
|
1706
|
+
* @returns {HTMLElement|null} The dialog element if opening succeeds; otherwise null.
|
|
1639
1707
|
* @description
|
|
1640
1708
|
* If a dialog is already open, it is closed before opening the new one.
|
|
1641
1709
|
* The dialog is appended to the viewer's shadow DOM and returned for further manipulation.
|
|
1710
|
+
* Shared dialog styles place its modal backdrop above the render menu and ViewCube.
|
|
1711
|
+
* Background pointer input is intercepted; backdrop dismissal does not also activate a covered control.
|
|
1642
1712
|
*/
|
|
1643
1713
|
openDialog(title, content, footer) {
|
|
1644
1714
|
if (this.#dialog && this.#dialog.hasAttribute("open")) {
|
|
@@ -1811,9 +1881,14 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1811
1881
|
*/
|
|
1812
1882
|
|
|
1813
1883
|
/**
|
|
1814
|
-
* Accepts a config object or JSON string and forwards it to `loadConfig()
|
|
1884
|
+
* Accepts a config object or JSON string and forwards it to `loadConfig()` in the existing task queue.
|
|
1885
|
+
* Includes optional boolean showRenderMenu/showViewCube flags with the same precedence and omission rules.
|
|
1886
|
+
* Supplied styles/culture and drawing retain the loadConfig ordering.
|
|
1815
1887
|
* @public
|
|
1816
1888
|
* @param {object|string} value - Configuration payload or serialized JSON.
|
|
1889
|
+
* @param {boolean} [value.showRenderMenu] - Optional render-menu visibility for an object payload.
|
|
1890
|
+
* @param {boolean} [value.showViewCube] - Optional cube visibility for an object payload.
|
|
1891
|
+
* @throws {SyntaxError} If a supplied JSON string cannot be parsed.
|
|
1817
1892
|
*/
|
|
1818
1893
|
set config(value) {
|
|
1819
1894
|
this.loadConfig(value);
|
package/src/styles.js
CHANGED
|
@@ -150,6 +150,94 @@ export const PrefViewer3DStyles = `
|
|
|
150
150
|
}
|
|
151
151
|
`;
|
|
152
152
|
|
|
153
|
+
export const PrefViewerViewCubeStyles = `
|
|
154
|
+
.pref-viewer-view-cube {
|
|
155
|
+
--cube-fill-color: #eef0f3;
|
|
156
|
+
--cube-border-color: #78838f;
|
|
157
|
+
--cube-border-width: 1.0px;
|
|
158
|
+
--cube-hover-color: var(--pref-viewer-color-primary, ${PrefViewerStyleVariables.colorPrimary});
|
|
159
|
+
--cube-hover-opacity: 0.50;
|
|
160
|
+
--cube-active-color: var(--pref-viewer-color-primary, ${PrefViewerStyleVariables.colorPrimary});
|
|
161
|
+
--cube-active-opacity: 0.15;
|
|
162
|
+
--cube-text-font-family: ${PrefViewerStyleVariables.fontFamily};
|
|
163
|
+
--cube-text-font-size: 9px;
|
|
164
|
+
--cube-text-color: #29323b;
|
|
165
|
+
--cube-text-font-weight: 600;
|
|
166
|
+
--cube-text-letter-spacing: 1.0px;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.pref-viewer-view-cube[hidden] {
|
|
170
|
+
display: none;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.pref-viewer-view-cube svg {
|
|
174
|
+
width: 100%;
|
|
175
|
+
height: 100%;
|
|
176
|
+
overflow: visible;
|
|
177
|
+
pointer-events: none;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.pref-viewer-view-cube polygon {
|
|
181
|
+
stroke-width: var(--cube-border-width);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.pref-viewer-view-cube .cube-shell {
|
|
185
|
+
fill: var(--cube-fill-color);
|
|
186
|
+
stroke: var(--cube-border-color);
|
|
187
|
+
pointer-events: none;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.pref-viewer-view-cube polygon[data-region] {
|
|
191
|
+
fill: transparent;
|
|
192
|
+
stroke: transparent;
|
|
193
|
+
pointer-events: visiblePainted;
|
|
194
|
+
cursor: pointer;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.pref-viewer-view-cube[data-locked="true"] polygon {
|
|
198
|
+
cursor: default;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.pref-viewer-view-cube polygon[data-current] {
|
|
202
|
+
fill: var(--cube-active-color);
|
|
203
|
+
fill-opacity: var(--cube-active-opacity);
|
|
204
|
+
stroke: transparent;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.pref-viewer-view-cube polygon[data-hover] {
|
|
208
|
+
fill: var(--cube-hover-color);
|
|
209
|
+
fill-opacity: var(--cube-hover-opacity);
|
|
210
|
+
stroke: transparent;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.pref-viewer-view-cube .hover-outline {
|
|
214
|
+
display: none;
|
|
215
|
+
fill: none;
|
|
216
|
+
stroke: var(--cube-hover-color);
|
|
217
|
+
stroke-opacity: 1;
|
|
218
|
+
stroke-width: var(--cube-border-width);
|
|
219
|
+
pointer-events: none;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.pref-viewer-view-cube .hover-outline[data-hover] {
|
|
223
|
+
display: inline;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.pref-viewer-view-cube text {
|
|
227
|
+
-webkit-user-select: none;
|
|
228
|
+
user-select: none;
|
|
229
|
+
pointer-events: none;
|
|
230
|
+
fill: var(--cube-text-color);
|
|
231
|
+
font-family: var(--cube-text-font-family);
|
|
232
|
+
font-size: var(--cube-text-font-size);
|
|
233
|
+
font-weight: var(--cube-text-font-weight);
|
|
234
|
+
letter-spacing: var(--cube-text-letter-spacing);
|
|
235
|
+
text-transform: uppercase;
|
|
236
|
+
text-anchor: middle;
|
|
237
|
+
dominant-baseline: middle;
|
|
238
|
+
}
|
|
239
|
+
`;
|
|
240
|
+
|
|
153
241
|
export const PrefViewerMenu3DStyles = `
|
|
154
242
|
pref-viewer-menu-3d {
|
|
155
243
|
--font-family: ${PrefViewerStyleVariables.fontFamily};
|
|
@@ -203,7 +291,7 @@ export const PrefViewerMenu3DStyles = `
|
|
|
203
291
|
--slider-bar-border: 1px solid rgba(255, 255, 255, 0.5);
|
|
204
292
|
|
|
205
293
|
position: absolute;
|
|
206
|
-
top: var(--toggle-margin);
|
|
294
|
+
top: var(--pref-viewer-render-menu-top, var(--toggle-margin));
|
|
207
295
|
right: var(--toggle-margin);
|
|
208
296
|
z-index: 1200;
|
|
209
297
|
/* The closed panel keeps its place in the flex column (opacity:0, not display:none), so
|
|
@@ -214,6 +302,8 @@ export const PrefViewerMenu3DStyles = `
|
|
|
214
302
|
pointer-events: none;
|
|
215
303
|
|
|
216
304
|
font-family: var(--font-family);
|
|
305
|
+
-webkit-user-select: none;
|
|
306
|
+
user-select: none;
|
|
217
307
|
}
|
|
218
308
|
|
|
219
309
|
pref-viewer-menu-3d>.menu-wrapper {
|
|
@@ -256,7 +346,7 @@ export const PrefViewerMenu3DStyles = `
|
|
|
256
346
|
|
|
257
347
|
pref-viewer-menu-3d>.menu-wrapper>.menu-panel {
|
|
258
348
|
width: var(--panel-width);
|
|
259
|
-
max-height: 70vh;
|
|
349
|
+
max-height: min(70vh, calc(var(--pref-viewer-viewport-height, 100vh) - var(--pref-viewer-render-menu-top, var(--toggle-margin)) - 84px));
|
|
260
350
|
overflow-y: auto;
|
|
261
351
|
border-radius: var(--panel-radius);
|
|
262
352
|
background: var(--panel-bg-color);
|
|
@@ -820,7 +910,8 @@ export const PrefViewerDialogStyles = `
|
|
|
820
910
|
justify-content: center;
|
|
821
911
|
background-color: var(--dialog-backdrop-color);
|
|
822
912
|
position: relative;
|
|
823
|
-
|
|
913
|
+
/* Cover all viewer overlays, including the 3D render menu (1200). */
|
|
914
|
+
z-index: 1300;
|
|
824
915
|
}
|
|
825
916
|
|
|
826
917
|
pref-viewer-dialog>.dialog-wrapper {
|