@liquidcars/atlas 0.1.49 → 0.1.50

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 CHANGED
@@ -191,6 +191,7 @@ generar el archivo.
191
191
  - `palette`: mapa de nombres de color a valores CSS/hex.
192
192
  - `theme` (opcional): configuración de `background`, `lighting`, `panel`, `toolbar`, `breadcrumbs`, `hint` y `ui`. `ui` permite mostrar u ocultar `panel`, `toolbar`, `breadcrumbs` y `hint`.
193
193
  - `render.camera` (opcional): vista inicial con `position`, `target` y `zoom`. Las coordenadas pertenecen al espacio del modelo; `zoom` conserva el encuadre relativo entre tamaños de visor.
194
+ - `render.initialMode`: `2d` o `3d`. `render.views."2d".theme` admite `auto` (hereda el fondo del documento), `light` o `dark`; `render.views."2d".grid` activa o desactiva los puntos (por defecto, `true`). `render.views."2d".background` permite un color CSS concreto. `render.ui.toolbar` acepta `true`, `false` o una lista como `[mode, zoom, fit]` para mostrar solo esos controles.
194
195
  - `render.focus` (opcional): filtrado visual por selección. `mode` acepta `all` o `connected`, `effect` acepta `dim` o `hide`, y `layout` distingue posiciones estables (`preserve`) de una proyección recompilada (`reflow`).
195
196
  - `render.relationMarker` (opcional): forma de los indicadores animados de relación. Admite `cone` (por defecto, conserva el sentido en capturas estáticas) o `ring`.
196
197
  - `style.label.anchor` (opcional): posición predeterminada de las etiquetas de los elementos (`auto`, `top`, `bottom`, `left` o `right`). Si se omite, los elementos usan `bottom`; una entidad puede sobrescribirlo con su propio `style.label.anchor`. Los títulos de contenedores mantienen su colocación automática salvo override explícito.
@@ -11890,7 +11890,7 @@ var $c = class {
11890
11890
  }
