@preference-sl/pref-viewer 2.18.0-beta.1 → 3.0.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 +267 -31
- package/index.d.ts +75 -6
- package/package.json +8 -2
- package/src/babylonjs-animation-controller.js +18 -10
- package/src/babylonjs-animation-opening-menu.js +80 -14
- package/src/babylonjs-animation-opening.js +3 -3
- package/src/babylonjs-ar-floor-bounds.js +169 -0
- package/src/babylonjs-ar-glass.js +128 -0
- package/src/babylonjs-ar-placement-feedback.js +449 -0
- package/src/babylonjs-ar-placement.js +1038 -0
- package/src/babylonjs-camera-wheel-motion.js +35 -2
- package/src/babylonjs-controller.js +507 -125
- package/src/babylonjs-orbital-pointers-input.js +186 -0
- package/src/{render-math.js → babylonjs-render-math.js} +11 -11
- package/src/babylonjs-selection-controller.js +4 -4
- package/src/babylonjs-view-cube-canvas-controller.js +1287 -0
- package/src/babylonjs-view-cube-canvas-orbit-math.js +220 -0
- package/src/babylonjs-view-cube-canvas-renderer.js +775 -0
- package/src/babylonjs-view-cube-controller.js +74 -1103
- package/src/babylonjs-view-cube-svg-controller.js +1012 -0
- package/src/file-storage.js +7 -4
- package/src/gltf-resolver.js +13 -8
- package/src/localization/translations.js +12 -0
- package/src/panzoom-controller.js +4 -4
- package/src/pref-viewer-2d.js +2 -2
- package/src/pref-viewer-3d.js +55 -9
- package/src/pref-viewer-controls-presentation.js +292 -0
- package/src/pref-viewer-dialog.js +86 -7
- package/src/pref-viewer-menu-3d.js +134 -17
- package/src/pref-viewer-style-controller.js +320 -0
- package/src/pref-viewer.js +133 -109
- package/src/quick-look-action.js +280 -0
- package/src/styles.js +702 -98
- package/src/babylonjs-view-cube-renderer.js +0 -548
- package/src/view-cube-orbit-math.js +0 -199
package/src/pref-viewer.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import PrefViewerTask from "./pref-viewer-task.js";
|
|
2
|
-
import {
|
|
2
|
+
import { PrefViewerStyles } from "./styles.js";
|
|
3
|
+
import PrefViewerStyleController from "./pref-viewer-style-controller.js";
|
|
4
|
+
import PrefViewerControlsPresentation from "./pref-viewer-controls-presentation.js";
|
|
3
5
|
import I18n from "./localization/i18n.js";
|
|
4
6
|
|
|
5
7
|
/**
|
|
@@ -7,9 +9,10 @@ import I18n from "./localization/i18n.js";
|
|
|
7
9
|
*
|
|
8
10
|
* Overview:
|
|
9
11
|
* - Hosts synchronized 2D (SVG) and 3D (Babylon.js) canvases plus a render-settings menu inside a single shadow DOM wrapper.
|
|
12
|
+
* - Loads optional font CSS without blocking local shadow styles or the canvas's initial layout measurement.
|
|
10
13
|
* - Queues mutations (config/model/scene/materials/drawing/options/culture) to guarantee deterministic execution and avoid race conditions.
|
|
11
14
|
* - Normalizes remote URLs, Base64 payloads, and IndexedDB lookups before forwarding jobs to the BabylonJSController stack.
|
|
12
|
-
* - Persists
|
|
15
|
+
* - Persists locale and optional instance-owned appearance overrides; mirrors locale to the menu and shared i18n module.
|
|
13
16
|
* - Surfaces a dialog API that powers built-in download flows (GLB, glTF+ZIP, USDZ) for model-only, scene-only, or combined asset exports.
|
|
14
17
|
* - Emits granular lifecycle custom events so host applications can react to loading progress, drawing zoom changes, selection changes, and menu interactions.
|
|
15
18
|
* - Exposes imperative methods for toggling visibility, updating options, switching modes, controlling animations, managing selection state, and requesting downloads without attribute juggling.
|
|
@@ -30,8 +33,9 @@ import I18n from "./localization/i18n.js";
|
|
|
30
33
|
* - mode: Switches between `2d` and `3d`, automatically hiding/showing the relevant subcomponents and menu states.
|
|
31
34
|
* - show-model / show-scene: Boolean flags to toggle visibility without reloading the underlying resources.
|
|
32
35
|
* - show-render-menu: Boolean flag to show or hide the render-settings menu (default: true).
|
|
36
|
+
* - view-cube-renderer: Selects independent Babylon Canvas (default) or SVG via reflected viewCubeRenderer.
|
|
33
37
|
* - show-view-cube: Enables the 3D orientation overlay unless "false"; visible cubes position the render menu below their measured height.
|
|
34
|
-
* - styles:
|
|
38
|
+
* - styles: Validated primary/ViewCube appearance overrides; optional versioned persistence and private CSS projection.
|
|
35
39
|
*
|
|
36
40
|
* Public Methods (selection):
|
|
37
41
|
* - loadConfig / loadModel / loadScene / loadMaterials / loadDrawing: Queue asset ingestion jobs.
|
|
@@ -67,6 +71,7 @@ import I18n from "./localization/i18n.js";
|
|
|
67
71
|
* - Legacy `scene-*` and `drawing-*` aliases are still emitted alongside their modern equivalents for backward compatibility.
|
|
68
72
|
*
|
|
69
73
|
* Notes:
|
|
74
|
+
* - Owns one responsive control presentation shared by nested overlays; disconnect releases its observers.
|
|
70
75
|
* - Stores the cube layout handler and subscribes only for active 3D cube layout; open dialogs render above viewer overlays.
|
|
71
76
|
* - Internally wires PrefViewerMenu3D hover/apply events to PrefViewer3D render settings, ensuring persisted toggles stay in sync with BabylonJSController.
|
|
72
77
|
* - Cleans up dialogs, listeners, and subcomponents on disconnect to prevent leaks when frameworks mount/unmount the custom element.
|
|
@@ -74,6 +79,9 @@ import I18n from "./localization/i18n.js";
|
|
|
74
79
|
* - Designed for embeddable configurators, product showcases, and sales tooling that require responsive 2D/3D switching plus offline-friendly exports.
|
|
75
80
|
*/
|
|
76
81
|
export default class PrefViewer extends HTMLElement {
|
|
82
|
+
#controlsPresentation = null;
|
|
83
|
+
#presentationFontLink = null;
|
|
84
|
+
#presentationRootStyle = null;
|
|
77
85
|
// Internal state flags
|
|
78
86
|
#isInitialized = false;
|
|
79
87
|
#isLoaded = false;
|
|
@@ -101,10 +109,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
101
109
|
#cultureSuppressAttribute = false;
|
|
102
110
|
|
|
103
111
|
// Runtime style management
|
|
104
|
-
#
|
|
105
|
-
#styles = {
|
|
106
|
-
colorPrimary: PrefViewerStyleVariables.colorPrimary,
|
|
107
|
-
};
|
|
112
|
+
#styleController;
|
|
108
113
|
|
|
109
114
|
// References to internal components
|
|
110
115
|
#wrapper = null;
|
|
@@ -126,9 +131,23 @@ export default class PrefViewer extends HTMLElement {
|
|
|
126
131
|
onViewCubeLayout: null,
|
|
127
132
|
};
|
|
128
133
|
|
|
134
|
+
/** @returns {"svg"|"canvas"} Per-instance normalized renderer; missing/invalid attributes use Canvas. */
|
|
135
|
+
get viewCubeRenderer() {
|
|
136
|
+
return this.getAttribute("view-cube-renderer") === "svg" ? "svg" : "canvas";
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Reflects the renderer preference immediately without reloading assets or changing visibility.
|
|
141
|
+
* @param {"svg"|"canvas"} value - SVG selects the vector widget; all other values select the dedicated Canvas 3D scene.
|
|
142
|
+
* @returns {void}
|
|
143
|
+
*/
|
|
144
|
+
set viewCubeRenderer(value) {
|
|
145
|
+
this.setAttribute("view-cube-renderer", value === "svg" ? "svg" : "canvas");
|
|
146
|
+
}
|
|
147
|
+
|
|
129
148
|
/**
|
|
130
149
|
* Creates a new PrefViewer instance and attaches a shadow DOM.
|
|
131
|
-
* Initializes
|
|
150
|
+
* Initializes instance-owned styling without reading storage until insertion; other component references are created on connection.
|
|
132
151
|
* @public
|
|
133
152
|
*/
|
|
134
153
|
constructor() {
|
|
@@ -141,22 +160,24 @@ export default class PrefViewer extends HTMLElement {
|
|
|
141
160
|
this.#culture = I18n.setLocale(this.#cultureInitial);
|
|
142
161
|
}
|
|
143
162
|
|
|
144
|
-
this.#
|
|
163
|
+
this.#styleController = new PrefViewerStyleController(this.ownerDocument);
|
|
145
164
|
}
|
|
146
165
|
|
|
147
166
|
/**
|
|
148
|
-
* Returns
|
|
167
|
+
* Returns observed data, visibility, renderer selection, styles and controls-density attributes.
|
|
149
168
|
* @public
|
|
150
169
|
* @returns {string[]} Array of attribute names to observe.
|
|
151
170
|
*/
|
|
152
171
|
static get observedAttributes() {
|
|
153
|
-
return ["config", "culture", "drawing", "materials", "mode", "model", "scene", "options", "show-model", "show-scene", "show-render-menu", "show-view-cube", "styles"];
|
|
172
|
+
return ["config", "culture", "drawing", "materials", "mode", "model", "scene", "options", "show-model", "show-scene", "show-render-menu", "show-view-cube", "view-cube-renderer", "styles", "controls-density"];
|
|
154
173
|
}
|
|
155
174
|
|
|
156
175
|
/**
|
|
157
176
|
* Observes changes to specific attributes and triggers corresponding actions.
|
|
158
177
|
* Loads configuration, drawing, model, scene, materials, or options when their attributes change.
|
|
159
178
|
* 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.
|
|
179
|
+
* "view-cube-renderer" switches the active cube without loading assets.
|
|
180
|
+
* "controls-density" refreshes shared control presentation without queuing asset work.
|
|
160
181
|
* "show-view-cube" synchronizes lazy cube activation and conditional layout subscription before forwarding the attribute.
|
|
161
182
|
* @public
|
|
162
183
|
* @param {string} name - The name of the changed attribute.
|
|
@@ -166,6 +187,12 @@ export default class PrefViewer extends HTMLElement {
|
|
|
166
187
|
*/
|
|
167
188
|
attributeChangedCallback(name, _old, value) {
|
|
168
189
|
switch (name) {
|
|
190
|
+
case "view-cube-renderer":
|
|
191
|
+
this.#component3D?.setAttribute("view-cube-renderer", this.viewCubeRenderer);
|
|
192
|
+
break;
|
|
193
|
+
case "controls-density":
|
|
194
|
+
this.#controlsPresentation?.refresh();
|
|
195
|
+
break;
|
|
169
196
|
case "show-view-cube":
|
|
170
197
|
this.#setViewCubeLayoutSubscription(this.#mode === "3d" && value !== "false");
|
|
171
198
|
this.#component3D?.setAttribute("show-view-cube", value === "false" ? "false" : "true");
|
|
@@ -236,17 +263,19 @@ export default class PrefViewer extends HTMLElement {
|
|
|
236
263
|
/**
|
|
237
264
|
* Called when the element is inserted into the DOM.
|
|
238
265
|
* Initializes the 3D and 2D viewer components and starts processing tasks.
|
|
239
|
-
* Restores
|
|
266
|
+
* Restores saved styles inside a CSS inheritance boundary before creating controls and synchronizes the effective primary highlight.
|
|
240
267
|
* @public
|
|
241
268
|
* @returns {void|boolean} Returns false if initialization fails; otherwise void.
|
|
242
269
|
*/
|
|
243
270
|
connectedCallback() {
|
|
244
271
|
this.#createShadowDOM();
|
|
245
|
-
this.#
|
|
272
|
+
this.#styleController.attach(this.#wrapper);
|
|
273
|
+
this.#controlsPresentation = new PrefViewerControlsPresentation(this.#wrapper,
|
|
274
|
+
() => this.getAttribute("controls-density"), () => this.#component3D?.refreshViewCube?.());
|
|
246
275
|
this.#createComponent3D();
|
|
247
276
|
this.#createComponent2D();
|
|
248
277
|
this.#createMenu3D();
|
|
249
|
-
this.#applyRenderSettings({ highlightColor: this.#
|
|
278
|
+
this.#applyRenderSettings({ highlightColor: this.#styleController.primaryColor, persist: false });
|
|
250
279
|
|
|
251
280
|
this.setMode(this.getAttribute("mode") ?? this.#mode);
|
|
252
281
|
|
|
@@ -264,11 +293,13 @@ export default class PrefViewer extends HTMLElement {
|
|
|
264
293
|
|
|
265
294
|
/**
|
|
266
295
|
* Removes stored child/menu/dialog listeners and subcomponents when detached.
|
|
267
|
-
*
|
|
296
|
+
* Disposes responsive control observers and unsubscribes the cube layout handler before the 3D component and its overlay are torn down.
|
|
268
297
|
* @public
|
|
269
298
|
* @returns {void}
|
|
270
299
|
*/
|
|
271
300
|
disconnectedCallback() {
|
|
301
|
+
this.#controlsPresentation?.dispose();
|
|
302
|
+
this.#controlsPresentation = null;
|
|
272
303
|
if (this.#wrapper) {
|
|
273
304
|
this.#wrapper.removeEventListener("mouseenter", this.#handlers.onViewerHoverStart);
|
|
274
305
|
this.#wrapper.removeEventListener("mouseleave", this.#handlers.onViewerHoverEnd);
|
|
@@ -296,21 +327,31 @@ export default class PrefViewer extends HTMLElement {
|
|
|
296
327
|
}
|
|
297
328
|
|
|
298
329
|
/**
|
|
299
|
-
*
|
|
330
|
+
* Replaces owned wrapper/font/style nodes on reconnect while preserving consumer-added shadow content.
|
|
331
|
+
* Optional font CSS starts with print media and switches on load, allowing local styles and canvas layout
|
|
332
|
+
* to become usable even while the external font stylesheet is pending or unavailable.
|
|
300
333
|
* @private
|
|
301
334
|
* @returns {void}
|
|
302
335
|
*/
|
|
303
336
|
#createShadowDOM() {
|
|
337
|
+
this.#wrapper?.remove();
|
|
338
|
+
this.#presentationFontLink?.remove();
|
|
339
|
+
this.#presentationRootStyle?.remove();
|
|
304
340
|
this.#wrapper = document.createElement("div");
|
|
305
341
|
this.#wrapper.classList.add("pref-viewer-wrapper");
|
|
306
342
|
this.shadowRoot.append(this.#wrapper);
|
|
307
343
|
|
|
308
|
-
const link = document.createElement("link");
|
|
344
|
+
const link = this.#presentationFontLink = document.createElement("link");
|
|
309
345
|
link.setAttribute("rel", "stylesheet");
|
|
310
346
|
link.setAttribute("href", "https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap");
|
|
347
|
+
// Font CSS must not block local shadow styles while Babylon measures its canvas.
|
|
348
|
+
// Otherwise its intrinsic buffer can be mistaken for the CSS viewport and scaled again.
|
|
349
|
+
link.media = "print";
|
|
350
|
+
link.addEventListener("load", () => { link.media = "all"; }, { once: true });
|
|
311
351
|
this.shadowRoot.append(link);
|
|
312
352
|
|
|
313
353
|
const style = document.createElement("style");
|
|
354
|
+
this.#presentationRootStyle = style;
|
|
314
355
|
style.textContent = PrefViewerStyles;
|
|
315
356
|
this.shadowRoot.append(style);
|
|
316
357
|
}
|
|
@@ -351,7 +392,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
351
392
|
}
|
|
352
393
|
/**
|
|
353
394
|
* 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
|
|
395
|
+
* Forwards renderer selection and show-view-cube, stores its layout handler in #handlers and subscribes before activation
|
|
355
396
|
* so the first measured layout positions the render menu correctly.
|
|
356
397
|
* @private
|
|
357
398
|
* @returns {void}
|
|
@@ -360,6 +401,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
360
401
|
this.#handlers.on3DElementClick = this.#on3DElementClick.bind(this);
|
|
361
402
|
this.#component3D = document.createElement("pref-viewer-3d");
|
|
362
403
|
this.#component3D.setAttribute("visible", "false");
|
|
404
|
+
this.#component3D.setAttribute("view-cube-renderer", this.viewCubeRenderer);
|
|
363
405
|
this.#component3D.setAttribute("show-view-cube", this.getAttribute("show-view-cube") === "false" ? "false" : "true");
|
|
364
406
|
this.#handlers.onViewCubeLayout = (event) => {
|
|
365
407
|
if (event.detail.offset > 0) {
|
|
@@ -490,80 +532,17 @@ export default class PrefViewer extends HTMLElement {
|
|
|
490
532
|
}
|
|
491
533
|
|
|
492
534
|
/**
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
* @
|
|
496
|
-
|
|
497
|
-
#stylesReadPersisted() {
|
|
498
|
-
if (typeof window === "undefined") {
|
|
499
|
-
return {};
|
|
500
|
-
}
|
|
501
|
-
try {
|
|
502
|
-
const serialized = window.localStorage?.getItem(this.#STYLES_STORAGE_KEY);
|
|
503
|
-
return serialized ? JSON.parse(serialized) : {};
|
|
504
|
-
} catch (_error) {
|
|
505
|
-
return {};
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* Persists current style overrides in localStorage.
|
|
511
|
-
* @private
|
|
512
|
-
* @returns {void}
|
|
513
|
-
*/
|
|
514
|
-
#stylesPersist() {
|
|
515
|
-
if (typeof window === "undefined") {
|
|
516
|
-
return;
|
|
517
|
-
}
|
|
518
|
-
try {
|
|
519
|
-
window.localStorage?.setItem(this.#STYLES_STORAGE_KEY, JSON.stringify(this.#styles));
|
|
520
|
-
} catch (_error) {}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
/**
|
|
524
|
-
* Keeps the host CSS custom properties in sync with the style variables.
|
|
525
|
-
* @private
|
|
526
|
-
* @returns {void}
|
|
535
|
+
* Validates and merges a partial appearance patch through the instance-owned controller.
|
|
536
|
+
* Projects styles inside the shadow boundary and persists only overrides when enabled.
|
|
537
|
+
* @param {object} styles - Supported primary/ViewCube leaves; null leaves or groups restore defaults.
|
|
538
|
+
* @returns {boolean} Whether at least one supported value or reset was accepted.
|
|
527
539
|
*/
|
|
528
|
-
#
|
|
529
|
-
this.
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* Applies supported style overrides to PrefViewerStyleVariables and the host CSS variables.
|
|
534
|
-
* @private
|
|
535
|
-
* @param {object} styles - Style overrides.
|
|
536
|
-
* @param {object} [options] - Apply options.
|
|
537
|
-
* @param {boolean} [options.persist=true] - Whether to persist the resolved styles.
|
|
538
|
-
* @param {boolean} [options.applyCssVariables=true] - Whether to update host CSS custom properties immediately.
|
|
539
|
-
* @returns {boolean} True when at least one supported style was applied.
|
|
540
|
-
*/
|
|
541
|
-
#applyStyles(styles, options = {}) {
|
|
542
|
-
const { persist = true, applyCssVariables = true } = options;
|
|
543
|
-
if (!styles || typeof styles !== "object") {
|
|
544
|
-
return false;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
const nextStyles = {};
|
|
548
|
-
if (typeof styles.colorPrimary === "string" && styles.colorPrimary.trim().length > 0) {
|
|
549
|
-
nextStyles.colorPrimary = styles.colorPrimary.trim();
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
if (!Object.keys(nextStyles).length) {
|
|
540
|
+
#applyStyles(styles) {
|
|
541
|
+
if (!this.#styleController.update(styles)) {
|
|
553
542
|
return false;
|
|
554
543
|
}
|
|
555
|
-
|
|
556
|
-
this.#
|
|
557
|
-
...this.#styles,
|
|
558
|
-
...nextStyles,
|
|
559
|
-
};
|
|
560
|
-
PrefViewerStyleVariables.colorPrimary = this.#styles.colorPrimary;
|
|
561
|
-
if (applyCssVariables) {
|
|
562
|
-
this.#stylesApplyCssVariables();
|
|
563
|
-
}
|
|
564
|
-
if (persist) {
|
|
565
|
-
this.#stylesPersist();
|
|
566
|
-
}
|
|
544
|
+
this.#controlsPresentation?.refresh();
|
|
545
|
+
this.#component3D?.refreshViewCube?.();
|
|
567
546
|
return true;
|
|
568
547
|
}
|
|
569
548
|
|
|
@@ -688,7 +667,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
688
667
|
}
|
|
689
668
|
|
|
690
669
|
/**
|
|
691
|
-
* Adds a
|
|
670
|
+
* Adds a task in order; every partial style patch is retained, while pending options/drawing tasks are replaced.
|
|
692
671
|
* If the viewer is initialized and not currently loading, immediately processes the next task.
|
|
693
672
|
* @private
|
|
694
673
|
* @param {*} value - The payload or data for the task.
|
|
@@ -697,7 +676,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
697
676
|
*/
|
|
698
677
|
#addTaskToQueue(value, type) {
|
|
699
678
|
const task = new PrefViewerTask(value, type);
|
|
700
|
-
if (task.type === PrefViewerTask.Types.Options || task.type === PrefViewerTask.Types.Drawing
|
|
679
|
+
if (task.type === PrefViewerTask.Types.Options || task.type === PrefViewerTask.Types.Drawing) {
|
|
701
680
|
this.#taskQueue = this.#taskQueue.filter((queuedTask) => queuedTask.type !== task.type);
|
|
702
681
|
}
|
|
703
682
|
this.#taskQueue.push(task);
|
|
@@ -932,10 +911,14 @@ export default class PrefViewer extends HTMLElement {
|
|
|
932
911
|
* @private
|
|
933
912
|
* @param {object} config - The configuration object to process.
|
|
934
913
|
* @param {boolean} [config.showRenderMenu] - Reflects render-menu visibility before loading assets; non-booleans are ignored.
|
|
914
|
+
* @param {"svg"|"canvas"} [config.viewCubeRenderer] - Optional per-instance renderer, applied in queue order; omission preserves it.
|
|
935
915
|
* @param {boolean} [config.showViewCube] - Reflects cube activation before loading assets; non-booleans are ignored.
|
|
936
916
|
* @returns {Promise<void>} Resolves after the load attempt and advances the task queue.
|
|
937
917
|
*/
|
|
938
918
|
async #processConfig(config) {
|
|
919
|
+
if (Object.hasOwn(config, "viewCubeRenderer")) {
|
|
920
|
+
this.viewCubeRenderer = config.viewCubeRenderer;
|
|
921
|
+
}
|
|
939
922
|
for (const [property, attribute] of [["showRenderMenu", "show-render-menu"], ["showViewCube", "show-view-cube"]]) {
|
|
940
923
|
if (typeof config[property] === "boolean") {
|
|
941
924
|
const value = String(config[property]);
|
|
@@ -1066,7 +1049,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1066
1049
|
}
|
|
1067
1050
|
|
|
1068
1051
|
/**
|
|
1069
|
-
* Applies queued
|
|
1052
|
+
* Applies queued appearance patches; only an accepted primary-color override synchronizes animation highlights.
|
|
1070
1053
|
* Waits for render settings/menu synchronization before advancing the task queue.
|
|
1071
1054
|
* @private
|
|
1072
1055
|
* @param {object} styles - Style overrides to apply.
|
|
@@ -1075,7 +1058,11 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1075
1058
|
async #processStyles(styles) {
|
|
1076
1059
|
try {
|
|
1077
1060
|
if (this.#applyStyles(styles)) {
|
|
1078
|
-
|
|
1061
|
+
const primary = styles.colorPrimary;
|
|
1062
|
+
const acceptedPrimary = primary === null || (typeof primary === "string" && primary.trim() === this.styles.colorPrimary);
|
|
1063
|
+
if (acceptedPrimary) {
|
|
1064
|
+
await this.#applyRenderSettings({ highlightColor: this.#styleController.primaryColor });
|
|
1065
|
+
}
|
|
1079
1066
|
}
|
|
1080
1067
|
} finally {
|
|
1081
1068
|
this.#processNextTask();
|
|
@@ -1355,12 +1342,13 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1355
1342
|
|
|
1356
1343
|
/**
|
|
1357
1344
|
* Loads a configuration object or JSON string and adds it to the task queue.
|
|
1358
|
-
*
|
|
1345
|
+
* Validates/snapshots supplied style patches through setStyles(), queues styles/culture before config and drawing afterward.
|
|
1359
1346
|
* Boolean showRenderMenu/showViewCube flags apply when that config task is processed, before its 3D load.
|
|
1360
1347
|
* Omitted/non-boolean flags preserve current attributes; equal values do not recreate the menu.
|
|
1361
1348
|
* @public
|
|
1362
1349
|
* @param {object|string} config - Configuration object or JSON string; overlay flags apply in queue order.
|
|
1363
1350
|
* @param {boolean} [config.showRenderMenu] - Sets show-render-menu when explicitly boolean.
|
|
1351
|
+
* @param {"svg"|"canvas"} [config.viewCubeRenderer] - Optional per-instance renderer, applied in queue order; omission preserves it.
|
|
1364
1352
|
* @param {boolean} [config.showViewCube] - Sets show-view-cube when explicitly boolean.
|
|
1365
1353
|
* @returns {false|void} Returns false for an absent/falsy payload; otherwise queues the configuration.
|
|
1366
1354
|
* @throws {SyntaxError} If a supplied JSON string cannot be parsed.
|
|
@@ -1371,7 +1359,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1371
1359
|
return false;
|
|
1372
1360
|
}
|
|
1373
1361
|
if (config.styles) {
|
|
1374
|
-
this
|
|
1362
|
+
this.setStyles(config.styles);
|
|
1375
1363
|
}
|
|
1376
1364
|
if (config.culture) {
|
|
1377
1365
|
this.#addTaskToQueue(config.culture, "culture");
|
|
@@ -1503,19 +1491,49 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1503
1491
|
}
|
|
1504
1492
|
|
|
1505
1493
|
/**
|
|
1506
|
-
* Sets
|
|
1507
|
-
*
|
|
1508
|
-
* synchronizes animation-opening highlight color (including active highlights), and persists the value in localStorage.
|
|
1494
|
+
* Sets instance-owned primary/ViewCube appearance from a JSON-safe object or JSON string through the task queue.
|
|
1495
|
+
* Synchronizes primary highlight settings and optionally persists supported overrides; external CSS is not consulted.
|
|
1509
1496
|
* @public
|
|
1510
|
-
*
|
|
1511
|
-
* @
|
|
1497
|
+
* Queues a detached partial primary/ViewCube style patch. Unknown/invalid leaves are ignored when processed.
|
|
1498
|
+
* @param {object|string} styles - Style tree or JSON; null leaves/groups reset customizations.
|
|
1499
|
+
* @returns {boolean|void} False for a non-object payload; accepted objects are queued and return void, not a Promise.
|
|
1500
|
+
* @throws {SyntaxError} If a JSON string is malformed.
|
|
1512
1501
|
*/
|
|
1513
1502
|
setStyles(styles) {
|
|
1514
1503
|
styles = typeof styles === "string" ? JSON.parse(styles) : styles;
|
|
1515
|
-
if (!styles || typeof styles !== "object") {
|
|
1504
|
+
if (!styles || typeof styles !== "object" || Array.isArray(styles)) {
|
|
1516
1505
|
return false;
|
|
1517
1506
|
}
|
|
1518
|
-
this.#addTaskToQueue(styles, "styles");
|
|
1507
|
+
this.#addTaskToQueue(structuredClone(styles), "styles");
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
/**
|
|
1511
|
+
* Removes only this viewer's configured saved styles, preserving its current appearance.
|
|
1512
|
+
* A later accepted patch can save the current overrides again. Disabled/unavailable storage is a no-op.
|
|
1513
|
+
* @returns {boolean} Whether the configured entry was successfully removed.
|
|
1514
|
+
*/
|
|
1515
|
+
clearPersistedStyles() {
|
|
1516
|
+
return this.#styleController.clearPersisted();
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
/** @returns {{enabled: boolean, key: string}} Detached optional persistence configuration. */
|
|
1520
|
+
get stylesPersistence() {
|
|
1521
|
+
return this.#styleController.persistence;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
/**
|
|
1525
|
+
* Selects optional origin-local storage. Existing explicit patches take priority over restored values.
|
|
1526
|
+
* Configure before insertion to disable reads; switching keys never writes automatically.
|
|
1527
|
+
* @param {{enabled?: boolean, key?: string}} value - Partial configuration; enabled defaults true, key defaults pref-viewer/styles.
|
|
1528
|
+
* @returns {void} Refreshes mounted controls and primary highlights without reloading assets.
|
|
1529
|
+
*/
|
|
1530
|
+
set stylesPersistence(value) {
|
|
1531
|
+
this.#styleController.setPersistence(value);
|
|
1532
|
+
this.#controlsPresentation?.refresh();
|
|
1533
|
+
this.#component3D?.refreshViewCube?.();
|
|
1534
|
+
if (this.#isInitialized) {
|
|
1535
|
+
this.#applyRenderSettings({ highlightColor: this.#styleController.primaryColor, persist: false });
|
|
1536
|
+
}
|
|
1519
1537
|
}
|
|
1520
1538
|
|
|
1521
1539
|
/**
|
|
@@ -1534,9 +1552,10 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1534
1552
|
|
|
1535
1553
|
/**
|
|
1536
1554
|
* Defines the elements that the host application considers selectable.
|
|
1537
|
-
* The normalized state is
|
|
1555
|
+
* The normalized state is forwarded to both renderers: SVG selection clones in 2D and material overlays in 3D.
|
|
1556
|
+
* Emits pref-viewer-selection-state-changed after applying the normalized state.
|
|
1538
1557
|
* @public
|
|
1539
|
-
* @param {Array<string|{id?: string, Id?: string}>} elements - Element ids or objects containing id/Id.
|
|
1558
|
+
* @param {Array<string|{id?: string, Id?: string}>} [elements=[]] - Element ids or objects containing id/Id.
|
|
1540
1559
|
* @returns {object} Current selection state.
|
|
1541
1560
|
*/
|
|
1542
1561
|
setSelectableElements(elements = []) {
|
|
@@ -1549,7 +1568,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1549
1568
|
/**
|
|
1550
1569
|
* Defines the currently selected elements using the semantic PrefViewer contract.
|
|
1551
1570
|
* @public
|
|
1552
|
-
* @param {Array<string|{id?: string, Id?: string, highlights?: string[], Highlights?: string[]}>} elements - Element ids or objects containing id/Id and optional highlights/Highlights.
|
|
1571
|
+
* @param {Array<string|{id?: string, Id?: string, highlights?: string[], Highlights?: string[]}>} [elements=[]] - Element ids or objects containing id/Id and optional highlights/Highlights.
|
|
1553
1572
|
* @returns {object} Current selection state.
|
|
1554
1573
|
*/
|
|
1555
1574
|
setSelectedElements(elements = []) {
|
|
@@ -1564,7 +1583,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1564
1583
|
/**
|
|
1565
1584
|
* Applies a complete host selection state in one call.
|
|
1566
1585
|
* @public
|
|
1567
|
-
* @param {{selectableIds?: Array<string|object>, selectables?: Array<string|object>, selectedItems?: Array<string|object>, selectedIds?: Array<string|object>, selected?: Array<string|object>}} state - Selection state with selectableIds/selectables and selectedItems/selectedIds/selected.
|
|
1586
|
+
* @param {{selectableIds?: Array<string|object>, selectables?: Array<string|object>, selectedItems?: Array<string|object>, selectedIds?: Array<string|object>, selected?: Array<string|object>}} [state={}] - Selection state with selectableIds/selectables and selectedItems/selectedIds/selected.
|
|
1568
1587
|
* @returns {object} Current selection state.
|
|
1569
1588
|
*/
|
|
1570
1589
|
applySelectionState(state = {}) {
|
|
@@ -1923,6 +1942,7 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1923
1942
|
* @public
|
|
1924
1943
|
* @param {object|string} value - Configuration payload or serialized JSON.
|
|
1925
1944
|
* @param {boolean} [value.showRenderMenu] - Optional render-menu visibility for an object payload.
|
|
1945
|
+
* @param {"svg"|"canvas"} [value.viewCubeRenderer] - Optional renderer applied with the queued configuration.
|
|
1926
1946
|
* @param {boolean} [value.showViewCube] - Optional cube visibility for an object payload.
|
|
1927
1947
|
* @throws {SyntaxError} If a supplied JSON string cannot be parsed.
|
|
1928
1948
|
*/
|
|
@@ -1984,10 +2004,14 @@ export default class PrefViewer extends HTMLElement {
|
|
|
1984
2004
|
this.setOptions(value);
|
|
1985
2005
|
}
|
|
1986
2006
|
|
|
2007
|
+
/** @returns {object} Detached merged style overrides including the effective primary color; missing leaves use internal defaults. */
|
|
2008
|
+
get styles() {
|
|
2009
|
+
return this.#styleController.styles;
|
|
2010
|
+
}
|
|
2011
|
+
|
|
1987
2012
|
/**
|
|
1988
|
-
*
|
|
1989
|
-
* @
|
|
1990
|
-
* @param {object|string} value - Style overrides object or JSON string.
|
|
2013
|
+
* Queues the same validated partial appearance patch as setStyles().
|
|
2014
|
+
* @param {object|string} value - Override tree or JSON; null leaves/groups restore defaults.
|
|
1991
2015
|
*/
|
|
1992
2016
|
set styles(value) {
|
|
1993
2017
|
this.setStyles(value);
|