11891
11891
  }, el = {
11892
11892
  name: "@liquidcars/atlas",
11893
- version: "0.1.49",
11893
+ version: "0.1.50",
11894
11894
  description: "Reusable 3D conceptual atlas Web Component for LiquidCars-style models",
11895
11895
  type: "module",
11896
11896
  scripts: {
@@ -12353,7 +12353,7 @@ function vl(e, t = {}) {
12353
12353
  return `<path data-relation="${s}" data-mode="${o}" d="M${H(i)} L${H(a)}" fill="none" stroke="${tl(t.connectionColor || "#58788d")}" stroke-width="2"${o === "bidirectional" ? " marker-start=\"url(#atlas-diagram-arrow)\"" : ""} marker-end="url(#atlas-diagram-arrow)"${l}/>`;
12354
12354
  }).join(""), pe = t.canvasColor || "#f5f5f5", W = /* @__PURE__ */ new Map(), G = [...re.values()].sort((e, t) => ne(e.node) - ne(t.node)).map((n) => {
12355
12355
  if (v(n.node.id)) return "";
12356
- let r = n.node.material?.color || new Y("#58788d"), i = `#${r.getHexString()}`, o = `#${r.clone().lerp(new Y("#254253"), .48).getHexString()}`, s = n.node.parent, c = 0;
12356
+ let r = n.node.material?.color || new Y("#58788d"), i = `#${r.getHexString()}`, o = `#${r.clone().lerp(new Y(t.containerInk || "#254253"), t.containerInk ? .65 : .48).getHexString()}`, s = n.node.parent, c = 0;
12357
12357
  for (; s && !W.has(s) && c++ < e.nodes.size;) s = e.nodes.get(s)?.parent;
12358
12358
  let l = W.get(s) || pe, u = al(l, i, .14);
12359
12359
  W.set(n.node.id, u);
@@ -12410,7 +12410,7 @@ var bl = (e) => String(e ?? "").replace(/[&<>"']/g, (e) => ({
12410
12410
  ">": "&gt;",
12411
12411
  "\"": "&quot;",
12412
12412
  "'": "&#39;"
12413
- })[e]), xl = (e, t, n) => Math.min(n, Math.max(t, e)), Sl = "\n .diagram-view{position:absolute;inset:0;overflow:auto;background-color:#f5f5f5;background-image:radial-gradient(circle,#b3b3b3 .8px,transparent 1px);background-size:16px 16px;color:#172c3a;cursor:grab;touch-action:none}\n .diagram-view[hidden],:host(:not([data-view-mode=\"2d\"])) .diagram-view{display:none!important}\n :host([data-view-mode=\"2d\"]) .viewport>canvas,:host([data-view-mode=\"2d\"]) .atlas-jump{visibility:hidden;pointer-events:none}\n :host([data-view-mode=\"2d\"]) .toolbar-group[data-toolbar-group=\"camera\"],\n :host([data-view-mode=\"2d\"]) .toolbar-group[data-toolbar-group=\"copy\"]{display:none}\n :host(:not([data-view-mode=\"2d\"])) .toolbar-group[data-toolbar-group=\"diagram\"]{display:none}\n :host(:not([data-view-mode=\"2d\"])) [data-action=\"diagram-relations-within\"]{display:none!important}\n :host([data-view-mode=\"2d\"]) .toolbar{width:max-content;max-width:calc(100% - 16px);flex-wrap:wrap;justify-content:center}\n :host([data-view-mode=\"2d\"]) .toolbar-group[data-toolbar-group=\"diagram\"]{flex-wrap:wrap;justify-content:center}\n .diagram-content{position:relative;width:max-content;min-width:100%;min-height:100%;display:grid;place-items:center;padding:12px}\n .diagram-content svg{display:block;max-width:none;overflow:visible}\n .diagram-content [data-entity],.diagram-content [data-relation]{cursor:pointer}\n .diagram-content [data-entity]:hover,.diagram-content [data-relation]:hover{filter:drop-shadow(0 0 5px #23a58f)}\n .diagram-content [data-entity].selected,.diagram-content [data-relation].selected{filter:drop-shadow(0 0 7px #008fcb)}\n .diagram-view.dragging{cursor:grabbing}\n .diagram-toolbar select,.diagram-toolbar input{accent-color:#6ad7c0}\n .diagram-toolbar .toolbar-popover{max-height:min(430px,65vh);overflow:auto}\n .diagram-toolbar .toolbar-option.checkbox{display:flex;gap:8px;align-items:center}\n .diagram-toolbar .toolbar-option.checkbox input{pointer-events:none}\n .diagram-toolbar .diagram-spacing{padding:7px 9px;color:#dbe7ec;font-size:12px}\n .diagram-toolbar .diagram-spacing input{width:100%;display:block;margin-top:6px}\n .diagram-toolbar .diagram-items{max-height:220px;overflow:auto}\n .diagram-orientation-cube{position:absolute;z-index:9;top:12px;left:12px;width:110px;height:110px;touch-action:none;cursor:grab}\n .diagram-orientation-cube[hidden],:host(:not([data-view-mode=\"2d\"])) .diagram-orientation-cube{display:none!important}\n .diagram-orientation-cube svg{width:100%;height:100%}\n .diagram-orientation-cube polygon{fill:#476782;stroke:#a8d0df;stroke-width:1.4}\n .diagram-orientation-cube polygon:hover{fill:#4caeaa}\n .diagram-orientation-cube text{fill:#fff;font:bold 10px system-ui;pointer-events:none}\n .diagram-orientation-cube circle{fill:#132b3b;stroke:#50758b}\n .diagram-toolbar .diagram-orbit,.diagram-toolbar .diagram-camera-zoom{display:block;padding:6px 9px;color:#dbe7ec;font-size:12px}\n .diagram-toolbar .diagram-orbit select,.diagram-toolbar .diagram-camera-zoom input{display:block;width:100%;margin-top:4px}\n :host([data-view-mode=\"2d\"]) .hint{color:#527286}\n @media print{:host([data-view-mode=\"2d\"]) .diagram-view{display:block!important;overflow:hidden}.diagram-orientation-cube{display:none!important}}\n", Cl = (e, t, n) => `<details class="toolbar-menu" data-toolbar-menu="diagram-${e}"><summary aria-label="${t}" title="${t}"><span class="toolbar-menu-status">${t}</span><svg class="toolbar-menu-chevron" viewBox="0 0 24 24" aria-hidden="true"><path d="m8 10 4 4 4-4"/></svg></summary><div class="toolbar-popover" role="menu"><div class="toolbar-popover-title">${t}</div>${n}</div></details>`, wl = (e, t) => `<button type="button" class="toolbar-option" data-action="${e}"><span>${t}</span></button>`, Tl = `<div class="toolbar-group diagram-toolbar" data-toolbar-group="diagram">
12413
+ })[e]), xl = (e, t, n) => Math.min(n, Math.max(t, e)), Sl = "\n .toolbar button[hidden],.toolbar-menu[hidden]{display:none!important}\n .diagram-view{position:absolute;inset:0;overflow:auto;background-color:var(--lc-diagram-background,#f5f5f5);background-image:radial-gradient(circle,var(--lc-diagram-dot,#b3b3b3) .8px,transparent 1px);background-size:16px 16px;color:#172c3a;cursor:grab;touch-action:none}\n .diagram-view[hidden],:host(:not([data-view-mode=\"2d\"])) .diagram-view{display:none!important}\n :host([data-view-mode=\"2d\"]) .viewport>canvas,:host([data-view-mode=\"2d\"]) .atlas-jump{visibility:hidden;pointer-events:none}\n :host([data-view-mode=\"2d\"]) .toolbar-group[data-toolbar-group=\"camera\"],\n :host([data-view-mode=\"2d\"]) .toolbar-group[data-toolbar-group=\"copy\"]{display:none}\n :host(:not([data-view-mode=\"2d\"])) .toolbar-group[data-toolbar-group=\"diagram\"]{display:none}\n :host(:not([data-view-mode=\"2d\"])) [data-action=\"diagram-relations-within\"]{display:none!important}\n :host([data-view-mode=\"2d\"]) .toolbar{width:max-content;max-width:calc(100% - 16px);flex-wrap:wrap;justify-content:center}\n :host([data-view-mode=\"2d\"]) .toolbar-group[data-toolbar-group=\"diagram\"]{flex-wrap:wrap;justify-content:center}\n .diagram-content{position:relative;width:max-content;min-width:100%;min-height:100%;display:grid;place-items:center;padding:12px}\n .diagram-content svg{display:block;max-width:none;overflow:visible}\n .diagram-content [data-entity],.diagram-content [data-relation]{cursor:pointer}\n .diagram-content [data-entity]:hover,.diagram-content [data-relation]:hover{filter:drop-shadow(0 0 5px #23a58f)}\n .diagram-content [data-entity].selected,.diagram-content [data-relation].selected{filter:drop-shadow(0 0 7px #008fcb)}\n .diagram-view.dragging{cursor:grabbing}\n .diagram-toolbar select,.diagram-toolbar input{accent-color:#6ad7c0}\n .diagram-toolbar .toolbar-popover{max-height:min(430px,65vh);overflow:auto}\n .diagram-toolbar .toolbar-option.checkbox{display:flex;gap:8px;align-items:center}\n .diagram-toolbar .toolbar-option.checkbox input{pointer-events:none}\n .diagram-toolbar .diagram-spacing{padding:7px 9px;color:#dbe7ec;font-size:12px}\n .diagram-toolbar .diagram-spacing input{width:100%;display:block;margin-top:6px}\n .diagram-toolbar .diagram-items{max-height:220px;overflow:auto}\n .diagram-orientation-cube{position:absolute;z-index:9;top:12px;left:12px;width:110px;height:110px;touch-action:none;cursor:grab}\n .diagram-orientation-cube[hidden],:host(:not([data-view-mode=\"2d\"])) .diagram-orientation-cube{display:none!important}\n .diagram-orientation-cube svg{width:100%;height:100%}\n .diagram-orientation-cube polygon{fill:#476782;stroke:#a8d0df;stroke-width:1.4}\n .diagram-orientation-cube polygon:hover{fill:#4caeaa}\n .diagram-orientation-cube text{fill:#fff;font:bold 10px system-ui;pointer-events:none}\n .diagram-orientation-cube circle{fill:#132b3b;stroke:#50758b}\n .diagram-toolbar .diagram-orbit,.diagram-toolbar .diagram-camera-zoom{display:block;padding:6px 9px;color:#dbe7ec;font-size:12px}\n .diagram-toolbar .diagram-orbit select,.diagram-toolbar .diagram-camera-zoom input{display:block;width:100%;margin-top:4px}\n :host([data-view-mode=\"2d\"]) .hint{color:var(--lc-diagram-hint,#527286)}\n @media print{:host([data-view-mode=\"2d\"]) .diagram-view{display:block!important;overflow:hidden}.diagram-orientation-cube{display:none!important}}\n", Cl = (e, t, n) => `<details class="toolbar-menu" data-toolbar-menu="diagram-${e}"><summary aria-label="${t}" title="${t}"><span class="toolbar-menu-status">${t}</span><svg class="toolbar-menu-chevron" viewBox="0 0 24 24" aria-hidden="true"><path d="m8 10 4 4 4-4"/></svg></summary><div class="toolbar-popover" role="menu"><div class="toolbar-popover-title">${t}</div>${n}</div></details>`, wl = (e, t) => `<button type="button" class="toolbar-option" data-action="${e}"><span>${t}</span></button>`, Tl = `<div class="toolbar-group diagram-toolbar" data-toolbar-group="diagram">
12414
12414
  <button class="toolbar-icon" data-action="diagram-minus" aria-label="Zoom out" title="Zoom out">−</button>
12415
12415
  <button class="toolbar-icon" data-action="diagram-plus" aria-label="Zoom in" title="Zoom in">+</button>
12416
12416
  <button class="toolbar-icon" data-action="diagram-fit" aria-label="Fit diagram" title="Fit diagram">⛶</button>
@@ -12443,6 +12443,8 @@ var bl = (e) => String(e ?? "").replace(/[&<>"']/g, (e) => ({
12443
12443
  labels: !0,
12444
12444
  relations: "all",
12445
12445
  showOrientationCube: !0,
12446
+ theme: "auto",
12447
+ grid: !0,
12446
12448
  focus: {
12447
12449
  mode: "all",
12448
12450
  effect: "dim",
@@ -12465,6 +12467,12 @@ function Dl(e = {}) {
12465
12467
  cameraZoom: xl(Number(t.cameraZoom) || 1, .5, 5),
12466
12468
  gap: xl(Number(t.gap ?? 20) || 0, 0, 150),
12467
12469
  labels: t.labels !== !1,
12470
+ theme: [
12471
+ "auto",
12472
+ "light",
12473
+ "dark"
12474
+ ].includes(t.theme) ? t.theme : "auto",
12475
+ grid: t.grid !== !1,
12468
12476
  showOrientationCube: t.showOrientationCube !== !1,
12469
12477
  relations: [
12470
12478
  "all",
@@ -12767,7 +12775,7 @@ var Il = class {
12767
12775
  }));
12768
12776
  }
12769
12777
  renderOptions(e = {}) {
12770
- let t = this.config, n = this._focusedIds();
12778
+ let t = this.config, n = this._focusedIds(), r = new Y(t.background || (t.theme === "dark" ? "#2d2f31" : t.theme === "light" ? "#f5f5f5" : null) || globalThis.getComputedStyle?.(this.root).backgroundColor || "#f5f5f5"), i = r.r * .2126 + r.g * .7152 + r.b * .0722 < .32, a = `#${r.getHexString()}`;
12771
12779
  return {
12772
12780
  cameraView: t.cameraView,
12773
12781
  cameraFrame: {
@@ -12785,7 +12793,11 @@ var Il = class {
12785
12793
  gap: t.gap,
12786
12794
  labels: t.labels,
12787
12795
  placements: t.placements,
12788
- background: "#f5f5f5",
12796
+ background: a,
12797
+ canvasColor: a,
12798
+ labelColor: i ? "#e9f0f5" : "#172c3a",
12799
+ connectionColor: i ? "#b1c7d3" : "#58788d",
12800
+ ...i ? { containerInk: "#e9f0f5" } : {},
12789
12801
  ...e
12790
12802
  };
12791
12803
  }
@@ -12825,7 +12837,7 @@ var Il = class {
12825
12837
  }
12826
12838
  refresh() {
12827
12839
  if (this._refreshQueued = !1, this.atlas.viewMode !== "2d" || !this.atlas.ready || !this.root.clientWidth) return !1;
12828
- this._syncControls();
12840
+ this._syncControls(), this.root.style.backgroundColor = this.config.background || (this.config.theme === "dark" ? "#2d2f31" : this.config.theme === "light" ? "#f5f5f5" : ""), this.root.style.backgroundImage = this.config.grid ? "" : "none", this.config.theme === "auto" ? this.root.style.removeProperty("--lc-diagram-dot") : this.root.style.setProperty("--lc-diagram-dot", this.config.theme === "dark" ? "#73777c" : "#b3b3b3");
12829
12841
  let e = this.renderOptions({
12830
12842
  faceCache: /* @__PURE__ */ new Map(),
12831
12843
  background: null,
@@ -12833,31 +12845,38 @@ var Il = class {
12833
12845
  }), t = {
12834
12846
  width: this.root.clientWidth,
12835
12847
  height: this.root.clientHeight
12836
- }, n = (e) => Math.min(1, (t.width - 32) / e.width, (t.height - 32) / e.height), r = this.atlas.exportDiagramSvg({
12848
+ }, n = this.atlas.toolbar, r = {
12849
+ top: this.atlas.shadowRoot.querySelector(".hint")?.hidden ? 16 : 34,
12850
+ right: 16,
12851
+ bottom: this.atlas.toolbarVisible && !n.hidden ? n.offsetHeight + 44 : 16,
12852
+ left: this.cube.hidden ? 16 : 132
12853
+ };
12854
+ this.content.style.padding = `${r.top}px ${r.right}px ${r.bottom}px ${r.left}px`;
12855
+ let i = (e) => Math.min(1, (t.width - r.left - r.right) / e.width, (t.height - r.top - r.bottom) / e.height), a = this.atlas.exportDiagramSvg({
12837
12856
  ...e,
12838
12857
  measureOnly: !0
12839
- }), i = this.zoom === "fit" ? n(r) : this.zoom;
12858
+ }), o = this.zoom === "fit" ? i(a) : this.zoom;
12840
12859
  for (let t = 0; t < (this.zoom === "fit" ? 8 : 1); t += 1) {
12841
- i = Math.max(.08, i);
12860
+ o = Math.max(.08, o);
12842
12861
  let t = this.atlas.exportDiagramSvg({
12843
12862
  ...e,
12844
- observerScale: i,
12863
+ observerScale: o,
12845
12864
  measureOnly: !0
12846
12865
  });
12847
12866
  if (this.zoom !== "fit") break;
12848
- let r = n(t);
12849
- if (Math.abs(r - i) < .002) break;
12850
- i = r;
12867
+ let n = i(t);
12868
+ if (Math.abs(n - o) < .002) break;
12869
+ o = n;
12851
12870
  }
12852
- let a = this.atlas.exportDiagramSvg({
12871
+ let s = this.atlas.exportDiagramSvg({
12853
12872
  ...e,
12854
- observerScale: i
12873
+ observerScale: o
12855
12874
  });
12856
- this.result = a;
12857
- let o = this.root.scrollLeft, s = this.root.scrollTop;
12858
- this.content.innerHTML = a.svg;
12859
- let c = this.content.querySelector("svg");
12860
- return c.style.width = `${Math.round(a.width * i)}px`, c.style.height = `${Math.round(a.height * i)}px`, this.root.scrollLeft = this.zoom === "fit" ? 0 : o, this.root.scrollTop = this.zoom === "fit" ? 0 : s, this._syncSelection(), !0;
12875
+ this.zoom === "fit" && (this._lastFitZoom = o), this.result = s;
12876
+ let c = this.root.scrollLeft, l = this.root.scrollTop;
12877
+ this.content.innerHTML = s.svg;
12878
+ let u = this.content.querySelector("svg");
12879
+ return u.style.width = `${Math.round(s.width * o)}px`, u.style.height = `${Math.round(s.height * o)}px`, this.root.scrollLeft = this.zoom === "fit" ? 0 : c, this.root.scrollTop = this.zoom === "fit" ? 0 : l, this._syncSelection(), !0;
12861
12880
  }
12862
12881
  _syncSelection() {
12863
12882
  if (this.content.querySelectorAll(".selected").forEach((e) => e.classList.remove("selected")), this.atlas.selectedId) for (let e of this.content.querySelectorAll("[data-entity]")) e.dataset.entity === this.atlas.selectedId && e.classList.add("selected");
@@ -12914,7 +12933,7 @@ var Il = class {
12914
12933
  }
12915
12934
  focusSelection() {
12916
12935
  if (this.zoom === "fit" && this.result) {
12917
- let e = Math.min(1, (this.root.clientWidth - 32) / this.result.width, (this.root.clientHeight - 32) / this.result.height);
12936
+ let e = this._lastFitZoom || 1;
12918
12937
  this.zoom = xl(Math.max(.75, e * 1.8), .08, 4), this.refresh();
12919
12938
  }
12920
12939
  let e = [...this.content.querySelectorAll("[data-entity], [data-relation]")].find((e) => e.dataset.entity === this.atlas.selectedId || e.dataset.relation === this.atlas.selectedRelation?.id);
@@ -12926,8 +12945,8 @@ var Il = class {
12926
12945
  if (!e) return !1;
12927
12946
  if (e === "diagram-fit") return this.zoom = "fit", this.refresh(), !0;
12928
12947
  if (e === "diagram-plus" || e === "diagram-minus") {
12929
- let t = this.zoom === "fit" ? Math.min(1, (this.root.clientWidth - 32) / (this.result?.width || 1), (this.root.clientHeight - 32) / (this.result?.height || 1)) : this.zoom;
12930
- return this.zoom = xl(t * (e === "diagram-plus" ? 1.4 : 1 / 1.4), .08, 4), this.refresh(), !0;
12948
+ let t = this.zoom === "fit" ? this._lastFitZoom || 1 : this.zoom;
12949
+ return this.zoom = xl(t * (e === "diagram-plus" ? 1.15 : 1 / 1.15), .08, 4), this.refresh(), !0;
12931
12950
  }
12932
12951
  if (e === "labels") return this.setConfig({ labels: !this.config.labels }, { layout: !0 }), !0;
12933
12952
  if (e === "diagram-cube") return this.setConfig({ showOrientationCube: !this.config.showOrientationCube }), !0;
@@ -13050,7 +13069,7 @@ var Il = class {
13050
13069
  this.root.scrollLeft -= t, this.root.scrollTop -= n;
13051
13070
  let i = t + this.root.scrollLeft - e, a = n + this.root.scrollTop - r;
13052
13071
  if ((i || a) && this.config.cameraZoom > 1) {
13053
- let e = Ml(this.config.cameraView), t = this.zoom === "fit" ? Math.min(1, this.root.clientWidth / (this.result?.width || 1), this.root.clientHeight / (this.result?.height || 1)) : this.zoom, n = Fl(this.config.cameraView.target, e, i, a, 80 * Math.max(.08, t));
13072
+ let e = Ml(this.config.cameraView), t = this.zoom === "fit" ? this._lastFitZoom || 1 : this.zoom, n = Fl(this.config.cameraView.target, e, i, a, 80 * Math.max(.08, t));
13054
13073
  this.setConfig({ cameraView: jl(n, e.yaw, e.pitch) }, {
13055
13074
  layout: !0,
13056
13075
  defer: !0
@@ -13065,7 +13084,7 @@ var Il = class {
13065
13084
  this.root.addEventListener("pointerup", t), this.root.addEventListener("pointercancel", t), this.root.addEventListener("contextmenu", (e) => e.preventDefault()), this.root.addEventListener("wheel", (e) => {
13066
13085
  if (!e.altKey && !e.ctrlKey) return;
13067
13086
  e.preventDefault();
13068
- let t = this.zoom === "fit" ? Math.min(1, this.root.clientWidth / (this.result?.width || 1), this.root.clientHeight / (this.result?.height || 1)) : this.zoom;
13087
+ let t = this.zoom === "fit" ? this._lastFitZoom || 1 : this.zoom;
13069
13088
  this.zoom = xl(t * (e.deltaY < 0 ? 1.15 : 1 / 1.15), .08, 4), this.scheduleRefresh();
13070
13089
  }, { passive: !1 });
13071
13090
  }
@@ -13907,8 +13926,8 @@ function cd(e, t, n, r, i) {
13907
13926
  side: a.doubleSided ? 2 : 0
13908
13927
  }), h, g = a.icon, _ = a.image, v = null;
13909
13928
  if (typeof _ == "string" && _) {
13910
- if (v = ad(_), m.map = new Ae(v?.canvas || new Image()), !v) {
13911
- let n = m.map.image;
13929
+ if (v = ad(_), m.map = v ? new wr(v.canvas) : a.fallbackIcon ? Yu(a.fallbackIcon) : new Ae(new Image()), !v) {
13930
+ let n = a.fallbackIcon ? new Image() : m.map.image;
13912
13931
  n.crossOrigin = "anonymous";
13913
13932
  let o = !1, s = null, c = /^\s*<svg(?:\s|>)/i.test(_) || /^data:image\/svg\+xml/i.test(_) || /\.svg(?:[?#]|$)/i.test(_), l = new AbortController(), u = () => {
13914
13933
  s &&= (URL.revokeObjectURL(s), null);
@@ -13919,12 +13938,13 @@ function cd(e, t, n, r, i) {
13919
13938
  u();
13920
13939
  return;
13921
13940
  }
13941
+ let s = n;
13922
13942
  if (c) try {
13923
13943
  let e = (n.naturalWidth || 1) / Math.max(1, n.naturalHeight || 1), t = 1024, r = document.createElement("canvas");
13924
13944
  r.width = e >= 1 ? t : Math.max(1, Math.round(t * e)), r.height = e >= 1 ? Math.max(1, Math.round(t / e)) : t;
13925
13945
  let i = r.getContext("2d");
13926
13946
  if (!i) throw Error("Canvas 2D is unavailable");
13927
- i.clearRect(0, 0, r.width, r.height), i.drawImage(n, 0, 0, r.width, r.height), m.map.image = r, od(_, r, n.naturalWidth / Math.max(1, n.naturalHeight));
13947
+ i.clearRect(0, 0, r.width, r.height), i.drawImage(n, 0, 0, r.width, r.height), s = r, od(_, r, n.naturalWidth / Math.max(1, n.naturalHeight));
13928
13948
  } catch (n) {
13929
13949
  i?.({
13930
13950
  code: "SVG_RASTERIZE_FAILED",
@@ -13932,11 +13952,15 @@ function cd(e, t, n, r, i) {
13932
13952
  entityId: t.id,
13933
13953
  image: _,
13934
13954
  error: n
13935
- });
13955
+ }), a.fallbackIcon && (s = null);
13936
13956
  }
13937
13957
  u();
13938
- let s = n.naturalWidth / Math.max(1, n.naturalHeight);
13939
- sd(a, h, m.map, s), m.map.needsUpdate = !0, r?.();
13958
+ let l = n.naturalWidth / Math.max(1, n.naturalHeight);
13959
+ if (s) {
13960
+ let e = m.map, t = s === n ? new Ae(n) : new wr(s);
13961
+ t.colorSpace = y, sd(a, h, t, l), t.needsUpdate = !0, m.map = t, m.needsUpdate = !0, e.dispose();
13962
+ }
13963
+ r?.();
13940
13964
  }, p = () => {
13941
13965
  d(), u(), o || (i?.({
13942
13966
  code: "IMAGE_LOAD_FAILED",
@@ -14367,7 +14391,7 @@ var xd = class extends HTMLElement {
14367
14391
  return this._visits = structuredClone(e.visits), this._visitIndex = e.index, this._visits[this._visitIndex] = this._captureVisit(), this._syncDocumentToolbar(), this;
14368
14392
  }
14369
14393
  _syncDocumentToolbar() {
14370
- let e = !!this.documentResolver && this._visitIndex >= 0, t = this.navigationToolbar?.querySelector("[data-toolbar-group=\"navigation\"]");
14394
+ let e = !!this.documentResolver && this._visitIndex >= 0 && (!this._toolbarControls || this._toolbarControls.has("navigation")), t = this.navigationToolbar?.querySelector("[data-toolbar-group=\"navigation\"]");
14371
14395
  t && (t.hidden = !e), this.navigationToolbar && (this.navigationToolbar.hidden = !e || !this.toolbarVisible);
14372
14396
  for (let [t, n] of [
14373
14397
  ["atlas-home", e && this._visitIndex > 0],
@@ -14765,13 +14789,35 @@ var xd = class extends HTMLElement {
14765
14789
  clearFocusFilter(e = {}) {
14766
14790
  return this.setFocusFilter({ mode: "all" }, e);
14767
14791
  }
14792
+ _setToolbarControls(e) {
14793
+ let t = Array.isArray(e) ? new Set(e.map((e) => String(e).trim())) : null;
14794
+ if (this._toolbarControls = t, !this.toolbar) return;
14795
+ let n = (...e) => !t || t.has("all") || e.some((e) => t.has(e)), r = this.toolbar, i = {
14796
+ "view-mode": ["mode", "view-mode"],
14797
+ minus: ["zoom", "minus"],
14798
+ plus: ["zoom", "plus"],
14799
+ fit: ["fit"],
14800
+ front: ["front"],
14801
+ "diagram-minus": ["zoom", "diagram-minus"],
14802
+ "diagram-plus": ["zoom", "diagram-plus"],
14803
+ "diagram-fit": ["fit", "diagram-fit"]
14804
+ };
14805
+ for (let e of r.querySelectorAll(".toolbar-group > button[data-action]")) e.hidden = !n(...i[e.dataset.action] || [e.dataset.action]);
14806
+ for (let e of r.querySelectorAll(".toolbar-group > .toolbar-menu")) {
14807
+ let t = e.dataset.toolbarMenu;
14808
+ e.hidden = !n(t, t?.replace(/^diagram-/, "")), e.hidden && (e.open = !1);
14809
+ }
14810
+ for (let e of r.querySelectorAll(".toolbar-group:not([data-toolbar-group=\"navigation\"])")) e.hidden = !e.querySelector(":scope > button[data-action]:not([hidden]), :scope > .toolbar-menu:not([hidden])");
14811
+ this._syncDocumentToolbar();
14812
+ }
14768
14813
  _applyModelRenderOptions() {
14769
14814
  let e = {
14770
14815
  ...this.modelData?.render,
14771
14816
  ...this.modelData?.render?.views?.["3d"]
14772
14817
  };
14773
14818
  if (!e || typeof e != "object") return this;
14774
- Kl.includes(e.relationMode) && e.relationMode !== this.relationMode && this.setRelationMode(e.relationMode), vu(e.relationMarker) !== this.relationMarker && this.setRelationMarker(e.relationMarker, {
14819
+ let t = this.modelData?.render?.ui?.toolbar ?? e.toolbar;
14820
+ this._setToolbarControls(Array.isArray(t) ? t : this.modelData?.render?.ui?.controls), Kl.includes(e.relationMode) && e.relationMode !== this.relationMode && this.setRelationMode(e.relationMode), vu(e.relationMarker) !== this.relationMarker && this.setRelationMarker(e.relationMarker, {
14775
14821
  emit: !1,
14776
14822
  source: "model"
14777
14823
  }), Array.isArray(e.visibleRelationGroups) ? this.setVisibleRelationGroups(e.visibleRelationGroups, {
@@ -14781,8 +14827,8 @@ var xd = class extends HTMLElement {
14781
14827
  emit: !1,
14782
14828
  source: "model"
14783
14829
  }), Object.hasOwn(e, "selectionMode") && e.selectionMode !== this.selectionMode && this.setSelectionMode(e.selectionMode);
14784
- let t = e.navigation?.onSelect ?? e.selectionNavigation;
14785
- return t != null && t !== this.selectionNavigation && this.setSelectionNavigation(t), Object.hasOwn(e, "toolbar") && e.toolbar !== !1 !== this.toolbarVisible && this.setToolbarVisible(e.toolbar !== !1), Object.hasOwn(e, "shellLabels") && e.shellLabels !== !1 !== this.showShellLabels && this.setShellLabels(e.shellLabels !== !1), Object.hasOwn(e, "itemFacing") && _u(e.itemFacing) !== this.itemFacing && this.setItemFacing(e.itemFacing, {
14830
+ let n = e.navigation?.onSelect ?? e.selectionNavigation;
14831
+ return n != null && n !== this.selectionNavigation && this.setSelectionNavigation(n), t !== void 0 && t !== !1 !== this.toolbarVisible && this.setToolbarVisible(t !== !1), Object.hasOwn(e, "shellLabels") && e.shellLabels !== !1 !== this.showShellLabels && this.setShellLabels(e.shellLabels !== !1), Object.hasOwn(e, "itemFacing") && _u(e.itemFacing) !== this.itemFacing && this.setItemFacing(e.itemFacing, {
14786
14832
  emit: !1,
14787
14833
  source: "model"
14788
14834
  }), e.focus && this.setFocusFilter(e.focus, { emit: !1 }), this;
@@ -15144,7 +15190,7 @@ var xd = class extends HTMLElement {
15144
15190
  t.setProperty("--lc-bg", e.background.color), t.setProperty("--lc-bg-glow", e.background.glow), t.setProperty("--lc-bg-fade", e.background.fade), t.setProperty("--lc-panel-bg", e.panel.background), t.setProperty("--lc-panel-border", e.panel.border), t.setProperty("--lc-panel-text", e.panel.text), t.setProperty("--lc-panel-title", e.panel.title), t.setProperty("--lc-toolbar-bg", e.toolbar.background), t.setProperty("--lc-toolbar-border", e.toolbar.border), t.setProperty("--lc-toolbar-text", e.toolbar.text), t.setProperty("--lc-toolbar-active", e.toolbar.active), t.setProperty("--lc-toolbar-active-text", e.toolbar.activeText), t.setProperty("--lc-crumb-bg", e.breadcrumbs.background), t.setProperty("--lc-crumb-text", e.breadcrumbs.text), t.setProperty("--lc-crumb-active", e.breadcrumbs.active), t.setProperty("--lc-crumb-active-text", e.breadcrumbs.activeText), t.setProperty("--lc-hint", e.hint);
15145
15191
  let n = this.shadowRoot.querySelector(".atlas"), r = this.shadowRoot.querySelector(".toolbar"), i = this.shadowRoot.querySelector(".panel"), a = this.shadowRoot.querySelector(".hint");
15146
15192
  n && (n.dataset.panel = this.panelVisible ? "visible" : "hidden");
15147
- let o = this.toolbarVisible, s = this.panelVisible, c = e.ui.hint !== !1;
15193
+ let o = this.toolbarVisible, s = this.panelVisible, c = (this.modelData?.render?.ui?.hint ?? e.ui.hint) !== !1;
15148
15194
  r && (r.dataset.hidden = String(!o), r.hidden = !o, r.style.setProperty("display", o ? "flex" : "none", "important")), this._syncDocumentToolbar(), i && (i.dataset.hidden = String(!s), i.hidden = !s), this._syncPanelToolbar(), a && (a.dataset.hidden = String(!c), a.hidden = !c), this.shadowRoot.querySelectorAll(".crumbs").forEach((t) => {
15149
15195
  t.dataset.hidden = String(e.ui.breadcrumbs === !1), t.hidden = e.ui.breadcrumbs === !1;
15150
15196
  });