@nebula-spatial/viewer 0.2.4 → 0.3.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/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
- var ze = Object.defineProperty;
2
- var He = (n, e, t) => e in n ? ze(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
3
- var a = (n, e, t) => He(n, typeof e != "symbol" ? e + "" : e, t);
4
- import { Texture as Ye, Vector3 as w, MathUtils as R, Scene as ee, Group as Ie, Raycaster as Xe, Vector2 as q, WebGLRenderer as _e, Color as qe, Euler as We, OrthographicCamera as te, PerspectiveCamera as $e, MOUSE as W, TOUCH as ie, Vector4 as je, Plane as Ue, WebGLRenderTarget as Ke, Box3 as S, Object3D as Ge, PMREMGenerator as Ze, EquirectangularReflectionMapping as Je, BoxHelper as Qe, Box3Helper as et, BoxGeometry as tt, Mesh as it, MeshBasicMaterial as rt, LineSegments as nt, EdgesGeometry as st, LineBasicMaterial as ot } from "three";
5
- import { RoomEnvironment as at } from "three/addons/environments/RoomEnvironment.js";
6
- import { MapControls as lt } from "three/addons/controls/MapControls.js";
7
- import { OrbitControls as ct } from "three/addons/controls/OrbitControls.js";
8
- import { HDRLoader as dt } from "three/addons/loaders/HDRLoader.js";
9
- import { createCadDocumentSession as ht, getCadDocumentRenderResource as ut, formatCadInsertId as pt } from "@nebula-spatial/cad-loader";
10
- import { configureCadTextBuilder as _i } from "@nebula-spatial/cad-loader";
11
- const mt = [
1
+ var $e = Object.defineProperty;
2
+ var Ke = (n, e, t) => e in n ? $e(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
3
+ var c = (n, e, t) => Ke(n, typeof e != "symbol" ? e + "" : e, t);
4
+ import { Texture as qe, Vector3 as C, MathUtils as I, Scene as ie, Group as Te, Raycaster as je, Vector2 as U, WebGLRenderer as We, Color as Ge, Euler as Ze, OrthographicCamera as re, PerspectiveCamera as Je, MOUSE as $, TOUCH as ne, Vector4 as Qe, Plane as et, WebGLRenderTarget as tt, Box3 as R, Object3D as it, PMREMGenerator as rt, EquirectangularReflectionMapping as nt, BoxHelper as st, Box3Helper as ot, BoxGeometry as at, Mesh as lt, MeshBasicMaterial as ct, LineSegments as dt, EdgesGeometry as ht, LineBasicMaterial as ut } from "three";
5
+ import { RoomEnvironment as pt } from "three/addons/environments/RoomEnvironment.js";
6
+ import { MapControls as mt } from "three/addons/controls/MapControls.js";
7
+ import { OrbitControls as vt } from "three/addons/controls/OrbitControls.js";
8
+ import { HDRLoader as ft } from "three/addons/loaders/HDRLoader.js";
9
+ import { createCadDocumentSession as bt, getCadDocumentRenderResource as gt, formatCadInsertId as se } from "@nebula-spatial/cad-loader";
10
+ import { configureCadTextBuilder as dr } from "@nebula-spatial/cad-loader";
11
+ const yt = [
12
12
  "alphaMap",
13
13
  "aoMap",
14
14
  "bumpMap",
@@ -34,31 +34,31 @@ const mt = [
34
34
  "thicknessMap",
35
35
  "transmissionMap"
36
36
  ];
37
- function X(n, e) {
37
+ function Y(n, e) {
38
38
  e.has(n) || (e.add(n), n.dispose());
39
39
  }
40
- function vt(n, e, t) {
40
+ function xt(n, e, t) {
41
41
  if (e) {
42
42
  const i = n;
43
- for (const r of mt) {
43
+ for (const r of yt) {
44
44
  const s = i[r];
45
- s instanceof Ye && X(s, t);
45
+ s instanceof qe && Y(s, t);
46
46
  }
47
47
  }
48
- X(n, t);
48
+ Y(n, t);
49
49
  }
50
- function re(n, e = {}) {
50
+ function oe(n, e = {}) {
51
51
  const t = e.disposedResources ?? /* @__PURE__ */ new WeakSet(), i = e.disposeTextures !== !1;
52
52
  n.traverse((r) => {
53
53
  const s = r;
54
- s.geometry && X(s.geometry, t);
54
+ s.geometry && Y(s.geometry, t);
55
55
  const o = Array.isArray(s.material) ? s.material : [s.material];
56
- for (const c of o)
57
- c && vt(c, i, t);
58
- s.renderTarget && X(s.renderTarget, t);
56
+ for (const a of o)
57
+ a && xt(a, i, t);
58
+ s.renderTarget && Y(s.renderTarget, t);
59
59
  });
60
60
  }
61
- function ft(n) {
61
+ function wt(n) {
62
62
  const {
63
63
  dxPx: e,
64
64
  dyPx: t,
@@ -66,58 +66,58 @@ function ft(n) {
66
66
  viewportHeightPx: r,
67
67
  orbitDistance: s,
68
68
  fovDeg: o,
69
- aspect: c,
70
- orbitYaw: l,
71
- panSpeed: d
69
+ aspect: a,
70
+ orbitYaw: d,
71
+ panSpeed: l
72
72
  } = n;
73
- if (!Number.isFinite(e) || !Number.isFinite(t) || !Number.isFinite(i) || !Number.isFinite(r) || !Number.isFinite(s) || !Number.isFinite(o) || !Number.isFinite(c) || !Number.isFinite(l) || !Number.isFinite(d) || i <= 0 || r <= 0 || s <= 0 || o <= 0 || o >= 180 || c <= 0)
73
+ if (!Number.isFinite(e) || !Number.isFinite(t) || !Number.isFinite(i) || !Number.isFinite(r) || !Number.isFinite(s) || !Number.isFinite(o) || !Number.isFinite(a) || !Number.isFinite(d) || !Number.isFinite(l) || i <= 0 || r <= 0 || s <= 0 || o <= 0 || o >= 180 || a <= 0)
74
74
  return { x: 0, y: 0, z: 0 };
75
- const h = 2 * s * Math.tan(o * Math.PI / 360), u = h / r, f = h * c / i, p = Math.sin(l), m = Math.cos(l), b = -p, g = m, y = -m, P = -p, x = -e * f * d, E = t * u * d;
75
+ const h = 2 * s * Math.tan(o * Math.PI / 360), u = h / r, b = h * a / i, v = Math.sin(d), y = Math.cos(d), m = -v, f = y, g = -y, w = -v, x = -e * b * l, E = t * u * l;
76
76
  return {
77
- x: b * x + y * E,
78
- y: g * x + P * E,
77
+ x: m * x + g * E,
78
+ y: f * x + w * E,
79
79
  z: 0
80
80
  };
81
81
  }
82
- function bt(n, e) {
82
+ function Ct(n, e) {
83
83
  return !Number.isFinite(n.x) || !Number.isFinite(n.y) || !Number.isFinite(n.z) || !Number.isFinite(e.x) || !Number.isFinite(e.y) || !Number.isFinite(e.z) ? { x: 0, y: 0, z: 0 } : {
84
84
  x: n.x - e.x,
85
85
  y: n.y - e.y,
86
86
  z: 0
87
87
  };
88
88
  }
89
- function gt(n, e, t) {
89
+ function Pt(n, e, t) {
90
90
  if (!Number.isFinite(n.x) || !Number.isFinite(n.y) || !Number.isFinite(n.z))
91
91
  return { x: 0, y: 0, z: 0 };
92
- const i = bt(e, t);
92
+ const i = Ct(e, t);
93
93
  return {
94
94
  x: n.x + i.x,
95
95
  y: n.y + i.y,
96
96
  z: n.z
97
97
  };
98
98
  }
99
- const yt = 0.35, L = 1, xt = 1, wt = 170;
100
- function N(n, e, t) {
99
+ const St = 0.35, A = 1, Et = 1, It = 170;
100
+ function V(n, e, t) {
101
101
  return Math.max(e, Math.min(t, n));
102
102
  }
103
- function M(n, e, t, i) {
103
+ function k(n, e, t, i) {
104
104
  const r = Number.isFinite(n) ? n : e;
105
- return N(r, t, i);
105
+ return V(r, t, i);
106
106
  }
107
- function Me(n) {
108
- return Number.isFinite(n) ? N(n, 0.1, 0.95) : yt;
107
+ function De(n) {
108
+ return Number.isFinite(n) ? V(n, 0.1, 0.95) : St;
109
109
  }
110
- function Ct(n, e) {
110
+ function Rt(n, e) {
111
111
  return !Number.isFinite(n) || !Number.isFinite(e) || n <= 0 || e <= 0 ? 1 : n / e;
112
112
  }
113
- function ke(n) {
114
- const e = M(n, 50, xt, wt), t = Math.tan(e * Math.PI / 360);
113
+ function Ae(n) {
114
+ const e = k(n, 50, Et, It), t = Math.tan(e * Math.PI / 360);
115
115
  return Math.max(t, 1e-4);
116
116
  }
117
- function Pt(n) {
117
+ function kt(n) {
118
118
  return Number.isFinite(n) ? Math.max(0.2, Math.abs(Math.sin(n))) : 0.2;
119
119
  }
120
- function St(n) {
120
+ function Mt(n) {
121
121
  return Number.isFinite(n) ? {
122
122
  sinAbs: Math.max(1e-4, Math.abs(Math.sin(n))),
123
123
  cosAbs: Math.abs(Math.cos(n))
@@ -126,94 +126,94 @@ function St(n) {
126
126
  cosAbs: Math.sqrt(1 - 0.2 * 0.2)
127
127
  };
128
128
  }
129
- function Te(n, e, t) {
130
- const i = Math.max(1e-4, 2 * n * e / Pt(t)), { sinAbs: r, cosAbs: s } = St(t), o = n * e, c = r * r - o * o * s * s;
131
- if (!Number.isFinite(c) || c <= 1e-4)
129
+ function Le(n, e, t) {
130
+ const i = Math.max(1e-4, 2 * n * e / kt(t)), { sinAbs: r, cosAbs: s } = Mt(t), o = n * e, a = r * r - o * o * s * s;
131
+ if (!Number.isFinite(a) || a <= 1e-4)
132
132
  return i;
133
- const l = 2 * o * r / c;
134
- return !Number.isFinite(l) || l <= 1e-4 ? i : l;
133
+ const d = 2 * o * r / a;
134
+ return !Number.isFinite(d) || d <= 1e-4 ? i : d;
135
135
  }
136
- function Rt(n) {
137
- const e = Me(n.ndcBand), t = n.useFixedOrientation ? n.fixedOrbitYaw : n.orbitYaw, i = n.useFixedOrientation ? n.fixedOrbitPitch : n.orbitPitch, r = Math.max(M(n.orthoFrustumSize, L, L, Number.MAX_VALUE), L), s = ke(n.perspectiveFovDeg), o = Te(e, s, i), c = M(n.orbitDistanceMin, 500, 1, Number.MAX_VALUE), l = Math.max(c, M(n.orbitDistanceMax, 2e5, c, Number.MAX_VALUE)), d = N(r / o, c, l);
136
+ function Tt(n) {
137
+ const e = De(n.ndcBand), t = n.useFixedOrientation ? n.fixedOrbitYaw : n.orbitYaw, i = n.useFixedOrientation ? n.fixedOrbitPitch : n.orbitPitch, r = Math.max(k(n.orthoFrustumSize, A, A, Number.MAX_VALUE), A), s = Ae(n.perspectiveFovDeg), o = Le(e, s, i), a = k(n.orbitDistanceMin, 500, 1, Number.MAX_VALUE), d = Math.max(a, k(n.orbitDistanceMax, 2e5, a, Number.MAX_VALUE)), l = V(r / o, a, d);
138
138
  return {
139
139
  orbitTarget: { x: n.orthoCenterX, y: n.orthoCenterY, z: 0 },
140
- orbitDistance: d,
140
+ orbitDistance: l,
141
141
  orbitYaw: t,
142
142
  orbitPitch: i
143
143
  };
144
144
  }
145
- function Et(n) {
146
- const e = Ct(n.viewportWidthPx, n.viewportHeightPx), t = Me(n.ndcBand), i = ke(n.perspectiveFovDeg), r = Te(t, i, n.orbitPitch), s = M(n.orthoFrustumMin, 1e3, L, Number.MAX_VALUE), o = Math.max(s, M(n.orthoFrustumMax, 1e5, s, Number.MAX_VALUE)), c = Math.max(M(n.orbitDistance, s, s, Number.MAX_VALUE), L), l = c * r, d = Number.isFinite(l) && l >= L ? l : N(c / Math.max(0.5, Math.min(2, e)), s, o);
145
+ function Dt(n) {
146
+ const e = Rt(n.viewportWidthPx, n.viewportHeightPx), t = De(n.ndcBand), i = Ae(n.perspectiveFovDeg), r = Le(t, i, n.orbitPitch), s = k(n.orthoFrustumMin, 1e3, A, Number.MAX_VALUE), o = Math.max(s, k(n.orthoFrustumMax, 1e5, s, Number.MAX_VALUE)), a = Math.max(k(n.orbitDistance, s, s, Number.MAX_VALUE), A), d = a * r, l = Number.isFinite(d) && d >= A ? d : V(a / Math.max(0.5, Math.min(2, e)), s, o);
147
147
  return {
148
148
  orthoCenterX: n.orbitTarget.x,
149
149
  orthoCenterY: n.orbitTarget.y,
150
- orthoFrustumSize: N(d, s, o)
150
+ orthoFrustumSize: V(l, s, o)
151
151
  };
152
152
  }
153
- function It(n) {
154
- const e = Math.max(n.xmax - n.xmin, n.ymax - n.ymin, 1), t = Math.max(1e-4, Math.tan(n.fovDeg * Math.PI / 360)), i = Math.max(1e-4, Math.abs(Math.sin(n.orbitPitchRad))), r = Math.abs(Math.cos(n.orbitPitchRad)), s = n.ndcBand * t, o = i * i - s * s * r * r, c = Math.max(
153
+ function At(n) {
154
+ const e = Math.max(n.xmax - n.xmin, n.ymax - n.ymin, 1), t = Math.max(1e-4, Math.tan(n.fovDeg * Math.PI / 360)), i = Math.max(1e-4, Math.abs(Math.sin(n.orbitPitchRad))), r = Math.abs(Math.cos(n.orbitPitchRad)), s = n.ndcBand * t, o = i * i - s * s * r * r, a = Math.max(
155
155
  1e-4,
156
156
  2 * n.ndcBand * t / Math.max(0.2, i)
157
- ), l = Number.isFinite(o) && o > 1e-4 ? Math.max(1e-4, 2 * s * i / o) : c;
158
- return e / l;
157
+ ), d = Number.isFinite(o) && o > 1e-4 ? Math.max(1e-4, 2 * s * i / o) : a;
158
+ return e / d;
159
159
  }
160
- function Mt(n, e, t, i = 40) {
160
+ function Lt(n, e, t, i = 40) {
161
161
  return e === 1 ? n * i : e === 2 ? n * t : n;
162
162
  }
163
- function kt(n) {
164
- const { valuePx: e, ctrlKey: t, eventTimeMs: i, state: r, resetMs: s } = n, o = Math.abs(e), c = r.lastEventTimeMs === 0 ? 0 : i - r.lastEventTimeMs;
165
- let l = r.type;
163
+ function Ft(n) {
164
+ const { valuePx: e, ctrlKey: t, eventTimeMs: i, state: r, resetMs: s } = n, o = Math.abs(e), a = r.lastEventTimeMs === 0 ? 0 : i - r.lastEventTimeMs;
165
+ let d = r.type;
166
166
  if (t)
167
- l = "trackpad";
167
+ d = "trackpad";
168
168
  else if (o > 0 && o < 4)
169
- l = "trackpad";
170
- else if (r.lastEventTimeMs === 0 || c > s)
171
- l = "wheel";
172
- else if (!l) {
173
- const d = Math.abs(e - r.lastValue);
174
- l = o >= 4 && d <= 4 ? "wheel" : "trackpad";
169
+ d = "trackpad";
170
+ else if (r.lastEventTimeMs === 0 || a > s)
171
+ d = "wheel";
172
+ else if (!d) {
173
+ const l = Math.abs(e - r.lastValue);
174
+ d = o >= 4 && l <= 4 ? "wheel" : "trackpad";
175
175
  }
176
176
  return {
177
177
  lastEventTimeMs: i,
178
178
  lastValue: e,
179
- type: l
179
+ type: d
180
180
  };
181
181
  }
182
- function Tt(n, e, t) {
182
+ function Ot(n, e, t) {
183
183
  if (!Number.isFinite(n) || n === 0) return 1;
184
184
  const i = e === "wheel" ? t.wheelZoomRate : t.trackpadZoomRate;
185
185
  if (e === "wheel") {
186
- const o = Math.log(t.maxScalePerFrame), c = Math.max(-o, Math.min(o, n * i));
187
- return Math.exp(c);
186
+ const o = Math.log(t.maxScalePerFrame), a = Math.max(-o, Math.min(o, n * i));
187
+ return Math.exp(a);
188
188
  }
189
189
  let r = t.maxScalePerFrame / (1 + Math.exp(-Math.abs(n * i)));
190
190
  n < 0 && r !== 0 && (r = 1 / r);
191
191
  const s = 1 / t.maxScalePerFrame;
192
192
  return Math.max(s, Math.min(t.maxScalePerFrame, r));
193
193
  }
194
- const $ = 500, ne = 2e5, j = 0.95, se = -Math.PI / 2, oe = R.degToRad(55);
195
- function k(n, e, t = 1e-4) {
194
+ const K = 500, ae = 2e5, q = 0.95, le = -Math.PI / 2, ce = I.degToRad(55);
195
+ function M(n, e, t = 1e-4) {
196
196
  return Math.abs(n - e) <= t;
197
197
  }
198
- class Dt {
198
+ class Nt {
199
199
  constructor() {
200
- a(this, "orbitTarget", new w(0, 0, 0));
201
- a(this, "orbitDistance", 14e3);
202
- a(this, "orbitYaw", se);
203
- a(this, "orbitPitch", oe);
204
- a(this, "viewportSnapshotBefore3D", null);
205
- a(this, "orbitSnapshotOn3DEntry", null);
206
- a(this, "dragMode", null);
207
- a(this, "dragPointerId", null);
208
- a(this, "dragPrevX", 0);
209
- a(this, "dragPrevY", 0);
210
- a(this, "groundPanAnchor", null);
211
- a(this, "wheelClassifier", {
200
+ c(this, "orbitTarget", new C(0, 0, 0));
201
+ c(this, "orbitDistance", 14e3);
202
+ c(this, "orbitYaw", le);
203
+ c(this, "orbitPitch", ce);
204
+ c(this, "viewportSnapshotBefore3D", null);
205
+ c(this, "orbitSnapshotOn3DEntry", null);
206
+ c(this, "dragMode", null);
207
+ c(this, "dragPointerId", null);
208
+ c(this, "dragPrevX", 0);
209
+ c(this, "dragPrevY", 0);
210
+ c(this, "groundPanAnchor", null);
211
+ c(this, "wheelClassifier", {
212
212
  lastEventTimeMs: 0,
213
213
  lastValue: 0,
214
214
  type: null
215
215
  });
216
- a(this, "runtime", null);
216
+ c(this, "runtime", null);
217
217
  }
218
218
  attach(e) {
219
219
  this.runtime = e, e.controls3d.enabled = !1, this.bindInput(e), this.syncPerspectiveCamera();
@@ -238,18 +238,18 @@ class Dt {
238
238
  fit3D(e) {
239
239
  const t = this.runtime;
240
240
  if (!t) return;
241
- const i = e.getSize(new w()), r = e.getCenter(new w());
241
+ const i = e.getSize(new C()), r = e.getCenter(new C());
242
242
  this.orbitTarget.set(r.x, r.y, 0);
243
- const s = It({
243
+ const s = At({
244
244
  xmin: e.min.x,
245
245
  ymin: e.min.y,
246
246
  xmax: e.max.x,
247
247
  ymax: e.max.y,
248
248
  fovDeg: t.camera3d.fov,
249
249
  orbitPitchRad: this.orbitPitch,
250
- ndcBand: j
251
- }), o = t.camera3d.fov * Math.PI / 180, c = Math.max(i.length() / 2, 1e-6) / Math.max(Math.sin(o / 2), 1e-6) * 1.05;
252
- this.orbitDistance = this.clampDistance(Math.max(s, c)), this.syncPerspectiveCamera();
250
+ ndcBand: q
251
+ }), o = t.camera3d.fov * Math.PI / 180, a = Math.max(i.length() / 2, 1e-6) / Math.max(Math.sin(o / 2), 1e-6) * 1.05;
252
+ this.orbitDistance = this.clampDistance(Math.max(s, a)), this.syncPerspectiveCamera();
253
253
  }
254
254
  getVisibleDocumentRect() {
255
255
  const e = this.runtime;
@@ -276,18 +276,18 @@ class Dt {
276
276
  };
277
277
  }
278
278
  applyOrbitSnapshot(e) {
279
- this.runtime && (this.orbitTarget.set(e.targetX, e.targetY, e.targetZ), this.orbitDistance = this.clampDistance(e.distance), this.orbitYaw = e.yaw, this.orbitPitch = R.clamp(e.pitch, R.degToRad(5), R.degToRad(85)), this.syncPerspectiveCamera({ sync2D: !1 }));
279
+ this.runtime && (this.orbitTarget.set(e.targetX, e.targetY, e.targetZ), this.orbitDistance = this.clampDistance(e.distance), this.orbitYaw = e.yaw, this.orbitPitch = I.clamp(e.pitch, I.degToRad(5), I.degToRad(85)), this.syncPerspectiveCamera({ sync2D: !1 }));
280
280
  }
281
281
  bindInput(e) {
282
282
  const t = e.renderer.domElement;
283
283
  e.bindRuntimeEvent(t, "contextmenu", (r) => {
284
284
  e.viewMode === "3d" && r.preventDefault();
285
285
  }), e.bindRuntimeEvent(t, "pointerdown", (r) => {
286
- var c;
286
+ var a;
287
287
  const s = r;
288
288
  if (e.viewMode !== "3d") return;
289
289
  const o = s.button === 0 ? "pan" : s.button === 2 ? "rotate" : null;
290
- !o || this.dragPointerId !== null || ((c = s.preventDefault) == null || c.call(s), this.beginDrag(o, s.pointerId, s.clientX, s.clientY));
290
+ !o || this.dragPointerId !== null || ((a = s.preventDefault) == null || a.call(s), this.beginDrag(o, s.pointerId, s.clientX, s.clientY));
291
291
  });
292
292
  const i = typeof globalThis.window > "u" ? t : globalThis.window;
293
293
  e.bindRuntimeEvent(i, "pointermove", (r) => {
@@ -319,7 +319,7 @@ class Dt {
319
319
  if (this.dragMode === "pan") {
320
320
  const i = this.screenToGround(e.clientX, e.clientY);
321
321
  if (this.groundPanAnchor && i) {
322
- const r = gt(this.orbitTarget, this.groundPanAnchor, i);
322
+ const r = Pt(this.orbitTarget, this.groundPanAnchor, i);
323
323
  this.translateOrbit(r.x - this.orbitTarget.x, r.y - this.orbitTarget.y);
324
324
  } else
325
325
  this.panByScreenDelta(
@@ -335,31 +335,31 @@ class Dt {
335
335
  e.pointerId === this.dragPointerId && this.clearDrag();
336
336
  }
337
337
  handleWheel(e) {
338
- var d;
338
+ var l;
339
339
  const t = this.runtime;
340
340
  if (!t || t.viewMode !== "3d") return;
341
- (d = e.preventDefault) == null || d.call(e);
342
- const i = Math.max(1, t.canvasArea.clientHeight), r = Mt(e.deltaY, e.deltaMode, i);
343
- this.wheelClassifier = kt({
341
+ (l = e.preventDefault) == null || l.call(e);
342
+ const i = Math.max(1, t.canvasArea.clientHeight), r = Lt(e.deltaY, e.deltaMode, i);
343
+ this.wheelClassifier = Ft({
344
344
  valuePx: r,
345
345
  ctrlKey: e.ctrlKey,
346
346
  eventTimeMs: typeof performance > "u" ? Date.now() : performance.now(),
347
347
  state: this.wheelClassifier,
348
348
  resetMs: 400
349
349
  });
350
- const s = this.wheelClassifier.type ?? "trackpad", o = s === "wheel" ? Math.sign(r) * 100 : r, c = Tt(-o, s, {
350
+ const s = this.wheelClassifier.type ?? "trackpad", o = s === "wheel" ? Math.sign(r) * 100 : r, a = Ot(-o, s, {
351
351
  trackpadZoomRate: 1 / 700,
352
352
  wheelZoomRate: 1 / 3200,
353
353
  maxScalePerFrame: 2
354
354
  });
355
- if (!Number.isFinite(c) || c <= 0) return;
356
- const l = this.clampDistance(this.orbitDistance / c);
357
- l !== this.orbitDistance && (this.orbitDistance = l, this.syncPerspectiveCamera());
355
+ if (!Number.isFinite(a) || a <= 0) return;
356
+ const d = this.clampDistance(this.orbitDistance / a);
357
+ d !== this.orbitDistance && (this.orbitDistance = d, this.syncPerspectiveCamera());
358
358
  }
359
359
  panByScreenDelta(e, t) {
360
360
  const i = this.runtime;
361
361
  if (!i) return;
362
- const r = ft({
362
+ const r = wt({
363
363
  dxPx: e,
364
364
  dyPx: t,
365
365
  viewportWidthPx: Math.max(1, i.canvasArea.clientWidth),
@@ -373,10 +373,10 @@ class Dt {
373
373
  this.translateOrbit(r.x, r.y);
374
374
  }
375
375
  rotateByScreenDelta(e, t) {
376
- const i = this.orbitYaw - e * 5e-3, r = R.clamp(
376
+ const i = this.orbitYaw - e * 5e-3, r = I.clamp(
377
377
  this.orbitPitch + t * 5e-3,
378
- R.degToRad(5),
379
- R.degToRad(85)
378
+ I.degToRad(5),
379
+ I.degToRad(85)
380
380
  );
381
381
  i === this.orbitYaw && r === this.orbitPitch || (this.orbitYaw = i, this.orbitPitch = r, this.syncPerspectiveCamera());
382
382
  }
@@ -388,31 +388,31 @@ class Dt {
388
388
  return i ? i.screenToWorldOnPlane(e, t, 0) : null;
389
389
  }
390
390
  syncOrbitFrom2D(e) {
391
- var c, l;
391
+ var a, d;
392
392
  const t = this.runtime;
393
393
  if (!t) return;
394
- const i = t.camera2d, r = i.zoom > 0 ? i.zoom : 1, s = Math.max((i.top - i.bottom) / r, 1), o = Rt({
395
- orthoCenterX: ((c = t.controls2d.target) == null ? void 0 : c.x) ?? i.position.x,
396
- orthoCenterY: ((l = t.controls2d.target) == null ? void 0 : l.y) ?? i.position.y,
394
+ const i = t.camera2d, r = i.zoom > 0 ? i.zoom : 1, s = Math.max((i.top - i.bottom) / r, 1), o = Tt({
395
+ orthoCenterX: ((a = t.controls2d.target) == null ? void 0 : a.x) ?? i.position.x,
396
+ orthoCenterY: ((d = t.controls2d.target) == null ? void 0 : d.y) ?? i.position.y,
397
397
  orthoFrustumSize: s,
398
398
  viewportWidthPx: Math.max(1, t.canvasArea.clientWidth),
399
399
  viewportHeightPx: Math.max(1, t.canvasArea.clientHeight),
400
400
  perspectiveFovDeg: t.camera3d.fov,
401
401
  orbitYaw: this.orbitYaw,
402
402
  orbitPitch: this.orbitPitch,
403
- orbitDistanceMin: $,
404
- orbitDistanceMax: ne,
403
+ orbitDistanceMin: K,
404
+ orbitDistanceMax: ae,
405
405
  useFixedOrientation: e,
406
- fixedOrbitYaw: se,
407
- fixedOrbitPitch: oe,
408
- ndcBand: j
406
+ fixedOrbitYaw: le,
407
+ fixedOrbitPitch: ce,
408
+ ndcBand: q
409
409
  });
410
410
  this.orbitTarget.set(o.orbitTarget.x, o.orbitTarget.y, o.orbitTarget.z), this.orbitDistance = this.clampDistance(o.orbitDistance), this.orbitYaw = o.orbitYaw, this.orbitPitch = o.orbitPitch;
411
411
  }
412
412
  sync2DFromOrbit() {
413
413
  const e = this.runtime;
414
414
  if (!e) return;
415
- const t = e.camera2d, i = Math.max(1, e.canvasArea.clientWidth), r = Math.max(1, e.canvasArea.clientHeight), s = i / r, o = t.top - t.bottom, c = o > 0 ? o : 2, l = e.controls2d.minZoom > 0 ? e.controls2d.minZoom : 2e-3, d = Math.max(l, e.controls2d.maxZoom > 0 ? e.controls2d.maxZoom : 5e4), h = Math.max(1, c / d), u = Math.max(h, c / l), v = Et({
415
+ const t = e.camera2d, i = Math.max(1, e.canvasArea.clientWidth), r = Math.max(1, e.canvasArea.clientHeight), s = i / r, o = t.top - t.bottom, a = o > 0 ? o : 2, d = e.controls2d.minZoom > 0 ? e.controls2d.minZoom : 2e-3, l = Math.max(d, e.controls2d.maxZoom > 0 ? e.controls2d.maxZoom : 5e4), h = Math.max(1, a / l), u = Math.max(h, a / d), p = Dt({
416
416
  orbitTarget: { x: this.orbitTarget.x, y: this.orbitTarget.y, z: this.orbitTarget.z },
417
417
  orbitDistance: this.orbitDistance,
418
418
  orbitYaw: this.orbitYaw,
@@ -422,24 +422,24 @@ class Dt {
422
422
  viewportHeightPx: r,
423
423
  orthoFrustumMin: h,
424
424
  orthoFrustumMax: u,
425
- ndcBand: j
426
- }), f = v.orthoFrustumSize > 0 ? v.orthoFrustumSize : c, p = c / 2;
425
+ ndcBand: q
426
+ }), b = p.orthoFrustumSize > 0 ? p.orthoFrustumSize : a, v = a / 2;
427
427
  e.setOrthographicViewport({
428
- left: -p * s,
429
- right: p * s,
430
- top: p,
431
- bottom: -p,
432
- zoom: R.clamp(c / f, l, d),
433
- positionX: v.orthoCenterX,
434
- positionY: v.orthoCenterY,
435
- targetX: v.orthoCenterX,
436
- targetY: v.orthoCenterY
428
+ left: -v * s,
429
+ right: v * s,
430
+ top: v,
431
+ bottom: -v,
432
+ zoom: I.clamp(a / b, d, l),
433
+ positionX: p.orthoCenterX,
434
+ positionY: p.orthoCenterY,
435
+ targetX: p.orthoCenterX,
436
+ targetY: p.orthoCenterY
437
437
  });
438
438
  }
439
439
  syncPerspectiveCamera(e = {}) {
440
440
  const t = this.runtime;
441
441
  if (!t) return;
442
- const i = Math.cos(this.orbitPitch), r = new w(
442
+ const i = Math.cos(this.orbitPitch), r = new C(
443
443
  this.orbitTarget.x + this.orbitDistance * Math.cos(this.orbitYaw) * i,
444
444
  this.orbitTarget.y + this.orbitDistance * Math.sin(this.orbitYaw) * i,
445
445
  this.orbitTarget.z + this.orbitDistance * Math.sin(this.orbitPitch)
@@ -464,7 +464,7 @@ class Dt {
464
464
  }
465
465
  isOrbitUnchangedFrom3DEntry() {
466
466
  const e = this.orbitSnapshotOn3DEntry;
467
- return e ? k(this.orbitTarget.x, e.targetX) && k(this.orbitTarget.y, e.targetY) && k(this.orbitTarget.z, e.targetZ) && k(this.orbitDistance, e.distance) && k(this.orbitYaw, e.yaw) && k(this.orbitPitch, e.pitch) : !1;
467
+ return e ? M(this.orbitTarget.x, e.targetX) && M(this.orbitTarget.y, e.targetY) && M(this.orbitTarget.z, e.targetZ) && M(this.orbitDistance, e.distance) && M(this.orbitYaw, e.yaw) && M(this.orbitPitch, e.pitch) : !1;
468
468
  }
469
469
  getPerspectiveDocumentRect() {
470
470
  const e = this.runtime;
@@ -472,12 +472,12 @@ class Dt {
472
472
  const t = [];
473
473
  for (const i of [-1, 1])
474
474
  for (const r of [-1, 1]) {
475
- const s = new w(i, r, -1).unproject(e.camera3d), c = new w(i, r, 1).unproject(e.camera3d).sub(s).normalize();
476
- if (Math.abs(c.z) < 1e-8) continue;
477
- const l = (0 - s.z) / c.z;
478
- !Number.isFinite(l) || l < 0 || t.push({
479
- x: s.x + c.x * l,
480
- y: s.y + c.y * l
475
+ const s = new C(i, r, -1).unproject(e.camera3d), a = new C(i, r, 1).unproject(e.camera3d).sub(s).normalize();
476
+ if (Math.abs(a.z) < 1e-8) continue;
477
+ const d = (0 - s.z) / a.z;
478
+ !Number.isFinite(d) || d < 0 || t.push({
479
+ x: s.x + a.x * d,
480
+ y: s.y + a.y * d
481
481
  });
482
482
  }
483
483
  if (t.length === 0) {
@@ -497,10 +497,10 @@ class Dt {
497
497
  };
498
498
  }
499
499
  clampDistance(e) {
500
- return R.clamp(
501
- Number.isFinite(e) ? e : $,
502
- $,
503
- ne
500
+ return I.clamp(
501
+ Number.isFinite(e) ? e : K,
502
+ K,
503
+ ae
504
504
  );
505
505
  }
506
506
  clearDrag(e = {}) {
@@ -515,77 +515,77 @@ class Dt {
515
515
  }
516
516
  }
517
517
  }
518
- const Lt = 1e3, At = -1e4, Ft = 1e4, ae = 1e3, Nt = 2e6, Ot = 1.15, Vt = 1.1, le = new We(Math.PI / 2, 0, Math.PI * 0.98 * 0.8);
519
- class Bt {
518
+ const Vt = 1e3, Bt = -1e4, zt = 1e4, de = 1e3, Ht = 2e6, _t = 1.15, Yt = 1.1, he = new Ze(Math.PI / 2, 0, Math.PI * 0.98 * 0.8);
519
+ class Xt {
520
520
  constructor(e) {
521
- a(this, "canvasArea");
522
- a(this, "canvas");
523
- a(this, "scene", new ee());
524
- a(this, "overlayRoot", new Ie());
525
- a(this, "renderer");
526
- a(this, "camera2d");
527
- a(this, "camera3d");
528
- a(this, "activeCamera");
529
- a(this, "controls2d");
530
- a(this, "controls3d");
531
- a(this, "options");
532
- a(this, "mountedObjects", /* @__PURE__ */ new Set());
533
- a(this, "ownedObjects", /* @__PURE__ */ new Set());
534
- a(this, "overlays", /* @__PURE__ */ new Map());
535
- a(this, "eventCleanups", []);
536
- a(this, "raycaster", new Xe());
537
- a(this, "pointerNdc", new q());
538
- a(this, "viewModeValue");
539
- a(this, "initialized", !1);
540
- a(this, "disposed", !1);
541
- a(this, "renderRequested", !0);
542
- a(this, "animationFrameId", null);
543
- a(this, "animationLoopActive", !1);
544
- a(this, "lastFrameTime", null);
545
- a(this, "infoFrames", 0);
546
- a(this, "infoLastTime", 0);
547
- a(this, "fpsCurrent", 0);
548
- a(this, "viewerOrbit", null);
549
- a(this, "previewScene", null);
550
- a(this, "previewCamera", null);
551
- a(this, "previewRenderTarget", null);
552
- a(this, "previewRenderTargetSize", { width: 0, height: 0 });
553
- a(this, "previewPixelBuffer", null);
554
- a(this, "previewImageDataBuffer", null);
555
- a(this, "environmentResource", null);
556
- a(this, "environmentLoadGeneration", 0);
521
+ c(this, "canvasArea");
522
+ c(this, "canvas");
523
+ c(this, "scene", new ie());
524
+ c(this, "overlayRoot", new Te());
525
+ c(this, "renderer");
526
+ c(this, "camera2d");
527
+ c(this, "camera3d");
528
+ c(this, "activeCamera");
529
+ c(this, "controls2d");
530
+ c(this, "controls3d");
531
+ c(this, "options");
532
+ c(this, "mountedObjects", /* @__PURE__ */ new Set());
533
+ c(this, "ownedObjects", /* @__PURE__ */ new Set());
534
+ c(this, "overlays", /* @__PURE__ */ new Map());
535
+ c(this, "eventCleanups", []);
536
+ c(this, "raycaster", new je());
537
+ c(this, "pointerNdc", new U());
538
+ c(this, "viewModeValue");
539
+ c(this, "initialized", !1);
540
+ c(this, "disposed", !1);
541
+ c(this, "renderRequested", !0);
542
+ c(this, "animationFrameId", null);
543
+ c(this, "animationLoopActive", !1);
544
+ c(this, "lastFrameTime", null);
545
+ c(this, "infoFrames", 0);
546
+ c(this, "infoLastTime", 0);
547
+ c(this, "fpsCurrent", 0);
548
+ c(this, "viewerOrbit", null);
549
+ c(this, "previewScene", null);
550
+ c(this, "previewCamera", null);
551
+ c(this, "previewRenderTarget", null);
552
+ c(this, "previewRenderTargetSize", { width: 0, height: 0 });
553
+ c(this, "previewPixelBuffer", null);
554
+ c(this, "previewImageDataBuffer", null);
555
+ c(this, "environmentResource", null);
556
+ c(this, "environmentLoadGeneration", 0);
557
557
  this.options = e, this.canvasArea = e.canvasArea, this.canvas = e.canvas, this.viewModeValue = e.initialViewMode ?? "2d", this.overlayRoot.name = "scene-runtime:overlays", this.scene.add(this.overlayRoot);
558
558
  }
559
559
  initialize() {
560
560
  if (this.disposed) throw new Error("SceneRuntime has been disposed.");
561
561
  if (this.initialized) return;
562
- const e = this.options.factories, t = (e == null ? void 0 : e.createRenderer) ?? ((l) => new _e(l)), i = (e == null ? void 0 : e.createMapControls) ?? ((l, d) => new lt(l, d)), r = (e == null ? void 0 : e.createOrbitControls) ?? ((l, d) => new ct(l, d));
562
+ const e = this.options.factories, t = (e == null ? void 0 : e.createRenderer) ?? ((d) => new We(d)), i = (e == null ? void 0 : e.createMapControls) ?? ((d, l) => new mt(d, l)), r = (e == null ? void 0 : e.createOrbitControls) ?? ((d, l) => new vt(d, l));
563
563
  this.renderer = t({
564
564
  canvas: this.canvas,
565
565
  antialias: this.options.antialias ?? !0,
566
566
  alpha: this.options.alpha ?? !1,
567
567
  powerPreference: this.options.powerPreference ?? "high-performance"
568
- }), this.options.clearColor !== void 0 && this.renderer.setClearColor(new qe(this.options.clearColor));
569
- const s = Math.max(1, this.canvasArea.clientWidth || 1), o = Math.max(1, this.canvasArea.clientHeight || 1), c = s / o;
568
+ }), this.options.clearColor !== void 0 && this.renderer.setClearColor(new Ge(this.options.clearColor));
569
+ const s = Math.max(1, this.canvasArea.clientWidth || 1), o = Math.max(1, this.canvasArea.clientHeight || 1), a = s / o;
570
570
  if (this.renderer.setPixelRatio(this.readDevicePixelRatio()), this.renderer.setSize(s, o, !1), this.options.environment) {
571
- const l = (e == null ? void 0 : e.createEnvironment) ?? zt;
572
- this.scene.environmentIntensity = Vt, this.scene.environmentRotation.copy(le), this.scene.backgroundRotation.copy(le);
573
- const d = ++this.environmentLoadGeneration, h = l(this.renderer, this.options.environment);
574
- Ht(h) ? h.then(
575
- (u) => this.applyEnvironmentResource(u, d),
571
+ const d = (e == null ? void 0 : e.createEnvironment) ?? Ut;
572
+ this.scene.environmentIntensity = Yt, this.scene.environmentRotation.copy(he), this.scene.backgroundRotation.copy(he);
573
+ const l = ++this.environmentLoadGeneration, h = d(this.renderer, this.options.environment);
574
+ $t(h) ? h.then(
575
+ (u) => this.applyEnvironmentResource(u, l),
576
576
  (u) => {
577
- !this.disposed && d === this.environmentLoadGeneration && console.warn("Failed to load scene environment HDR.", u);
577
+ !this.disposed && l === this.environmentLoadGeneration && console.warn("Failed to load scene environment HDR.", u);
578
578
  }
579
- ) : this.applyEnvironmentResource(h, d);
579
+ ) : this.applyEnvironmentResource(h, l);
580
580
  }
581
- this.camera2d = new te(-c, c, 1, -1, At, Ft), this.camera2d.position.set(0, 0, 1), this.camera2d.lookAt(0, 0, 0), this.camera3d = new $e(40, c, ae, Nt), this.camera3d.up.set(0, 0, 1), this.camera3d.position.set(1e4, 0, 1e4), this.camera3d.lookAt(0, 0, 0), this.controls2d = i(this.camera2d, this.renderer.domElement), this.controls2d.enableRotate = !1, this.controls2d.screenSpacePanning = !0, this.controls2d.zoomToCursor = !0, this.controls2d.minZoom = 2e-3, this.controls2d.maxZoom = 5e4, this.controls2d.mouseButtons = {
582
- LEFT: W.PAN,
583
- MIDDLE: W.DOLLY,
584
- RIGHT: W.PAN
581
+ this.camera2d = new re(-a, a, 1, -1, Bt, zt), this.camera2d.position.set(0, 0, 1), this.camera2d.lookAt(0, 0, 0), this.camera3d = new Je(40, a, de, Ht), this.camera3d.up.set(0, 0, 1), this.camera3d.position.set(1e4, 0, 1e4), this.camera3d.lookAt(0, 0, 0), this.controls2d = i(this.camera2d, this.renderer.domElement), this.controls2d.enableRotate = !1, this.controls2d.screenSpacePanning = !0, this.controls2d.zoomToCursor = !0, this.controls2d.minZoom = 2e-3, this.controls2d.maxZoom = 5e4, this.controls2d.mouseButtons = {
582
+ LEFT: $.PAN,
583
+ MIDDLE: $.DOLLY,
584
+ RIGHT: $.PAN
585
585
  }, this.controls2d.touches = {
586
- ONE: ie.PAN,
587
- TWO: ie.DOLLY_PAN
588
- }, this.controls3d = r(this.camera3d, this.renderer.domElement), this.controls3d.enablePan = !1, this.listen(this.controls2d, "change", () => this.requestRender()), this.listen(this.controls3d, "change", () => this.requestRender()), this.options.navigationPolicy === "viewer" && (this.viewerOrbit = new Dt(), this.viewerOrbit.attach(this)), this.initialized = !0, this.setViewMode(this.viewModeValue);
586
+ ONE: ne.PAN,
587
+ TWO: ne.DOLLY_PAN
588
+ }, this.controls3d = r(this.camera3d, this.renderer.domElement), this.controls3d.enablePan = !1, this.listen(this.controls2d, "change", () => this.requestRender()), this.listen(this.controls3d, "change", () => this.requestRender()), this.options.navigationPolicy === "viewer" && (this.viewerOrbit = new Nt(), this.viewerOrbit.attach(this)), this.initialized = !0, this.setViewMode(this.viewModeValue);
589
589
  }
590
590
  get isInitialized() {
591
591
  return this.initialized;
@@ -642,7 +642,7 @@ class Bt {
642
642
  if (!this.mountedObjects.has(e) && e.parent !== this.scene) return !1;
643
643
  e.removeFromParent(), this.mountedObjects.delete(e);
644
644
  const i = this.ownedObjects.delete(e);
645
- return (t.dispose === !0 || t.dispose === void 0 && i) && re(e), this.requestRender(), !0;
645
+ return (t.dispose === !0 || t.dispose === void 0 && i) && oe(e), this.requestRender(), !0;
646
646
  }
647
647
  setObjectVisible(e, t) {
648
648
  e.visible !== t && (e.visible = t, this.requestRender());
@@ -652,7 +652,7 @@ class Bt {
652
652
  }
653
653
  removeOverlay(e, t = {}) {
654
654
  const i = this.overlays.get(e);
655
- return i ? (this.overlays.delete(e), i.object.removeFromParent(), (t.dispose === !0 || t.dispose === void 0 && i.owned) && re(i.object), this.requestRender(), i.object) : null;
655
+ return i ? (this.overlays.delete(e), i.object.removeFromParent(), (t.dispose === !0 || t.dispose === void 0 && i.owned) && oe(i.object), this.requestRender(), i.object) : null;
656
656
  }
657
657
  setHighlight(e, t = {}) {
658
658
  if (!e) {
@@ -675,20 +675,20 @@ class Bt {
675
675
  if (!this.camera2d || !this.camera3d) return !1;
676
676
  const i = this.resolveBox3(e);
677
677
  if (!i || i.isEmpty()) return !1;
678
- const r = i.getSize(new w()), s = i.getCenter(new w());
678
+ const r = i.getSize(new C()), s = i.getCenter(new C());
679
679
  if (![r.x, r.y, r.z, s.x, s.y, s.z].every(Number.isFinite)) return !1;
680
680
  const o = Math.max(1, t.padding ?? 1.05);
681
681
  if ((t.viewMode ?? this.viewModeValue) === "2d") {
682
- const l = Math.max(r.x, 1e-6) * o, d = Math.max(r.y, 1e-6) * o, h = Math.max(1, this.canvasArea.clientWidth), u = Math.max(1, this.canvasArea.clientHeight), v = h / u;
683
- let f = l / 2, p = d / 2;
684
- f / p < v ? f = p * v : p = f / v, this.camera2d.left = -f, this.camera2d.right = f, this.camera2d.top = p, this.camera2d.bottom = -p, this.camera2d.zoom = 1, this.camera2d.position.set(s.x, s.y, Math.max(s.z + 1, 1)), this.camera2d.updateProjectionMatrix(), this.controls2d.target.copy(s), this.controls2d.update();
682
+ const d = Math.max(r.x, 1e-6) * o, l = Math.max(r.y, 1e-6) * o, h = Math.max(1, this.canvasArea.clientWidth), u = Math.max(1, this.canvasArea.clientHeight), p = h / u;
683
+ let b = d / 2, v = l / 2;
684
+ b / v < p ? b = v * p : v = b / p, this.camera2d.left = -b, this.camera2d.right = b, this.camera2d.top = v, this.camera2d.bottom = -v, this.camera2d.zoom = 1, this.camera2d.position.set(s.x, s.y, Math.max(s.z + 1, 1)), this.camera2d.updateProjectionMatrix(), this.controls2d.target.copy(s), this.controls2d.update();
685
685
  } else if (this.viewerOrbit)
686
686
  this.viewerOrbit.fit3D(i);
687
687
  else {
688
- const l = s.clone(), d = this.camera3d.fov * Math.PI / 180, h = 2 * Math.atan(Math.tan(d / 2) * Math.max(this.camera3d.aspect, 1e-6)), u = Math.max(r.length() / 2, 1e-6), v = Math.max(Math.min(d, h) / 2, 1e-6), f = u / Math.sin(v) * o, p = this.camera3d.position.clone().sub(this.controls3d.target);
689
- p.lengthSq() <= 1e-12 && p.set(1, -1, 1), p.normalize(), this.controls3d.target.copy(l), this.camera3d.position.copy(l).addScaledVector(p, f), this.camera3d.lookAt(l), this.camera3d.near = Math.min(
690
- ae,
691
- Math.max(f * 0.01, 1e-6)
688
+ const d = s.clone(), l = this.camera3d.fov * Math.PI / 180, h = 2 * Math.atan(Math.tan(l / 2) * Math.max(this.camera3d.aspect, 1e-6)), u = Math.max(r.length() / 2, 1e-6), p = Math.max(Math.min(l, h) / 2, 1e-6), b = u / Math.sin(p) * o, v = this.camera3d.position.clone().sub(this.controls3d.target);
689
+ v.lengthSq() <= 1e-12 && v.set(1, -1, 1), v.normalize(), this.controls3d.target.copy(d), this.camera3d.position.copy(d).addScaledVector(v, b), this.camera3d.lookAt(d), this.camera3d.near = Math.min(
690
+ de,
691
+ Math.max(b * 0.01, 1e-6)
692
692
  ), this.camera3d.updateProjectionMatrix(), this.controls3d.update();
693
693
  }
694
694
  return this.requestRender(), !0;
@@ -751,36 +751,36 @@ class Bt {
751
751
  };
752
752
  }
753
753
  renderOrthographicPreview(e, t, i) {
754
- var J;
755
- if (!this.renderer || this.disposed || t.parent || !Yt(i)) return !1;
756
- const r = Math.max(1, Math.floor(e.clientWidth || e.width || 0)), s = Math.max(1, Math.floor(e.clientHeight || e.height || 0)), o = this.resolveRendererPixelRatio(), c = Math.min(2, o), l = Math.max(1, Math.floor(r * c)), d = Math.max(1, Math.floor(s * c)), h = l / o, u = d / o, v = Math.min(h, u), f = (i.minX + i.maxX) / 2, p = (i.minY + i.maxY) / 2, b = Math.max(i.maxX - i.minX, i.maxY - i.minY, 1) * Ot / 2, g = this.getOrCreatePreviewRenderTarget(l, d), y = this.getOrCreatePreviewCamera();
757
- y.left = -b, y.right = b, y.top = b, y.bottom = -b, y.position.set(f, p, 1), y.up.copy(((J = this.camera2d) == null ? void 0 : J.up) ?? new w(0, 1, 0)), y.lookAt(f, p, 0), y.updateProjectionMatrix(), y.updateMatrixWorld(!0);
758
- const P = this.getOrCreatePreviewScene(), x = this.renderer, E = x.getRenderTarget(), Oe = x.getClearAlpha(), Ve = x.autoClear, A = new je();
759
- x.getViewport(A);
760
- const Be = x.getScissorTest();
761
- P.add(t);
754
+ var ee;
755
+ if (!this.renderer || this.disposed || t.parent || !Kt(i)) return !1;
756
+ const r = Math.max(1, Math.floor(e.clientWidth || e.width || 0)), s = Math.max(1, Math.floor(e.clientHeight || e.height || 0)), o = this.resolveRendererPixelRatio(), a = Math.min(2, o), d = Math.max(1, Math.floor(r * a)), l = Math.max(1, Math.floor(s * a)), h = d / o, u = l / o, p = Math.min(h, u), b = (i.minX + i.maxX) / 2, v = (i.minY + i.maxY) / 2, m = Math.max(i.maxX - i.minX, i.maxY - i.minY, 1) * _t / 2, f = this.getOrCreatePreviewRenderTarget(d, l), g = this.getOrCreatePreviewCamera();
757
+ g.left = -m, g.right = m, g.top = m, g.bottom = -m, g.position.set(b, v, 1), g.up.copy(((ee = this.camera2d) == null ? void 0 : ee.up) ?? new C(0, 1, 0)), g.lookAt(b, v, 0), g.updateProjectionMatrix(), g.updateMatrixWorld(!0);
758
+ const w = this.getOrCreatePreviewScene(), x = this.renderer, E = x.getRenderTarget(), Ye = x.getClearAlpha(), Xe = x.autoClear, F = new Qe();
759
+ x.getViewport(F);
760
+ const Ue = x.getScissorTest();
761
+ w.add(t);
762
762
  try {
763
- x.setRenderTarget(g), x.setViewport(0, 0, h, u), x.setScissorTest(!1), x.setClearAlpha(0), x.autoClear = !1, x.clear(), x.setViewport(
764
- Math.floor((h - v) / 2),
765
- Math.floor((u - v) / 2),
766
- v,
767
- v
768
- ), x.render(P, y);
769
- const Q = this.getOrCreatePreviewPixelBuffer(l, d);
770
- return x.readRenderTargetPixels(g, 0, 0, l, d, Q), this.blitPreviewPixelsToCanvas(e, Q, l, d);
763
+ x.setRenderTarget(f), x.setViewport(0, 0, h, u), x.setScissorTest(!1), x.setClearAlpha(0), x.autoClear = !1, x.clear(), x.setViewport(
764
+ Math.floor((h - p) / 2),
765
+ Math.floor((u - p) / 2),
766
+ p,
767
+ p
768
+ ), x.render(w, g);
769
+ const te = this.getOrCreatePreviewPixelBuffer(d, l);
770
+ return x.readRenderTargetPixels(f, 0, 0, d, l, te), this.blitPreviewPixelsToCanvas(e, te, d, l);
771
771
  } finally {
772
- t.removeFromParent(), x.setRenderTarget(E), x.setClearAlpha(Oe), x.autoClear = Ve, x.setViewport(
773
- A.x,
774
- A.y,
775
- A.z,
776
- A.w
777
- ), x.setScissorTest(Be), this.requestRender();
772
+ t.removeFromParent(), x.setRenderTarget(E), x.setClearAlpha(Ye), x.autoClear = Xe, x.setViewport(
773
+ F.x,
774
+ F.y,
775
+ F.z,
776
+ F.w
777
+ ), x.setScissorTest(Ue), this.requestRender();
778
778
  }
779
779
  }
780
780
  bindRuntimeEvent(e, t, i, r) {
781
781
  this.listen(e, t, i, r);
782
782
  }
783
- clientToNdc(e, t, i = new q()) {
783
+ clientToNdc(e, t, i = new U()) {
784
784
  var o;
785
785
  const r = (o = this.renderer) == null ? void 0 : o.domElement;
786
786
  if (!r) return null;
@@ -792,9 +792,9 @@ class Bt {
792
792
  }
793
793
  screenToWorldOnPlane(e, t, i = 0) {
794
794
  const r = this.clientToNdc(e, t, this.pointerNdc);
795
- return !r || !this.activeCamera ? null : (this.raycaster.setFromCamera(r, this.activeCamera), this.raycaster.ray.intersectPlane(new Ue(new w(0, 0, 1), -i), new w()));
795
+ return !r || !this.activeCamera ? null : (this.raycaster.setFromCamera(r, this.activeCamera), this.raycaster.ray.intersectPlane(new et(new C(0, 0, 1), -i), new C()));
796
796
  }
797
- worldToClient(e, t = new q()) {
797
+ worldToClient(e, t = new U()) {
798
798
  var o;
799
799
  const i = (o = this.renderer) == null ? void 0 : o.domElement;
800
800
  if (!i || !this.activeCamera) return null;
@@ -811,36 +811,36 @@ class Bt {
811
811
  if (!r || !this.activeCamera) return null;
812
812
  const s = i.roots ?? [...this.mountedObjects], o = i.includeInvisible ? s : s.filter((h) => h.visible);
813
813
  this.raycaster.setFromCamera(r, this.activeCamera);
814
- const [c] = this.raycaster.intersectObjects([...o], i.recursive !== !1);
815
- if (!c) return null;
816
- const d = o.find((h) => h === c.object || this.isDescendantOf(c.object, h)) ?? c.object;
814
+ const [a] = this.raycaster.intersectObjects([...o], i.recursive !== !1);
815
+ if (!a) return null;
816
+ const l = o.find((h) => h === a.object || this.isDescendantOf(a.object, h)) ?? a.object;
817
817
  return {
818
- object: c.object,
819
- root: d,
820
- point: c.point.clone(),
821
- distance: c.distance,
822
- faceIndex: c.faceIndex ?? null,
823
- instanceId: c.instanceId,
824
- intersection: c
818
+ object: a.object,
819
+ root: l,
820
+ point: a.point.clone(),
821
+ distance: a.distance,
822
+ faceIndex: a.faceIndex ?? null,
823
+ instanceId: a.instanceId,
824
+ intersection: a
825
825
  };
826
826
  }
827
827
  startAnimation(e = {}) {
828
828
  if (this.disposed || this.animationLoopActive) return;
829
829
  this.animationLoopActive = !0, this.infoFrames = 0, this.infoLastTime = performance.now();
830
- const t = e.infoUpdateIntervalMs ?? Lt, i = (r = performance.now()) => {
831
- var c, l, d, h, u, v, f;
830
+ const t = e.infoUpdateIntervalMs ?? Vt, i = (r = performance.now()) => {
831
+ var a, d, l, h, u, p, b;
832
832
  if (!this.animationLoopActive || this.disposed) {
833
833
  this.animationFrameId = null;
834
834
  return;
835
835
  }
836
836
  this.animationFrameId = requestAnimationFrame(i);
837
837
  const s = this.lastFrameTime === null ? 0 : Math.max(0, (r - this.lastFrameTime) / 1e3);
838
- this.lastFrameTime = r, this.viewModeValue === "2d" && ((c = this.controls2d) == null || c.update()), (l = e.onFrame) == null || l.call(e, r, s);
838
+ this.lastFrameTime = r, this.viewModeValue === "2d" && ((a = this.controls2d) == null || a.update()), (d = e.onFrame) == null || d.call(e, r, s);
839
839
  let o = !1;
840
- if (this.renderRequested && (((d = e.shouldRender) == null ? void 0 : d.call(e, r)) ?? !0) && ((h = e.beforeRender) == null || h.call(e, r), this.renderer.render(this.scene, this.activeCamera), this.renderRequested = !1, o = !0, (u = e.afterRender) == null || u.call(e, r)), this.infoFrames += 1, r - this.infoLastTime >= t) {
841
- const p = Math.max(1, r - this.infoLastTime);
842
- this.fpsCurrent = this.infoFrames * 1e3 / p, this.infoFrames = 0, this.infoLastTime = r, (v = e.onInfoUpdate) == null || v.call(e);
843
- } else o && ((f = e.onInfoUpdate) == null || f.call(e));
840
+ if (this.renderRequested && (((l = e.shouldRender) == null ? void 0 : l.call(e, r)) ?? !0) && ((h = e.beforeRender) == null || h.call(e, r), this.renderer.render(this.scene, this.activeCamera), this.renderRequested = !1, o = !0, (u = e.afterRender) == null || u.call(e, r)), this.infoFrames += 1, r - this.infoLastTime >= t) {
841
+ const v = Math.max(1, r - this.infoLastTime);
842
+ this.fpsCurrent = this.infoFrames * 1e3 / v, this.infoFrames = 0, this.infoLastTime = r, (p = e.onInfoUpdate) == null || p.call(e);
843
+ } else o && ((b = e.onInfoUpdate) == null || b.call(e));
844
844
  };
845
845
  i();
846
846
  }
@@ -848,12 +848,12 @@ class Bt {
848
848
  this.animationLoopActive = !1, this.animationFrameId !== null && typeof cancelAnimationFrame == "function" && cancelAnimationFrame(this.animationFrameId), this.animationFrameId = null, this.lastFrameTime = null;
849
849
  }
850
850
  dispose() {
851
- var e, t, i, r, s, o, c, l, d;
851
+ var e, t, i, r, s, o, a, d, l;
852
852
  if (!this.disposed) {
853
853
  for (this.disposed = !0, this.stopAnimation(), (e = this.viewerOrbit) == null || e.dispose(), this.viewerOrbit = null; this.eventCleanups.length > 0; ) (t = this.eventCleanups.pop()) == null || t();
854
854
  for (const h of [...this.overlays.keys()]) this.removeOverlay(h);
855
855
  for (const h of [...this.mountedObjects]) this.removeObject(h);
856
- (r = (i = this.controls2d) == null ? void 0 : i.dispose) == null || r.call(i), (o = (s = this.controls3d) == null ? void 0 : s.dispose) == null || o.call(s), this.disposePreviewResources(), this.environmentLoadGeneration += 1, this.scene.environment = null, (c = this.environmentResource) == null || c.dispose(), this.environmentResource = null, (d = (l = this.renderer) == null ? void 0 : l.dispose) == null || d.call(l);
856
+ (r = (i = this.controls2d) == null ? void 0 : i.dispose) == null || r.call(i), (o = (s = this.controls3d) == null ? void 0 : s.dispose) == null || o.call(s), this.disposePreviewResources(), this.environmentLoadGeneration += 1, this.scene.environment = null, (a = this.environmentResource) == null || a.dispose(), this.environmentResource = null, (l = (d = this.renderer) == null ? void 0 : d.dispose) == null || l.call(d);
857
857
  }
858
858
  }
859
859
  applyEnvironmentResource(e, t) {
@@ -865,14 +865,14 @@ class Bt {
865
865
  (i = this.environmentResource) == null || i.dispose(), this.environmentResource = e, this.scene.environment = e.texture, this.requestRender();
866
866
  }
867
867
  getOrCreatePreviewScene() {
868
- return this.previewScene || (this.previewScene = new ee()), this.previewScene;
868
+ return this.previewScene || (this.previewScene = new ie()), this.previewScene;
869
869
  }
870
870
  getOrCreatePreviewCamera() {
871
- return this.previewCamera || (this.previewCamera = new te(-1, 1, 1, -1, -1e6, 1e6)), this.previewCamera;
871
+ return this.previewCamera || (this.previewCamera = new re(-1, 1, 1, -1, -1e6, 1e6)), this.previewCamera;
872
872
  }
873
873
  getOrCreatePreviewRenderTarget(e, t) {
874
874
  var i;
875
- return this.previewRenderTarget && this.previewRenderTargetSize.width === e && this.previewRenderTargetSize.height === t ? this.previewRenderTarget : ((i = this.previewRenderTarget) == null || i.dispose(), this.previewRenderTarget = new Ke(e, t), this.previewRenderTargetSize = { width: e, height: t }, this.previewRenderTarget);
875
+ return this.previewRenderTarget && this.previewRenderTargetSize.width === e && this.previewRenderTargetSize.height === t ? this.previewRenderTarget : ((i = this.previewRenderTarget) == null || i.dispose(), this.previewRenderTarget = new tt(e, t), this.previewRenderTargetSize = { width: e, height: t }, this.previewRenderTarget);
876
876
  }
877
877
  getOrCreatePreviewPixelBuffer(e, t) {
878
878
  const i = e * t * 4;
@@ -884,13 +884,13 @@ class Bt {
884
884
  if (!s) return !1;
885
885
  const o = i * r * 4;
886
886
  (!this.previewImageDataBuffer || this.previewImageDataBuffer.length !== o) && (this.previewImageDataBuffer = new Uint8ClampedArray(o));
887
- const c = this.previewImageDataBuffer, l = i * 4;
887
+ const a = this.previewImageDataBuffer, d = i * 4;
888
888
  for (let h = 0; h < r; h += 1) {
889
- const u = (r - 1 - h) * l;
890
- c.set(t.subarray(u, u + l), h * l);
889
+ const u = (r - 1 - h) * d;
890
+ a.set(t.subarray(u, u + d), h * d);
891
891
  }
892
- const d = s.createImageData(i, r);
893
- return d.data.set(c), s.putImageData(d, 0, 0), !0;
892
+ const l = s.createImageData(i, r);
893
+ return l.data.set(a), s.putImageData(l, 0, 0), !0;
894
894
  }
895
895
  resolveRendererPixelRatio() {
896
896
  const e = this.renderer.getPixelRatio();
@@ -905,10 +905,10 @@ class Bt {
905
905
  return typeof e == "number" && Number.isFinite(e) && e > 0 ? e : 1;
906
906
  }
907
907
  resolveBox3(e) {
908
- if (e instanceof S) return e.clone();
909
- if (e instanceof Ge) return new S().setFromObject(e);
908
+ if (e instanceof R) return e.clone();
909
+ if (e instanceof it) return new R().setFromObject(e);
910
910
  const { minX: t, minY: i, maxX: r, maxY: s } = e;
911
- return ![t, i, r, s].every(Number.isFinite) || r < t || s < i ? null : new S(new w(t, i, 0), new w(r, s, 0));
911
+ return ![t, i, r, s].every(Number.isFinite) || r < t || s < i ? null : new R(new C(t, i, 0), new C(r, s, 0));
912
912
  }
913
913
  isDescendantOf(e, t) {
914
914
  let i = e.parent;
@@ -925,9 +925,9 @@ class Bt {
925
925
  });
926
926
  }
927
927
  }
928
- function zt(n, e) {
928
+ function Ut(n, e) {
929
929
  if (e === "room") {
930
- const t = new Ze(n), i = new at(), r = t.fromScene(i);
930
+ const t = new rt(n), i = new pt(), r = t.fromScene(i);
931
931
  return i.dispose(), t.dispose(), {
932
932
  texture: r.texture,
933
933
  dispose: () => r.dispose()
@@ -935,23 +935,23 @@ function zt(n, e) {
935
935
  }
936
936
  if (e.type !== "hdr" || e.url.trim().length === 0)
937
937
  throw new Error("HDR scene environment requires a non-empty URL.");
938
- return new dt().loadAsync(e.url).then((t) => (t.mapping = Je, {
938
+ return new ft().loadAsync(e.url).then((t) => (t.mapping = nt, {
939
939
  texture: t,
940
940
  dispose: () => t.dispose()
941
941
  }));
942
942
  }
943
- function Ht(n) {
943
+ function $t(n) {
944
944
  return typeof (n == null ? void 0 : n.then) == "function";
945
945
  }
946
- function Yt(n) {
946
+ function Kt(n) {
947
947
  return Number.isFinite(n.minX) && Number.isFinite(n.minY) && Number.isFinite(n.maxX) && Number.isFinite(n.maxY) && n.maxX >= n.minX && n.maxY >= n.minY;
948
948
  }
949
949
  const Z = 1;
950
- function Xt() {
951
- return typeof globalThis.localStorage > "u" ? _t() : {
950
+ function qt() {
951
+ return typeof globalThis.localStorage > "u" ? jt() : {
952
952
  read(n) {
953
953
  try {
954
- const e = globalThis.localStorage.getItem(ce(n));
954
+ const e = globalThis.localStorage.getItem(ue(n));
955
955
  return e ? JSON.parse(e) : null;
956
956
  } catch {
957
957
  return null;
@@ -959,13 +959,13 @@ function Xt() {
959
959
  },
960
960
  write(n, e) {
961
961
  try {
962
- globalThis.localStorage.setItem(ce(n), JSON.stringify(e));
962
+ globalThis.localStorage.setItem(ue(n), JSON.stringify(e));
963
963
  } catch {
964
964
  }
965
965
  }
966
966
  };
967
967
  }
968
- function _t() {
968
+ function jt() {
969
969
  const n = /* @__PURE__ */ new Map();
970
970
  return {
971
971
  read(e) {
@@ -976,17 +976,46 @@ function _t() {
976
976
  }
977
977
  };
978
978
  }
979
- function qt(n, e) {
979
+ function Wt(n, e) {
980
980
  if (!n || !e) return null;
981
981
  const t = n.read(e);
982
- if (!t || typeof t != "object") return null;
983
- const i = t;
984
- return i.schemaVersion !== Z || i.viewMode !== "2d" && i.viewMode !== "3d" || i.viewMode === "2d" && !i.orthographic || i.viewMode === "3d" && !i.orbit ? null : i;
982
+ return Fe(t) ? t : null;
985
983
  }
986
- function Wt(n, e, t) {
984
+ function Fe(n) {
985
+ if (!n || typeof n != "object") return !1;
986
+ const e = n;
987
+ if (e.schemaVersion !== Z) return !1;
988
+ if (e.viewMode === "2d") {
989
+ const t = e.orthographic;
990
+ return !t || ![
991
+ t.left,
992
+ t.right,
993
+ t.top,
994
+ t.bottom,
995
+ t.zoom,
996
+ t.positionX,
997
+ t.positionY,
998
+ t.targetX,
999
+ t.targetY
1000
+ ].every(Number.isFinite) ? !1 : t.left < t.right && t.bottom < t.top && t.zoom > 0;
1001
+ }
1002
+ if (e.viewMode === "3d") {
1003
+ const t = e.orbit;
1004
+ return !t || ![
1005
+ t.targetX,
1006
+ t.targetY,
1007
+ t.targetZ,
1008
+ t.distance,
1009
+ t.yaw,
1010
+ t.pitch
1011
+ ].every(Number.isFinite) ? !1 : t.distance > 0;
1012
+ }
1013
+ return !1;
1014
+ }
1015
+ function Gt(n, e, t) {
987
1016
  !n || !e || n.write(e, t);
988
1017
  }
989
- function $t(n) {
1018
+ function Zt(n) {
990
1019
  return {
991
1020
  schemaVersion: Z,
992
1021
  viewMode: n.viewMode,
@@ -994,322 +1023,404 @@ function $t(n) {
994
1023
  ...n.orbit ? { orbit: n.orbit } : {}
995
1024
  };
996
1025
  }
997
- function ce(n) {
1026
+ function ue(n) {
998
1027
  return `nebula-viewer:camera:v${Z}:${n}`;
999
1028
  }
1000
- function V(n) {
1001
- return new S(
1002
- new w(n.minX, n.minY, n.minZ),
1003
- new w(n.maxX, n.maxY, n.maxZ)
1029
+ function O(n) {
1030
+ return new R(
1031
+ new C(n.minX, n.minY, n.minZ),
1032
+ new C(n.maxX, n.maxY, n.maxZ)
1004
1033
  );
1005
1034
  }
1006
- function De(n) {
1035
+ function Oe(n) {
1007
1036
  const [e, t, i] = n;
1008
1037
  return (e & 255) << 16 | (t & 255) << 8 | i & 255;
1009
1038
  }
1010
- class jt {
1039
+ class Jt {
1011
1040
  constructor() {
1012
- a(this, "rows", []);
1013
- a(this, "allColor", null);
1014
- a(this, "renderNode", null);
1015
- a(this, "onChange", () => {
1041
+ c(this, "rows", []);
1042
+ c(this, "allColor", null);
1043
+ c(this, "revision", 0);
1044
+ c(this, "renderNode", null);
1045
+ c(this, "onChange", () => {
1016
1046
  });
1017
- a(this, "visibilityRevision", 0);
1018
- }
1019
- bind(e, t) {
1020
- this.renderNode = e, this.onChange = t;
1021
- }
1022
- sync(e) {
1023
- const t = new Map(this.rows.map((i) => [i.index, i.color]));
1024
- this.rows = e.getLayers().map((i) => ({
1025
- index: i.index,
1026
- name: i.name,
1027
- visible: i.visible,
1028
- color: t.get(i.index) ?? this.allColor,
1029
- sourceColor: i.color
1030
- })), this.onChange();
1047
+ c(this, "assertActive", () => {
1048
+ });
1049
+ c(this, "visibilityRevision", 0);
1050
+ }
1051
+ bind(e, t, i) {
1052
+ this.renderNode = e, this.onChange = t, i && (this.assertActive = i);
1053
+ }
1054
+ sync(e, t = !0) {
1055
+ const i = new Map(this.rows.map((s) => [s.index, s.color])), r = e.getLayers().map((s) => ({
1056
+ index: s.index,
1057
+ name: s.name,
1058
+ visible: s.visible,
1059
+ color: i.has(s.index) ? i.get(s.index) : this.allColor,
1060
+ sourceColor: s.color
1061
+ }));
1062
+ ii(this.rows, r) || (this.rows = r, this.revision += 1, t && this.onChange());
1031
1063
  }
1032
- clear() {
1033
- this.rows = [], this.allColor = null, this.renderNode = null, this.onChange();
1064
+ clear(e = !0) {
1065
+ const t = this.rows.length > 0 || this.allColor !== null;
1066
+ return this.renderNode = null, t ? (this.rows = [], this.allColor = null, this.revision += 1, e && this.onChange(), !0) : !1;
1034
1067
  }
1035
1068
  getVisibilityRevision() {
1036
1069
  return this.visibilityRevision;
1037
1070
  }
1038
1071
  toggle(e) {
1039
- const t = this.rows.find((r) => r.index === e);
1040
- if (!t || !this.renderNode) return;
1041
- const i = !t.visible;
1042
- this.renderNode.setLayerVisible(e, i), t.visible = i, this.visibilityRevision += 1, this.onChange();
1072
+ this.assertActive();
1073
+ const t = this.rows.find((i) => i.index === e);
1074
+ !t || !this.renderNode || this.setVisible(e, !t.visible);
1043
1075
  }
1044
- showAll() {
1045
- if (this.renderNode) {
1046
- for (const e of this.rows)
1047
- e.visible || (this.renderNode.setLayerVisible(e.index, !0), e.visible = !0);
1048
- this.visibilityRevision += 1, this.onChange();
1076
+ setVisible(e, t) {
1077
+ this.assertActive();
1078
+ const i = this.rows.find((r) => r.index === e);
1079
+ return !i || !this.renderNode || i.visible === t ? !1 : (this.renderNode.setLayerVisible(e, t), i.visible = t, this.visibilityRevision += 1, this.revision += 1, this.onChange(), !0);
1080
+ }
1081
+ setVisibleBatch(e) {
1082
+ if (this.assertActive(), !this.renderNode || e.length === 0) return 0;
1083
+ const t = /* @__PURE__ */ new Map();
1084
+ for (const s of e)
1085
+ t.set(s.index, s.visible);
1086
+ const i = new Map(this.rows.map((s) => [s.index, s])), r = [];
1087
+ for (const [s, o] of t) {
1088
+ const a = i.get(s);
1089
+ a && a.visible !== o && r.push({ index: s, visible: o });
1049
1090
  }
1091
+ if (r.length === 0) return 0;
1092
+ this.renderNode.setLayerVisibleBatch(r.map(({ index: s, visible: o }) => ({
1093
+ layerIndex: s,
1094
+ visible: o
1095
+ })));
1096
+ for (const { index: s, visible: o } of r) i.get(s).visible = o;
1097
+ return this.visibilityRevision += 1, this.revision += 1, this.onChange(), r.length;
1098
+ }
1099
+ showAll() {
1100
+ this.setVisibleBatch(this.rows.map((e) => ({ index: e.index, visible: !0 })));
1050
1101
  }
1051
1102
  hideAll() {
1052
- if (this.renderNode) {
1053
- for (const e of this.rows)
1054
- e.visible && (this.renderNode.setLayerVisible(e.index, !1), e.visible = !1);
1055
- this.visibilityRevision += 1, this.onChange();
1056
- }
1103
+ this.setVisibleBatch(this.rows.map((e) => ({ index: e.index, visible: !1 })));
1057
1104
  }
1058
1105
  setColor(e, t) {
1059
- if (!this.renderNode) return;
1106
+ if (this.assertActive(), !this.renderNode) return;
1060
1107
  this.renderNode.setLayerColorOverride(e, t);
1061
1108
  const i = this.rows.find((r) => r.index === e);
1062
- i && (i.color = t);
1109
+ i && i.color !== t && (i.color = t, this.revision += 1, this.onChange());
1063
1110
  }
1064
1111
  setAllColor(e) {
1065
- if (this.renderNode) {
1066
- for (const t of this.rows)
1067
- this.renderNode.setLayerColorOverride(t.index, e), t.color = e;
1068
- this.allColor = e;
1069
- }
1112
+ if (this.assertActive(), !this.renderNode) return;
1113
+ let t = this.allColor !== e;
1114
+ for (const i of this.rows)
1115
+ this.renderNode.setLayerColorOverride(i.index, e), t || (t = i.color !== e), i.color = e;
1116
+ t && (this.allColor = e, this.revision += 1, this.onChange());
1070
1117
  }
1071
1118
  }
1072
- class Ut {
1119
+ class Qt {
1073
1120
  constructor() {
1074
- a(this, "usages", []);
1075
- a(this, "renderNode", null);
1076
- a(this, "onChange", () => {
1121
+ c(this, "usages", []);
1122
+ c(this, "revision", 0);
1123
+ c(this, "renderNode", null);
1124
+ c(this, "onChange", () => {
1077
1125
  });
1078
- a(this, "visibilityRevision", 0);
1079
- }
1080
- bind(e, t) {
1081
- this.renderNode = e, this.onChange = t;
1082
- }
1083
- sync(e) {
1084
- this.usages = e.listInsertUsages().map((t) => ({
1085
- insertId: t.insertId,
1086
- blockName: t.blockName,
1087
- layerName: t.layerName,
1088
- layerIndex: t.layerIndex,
1089
- variantId: t.variantId,
1090
- instanceId: t.instanceId,
1091
- label: t.label,
1092
- canHighlight: t.canHighlight,
1093
- visible: t.visible
1094
- })), this.onChange();
1126
+ c(this, "assertActive", () => {
1127
+ });
1128
+ c(this, "visibilityRevision", 0);
1129
+ }
1130
+ bind(e, t, i) {
1131
+ this.renderNode = e, this.onChange = t, i && (this.assertActive = i);
1132
+ }
1133
+ sync(e, t = !0) {
1134
+ const i = e.listInsertUsages().map((r) => ({
1135
+ insertId: r.insertId,
1136
+ blockName: r.blockName,
1137
+ layerName: r.layerName,
1138
+ layerIndex: r.layerIndex,
1139
+ variantId: r.variantId,
1140
+ instanceId: r.instanceId,
1141
+ label: r.label,
1142
+ canHighlight: r.canHighlight,
1143
+ visible: r.visible
1144
+ }));
1145
+ ri(this.usages, i) || (this.usages = i, this.revision += 1, t && this.onChange());
1095
1146
  }
1096
- clear() {
1097
- this.usages = [], this.renderNode = null, this.onChange();
1147
+ clear(e = !0) {
1148
+ const t = this.usages.length > 0;
1149
+ return this.renderNode = null, t ? (this.usages = [], this.revision += 1, e && this.onChange(), !0) : !1;
1098
1150
  }
1099
1151
  getVisibilityRevision() {
1100
1152
  return this.visibilityRevision;
1101
1153
  }
1102
1154
  toggleInsert(e, t) {
1103
- if (!this.renderNode) return;
1155
+ if (this.assertActive(), !this.renderNode) return;
1104
1156
  const i = this.usages.find((s) => s.insertId === e);
1105
1157
  if (!i) return;
1106
1158
  const r = t ?? !i.visible;
1107
- this.renderNode.setInsertVisible(e, r), i.visible = r, this.visibilityRevision += 1, this.onChange();
1159
+ i.visible !== r && (this.renderNode.setInsertVisible(e, r), i.visible = r, this.visibilityRevision += 1, this.revision += 1, this.onChange());
1108
1160
  }
1109
1161
  batchToggleInserts(e) {
1110
- if (!this.renderNode || e.length === 0) return;
1162
+ if (this.assertActive(), !this.renderNode || e.length === 0) return;
1111
1163
  const t = [];
1112
- for (const i of e) {
1113
- const r = this.usages.find((s) => s.insertId === i.insertId);
1114
- r && (t.push(i), r.visible = i.visible);
1164
+ let i = !1;
1165
+ for (const r of e) {
1166
+ const s = this.usages.find((o) => o.insertId === r.insertId);
1167
+ s && (t.push(r), i || (i = s.visible !== r.visible), s.visible = r.visible);
1115
1168
  }
1116
- t.length !== 0 && (this.renderNode.setInsertVisibleBatch(t), this.visibilityRevision += 1, this.onChange());
1169
+ t.length !== 0 && (this.renderNode.setInsertVisibleBatch(t), i && (this.visibilityRevision += 1, this.revision += 1, this.onChange()));
1117
1170
  }
1118
1171
  }
1119
- class Kt {
1172
+ class ei {
1120
1173
  constructor() {
1121
- a(this, "selection", null);
1122
- a(this, "details", null);
1123
- a(this, "textSelection", null);
1124
- a(this, "textDetails", null);
1174
+ c(this, "selection", null);
1175
+ c(this, "details", null);
1176
+ c(this, "textSelection", null);
1177
+ c(this, "textDetails", null);
1178
+ c(this, "revision", 0);
1125
1179
  }
1126
1180
  setSelection(e, t) {
1127
- this.selection = e, this.details = t, this.textSelection = null, this.textDetails = null;
1181
+ this.selection = e, this.details = t, this.textSelection = null, this.textDetails = null, this.revision += 1;
1128
1182
  }
1129
1183
  setTextSelection(e, t) {
1130
- this.selection = null, this.details = null, this.textSelection = e, this.textDetails = t;
1184
+ this.selection = null, this.details = null, this.textSelection = e, this.textDetails = t, this.revision += 1;
1131
1185
  }
1132
1186
  clear() {
1133
- this.selection = null, this.details = null, this.textSelection = null, this.textDetails = null;
1187
+ return !this.selection && !this.details && !this.textSelection && !this.textDetails ? !1 : (this.selection = null, this.details = null, this.textSelection = null, this.textDetails = null, this.revision += 1, !0);
1134
1188
  }
1135
1189
  }
1136
- class Gt {
1190
+ class ti {
1137
1191
  constructor() {
1138
- a(this, "filename", null);
1139
- a(this, "fileCount", 0);
1140
- a(this, "visibleLayerCount", 0);
1141
- a(this, "totalLayerCount", 0);
1142
- a(this, "statusMessage", "");
1143
- a(this, "zoomLabel", "");
1144
- a(this, "orbitDistanceLabel", "");
1145
- a(this, "scaleRuler", null);
1146
- a(this, "viewportVertexCount", 0);
1147
- a(this, "drawCalls", 0);
1148
- a(this, "fps", 0);
1149
- a(this, "lineRenderMode", "");
1150
- a(this, "entityCount", 0);
1151
- a(this, "lineCount", 0);
1152
- a(this, "fillCount", 0);
1153
- a(this, "dotCount", 0);
1154
- a(this, "textCount", 0);
1155
- a(this, "renderableCount", 0);
1156
- a(this, "submittedVertexRefs", 0);
1157
- a(this, "blockVariantCount", 0);
1158
- a(this, "blockInstanceCount", 0);
1159
- a(this, "splitBlockLayerGroupCount", 0);
1160
- a(this, "renderDebugBreakdown", []);
1161
- a(this, "splitBlockLayerDetails", []);
1162
- a(this, "phase", null);
1192
+ c(this, "revision", 0);
1193
+ c(this, "filename", null);
1194
+ c(this, "fileCount", 0);
1195
+ c(this, "visibleLayerCount", 0);
1196
+ c(this, "totalLayerCount", 0);
1197
+ c(this, "statusMessage", "");
1198
+ c(this, "zoomLabel", "");
1199
+ c(this, "orbitDistanceLabel", "");
1200
+ c(this, "scaleRuler", null);
1201
+ c(this, "viewportVertexCount", 0);
1202
+ c(this, "drawCalls", 0);
1203
+ c(this, "fps", 0);
1204
+ c(this, "lineRenderMode", "");
1205
+ c(this, "entityCount", 0);
1206
+ c(this, "lineCount", 0);
1207
+ c(this, "fillCount", 0);
1208
+ c(this, "dotCount", 0);
1209
+ c(this, "textCount", 0);
1210
+ c(this, "renderableCount", 0);
1211
+ c(this, "submittedVertexRefs", 0);
1212
+ c(this, "blockVariantCount", 0);
1213
+ c(this, "blockInstanceCount", 0);
1214
+ c(this, "splitBlockLayerGroupCount", 0);
1215
+ c(this, "renderDebugBreakdown", []);
1216
+ c(this, "splitBlockLayerDetails", []);
1217
+ c(this, "phase", null);
1163
1218
  }
1164
1219
  sync(e) {
1165
- var s, o, c, l;
1166
- this.filename = e.filename, this.fileCount = e.hasDocument ? 1 : 0, this.totalLayerCount = e.layers.length, this.visibleLayerCount = e.layers.filter((d) => d.visible).length, this.statusMessage = ((s = e.statusMessage) == null ? void 0 : s.trim()) ?? "";
1220
+ var s, o, a, d, l;
1221
+ this.revision += 1, this.filename = e.filename, this.fileCount = e.hasDocument ? 1 : 0, this.totalLayerCount = e.layers.length, this.visibleLayerCount = e.layers.filter((h) => h.visible).length, this.statusMessage = ((s = e.statusMessage) == null ? void 0 : s.trim()) ?? "";
1167
1222
  const t = e.host.runtime.getRenderStats();
1168
1223
  this.viewportVertexCount = t.submittedVertexRefs, this.drawCalls = t.drawCalls, this.fps = t.fps;
1169
1224
  const i = e.diagnostics;
1170
1225
  this.lineRenderMode = (i == null ? void 0 : i.lineRenderMode) ?? "", this.entityCount = (i == null ? void 0 : i.entityCount) ?? 0, this.lineCount = (i == null ? void 0 : i.lineCount) ?? 0, this.fillCount = (i == null ? void 0 : i.fillCount) ?? 0, this.dotCount = (i == null ? void 0 : i.dotCount) ?? 0, this.textCount = (i == null ? void 0 : i.textCount) ?? 0, this.renderableCount = (i == null ? void 0 : i.renderableCount) ?? 0, this.submittedVertexRefs = (i == null ? void 0 : i.submittedVertexRefs) ?? 0, this.blockVariantCount = (i == null ? void 0 : i.blockVariantCount) ?? 0, this.blockInstanceCount = (i == null ? void 0 : i.blockInstanceCount) ?? 0, this.splitBlockLayerGroupCount = (i == null ? void 0 : i.splitBlockLayerGroupCount) ?? 0, this.renderDebugBreakdown = (i == null ? void 0 : i.renderDebugBreakdown) ?? [], this.splitBlockLayerDetails = (i == null ? void 0 : i.splitBlockLayerDetails) ?? [], this.phase = e.phase ?? null;
1171
1226
  const r = e.host.runtime.getWorldUnitsPerPixel();
1172
1227
  if (e.host.viewMode === "2d" && Number.isFinite(r) && r > 0) {
1173
- const d = r * 100, h = (c = (o = e.host.runtime.captureCameraSnapshot()) == null ? void 0 : o.orthographic) == null ? void 0 : c.zoom;
1174
- this.zoomLabel = Number.isFinite(h) && (h ?? 0) > 0 ? `${Math.round(h * 100)}%` : "", this.scaleRuler = {
1228
+ const h = r * 100, u = (a = (o = e.host.runtime.captureCameraSnapshot()) == null ? void 0 : o.orthographic) == null ? void 0 : a.zoom;
1229
+ this.zoomLabel = Number.isFinite(u) && (u ?? 0) > 0 ? `${Math.round(u * 100)}%` : "", this.scaleRuler = {
1175
1230
  visible: !0,
1176
- worldLength: d,
1177
- lengthLabel: Zt(d)
1231
+ worldLength: h,
1232
+ lengthLabel: ni(h, ((d = e.units) == null ? void 0 : d.source) ?? "mm")
1178
1233
  }, this.orbitDistanceLabel = "";
1179
1234
  } else {
1180
- const d = (l = e.host.runtime.captureCameraSnapshot()) == null ? void 0 : l.orbit;
1181
- this.zoomLabel = "", this.orbitDistanceLabel = d ? `${Math.round(d.distance)}` : "", this.scaleRuler = null;
1235
+ const h = (l = e.host.runtime.captureCameraSnapshot()) == null ? void 0 : l.orbit;
1236
+ this.zoomLabel = "", this.orbitDistanceLabel = h ? `${Math.round(h.distance)}` : "", this.scaleRuler = null;
1182
1237
  }
1183
1238
  }
1184
1239
  clear() {
1185
- this.filename = null, this.fileCount = 0, this.visibleLayerCount = 0, this.totalLayerCount = 0, this.statusMessage = "", this.zoomLabel = "", this.orbitDistanceLabel = "", this.scaleRuler = null, this.viewportVertexCount = 0, this.drawCalls = 0, this.fps = 0, this.lineRenderMode = "", this.entityCount = 0, this.lineCount = 0, this.fillCount = 0, this.dotCount = 0, this.textCount = 0, this.renderableCount = 0, this.submittedVertexRefs = 0, this.blockVariantCount = 0, this.blockInstanceCount = 0, this.splitBlockLayerGroupCount = 0, this.renderDebugBreakdown = [], this.splitBlockLayerDetails = [], this.phase = null;
1240
+ return this.filename !== null || this.fileCount !== 0 || this.visibleLayerCount !== 0 || this.totalLayerCount !== 0 || this.statusMessage !== "" || this.zoomLabel !== "" || this.orbitDistanceLabel !== "" || this.scaleRuler !== null || this.viewportVertexCount !== 0 || this.drawCalls !== 0 || this.fps !== 0 || this.lineRenderMode !== "" || this.entityCount !== 0 || this.lineCount !== 0 || this.fillCount !== 0 || this.dotCount !== 0 || this.textCount !== 0 || this.renderableCount !== 0 || this.submittedVertexRefs !== 0 || this.blockVariantCount !== 0 || this.blockInstanceCount !== 0 || this.splitBlockLayerGroupCount !== 0 || this.renderDebugBreakdown.length > 0 || this.splitBlockLayerDetails.length > 0 || this.phase !== null ? (this.revision += 1, this.filename = null, this.fileCount = 0, this.visibleLayerCount = 0, this.totalLayerCount = 0, this.statusMessage = "", this.zoomLabel = "", this.orbitDistanceLabel = "", this.scaleRuler = null, this.viewportVertexCount = 0, this.drawCalls = 0, this.fps = 0, this.lineRenderMode = "", this.entityCount = 0, this.lineCount = 0, this.fillCount = 0, this.dotCount = 0, this.textCount = 0, this.renderableCount = 0, this.submittedVertexRefs = 0, this.blockVariantCount = 0, this.blockInstanceCount = 0, this.splitBlockLayerGroupCount = 0, this.renderDebugBreakdown = [], this.splitBlockLayerDetails = [], this.phase = null, !0) : !1;
1186
1241
  }
1187
1242
  }
1188
- function Zt(n) {
1189
- return n >= 1e6 ? `${(n / 1e6).toFixed(2)} km` : n >= 1e3 ? `${(n / 1e3).toFixed(2)} m` : `${n.toFixed(2)} mm`;
1243
+ function ii(n, e) {
1244
+ return n.length === e.length && n.every((t, i) => {
1245
+ const r = e[i];
1246
+ return r !== void 0 && t.index === r.index && t.name === r.name && t.visible === r.visible && t.color === r.color && t.sourceColor[0] === r.sourceColor[0] && t.sourceColor[1] === r.sourceColor[1] && t.sourceColor[2] === r.sourceColor[2];
1247
+ });
1248
+ }
1249
+ function ri(n, e) {
1250
+ return n.length === e.length && n.every((t, i) => {
1251
+ const r = e[i];
1252
+ return r !== void 0 && t.insertId === r.insertId && t.blockName === r.blockName && t.layerName === r.layerName && t.layerIndex === r.layerIndex && t.variantId === r.variantId && t.instanceId === r.instanceId && t.label === r.label && t.canHighlight === r.canHighlight && t.visible === r.visible;
1253
+ });
1254
+ }
1255
+ function ni(n, e) {
1256
+ if (e === "mm") {
1257
+ if (n >= 1e6) return `${(n / 1e6).toFixed(2)} km`;
1258
+ if (n >= 1e3) return `${(n / 1e3).toFixed(2)} m`;
1259
+ }
1260
+ return `${n.toFixed(2)}${e ? ` ${e}` : ""}`;
1190
1261
  }
1191
- function de(n) {
1262
+ function pe(n) {
1192
1263
  return {
1193
1264
  documentKey: n.documentKey,
1194
1265
  filename: n.filename,
1195
1266
  phase: n.phase,
1196
1267
  headerBounds: n.headerBounds,
1197
- layerCount: n.layerCount
1268
+ layerCount: n.layerCount,
1269
+ // Preserve the historical viewer labels when older packs carry no unit
1270
+ // metadata; packs that explicitly declare `unitless` still round-trip it.
1271
+ units: n.units ?? { source: "mm" }
1198
1272
  };
1199
1273
  }
1200
- const Jt = 160;
1201
- class Qt {
1274
+ const si = 160, me = 5e3;
1275
+ class oi {
1202
1276
  constructor(e) {
1203
- a(this, "layers", new jt());
1204
- a(this, "blocks", new Ut());
1205
- a(this, "inspector", new Kt());
1206
- a(this, "hud", new Gt());
1207
- a(this, "document", null);
1208
- a(this, "loadTiming", null);
1209
- a(this, "listeners", /* @__PURE__ */ new Map());
1210
- a(this, "host");
1211
- a(this, "disposed", !1);
1212
- a(this, "openEpoch", 0);
1213
- a(this, "cameraSettled", !1);
1214
- a(this, "initialDemandSettled", !1);
1215
- a(this, "initialCameraRestored", !1);
1216
- a(this, "cameraChangedDuringInitialLoad", !1);
1217
- a(this, "statusMessage", "");
1218
- a(this, "session", null);
1219
- a(this, "renderNode", null);
1220
- a(this, "unsubscribers", []);
1221
- a(this, "viewportDemandTimer", null);
1222
- this.host = e, this.layers.bind(null, () => this.emit("layer-change", { layers: this.layers })), this.blocks.bind(null, () => this.emit("block-change", { blocks: this.blocks }));
1277
+ c(this, "layers", new Jt());
1278
+ c(this, "blocks", new Qt());
1279
+ c(this, "inspector", new ei());
1280
+ c(this, "hud", new ti());
1281
+ c(this, "document", null);
1282
+ c(this, "loadTiming", null);
1283
+ c(this, "capabilities", {
1284
+ insertSelection: !0,
1285
+ textSelection: !0,
1286
+ insertPreview: !0,
1287
+ batchVisibility: !0
1288
+ });
1289
+ c(this, "listeners", /* @__PURE__ */ new Map());
1290
+ c(this, "host");
1291
+ c(this, "disposed", !1);
1292
+ c(this, "openEpoch", 0);
1293
+ c(this, "cameraSettled", !1);
1294
+ c(this, "initialDemandSettled", !1);
1295
+ c(this, "initialCameraRestored", !1);
1296
+ c(this, "cameraChangedDuringInitialLoad", !1);
1297
+ c(this, "statusMessage", "");
1298
+ c(this, "session", null);
1299
+ c(this, "renderNode", null);
1300
+ c(this, "unsubscribers", []);
1301
+ c(this, "viewportDemandTimer", null);
1302
+ c(this, "revision", 0);
1303
+ this.host = e, this.layers.bind(null, () => this.emit("layer-change", { layers: this.layers }), () => this.assertActive()), this.blocks.bind(null, () => this.emit("block-change", { blocks: this.blocks }), () => this.assertActive());
1223
1304
  }
1224
1305
  async open(e, t = {}) {
1306
+ var d;
1225
1307
  this.assertActive(), this.closeInternal();
1226
1308
  const i = ++this.openEpoch;
1227
1309
  this.cameraSettled = !1, this.initialDemandSettled = !1, this.initialCameraRestored = !1, this.cameraChangedDuringInitialLoad = !1, this.loadTiming = null;
1228
- const r = t.documentKey ?? ei(e), s = ht(e, {
1229
- documentKey: r ?? void 0,
1230
- filename: t.filename,
1231
- loadAnnotations: t.loadAnnotations,
1232
- workerUrl: t.workerUrl,
1233
- workerFactory: t.workerFactory,
1234
- fontResolver: t.fontResolver,
1235
- resolveTextFont: t.resolveTextFont,
1236
- textWarmup: t.textWarmup
1237
- });
1310
+ const r = t.documentKey ?? hi(e);
1311
+ let s;
1312
+ try {
1313
+ s = bt(e, {
1314
+ documentKey: r ?? void 0,
1315
+ filename: t.filename,
1316
+ loadAnnotations: t.loadAnnotations,
1317
+ workerUrl: t.workerUrl,
1318
+ workerFactory: t.workerFactory,
1319
+ fontResolver: t.fontResolver,
1320
+ resolveTextFont: t.resolveTextFont,
1321
+ textWarmup: t.textWarmup,
1322
+ signal: t.signal
1323
+ });
1324
+ } catch (l) {
1325
+ const h = l instanceof Error ? l : new Error(String(l)), u = Object.assign(new Error(h.message), {
1326
+ name: h.name,
1327
+ code: h.code,
1328
+ cause: h
1329
+ });
1330
+ throw this.emit("error", { ...N(u, !0, e), error: u }), u;
1331
+ }
1238
1332
  this.session = s, this.loadTiming = s.loadTiming, this.statusMessage = "加载中…";
1239
- const o = ut(s);
1333
+ const o = gt(s);
1240
1334
  this.renderNode = o, this.layers.bind(o, () => this.emit("layer-change", { layers: this.layers })), this.blocks.bind(o, () => this.emit("block-change", { blocks: this.blocks })), this.unsubscribers.push(
1241
1335
  o.onChange(() => {
1242
1336
  this.host.requestRender(), this.host.emitContentChange();
1243
1337
  }),
1244
1338
  s.on("content-appended", ({ kind: l }) => {
1245
- var d;
1246
- this.openEpoch === i && (!this.initialDemandSettled && l === "geometry" && (this.statusMessage = "增量渲染中…"), this.layers.sync(s), this.blocks.sync(s), this.refreshInspectorDetails(s), this.syncHud(((d = this.document) == null ? void 0 : d.filename) ?? null), this.host.requestRender(), this.host.emitContentChange(), this.emit("layer-change", { layers: this.layers }), this.emit("block-change", { blocks: this.blocks }), this.emit("hud-change", { hud: this.hud }));
1339
+ var h;
1340
+ this.openEpoch === i && (!this.initialDemandSettled && l === "geometry" && (this.statusMessage = "增量渲染中…"), this.layers.sync(s), this.blocks.sync(s), this.refreshInspectorDetails(s), this.syncHud(((h = this.document) == null ? void 0 : h.filename) ?? null), this.host.requestRender(), this.host.emitContentChange(), this.emit("hud-change", { hud: this.hud }));
1247
1341
  }),
1248
1342
  s.on("phase-change", (l) => {
1249
- var d;
1250
- this.openEpoch === i && (l.phase === "header-ready" || l.phase === "initial-loading" ? this.statusMessage = "解析中…" : l.phase === "interactive" && !this.initialDemandSettled ? this.statusMessage = "增量渲染中…" : (l.phase === "failed" || l.phase === "disposed") && (this.statusMessage = ""), this.syncHud(((d = this.document) == null ? void 0 : d.filename) ?? t.filename ?? null), this.document && (this.publishDocumentPhase(
1343
+ var h;
1344
+ this.openEpoch === i && (l.phase === "header-ready" || l.phase === "initial-loading" ? this.statusMessage = "解析中…" : l.phase === "interactive" && !this.initialDemandSettled ? this.statusMessage = "增量渲染中…" : (l.phase === "failed" || l.phase === "disposed") && (this.statusMessage = ""), this.syncHud(((h = this.document) == null ? void 0 : h.filename) ?? t.filename ?? null), this.document && (this.publishDocumentPhase(
1251
1345
  l.phase === "interactive" && !this.initialDemandSettled ? "initial-loading" : l.phase
1252
1346
  ), this.emit("hud-change", { hud: this.hud })));
1253
1347
  }),
1254
1348
  s.on("fatal-error", ({ error: l }) => {
1255
- this.openEpoch === i && console.error("[cad-viewer] CAD session failed", l);
1349
+ this.openEpoch === i && (console.error("[cad-viewer] CAD session failed", l), this.emit("error", { ...N(l, !0, e), error: l }));
1350
+ }),
1351
+ s.on("non-fatal-error", ({ error: l }) => {
1352
+ this.openEpoch === i && this.emit("error", { ...N(l, !1, e), error: l });
1256
1353
  }),
1257
1354
  s.on("load-timing", ({ timing: l }) => {
1258
1355
  this.openEpoch === i && (this.loadTiming = l, this.emit("load-timing", { timing: l }));
1259
1356
  }),
1260
1357
  s.on("demand-progress", (l) => {
1261
- var d, h;
1358
+ var h, u, p;
1262
1359
  if (this.openEpoch === i) {
1263
- if (this.statusMessage = l.settled ? "" : "增量渲染中…", this.syncHud(((d = this.document) == null ? void 0 : d.filename) ?? t.filename ?? null), !l.settled || this.initialDemandSettled) {
1360
+ if (this.statusMessage = l.settled ? "" : "增量渲染中…", this.emit("load-progress", {
1361
+ progress: l.settled ? 1 : l.loaded + l.pending > 0 ? l.loaded / (l.loaded + l.pending) : 0,
1362
+ phase: ((h = this.document) == null ? void 0 : h.phase) ?? s.phase,
1363
+ pending: l.pending,
1364
+ loaded: l.loaded,
1365
+ settled: l.settled
1366
+ }), this.syncHud(((u = this.document) == null ? void 0 : u.filename) ?? t.filename ?? null), !l.settled || this.initialDemandSettled) {
1264
1367
  this.emit("hud-change", { hud: this.hud });
1265
1368
  return;
1266
1369
  }
1267
1370
  if (this.initialDemandSettled = !0, this.layers.sync(s), this.blocks.sync(s), !this.initialCameraRestored && !this.cameraChangedDuringInitialLoad) {
1268
- const u = o.getAuthoritativeBounds({
1371
+ const b = o.getAuthoritativeBounds({
1269
1372
  includeUnmountedExternal: !0
1270
1373
  });
1271
- u && this.host.fitBox3(V(u));
1374
+ b && this.host.fitBox3(O(b));
1272
1375
  }
1273
- this.syncDisplayContext(), this.syncHud(((h = this.document) == null ? void 0 : h.filename) ?? null), this.publishDocumentPhase(s.phase), this.emit("layer-change", { layers: this.layers }), this.emit("block-change", { blocks: this.blocks }), this.emit("hud-change", { hud: this.hud }), this.flushViewportDemand();
1376
+ this.syncDisplayContext(), this.syncHud(((p = this.document) == null ? void 0 : p.filename) ?? null), this.publishDocumentPhase(s.phase), this.emit("hud-change", { hud: this.hud }), this.flushViewportDemand();
1274
1377
  }
1275
1378
  })
1276
1379
  ), this.host.mountCadObject(o.object), this.host.runtime.resize(), this.syncDisplayContext(), this.syncHud(t.filename ?? null), this.emit("hud-change", { hud: this.hud });
1277
- const c = await s.headerReady;
1380
+ let a;
1381
+ try {
1382
+ a = await s.headerReady;
1383
+ } catch (l) {
1384
+ const h = l instanceof Error ? l : new Error(String(l)), u = this.openEpoch !== i, p = h.name === "AbortError" || ((d = t.signal) == null ? void 0 : d.aborted), b = Object.assign(new Error(
1385
+ u ? "CAD open superseded" : p ? "CAD open aborted" : h.message
1386
+ ), {
1387
+ name: u ? "AbortError" : h.name,
1388
+ code: u ? "E_SUPERSEDED" : p ? "E_ABORTED" : h.code,
1389
+ cause: h
1390
+ });
1391
+ throw !u && this.openEpoch === i && p && this.emit("error", {
1392
+ ...N(b, !0, e),
1393
+ code: u ? "E_SUPERSEDED" : p ? "E_ABORTED" : N(b, !0, e).code,
1394
+ error: b
1395
+ }), b;
1396
+ }
1278
1397
  if (this.openEpoch !== i)
1279
- throw new Error("CAD open superseded");
1280
- return this.layers.sync(s), this.blocks.sync(s), this.syncHud(t.filename ?? c.filename ?? null), this.initialCameraRestored = this.tryRestoreCamera(r), !this.initialCameraRestored && c.bounds && this.host.fitBox3(V(c.bounds)), this.cameraSettled = !0, this.document = de({
1398
+ throw Object.assign(new Error("CAD open superseded"), {
1399
+ name: "AbortError",
1400
+ code: "E_SUPERSEDED"
1401
+ });
1402
+ return this.layers.sync(s, !1), this.blocks.sync(s, !1), this.syncHud(t.filename ?? a.filename ?? null), this.initialCameraRestored = this.tryRestoreCamera(r), !this.initialCameraRestored && a.bounds && this.host.fitBox3(O(a.bounds)), this.cameraSettled = !0, this.syncDisplayContext(), this.document = pe({
1281
1403
  documentKey: r,
1282
- filename: t.filename ?? c.filename ?? null,
1404
+ filename: t.filename ?? a.filename ?? null,
1283
1405
  phase: s.phase === "interactive" && !this.initialDemandSettled ? "initial-loading" : s.phase,
1284
- headerBounds: c.bounds,
1285
- layerCount: c.layers.length
1286
- }), this.emit("document-change", { document: this.document }), this.emit("layer-change", { layers: this.layers }), this.emit("block-change", { blocks: this.blocks }), this.emit("hud-change", { hud: this.hud }), this.flushViewportDemand(), s.initialContentReady.then(() => {
1406
+ headerBounds: a.bounds,
1407
+ layerCount: a.layers.length,
1408
+ units: a.units ? {
1409
+ source: a.units.source,
1410
+ ...a.units.scaleToMeters === void 0 ? {} : { scaleToMeters: a.units.scaleToMeters }
1411
+ } : void 0
1412
+ }), this.syncHud(this.document.filename), this.emit("document-change", { document: this.document }), this.emit("layer-change", { layers: this.layers }), this.emit("block-change", { blocks: this.blocks }), this.emit("hud-change", { hud: this.hud }), this.flushViewportDemand(), s.initialContentReady.then(() => {
1287
1413
  var l;
1288
- this.openEpoch !== i || !this.session || (this.layers.sync(s), this.blocks.sync(s), this.syncHud(((l = this.document) == null ? void 0 : l.filename) ?? null), this.flushViewportDemand(), this.emit("layer-change", { layers: this.layers }), this.emit("block-change", { blocks: this.blocks }), this.emit("hud-change", { hud: this.hud }));
1414
+ this.openEpoch !== i || !this.session || (this.layers.sync(s), this.blocks.sync(s), this.syncHud(((l = this.document) == null ? void 0 : l.filename) ?? null), this.flushViewportDemand(), this.emit("hud-change", { hud: this.hud }));
1289
1415
  }).catch(() => {
1290
1416
  }), this.document;
1291
1417
  }
1292
1418
  close() {
1293
1419
  this.assertActive(), this.closeInternal();
1294
1420
  }
1295
- selectInsert(e) {
1296
- var i;
1297
- if (!e || !this.session) {
1298
- this.setInsertSelection(null, null);
1299
- return;
1300
- }
1301
- const t = this.session.getBlockDetails(e);
1302
- if (!t) {
1303
- this.setInsertSelection(null, null);
1304
- return;
1305
- }
1306
- this.setInsertSelection({
1307
- documentKey: ((i = this.document) == null ? void 0 : i.documentKey) ?? null,
1308
- id: t.id
1309
- }, t);
1310
- }
1311
1421
  renderInsertPreview(e) {
1312
1422
  var r;
1423
+ this.assertActive();
1313
1424
  const t = this.inspector.selection, i = t ? ((r = this.renderNode) == null ? void 0 : r.createInsertPreview(t.id.instanceId)) ?? null : null;
1314
1425
  if (!i) return !1;
1315
1426
  try {
@@ -1348,7 +1459,7 @@ class Qt {
1348
1459
  details: s.details
1349
1460
  } : null;
1350
1461
  }
1351
- pickTextAtScreen(e, t) {
1462
+ pickTextAtScreenInternal(e, t) {
1352
1463
  var s, o;
1353
1464
  if (!this.session) return null;
1354
1465
  const i = this.host.screenToWorldOnPlane(e, t, 0);
@@ -1363,20 +1474,21 @@ class Qt {
1363
1474
  return this.layers.getVisibilityRevision() + this.blocks.getVisibilityRevision();
1364
1475
  }
1365
1476
  setInsertSelection(e, t) {
1366
- this.inspector.setSelection(e, t), this.emit("inspector-change", { inspector: this.inspector });
1477
+ ai(this.inspector.selection, e) && ci(this.inspector.details, t) && !this.inspector.textSelection || (this.inspector.setSelection(e, t), this.emit("inspector-change", { inspector: this.inspector }));
1367
1478
  }
1368
- setTextSelection(e, t) {
1369
- this.inspector.setTextSelection(e, t), this.emit("inspector-change", { inspector: this.inspector });
1479
+ /** @internal Used by the viewer's managed interaction pipeline. */
1480
+ setTextSelectionInternal(e, t) {
1481
+ li(this.inspector.textSelection, e) && di(this.inspector.textDetails, t) && !this.inspector.selection || (this.inspector.setTextSelection(e, t), this.emit("inspector-change", { inspector: this.inspector }));
1370
1482
  }
1371
1483
  getAuthoritativeBoundsBox() {
1372
1484
  if (!this.session) return null;
1373
1485
  const e = this.session.getBounds({});
1374
- return e ? V(e) : null;
1486
+ return e ? O(e) : null;
1375
1487
  }
1376
1488
  getMountedBoundsBox() {
1377
1489
  var t;
1378
1490
  const e = ((t = this.renderNode) == null ? void 0 : t.getMountedBounds({})) ?? null;
1379
- return e ? V(e) : null;
1491
+ return e ? O(e) : null;
1380
1492
  }
1381
1493
  onViewportChanged() {
1382
1494
  var e;
@@ -1388,29 +1500,96 @@ class Qt {
1388
1500
  onInteractionChanged() {
1389
1501
  this.cameraSettled && (this.clearViewportDemandTimer(), this.syncDisplayContext(), this.flushViewportDemand());
1390
1502
  }
1391
- onCameraChanged() {
1392
- var e;
1393
- this.cameraSettled && (this.initialDemandSettled || (this.cameraChangedDuringInitialLoad = !0), this.persistCurrentCamera(), this.host.emitCameraChange(), this.scheduleViewportDemand(), this.syncHud(((e = this.document) == null ? void 0 : e.filename) ?? null), this.emit("hud-change", { hud: this.hud }));
1503
+ onCameraChanged(e) {
1504
+ var t;
1505
+ this.host.emitCameraChange(e), this.cameraSettled && (this.initialDemandSettled || (this.cameraChangedDuringInitialLoad = !0), this.persistCurrentCamera(), this.syncDisplayContext(), this.scheduleViewportDemand(), this.syncHud(((t = this.document) == null ? void 0 : t.filename) ?? null), this.emit("hud-change", { hud: this.hud }));
1394
1506
  }
1395
1507
  onRuntimeStatsChanged() {
1396
1508
  this.document && (this.syncHud(this.document.filename), this.emit("hud-change", { hud: this.hud }));
1397
1509
  }
1398
1510
  closeInternal() {
1399
1511
  this.openEpoch += 1, this.clearViewportDemandTimer(), this.cameraSettled && this.persistCurrentCamera(), this.cameraSettled = !1, this.initialDemandSettled = !1, this.initialCameraRestored = !1, this.cameraChangedDuringInitialLoad = !1, this.statusMessage = "", this.loadTiming = null;
1400
- for (const e of this.unsubscribers) e();
1401
- this.unsubscribers = [], this.session && (this.session.dispose(), this.session = null), this.renderNode = null, this.host.unmountCadObject(), this.document = null, this.layers.clear(), this.blocks.clear(), this.inspector.clear(), this.hud.clear(), this.layers.bind(null, () => this.emit("layer-change", { layers: this.layers })), this.blocks.bind(null, () => this.emit("block-change", { blocks: this.blocks })), this.emit("document-change", { document: null }), this.emit("layer-change", { layers: this.layers }), this.emit("block-change", { blocks: this.blocks }), this.emit("inspector-change", { inspector: this.inspector }), this.emit("hud-change", { hud: this.hud });
1512
+ for (const o of this.unsubscribers) o();
1513
+ this.unsubscribers = [], this.session && (this.session.dispose(), this.session = null), this.renderNode = null, this.host.unmountCadObject();
1514
+ const e = this.document !== null;
1515
+ this.document = null;
1516
+ const t = this.layers.clear(!1), i = this.blocks.clear(!1), r = this.inspector.clear(), s = this.hud.clear();
1517
+ this.layers.bind(null, () => this.emit("layer-change", { layers: this.layers })), this.blocks.bind(null, () => this.emit("block-change", { blocks: this.blocks })), e && this.emit("document-change", { document: null }), t && this.emit("layer-change", { layers: this.layers }), i && this.emit("block-change", { blocks: this.blocks }), r && this.emit("inspector-change", { inspector: this.inspector }), s && this.emit("hud-change", { hud: this.hud });
1518
+ }
1519
+ hitTest(e, t, i = {}) {
1520
+ this.assertActive();
1521
+ const r = i.kinds ?? ["insert", "text"];
1522
+ if (r.includes("insert")) {
1523
+ const s = this.pickInsertAtScreen(e, t);
1524
+ if (s) return { kind: "insert", selection: s.selection, details: s.details };
1525
+ }
1526
+ if (r.includes("text")) {
1527
+ const s = this.pickTextAtScreenInternal(e, t);
1528
+ if (s) return { kind: "text", selection: s.selection, details: s.details };
1529
+ }
1530
+ return null;
1531
+ }
1532
+ select(e) {
1533
+ var t, i, r;
1534
+ this.assertActive(), e ? !this.document || !this.session || e.selection.documentKey !== this.document.documentKey ? this.clearSelection() : e.kind === "insert" ? this.setInsertSelection(e.selection, ((t = this.session) == null ? void 0 : t.getBlockDetails(se(e.selection.id))) ?? null) : this.setTextSelectionInternal(e.selection, ((r = (i = this.session) == null ? void 0 : i.getTextDetails) == null ? void 0 : r.call(i, e.selection.id)) ?? null) : this.clearSelection();
1535
+ }
1536
+ clearSelection() {
1537
+ this.assertActive(), !(!this.inspector.selection && !this.inspector.textSelection) && (this.inspector.clear(), this.emit("inspector-change", { inspector: this.inspector }));
1538
+ }
1539
+ getSnapshot() {
1540
+ const e = (i) => typeof structuredClone == "function" ? structuredClone(i) : JSON.parse(JSON.stringify(i)), t = {
1541
+ revision: this.revision,
1542
+ document: e(this.document),
1543
+ layers: { rows: e(this.layers.rows), allColor: this.layers.allColor ?? null, revision: this.layers.revision },
1544
+ blocks: { usages: e(this.blocks.usages), revision: this.blocks.revision },
1545
+ inspector: e({
1546
+ selection: this.inspector.selection,
1547
+ details: this.inspector.details,
1548
+ textSelection: this.inspector.textSelection,
1549
+ textDetails: this.inspector.textDetails,
1550
+ revision: this.inspector.revision
1551
+ }),
1552
+ hud: e(this.hud),
1553
+ loadTiming: e(this.loadTiming)
1554
+ };
1555
+ return Ne(t);
1556
+ }
1557
+ fitDocument() {
1558
+ this.assertActive();
1559
+ const e = this.getAuthoritativeBoundsBox();
1560
+ return e ? this.host.fitBox3(e) : !1;
1561
+ }
1562
+ fitSelection() {
1563
+ var l;
1564
+ this.assertActive();
1565
+ const e = (l = this.inspector.details) == null ? void 0 : l.bbox;
1566
+ if (!e) return !1;
1567
+ let { minX: t, minY: i, maxX: r, maxY: s } = e;
1568
+ const o = r - t, a = s - i, d = Math.max(o, a);
1569
+ if (o > 0 && a > 0 && d < me) {
1570
+ const h = (t + r) / 2, u = (i + s) / 2, p = me / 2;
1571
+ t = h - p, i = u - p, r = h + p, s = u + p;
1572
+ }
1573
+ return this.host.fitBox3(O({
1574
+ minX: t,
1575
+ minY: i,
1576
+ maxX: r,
1577
+ maxY: s,
1578
+ minZ: -0.01,
1579
+ maxZ: 0.01
1580
+ }));
1402
1581
  }
1403
1582
  refreshInspectorDetails(e) {
1404
1583
  const t = this.inspector.selection;
1405
1584
  if (!t) return;
1406
- const i = e.getBlockDetails(pt(t.id));
1585
+ const i = e.getBlockDetails(se(t.id));
1407
1586
  if (!i) return;
1408
1587
  const r = this.inspector.details, s = r == null ? void 0 : r.bbox;
1409
1588
  (s == null ? void 0 : s.minX) === i.bbox.minX && (s == null ? void 0 : s.minY) === i.bbox.minY && (s == null ? void 0 : s.maxX) === i.bbox.maxX && (s == null ? void 0 : s.maxY) === i.bbox.maxY || (this.inspector.setSelection(t, i), this.emit("inspector-change", { inspector: this.inspector }));
1410
1589
  }
1411
1590
  tryRestoreCamera(e) {
1412
1591
  const t = this.host.readCameraSnapshot(e);
1413
- return t ? this.host.runtime.applyCameraSnapshot(t) : !1;
1592
+ return t ? this.host.applyCameraSnapshot(t, "restore") : !1;
1414
1593
  }
1415
1594
  persistCurrentCamera() {
1416
1595
  var t;
@@ -1418,7 +1597,7 @@ class Qt {
1418
1597
  const e = this.host.runtime.captureCameraSnapshot();
1419
1598
  e && this.host.persistCameraSnapshot(
1420
1599
  this.document.documentKey,
1421
- $t(e)
1600
+ Zt(e)
1422
1601
  );
1423
1602
  }
1424
1603
  syncDisplayContext() {
@@ -1447,11 +1626,6 @@ class Qt {
1447
1626
  viewMode: this.host.viewMode,
1448
1627
  interaction: this.host.interaction,
1449
1628
  visibilityRevision: this.host.visibilityRevision
1450
- }), this.host.emitViewportChange({
1451
- viewportWidthPx: t,
1452
- viewportHeightPx: i,
1453
- worldUnitsPerPixel: r,
1454
- interaction: this.host.interaction
1455
1629
  });
1456
1630
  }
1457
1631
  /**
@@ -1469,13 +1643,13 @@ class Qt {
1469
1643
  }
1470
1644
  this.viewportDemandTimer === null && (this.viewportDemandTimer = globalThis.setTimeout(() => {
1471
1645
  this.viewportDemandTimer = null, !(this.disposed || !this.session) && this.host.interaction === "active" && this.flushViewportDemand();
1472
- }, Math.max(0, this.host.viewportDemandCoalesceMs ?? Jt)));
1646
+ }, Math.max(0, this.host.viewportDemandCoalesceMs ?? si)));
1473
1647
  }
1474
1648
  clearViewportDemandTimer() {
1475
1649
  this.viewportDemandTimer !== null && (globalThis.clearTimeout(this.viewportDemandTimer), this.viewportDemandTimer = null);
1476
1650
  }
1477
1651
  syncHud(e) {
1478
- var t;
1652
+ var t, i;
1479
1653
  this.hud.sync({
1480
1654
  filename: e,
1481
1655
  hasDocument: this.session !== null,
@@ -1483,19 +1657,22 @@ class Qt {
1483
1657
  host: this.host,
1484
1658
  statusMessage: this.statusMessage,
1485
1659
  diagnostics: this.renderNode && typeof this.renderNode.getDiagnostics == "function" ? this.renderNode.getDiagnostics() : null,
1486
- phase: ((t = this.document) == null ? void 0 : t.phase) ?? null
1660
+ phase: ((t = this.document) == null ? void 0 : t.phase) ?? null,
1661
+ units: (i = this.document) == null ? void 0 : i.units
1487
1662
  });
1488
1663
  }
1489
1664
  publishDocumentPhase(e) {
1490
- this.document && (this.document = de({
1665
+ this.document && (this.document = pe({
1491
1666
  documentKey: this.document.documentKey,
1492
1667
  filename: this.document.filename,
1493
1668
  phase: e,
1494
1669
  headerBounds: this.document.headerBounds,
1495
- layerCount: this.document.layerCount
1670
+ layerCount: this.document.layerCount,
1671
+ units: this.document.units
1496
1672
  }), this.emit("document-change", { document: this.document }));
1497
1673
  }
1498
1674
  emit(e, t) {
1675
+ this.revision += 1;
1499
1676
  for (const i of this.listeners.get(e) ?? [])
1500
1677
  i(t);
1501
1678
  }
@@ -1503,7 +1680,19 @@ class Qt {
1503
1680
  if (this.disposed) throw new Error("Viewer has been disposed.");
1504
1681
  }
1505
1682
  }
1506
- function ei(n) {
1683
+ function ai(n, e) {
1684
+ return n === e || !!(n && e && n.documentKey === e.documentKey && n.id.layerIndex === e.id.layerIndex && n.id.variantId === e.id.variantId && n.id.instanceId === e.id.instanceId);
1685
+ }
1686
+ function li(n, e) {
1687
+ return n === e || !!(n && e && n.documentKey === e.documentKey && n.id.textId === e.id.textId);
1688
+ }
1689
+ function ci(n, e) {
1690
+ return n === e || !!(n && e && n.id.layerIndex === e.id.layerIndex && n.id.variantId === e.id.variantId && n.id.instanceId === e.id.instanceId && n.label === e.label && n.blockName === e.blockName && n.layerName === e.layerName && n.layerIndex === e.layerIndex && n.tx === e.tx && n.ty === e.ty && n.rotation === e.rotation && n.scaleX === e.scaleX && n.scaleY === e.scaleY && n.bbox.minX === e.bbox.minX && n.bbox.minY === e.bbox.minY && n.bbox.maxX === e.bbox.maxX && n.bbox.maxY === e.bbox.maxY);
1691
+ }
1692
+ function di(n, e) {
1693
+ return n === e || !!(n && e && n.id.textId === e.id.textId && n.content === e.content && n.x === e.x && n.y === e.y && n.height === e.height && n.rotation === e.rotation && n.layerName === e.layerName && n.layerIndex === e.layerIndex);
1694
+ }
1695
+ function hi(n) {
1507
1696
  let e = null;
1508
1697
  if (typeof n == "string" ? e = n : typeof URL < "u" && n instanceof URL ? e = n.href : typeof n == "object" && n !== null && "kind" in n && n.kind === "url" && (e = n.url), !e) return null;
1509
1698
  let t = 2166136261;
@@ -1511,16 +1700,27 @@ function ei(n) {
1511
1700
  t ^= e.charCodeAt(i), t = Math.imul(t, 16777619);
1512
1701
  return `reference:src-${(t >>> 0).toString(16)}`;
1513
1702
  }
1514
- const he = 1;
1515
- class ti {
1703
+ function Ne(n) {
1704
+ if (!n || typeof n != "object") return n;
1705
+ Object.freeze(n);
1706
+ for (const e of Object.values(n))
1707
+ e && typeof e == "object" && !Object.isFrozen(e) && Ne(e);
1708
+ return n;
1709
+ }
1710
+ function N(n, e, t) {
1711
+ const i = n.code, r = n.name, s = n.message.toLowerCase(), o = /external block|sidecar|variant .*fetch/.test(s), a = /annotation/.test(s), d = /font|troika/.test(s), l = i === "E_SUPERSEDED" ? "E_SUPERSEDED" : r === "AbortError" || i === "E_DISPOSED" ? "E_ABORTED" : o ? "E_SIDECAR_FETCH" : a ? "E_ANNOTATION" : d ? "E_FONT" : i === "E_SOURCE" ? "E_SOURCE" : i === "E_PACK_HTTP" || i === "E_PACK_NETWORK" ? "E_FETCH" : i === "E_HEADER" || i === "E_HEADER_JSON" || i === "E_UNSUPPORTED_PACK_VERSION" ? "E_PARSE_HEADER" : i === "E_WORKER" || i === "E_MAIN_BUFFER_PROTOCOL" || i === "E_MAIN_BUFFER_MISSING" || /worker/.test(s) ? "E_WORKER" : "E_PARSE_GEOMETRY";
1712
+ return { code: l, stage: l === "E_FETCH" ? "source" : l === "E_PARSE_HEADER" ? "header" : l === "E_WORKER" ? "worker" : l === "E_PARSE_GEOMETRY" ? "geometry" : l === "E_SIDECAR_FETCH" ? "sidecar" : l === "E_ANNOTATION" ? "annotation" : l === "E_FONT" ? "font" : l === "E_ABORTED" || l === "E_SUPERSEDED" ? "lifecycle" : "source", fatal: e, source: t };
1713
+ }
1714
+ const ve = 1;
1715
+ class ui {
1516
1716
  constructor(e) {
1517
- a(this, "startX", 0);
1518
- a(this, "startY", 0);
1519
- a(this, "lastX", 0);
1520
- a(this, "lastY", 0);
1521
- a(this, "primaryPointerDown", !1);
1522
- a(this, "exceededDragThreshold", !1);
1523
- a(this, "travelPx", 0);
1717
+ c(this, "startX", 0);
1718
+ c(this, "startY", 0);
1719
+ c(this, "lastX", 0);
1720
+ c(this, "lastY", 0);
1721
+ c(this, "primaryPointerDown", !1);
1722
+ c(this, "exceededDragThreshold", !1);
1723
+ c(this, "travelPx", 0);
1524
1724
  this.thresholds = e;
1525
1725
  }
1526
1726
  get isPrimaryPointerDown() {
@@ -1557,21 +1757,21 @@ class ti {
1557
1757
  this.release(), this.resetMotion(), this.startX = 0, this.startY = 0, this.lastX = 0, this.lastY = 0;
1558
1758
  }
1559
1759
  isTrackingPrimaryPointer(e) {
1560
- return this.primaryPointerDown || (e & he) === he;
1760
+ return this.primaryPointerDown || (e & ve) === ve;
1561
1761
  }
1562
1762
  }
1563
- function U(n, e) {
1763
+ function W(n, e) {
1564
1764
  return `${n}:${e}`;
1565
1765
  }
1566
- class ii {
1766
+ class pi {
1567
1767
  constructor() {
1568
- a(this, "expandedLayers", /* @__PURE__ */ new Set());
1569
- a(this, "expandedBlocks", /* @__PURE__ */ new Set());
1570
- a(this, "blockVisibilitySnapshots", /* @__PURE__ */ new Map());
1571
- a(this, "filterText", "");
1572
- a(this, "scopeKey", null);
1573
- a(this, "revealedSelectionKey", null);
1574
- a(this, "suppressedSelectionKey", null);
1768
+ c(this, "expandedLayers", /* @__PURE__ */ new Set());
1769
+ c(this, "expandedBlocks", /* @__PURE__ */ new Set());
1770
+ c(this, "blockVisibilitySnapshots", /* @__PURE__ */ new Map());
1771
+ c(this, "filterText", "");
1772
+ c(this, "scopeKey", null);
1773
+ c(this, "revealedSelectionKey", null);
1774
+ c(this, "suppressedSelectionKey", null);
1575
1775
  }
1576
1776
  collapseAll(e = null) {
1577
1777
  this.expandedLayers.clear(), this.expandedBlocks.clear(), this.suppressedSelectionKey = e;
@@ -1583,7 +1783,7 @@ class ii {
1583
1783
  this.expandedLayers.has(e) ? this.expandedLayers.delete(e) : this.expandedLayers.add(e), this.suppressedSelectionKey = null;
1584
1784
  }
1585
1785
  toggleBlockExpanded(e, t) {
1586
- const i = U(e, t);
1786
+ const i = W(e, t);
1587
1787
  this.expandedBlocks.has(i) ? this.expandedBlocks.delete(i) : this.expandedBlocks.add(i), this.suppressedSelectionKey = null;
1588
1788
  }
1589
1789
  prune(e, t) {
@@ -1595,7 +1795,7 @@ class ii {
1595
1795
  t.has(i) || this.blockVisibilitySnapshots.delete(i);
1596
1796
  }
1597
1797
  ensureSelectionVisible(e, t, i) {
1598
- this.suppressedSelectionKey !== e && (this.suppressedSelectionKey !== null && (this.suppressedSelectionKey = null), this.expandedLayers.add(t), this.expandedBlocks.add(U(t, i)));
1798
+ this.suppressedSelectionKey !== e && (this.suppressedSelectionKey !== null && (this.suppressedSelectionKey = null), this.expandedLayers.add(t), this.expandedBlocks.add(W(t, i)));
1599
1799
  }
1600
1800
  needsSelectionReveal(e) {
1601
1801
  return this.revealedSelectionKey !== e;
@@ -1607,10 +1807,251 @@ class ii {
1607
1807
  this.revealedSelectionKey = null, this.suppressedSelectionKey = null;
1608
1808
  }
1609
1809
  }
1610
- function ri(n) {
1810
+ function S(n) {
1811
+ return n.replace(/[&<>"']/g, (e) => ({
1812
+ "&": "&amp;",
1813
+ "<": "&lt;",
1814
+ ">": "&gt;",
1815
+ '"': "&quot;",
1816
+ "'": "&#39;"
1817
+ })[e] ?? e);
1818
+ }
1819
+ const mi = {
1820
+ "panel.layers": "图层",
1821
+ "panel.properties": "属性",
1822
+ "panel.layers.aria": "图层面板",
1823
+ "panel.properties.aria": "属性面板",
1824
+ "panel.collapse": "收起",
1825
+ "panel.expand": "展开",
1826
+ "panel.toggle": "{action}{panel}",
1827
+ "infobar.collapse": "收起信息栏",
1828
+ "infobar.expand": "展开信息栏",
1829
+ "toolbar.viewControls": "视图控制",
1830
+ "toolbar.viewMode": "视图模式",
1831
+ "toolbar.fit": "适应",
1832
+ "toolbar.details": "详细",
1833
+ "toolbar.zoom": "缩放 {value}",
1834
+ "toolbar.vertices": "顶点 {value}",
1835
+ "toolbar.drawCalls": "DrawCalls {value}",
1836
+ "toolbar.fps": "{value} FPS",
1837
+ "toolbar.fpsEmpty": "— FPS",
1838
+ "toolbar.lineMode": "线模式 {value}",
1839
+ "toolbar.layerSummary": "{visible} / {total} 图层",
1840
+ "toolbar.debugSummary": "Debug · Block {blocks} · 跨层 {split}",
1841
+ "toolbar.debug.submitted": "提交",
1842
+ "toolbar.debug.lineMode": "线模式",
1843
+ "toolbar.debug.layers": "图层",
1844
+ "toolbar.debug.drawCallSource": "DrawCall 来源",
1845
+ "toolbar.debug.block": "Block",
1846
+ "toolbar.debug.splitLayer": "分散 layer",
1847
+ "toolbar.debug.splitLayerCount": "跨层 {count}",
1848
+ "toolbar.debug.moreSplitLayers": "另有 {count} 个跨层 block",
1849
+ "toolbar.debug.renderables": "{renderables} renderables / {calls} calls",
1850
+ "toolbar.debug.breakdown": "{renderables} call-ish / {vertices} vertices",
1851
+ "toolbar.debug.blockCount": "{variants} / INSERT {instances}",
1852
+ "toolbar.debug.layerCount": "{visible} / {total}",
1853
+ "toolbar.debug.spreadMeta": "{layers} layer / {instances} insert",
1854
+ "layer.searchPlaceholder": "搜索图层…",
1855
+ "layer.showAll": "全显",
1856
+ "layer.hideAll": "全隐",
1857
+ "layer.collapse": "折叠",
1858
+ "layer.collapseTitle": "折叠全部已展开层级",
1859
+ "layer.all": "全部图层",
1860
+ "layer.colorOverride": "覆盖颜色(右键重置)",
1861
+ "layer.colorOverrideAll": "全部图层颜色覆盖(右键重置)",
1862
+ "layer.unnamed": "(未命名)",
1863
+ "layer.hide": "隐藏图层",
1864
+ "layer.show": "显示图层",
1865
+ "layer.hideInsert": "隐藏该 insert",
1866
+ "layer.showInsert": "显示该 insert",
1867
+ "layer.hideBlock": "隐藏整个 block",
1868
+ "layer.showBlockRestore": "显示整个 block(恢复子 insert 状态)",
1869
+ "layer.hideBlockKeep": "隐藏整个 block(保留子 insert 状态)",
1870
+ "layer.noHighlightBlock": "该 block 无可高亮几何",
1871
+ "layer.noHighlightInsert": "该 insert 无可高亮几何",
1872
+ "layer.empty": "加载 CAD 文档后显示图层。",
1873
+ "property.empty": "点击画布中的对象查看属性",
1874
+ "property.insert": "INSERT",
1875
+ "property.text": "文本",
1876
+ "property.basic": "基本",
1877
+ "property.transform": "变换",
1878
+ "property.block": "Block",
1879
+ "property.layer": "图层",
1880
+ "property.instance": "Instance",
1881
+ "property.currentShape": "当前形态",
1882
+ "property.normalShape": "普通图形",
1883
+ "property.content": "内容",
1884
+ "property.height": "高度",
1885
+ "property.rotation": "旋转",
1886
+ "scale.title": "当前视图比例尺(按图纸单位)",
1887
+ "status.created": "状态 创建",
1888
+ "status.headerReady": "状态 头部就绪",
1889
+ "status.initialLoading": "状态 加载中",
1890
+ "status.interactive": "状态 就绪",
1891
+ "status.failed": "状态 失败",
1892
+ "status.disposed": "状态 已关闭",
1893
+ "status.3dDistance": "3D 距离 {value}",
1894
+ "status.loading": "加载中…",
1895
+ "status.parsing": "解析中…",
1896
+ "status.incrementalLoading": "增量渲染中…",
1897
+ "unit.mm": "mm"
1898
+ }, vi = {
1899
+ "panel.layers": "Layers",
1900
+ "panel.properties": "Properties",
1901
+ "panel.layers.aria": "Layers panel",
1902
+ "panel.properties.aria": "Properties panel",
1903
+ "panel.collapse": "Collapse",
1904
+ "panel.expand": "Expand",
1905
+ "panel.toggle": "{action} {panel}",
1906
+ "infobar.collapse": "Collapse info bar",
1907
+ "infobar.expand": "Expand info bar",
1908
+ "toolbar.viewControls": "View controls",
1909
+ "toolbar.viewMode": "View mode",
1910
+ "toolbar.fit": "Fit",
1911
+ "toolbar.details": "Details",
1912
+ "toolbar.zoom": "Zoom {value}",
1913
+ "toolbar.vertices": "Vertices {value}",
1914
+ "toolbar.drawCalls": "DrawCalls {value}",
1915
+ "toolbar.fps": "{value} FPS",
1916
+ "toolbar.fpsEmpty": "— FPS",
1917
+ "toolbar.lineMode": "Line mode {value}",
1918
+ "toolbar.layerSummary": "{visible} / {total} layers",
1919
+ "toolbar.debugSummary": "Debug · Block {blocks} · split {split}",
1920
+ "toolbar.debug.submitted": "Submitted",
1921
+ "toolbar.debug.lineMode": "Line mode",
1922
+ "toolbar.debug.layers": "Layers",
1923
+ "toolbar.debug.drawCallSource": "DrawCall source",
1924
+ "toolbar.debug.block": "Block",
1925
+ "toolbar.debug.splitLayer": "Split layer",
1926
+ "toolbar.debug.splitLayerCount": "Split {count}",
1927
+ "toolbar.debug.moreSplitLayers": "{count} more split blocks",
1928
+ "toolbar.debug.renderables": "{renderables} renderables / {calls} calls",
1929
+ "toolbar.debug.breakdown": "{renderables} call-ish / {vertices} vertices",
1930
+ "toolbar.debug.blockCount": "{variants} / INSERT {instances}",
1931
+ "toolbar.debug.layerCount": "{visible} / {total}",
1932
+ "toolbar.debug.spreadMeta": "{layers} layers / {instances} inserts",
1933
+ "layer.searchPlaceholder": "Search layers…",
1934
+ "layer.showAll": "Show all",
1935
+ "layer.hideAll": "Hide all",
1936
+ "layer.collapse": "Collapse",
1937
+ "layer.collapseTitle": "Collapse all expanded levels",
1938
+ "layer.all": "All layers",
1939
+ "layer.colorOverride": "Override color (right-click to reset)",
1940
+ "layer.colorOverrideAll": "Override all layer colors (right-click to reset)",
1941
+ "layer.unnamed": "(unnamed)",
1942
+ "layer.hide": "Hide layer",
1943
+ "layer.show": "Show layer",
1944
+ "layer.hideInsert": "Hide insert",
1945
+ "layer.showInsert": "Show insert",
1946
+ "layer.hideBlock": "Hide block",
1947
+ "layer.showBlockRestore": "Show block (restore child insert state)",
1948
+ "layer.hideBlockKeep": "Hide block (keep child insert state)",
1949
+ "layer.noHighlightBlock": "This block has no highlightable geometry",
1950
+ "layer.noHighlightInsert": "This insert has no highlightable geometry",
1951
+ "layer.empty": "Load a CAD document to show layers.",
1952
+ "property.empty": "Click an object on the canvas to view its properties",
1953
+ "property.insert": "INSERT",
1954
+ "property.text": "Text",
1955
+ "property.basic": "Basic",
1956
+ "property.transform": "Transform",
1957
+ "property.block": "Block",
1958
+ "property.layer": "Layer",
1959
+ "property.instance": "Instance",
1960
+ "property.currentShape": "Current shape",
1961
+ "property.normalShape": "Normal geometry",
1962
+ "property.content": "Content",
1963
+ "property.height": "Height",
1964
+ "property.rotation": "Rotation",
1965
+ "scale.title": "Current view scale (drawing units)",
1966
+ "status.created": "Status Created",
1967
+ "status.headerReady": "Status Header ready",
1968
+ "status.initialLoading": "Status Loading",
1969
+ "status.interactive": "Status Ready",
1970
+ "status.failed": "Status Failed",
1971
+ "status.disposed": "Status Closed",
1972
+ "status.3dDistance": "3D distance {value}",
1973
+ "status.loading": "Loading…",
1974
+ "status.parsing": "Parsing…",
1975
+ "status.incrementalLoading": "Rendering incrementally…",
1976
+ "unit.mm": "mm"
1977
+ };
1978
+ function fi(n, e) {
1979
+ return e ? n.replace(/\{([a-zA-Z0-9_]+)\}/g, (t, i) => {
1980
+ const r = e[i];
1981
+ return r === void 0 ? t : String(r);
1982
+ }) : n;
1983
+ }
1984
+ function bi(n) {
1985
+ try {
1986
+ return new Intl.NumberFormat(n, { maximumFractionDigits: 4, useGrouping: !1 });
1987
+ } catch {
1988
+ return new Intl.NumberFormat("zh-CN", { maximumFractionDigits: 4, useGrouping: !1 });
1989
+ }
1990
+ }
1991
+ function gi(n) {
1992
+ try {
1993
+ return new Intl.NumberFormat(n, { maximumFractionDigits: 0 });
1994
+ } catch {
1995
+ return new Intl.NumberFormat("zh-CN", { maximumFractionDigits: 0 });
1996
+ }
1997
+ }
1998
+ function Ve(n) {
1999
+ var o;
2000
+ const e = ((o = n.locale) == null ? void 0 : o.trim()) || "zh-CN", t = e.toLowerCase().startsWith("en") ? vi : mi, i = bi(e), r = gi(e), s = {
2001
+ locale: e,
2002
+ t(a, d) {
2003
+ var u;
2004
+ let l;
2005
+ if (n.messageResolver)
2006
+ try {
2007
+ l = n.messageResolver(a, d);
2008
+ } catch {
2009
+ l = void 0;
2010
+ }
2011
+ const h = l ?? ((u = n.messages) == null ? void 0 : u[a]) ?? t[a] ?? a;
2012
+ return fi(h, d);
2013
+ },
2014
+ formatNumber(a) {
2015
+ return a == null || !Number.isFinite(a) ? "—" : i.format(a);
2016
+ },
2017
+ formatInteger(a) {
2018
+ return Number.isFinite(a) ? r.format(a) : "—";
2019
+ },
2020
+ formatUnit(a, d, l = "2d") {
2021
+ if (a == null || !Number.isFinite(a)) return "—";
2022
+ if (n.unitFormatter)
2023
+ try {
2024
+ return n.unitFormatter(a, { unit: d, viewMode: l });
2025
+ } catch {
2026
+ }
2027
+ return d ? `${s.formatNumber(a)} ${d}` : s.formatNumber(a);
2028
+ },
2029
+ formatScaleLabel(a, d = "mm", l = "2d") {
2030
+ if (!Number.isFinite(a)) return "—";
2031
+ if (n.unitFormatter) return s.formatUnit(a, d, l);
2032
+ if (d === "mm") {
2033
+ if (a >= 1e6) return `${(a / 1e6).toFixed(2)} km`;
2034
+ if (a >= 1e3) return `${(a / 1e3).toFixed(2)} m`;
2035
+ }
2036
+ return d ? `${a.toFixed(2)} ${d}` : a.toFixed(2);
2037
+ }
2038
+ };
2039
+ return s;
2040
+ }
2041
+ const yi = {
2042
+ "加载中…": "status.loading",
2043
+ "解析中…": "status.parsing",
2044
+ "增量渲染中…": "status.incrementalLoading"
2045
+ };
2046
+ function xi(n, e) {
2047
+ const t = n.trim(), i = yi[t];
2048
+ return i ? e.t(i) : t;
2049
+ }
2050
+ const J = Ve({});
2051
+ function wi(n) {
1611
2052
  const e = /* @__PURE__ */ new Map();
1612
2053
  for (const i of n.usages) {
1613
- const r = e.get(i.layerIndex) ?? /* @__PURE__ */ new Map(), s = U(i.layerIndex, i.variantId);
2054
+ const r = e.get(i.layerIndex) ?? /* @__PURE__ */ new Map(), s = W(i.layerIndex, i.variantId);
1614
2055
  let o = r.get(s);
1615
2056
  o || (o = {
1616
2057
  key: s,
@@ -1632,26 +2073,26 @@ function ri(n) {
1632
2073
  t.set(i, [...r.values()]);
1633
2074
  return t;
1634
2075
  }
1635
- function ni(n, e) {
2076
+ function Ci(n, e) {
1636
2077
  return n ? e.toLowerCase().includes(n) : !0;
1637
2078
  }
1638
- function _(n, e) {
1639
- n.dataset.visible = e ? "1" : "0", n.classList.toggle("off", !e), n.textContent = e ? "●" : "○", n.title = e ? "隐藏该 insert" : "显示该 insert";
2079
+ function X(n, e, t) {
2080
+ n.dataset.visible = e ? "1" : "0", n.classList.toggle("off", !e), n.textContent = e ? "●" : "○", n.title = e ? t.t("layer.hideInsert") : t.t("layer.showInsert");
1640
2081
  }
1641
- function Y(n, e) {
1642
- n.classList.toggle("off", e === "none"), n.classList.toggle("mixed", e === "mixed"), n.textContent = e === "all" ? "●" : e === "none" ? "○" : "◐", n.title = e === "all" ? "隐藏整个 block" : e === "none" ? "显示整个 block(恢复子 insert 状态)" : "隐藏整个 block(保留子 insert 状态)";
2082
+ function _(n, e, t) {
2083
+ n.classList.toggle("off", e === "none"), n.classList.toggle("mixed", e === "mixed"), n.textContent = e === "all" ? "●" : e === "none" ? "○" : "◐", n.title = e === "all" ? t.t("layer.hideBlock") : e === "none" ? t.t("layer.showBlockRestore") : t.t("layer.hideBlockKeep");
1643
2084
  }
1644
- function si(n) {
2085
+ function Pi(n) {
1645
2086
  let e = 0;
1646
2087
  for (const t of n) t.visible && (e += 1);
1647
2088
  return e <= 0 ? "none" : e >= n.length ? "all" : "mixed";
1648
2089
  }
1649
- function Le(n, e, t, i) {
2090
+ function Be(n, e, t, i) {
1650
2091
  if (!n) return !1;
1651
2092
  const r = n.id;
1652
2093
  return r.layerIndex !== e || r.variantId !== t ? !1 : i === void 0 ? !0 : r.instanceId === i;
1653
2094
  }
1654
- function ue(n) {
2095
+ function fe(n) {
1655
2096
  const e = n.querySelector(".vui-lrow-insert.active") ?? n.querySelector(".vui-lrow-block.active");
1656
2097
  if (!e) return !1;
1657
2098
  const t = n.getBoundingClientRect(), i = e.getBoundingClientRect();
@@ -1659,38 +2100,38 @@ function ue(n) {
1659
2100
  const r = i.top - t.top, s = n.scrollTop + r - (t.height - i.height) / 2;
1660
2101
  return n.scrollTop = Math.max(0, s), !0;
1661
2102
  }
1662
- function Ae(n, e, t = 0) {
2103
+ function ze(n, e, t = 0) {
1663
2104
  const i = () => {
1664
2105
  const r = n.getBoundingClientRect(), s = e.getBoundingClientRect();
1665
2106
  if (r.height <= 0) return;
1666
- const o = r.top + t, c = r.bottom;
1667
- if (!(s.top >= o && s.bottom <= c)) {
2107
+ const o = r.top + t, a = r.bottom;
2108
+ if (!(s.top >= o && s.bottom <= a)) {
1668
2109
  if (s.top < o) {
1669
- const l = s.top - r.top + n.scrollTop, d = Math.max(0, l - t);
1670
- n.scrollTop = d;
2110
+ const d = s.top - r.top + n.scrollTop, l = Math.max(0, d - t);
2111
+ n.scrollTop = l;
1671
2112
  return;
1672
2113
  }
1673
- if (s.bottom > c) {
1674
- const l = s.bottom - r.top + n.scrollTop, d = Math.max(0, l - r.height);
1675
- n.scrollTop = d;
2114
+ if (s.bottom > a) {
2115
+ const d = s.bottom - r.top + n.scrollTop, l = Math.max(0, d - r.height);
2116
+ n.scrollTop = l;
1676
2117
  }
1677
2118
  }
1678
2119
  };
1679
2120
  i(), typeof requestAnimationFrame == "function" && requestAnimationFrame(i);
1680
2121
  }
1681
- function oi(n, e) {
2122
+ function Si(n, e) {
1682
2123
  const t = e.trim().toLowerCase();
1683
2124
  n.querySelectorAll(".vui-lrow-wrap").forEach((i) => {
1684
- var c, l;
2125
+ var a, d;
1685
2126
  const r = i.querySelector(".vui-lrow:not(.vui-lrow-all)");
1686
2127
  if (!r) return;
1687
- const s = ((l = (c = r.querySelector(".vui-lrow-name")) == null ? void 0 : c.textContent) == null ? void 0 : l.toLowerCase()) ?? "", o = !t || s.includes(t);
2128
+ const s = ((d = (a = r.querySelector(".vui-lrow-name")) == null ? void 0 : a.textContent) == null ? void 0 : d.toLowerCase()) ?? "", o = !t || s.includes(t);
1688
2129
  i.style.display = o ? "" : "none";
1689
2130
  });
1690
2131
  }
1691
- function ai(n, e) {
1692
- if (n.querySelectorAll(".vui-lrow-block.active, .vui-lrow-insert.active").forEach((c) => {
1693
- c.classList.remove("active");
2132
+ function Ei(n, e) {
2133
+ if (n.querySelectorAll(".vui-lrow-block.active, .vui-lrow-insert.active").forEach((a) => {
2134
+ a.classList.remove("active");
1694
2135
  }), !e) return;
1695
2136
  const { layerIndex: t, variantId: i, instanceId: r } = e.id, s = n.querySelector(
1696
2137
  `.vui-lrow[data-layer-index="${t}"] ~ .vui-lrow-blocks .vui-lrow-block[data-variant-id="${i}"]`
@@ -1701,60 +2142,80 @@ function ai(n, e) {
1701
2142
  );
1702
2143
  o && o.classList.add("active");
1703
2144
  }
1704
- function pe(n, e, t) {
1705
- var f;
2145
+ function Ii(n, e, t, i = J) {
2146
+ var d;
2147
+ const r = new Map(e.map((l) => [l.index, l]));
2148
+ n.querySelectorAll(".vui-lrow[data-layer-index]:not(.vui-lrow-all)").forEach((l) => {
2149
+ const h = r.get(Number(l.dataset.layerIndex));
2150
+ if (!h) return;
2151
+ const u = l.querySelector(".vui-lrow-eye");
2152
+ u && (u.textContent = h.visible ? "●" : "○", u.title = h.visible ? i.t("layer.hide") : i.t("layer.show")), l.classList.toggle("off", !h.visible), He(l, Q(h));
2153
+ });
2154
+ const s = n.querySelector(".vui-lrow-all"), o = t === null ? "#c8c8c8" : L(t);
2155
+ (d = s == null ? void 0 : s.querySelector(".vui-lrow-clr")) == null || d.style.setProperty("background", o);
2156
+ const a = s == null ? void 0 : s.querySelector('input[type="color"]');
2157
+ a && a.value !== o && (a.value = o);
2158
+ }
2159
+ function Ri(n, e, t) {
2160
+ var v;
2161
+ const i = t.text ?? J;
1706
2162
  e.resetForScope(t.scopeKey);
1707
- const i = e.filterText.trim().toLowerCase(), r = t.layers.rows, s = ri(t.blocks);
1708
- if (n.list.replaceChildren(), n.count.textContent = String(r.length), r.length === 0) {
1709
- n.list.appendChild(di("加载 CAD 文档后显示图层。"));
2163
+ const r = e.filterText.trim().toLowerCase(), s = t.layers.rows, o = wi(t.blocks);
2164
+ if (n.list.replaceChildren(), n.count.textContent = String(s.length), s.length === 0) {
2165
+ n.list.appendChild(Mi(i.t("layer.empty")));
1710
2166
  return;
1711
2167
  }
1712
- const o = /* @__PURE__ */ new Set(), c = /* @__PURE__ */ new Set();
1713
- for (const p of r) {
1714
- o.add(p.index);
1715
- for (const m of s.get(p.index) ?? []) c.add(m.key);
2168
+ const a = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Set();
2169
+ for (const y of s) {
2170
+ a.add(y.index);
2171
+ for (const m of o.get(y.index) ?? []) d.add(m.key);
1716
2172
  }
1717
- e.prune(o, c);
1718
- const l = (f = t.selection) == null ? void 0 : f.id, d = l ? `${l.layerIndex}:${l.variantId}:${l.instanceId}` : null;
1719
- l && d && e.needsSelectionReveal(d) ? e.ensureSelectionVisible(d, l.layerIndex, l.variantId) : l || e.clearSelectionReveal();
1720
- const h = document.createElement("div");
1721
- h.className = "vui-lrow vui-lrow-all", h.innerHTML = `
2173
+ e.prune(a, d);
2174
+ const l = (v = t.selection) == null ? void 0 : v.id, h = l ? `${l.layerIndex}:${l.variantId}:${l.instanceId}` : null;
2175
+ l && h && e.needsSelectionReveal(h) ? e.ensureSelectionVisible(h, l.layerIndex, l.variantId) : l || e.clearSelectionReveal();
2176
+ const u = document.createElement("div");
2177
+ u.className = "vui-lrow vui-lrow-all", u.innerHTML = `
1722
2178
  <span class="vui-lrow-eye">◎</span>
1723
2179
  <span class="vui-lrow-dot"></span>
1724
2180
  <span class="vui-lrow-toggle placeholder">▶</span>
1725
- <span class="vui-lrow-name">全部图层</span>
1726
- <span class="vui-lrow-clr" style="background: ${t.layers.allColor == null ? "#c8c8c8" : `#${t.layers.allColor.toString(16).padStart(6, "0")}`}" title="全部图层颜色覆盖(右键重置)">
2181
+ <span class="vui-lrow-name">${S(i.t("layer.all"))}</span>
2182
+ <span class="vui-lrow-clr" style="background: ${t.layers.allColor == null ? "#c8c8c8" : `#${t.layers.allColor.toString(16).padStart(6, "0")}`}" title="${S(i.t("layer.colorOverrideAll"))}">
1727
2183
  <input type="color" value="#${(t.layers.allColor ?? 13158600).toString(16).padStart(6, "0")}">
1728
2184
  </span>`;
1729
- const u = h.querySelector('input[type="color"]');
1730
- u && u.addEventListener("input", () => {
1731
- var g;
1732
- const p = Number.parseInt(u.value.slice(1), 16), m = Number.isFinite(p) ? p : null;
1733
- if (t.setAllLayerColor) t.setAllLayerColor(m);
1734
- else for (const y of r) t.setLayerColor(y.index, m);
1735
- const b = m === null ? "#c8c8c8" : O(m);
1736
- (g = u.closest(".vui-lrow-clr")) == null || g.style.setProperty("background", b), me(n.list, r, m);
1737
- }), u == null || u.addEventListener("click", (p) => p.stopPropagation());
1738
- const v = h.querySelector(".vui-lrow-clr");
1739
- v && v.addEventListener("contextmenu", (p) => {
2185
+ const p = u.querySelector('input[type="color"]');
2186
+ p && p.addEventListener("input", () => {
2187
+ var f, g, w;
2188
+ const y = Number.parseInt(p.value.slice(1), 16), m = Number.isFinite(y) ? y : null;
2189
+ (f = t.beginLayerColorPreview) == null || f.call(t, p);
2190
+ try {
2191
+ if (t.setAllLayerColor) t.setAllLayerColor(m);
2192
+ else for (const E of s) t.setLayerColor(E.index, m);
2193
+ const x = m === null ? "#c8c8c8" : L(m);
2194
+ (g = p.closest(".vui-lrow-clr")) == null || g.style.setProperty("background", x), be(n.list, s, m);
2195
+ } finally {
2196
+ (w = t.endLayerColorPreview) == null || w.call(t, p);
2197
+ }
2198
+ }), p == null || p.addEventListener("click", (y) => y.stopPropagation());
2199
+ const b = u.querySelector(".vui-lrow-clr");
2200
+ b && b.addEventListener("contextmenu", (y) => {
1740
2201
  var m;
1741
- if (p.preventDefault(), p.stopPropagation(), t.setAllLayerColor) t.setAllLayerColor(null);
1742
- else for (const b of r) t.setLayerColor(b.index, null);
1743
- (m = u == null ? void 0 : u.closest(".vui-lrow-clr")) == null || m.style.setProperty("background", "#c8c8c8"), u && (u.value = "#c8c8c8"), me(n.list, r, null);
1744
- }), n.list.appendChild(h);
1745
- for (const p of r)
1746
- ni(i, p.name) && n.list.appendChild(ci(p, e, t, s.get(p.index) ?? []));
1747
- d && e.needsSelectionReveal(d) && (ue(n.list) && e.markSelectionRevealed(d), typeof requestAnimationFrame == "function" && requestAnimationFrame(() => {
1748
- e.needsSelectionReveal(d) && ue(n.list) && e.markSelectionRevealed(d);
2202
+ if (y.preventDefault(), y.stopPropagation(), t.setAllLayerColor) t.setAllLayerColor(null);
2203
+ else for (const f of s) t.setLayerColor(f.index, null);
2204
+ (m = p == null ? void 0 : p.closest(".vui-lrow-clr")) == null || m.style.setProperty("background", "#c8c8c8"), p && (p.value = "#c8c8c8"), be(n.list, s, null);
2205
+ }), n.list.appendChild(u);
2206
+ for (const y of s)
2207
+ Ci(r, y.name) && n.list.appendChild(ki(y, e, t, o.get(y.index) ?? [], i));
2208
+ h && e.needsSelectionReveal(h) && (fe(n.list) && e.markSelectionRevealed(h), typeof requestAnimationFrame == "function" && requestAnimationFrame(() => {
2209
+ e.needsSelectionReveal(h) && fe(n.list) && e.markSelectionRevealed(h);
1749
2210
  }));
1750
2211
  }
1751
- function O(n) {
2212
+ function L(n) {
1752
2213
  return `#${n.toString(16).padStart(6, "0")}`;
1753
2214
  }
1754
- function Fe(n) {
1755
- return n.color !== null ? O(n.color) : O(De(n.sourceColor));
2215
+ function Q(n) {
2216
+ return n.color !== null ? L(n.color) : L(Oe(n.sourceColor));
1756
2217
  }
1757
- function li(n, e) {
2218
+ function He(n, e) {
1758
2219
  var r;
1759
2220
  (r = n.querySelector(".vui-lrow-dot")) == null || r.style.setProperty("background", e);
1760
2221
  const t = n.querySelector(".vui-lrow-clr");
@@ -1762,219 +2223,209 @@ function li(n, e) {
1762
2223
  const i = n.querySelector('input[type="color"]');
1763
2224
  i && i.value !== e && (i.value = e);
1764
2225
  }
1765
- function me(n, e, t) {
2226
+ function be(n, e, t) {
1766
2227
  const i = new Map(e.map((r) => [r.index, r]));
1767
2228
  n.querySelectorAll(".vui-lrow[data-layer-index]").forEach((r) => {
1768
2229
  const s = i.get(Number(r.dataset.layerIndex));
1769
- s && li(r, t === null ? Fe(s) : O(t));
2230
+ s && He(r, t === null ? Q(s) : L(t));
1770
2231
  });
1771
2232
  }
1772
- function ci(n, e, t, i) {
1773
- const r = i.length > 0, s = e.expandedLayers.has(n.index), o = Fe(n), c = document.createElement("div");
1774
- c.className = "vui-lrow-wrap";
2233
+ function ki(n, e, t, i, r) {
2234
+ const s = i.length > 0, o = e.expandedLayers.has(n.index), a = Q(n), d = document.createElement("div");
2235
+ d.className = "vui-lrow-wrap";
1775
2236
  const l = document.createElement("div");
1776
2237
  l.className = `vui-lrow${n.visible ? "" : " off"}`, l.dataset.layerIndex = String(n.index);
1777
- const d = document.createElement("button");
1778
- d.type = "button", d.className = "vui-lrow-eye", d.textContent = n.visible ? "●" : "○", d.title = n.visible ? "隐藏图层" : "显示图层", d.addEventListener("click", (b) => {
1779
- b.stopPropagation();
2238
+ const h = document.createElement("button");
2239
+ h.type = "button", h.className = "vui-lrow-eye", h.textContent = n.visible ? "●" : "○", h.title = n.visible ? r.t("layer.hide") : r.t("layer.show"), h.addEventListener("click", (f) => {
2240
+ f.stopPropagation();
1780
2241
  const g = !n.visible;
1781
- d.textContent = g ? "●" : "○", d.title = g ? "隐藏图层" : "显示图层", l.classList.toggle("off", !g), t.toggleLayer(n.index);
2242
+ h.textContent = g ? "●" : "○", h.title = g ? r.t("layer.hide") : r.t("layer.show"), l.classList.toggle("off", !g), t.toggleLayer(n.index);
1782
2243
  });
1783
- const h = document.createElement("span");
1784
- h.className = "vui-lrow-dot", h.style.background = o;
1785
- const u = document.createElement("button");
1786
- u.type = "button", u.className = `vui-lrow-toggle${r ? "" : " placeholder"}`, u.textContent = s ? "▼" : "▶", u.disabled = !r;
1787
- const v = (b) => {
1788
- if (b.stopPropagation(), !r) return;
2244
+ const u = document.createElement("span");
2245
+ u.className = "vui-lrow-dot", u.style.background = a;
2246
+ const p = document.createElement("button");
2247
+ p.type = "button", p.className = `vui-lrow-toggle${s ? "" : " placeholder"}`, p.textContent = o ? "▼" : "▶", p.disabled = !s;
2248
+ const b = (f) => {
2249
+ if (f.stopPropagation(), !s) return;
1789
2250
  e.toggleLayerExpanded(n.index);
1790
2251
  const g = e.expandedLayers.has(n.index);
1791
- u.textContent = g ? "▼" : "▶";
1792
- let y = c.querySelector(":scope > .vui-lrow-blocks");
2252
+ p.textContent = g ? "▼" : "▶";
2253
+ let w = d.querySelector(":scope > .vui-lrow-blocks");
1793
2254
  if (g)
1794
- if (y)
1795
- y.classList.add("open");
2255
+ if (w)
2256
+ w.classList.add("open");
1796
2257
  else {
1797
- y = document.createElement("div"), y.className = "vui-lrow-blocks open";
1798
- for (const P of i)
1799
- y.appendChild(ve(P, e, t));
1800
- c.appendChild(y);
2258
+ w = document.createElement("div"), w.className = "vui-lrow-blocks open";
2259
+ for (const x of i)
2260
+ w.appendChild(ge(x, e, t, r));
2261
+ d.appendChild(w);
1801
2262
  }
1802
2263
  else {
1803
- y == null || y.classList.remove("open");
1804
- const P = c.closest(".vui-section-list") ?? c.parentElement;
1805
- P && Ae(P, l, 0);
2264
+ w == null || w.classList.remove("open");
2265
+ const x = d.closest(".vui-section-list") ?? d.parentElement;
2266
+ x && ze(x, l, 0);
1806
2267
  }
1807
2268
  };
1808
- u.addEventListener("click", v);
1809
- const f = document.createElement("span");
1810
- f.className = "vui-lrow-name", f.textContent = n.name || "(unnamed)", f.title = n.name;
1811
- const p = document.createElement("span");
1812
- p.className = "vui-lrow-clr", p.style.background = o, p.title = "覆盖颜色(右键重置)";
2269
+ p.addEventListener("click", b);
2270
+ const v = document.createElement("span");
2271
+ v.className = "vui-lrow-name", v.textContent = n.name || r.t("layer.unnamed"), v.title = n.name;
2272
+ const y = document.createElement("span");
2273
+ y.className = "vui-lrow-clr", y.style.background = a, y.title = r.t("layer.colorOverride");
1813
2274
  const m = document.createElement("input");
1814
- if (m.type = "color", m.value = o, m.addEventListener("input", () => {
1815
- const b = Number.parseInt(m.value.slice(1), 16);
1816
- t.setLayerColor(n.index, Number.isFinite(b) ? b : null), h.style.background = m.value, p.style.background = m.value;
1817
- }), m.addEventListener("click", (b) => b.stopPropagation()), p.addEventListener("contextmenu", (b) => {
1818
- b.preventDefault(), b.stopPropagation(), t.setLayerColor(n.index, null);
1819
- const g = O(De(n.sourceColor));
1820
- m.value = g, h.style.background = g, p.style.background = g;
1821
- }), p.appendChild(m), l.append(d, h, u, f, p), l.addEventListener("click", (b) => {
1822
- const g = b.target;
2275
+ if (m.type = "color", m.value = a, m.addEventListener("input", () => {
2276
+ var g, w;
2277
+ const f = Number.parseInt(m.value.slice(1), 16);
2278
+ (g = t.beginLayerColorPreview) == null || g.call(t, m);
2279
+ try {
2280
+ t.setLayerColor(n.index, Number.isFinite(f) ? f : null), u.style.background = m.value, y.style.background = m.value;
2281
+ } finally {
2282
+ (w = t.endLayerColorPreview) == null || w.call(t, m);
2283
+ }
2284
+ }), m.addEventListener("click", (f) => f.stopPropagation()), y.addEventListener("contextmenu", (f) => {
2285
+ f.preventDefault(), f.stopPropagation(), t.setLayerColor(n.index, null);
2286
+ const g = L(Oe(n.sourceColor));
2287
+ m.value = g, u.style.background = g, y.style.background = g;
2288
+ }), y.appendChild(m), l.append(h, u, p, v, y), l.addEventListener("click", (f) => {
2289
+ const g = f.target;
1823
2290
  if (g instanceof HTMLInputElement && g.type === "color" || g.closest(".vui-lrow-clr") || g.closest(".vui-lrow-toggle") || g.closest(".vui-lrow-eye")) return;
1824
- const y = !n.visible;
1825
- d.textContent = y ? "●" : "○", d.title = y ? "隐藏图层" : "显示图层", l.classList.toggle("off", !y), t.toggleLayer(n.index);
1826
- }), c.appendChild(l), r && s) {
1827
- const b = document.createElement("div");
1828
- b.className = "vui-lrow-blocks open";
2291
+ const w = !n.visible;
2292
+ h.textContent = w ? "●" : "○", h.title = w ? r.t("layer.hide") : r.t("layer.show"), l.classList.toggle("off", !w), t.toggleLayer(n.index);
2293
+ }), d.appendChild(l), s && o) {
2294
+ const f = document.createElement("div");
2295
+ f.className = "vui-lrow-blocks open";
1829
2296
  for (const g of i)
1830
- b.appendChild(ve(g, e, t));
1831
- c.appendChild(b);
2297
+ f.appendChild(ge(g, e, t, r));
2298
+ d.appendChild(f);
1832
2299
  }
1833
- return c;
2300
+ return d;
1834
2301
  }
1835
- function ve(n, e, t) {
1836
- const i = document.createElement("div");
1837
- i.className = "vui-lrow-block-wrap";
1838
- const r = e.expandedBlocks.has(n.key), s = si(n.inserts), o = Le(t.selection, n.layerIndex, n.variantId), c = document.createElement("div");
1839
- c.className = `vui-lrow-block${o ? " active" : ""}${n.canHighlight ? "" : " disabled"}`, c.dataset.variantId = String(n.variantId), c.dataset.layerIndex = String(n.layerIndex), n.canHighlight || (c.title = "该 block 无可高亮几何");
2302
+ function ge(n, e, t, i) {
2303
+ const r = document.createElement("div");
2304
+ r.className = "vui-lrow-block-wrap";
2305
+ const s = e.expandedBlocks.has(n.key), o = Pi(n.inserts), a = Be(t.selection, n.layerIndex, n.variantId), d = document.createElement("div");
2306
+ d.className = `vui-lrow-block${a ? " active" : ""}${n.canHighlight ? "" : " disabled"}`, d.dataset.variantId = String(n.variantId), d.dataset.layerIndex = String(n.layerIndex), n.canHighlight || (d.title = i.t("layer.noHighlightBlock"));
1840
2307
  const l = document.createElement("button");
1841
- l.type = "button", l.className = "vui-lrow-block-visibility", Y(l, s), l.addEventListener("click", (f) => {
1842
- if (f.stopPropagation(), s === "none") {
1843
- const m = e.blockVisibilitySnapshots.get(n.key), b = [];
2308
+ l.type = "button", l.className = "vui-lrow-block-visibility", _(l, o, i), l.addEventListener("click", (v) => {
2309
+ if (v.stopPropagation(), o === "none") {
2310
+ const m = e.blockVisibilitySnapshots.get(n.key), f = [];
1844
2311
  for (const g of n.inserts) {
1845
- const y = (m == null ? void 0 : m.get(g.instanceId)) ?? !0;
1846
- g.visible !== y && b.push({ insertId: g.insertId, visible: y });
2312
+ const w = (m == null ? void 0 : m.get(g.instanceId)) ?? !0;
2313
+ g.visible !== w && f.push({ insertId: g.insertId, visible: w });
1847
2314
  }
1848
- if (Y(l, "all"), i.querySelectorAll(".vui-lrow-insert-visibility").forEach((g) => {
1849
- _(g, !0);
1850
- }), t.batchToggleInserts && b.length > 0)
1851
- t.batchToggleInserts(b);
2315
+ if (_(l, "all", i), r.querySelectorAll(".vui-lrow-insert-visibility").forEach((g) => {
2316
+ X(g, !0, i);
2317
+ }), t.batchToggleInserts && f.length > 0)
2318
+ t.batchToggleInserts(f);
1852
2319
  else
1853
- for (const g of b) t.toggleInsert(g.insertId, g.visible);
2320
+ for (const g of f) t.toggleInsert(g.insertId, g.visible);
1854
2321
  return;
1855
2322
  }
1856
2323
  e.blockVisibilitySnapshots.set(
1857
2324
  n.key,
1858
2325
  new Map(n.inserts.map((m) => [m.instanceId, m.visible]))
1859
2326
  );
1860
- const p = n.inserts.filter((m) => m.visible).map((m) => ({ insertId: m.insertId, visible: !1 }));
1861
- if (Y(l, "none"), i.querySelectorAll(".vui-lrow-insert-visibility").forEach((m) => {
1862
- _(m, !1);
1863
- }), t.batchToggleInserts && p.length > 0)
1864
- t.batchToggleInserts(p);
2327
+ const y = n.inserts.filter((m) => m.visible).map((m) => ({ insertId: m.insertId, visible: !1 }));
2328
+ if (_(l, "none", i), r.querySelectorAll(".vui-lrow-insert-visibility").forEach((m) => {
2329
+ X(m, !1, i);
2330
+ }), t.batchToggleInserts && y.length > 0)
2331
+ t.batchToggleInserts(y);
1865
2332
  else
1866
- for (const m of p) t.toggleInsert(m.insertId, !1);
2333
+ for (const m of y) t.toggleInsert(m.insertId, !1);
1867
2334
  });
1868
- const d = document.createElement("button");
1869
- d.type = "button", d.className = "vui-lrow-block-toggle", d.textContent = r ? "▼" : "▶";
1870
- const h = (f) => {
1871
- f.stopPropagation(), e.toggleBlockExpanded(n.layerIndex, n.variantId);
1872
- const p = e.expandedBlocks.has(n.key);
1873
- d.textContent = p ? "▼" : "▶";
1874
- let m = i.querySelector(":scope > .vui-lrow-inserts");
1875
- if (p)
1876
- m ? m.classList.add("open") : (m = fe(n, e, t, l), i.appendChild(m));
2335
+ const h = document.createElement("button");
2336
+ h.type = "button", h.className = "vui-lrow-block-toggle", h.textContent = s ? "▼" : "▶";
2337
+ const u = (v) => {
2338
+ v.stopPropagation(), e.toggleBlockExpanded(n.layerIndex, n.variantId);
2339
+ const y = e.expandedBlocks.has(n.key);
2340
+ h.textContent = y ? "▼" : "▶";
2341
+ let m = r.querySelector(":scope > .vui-lrow-inserts");
2342
+ if (y)
2343
+ m ? m.classList.add("open") : (m = ye(n, e, t, l, i), r.appendChild(m));
1877
2344
  else {
1878
2345
  m == null || m.classList.remove("open");
1879
- const b = i.closest(".vui-section-list") ?? i.parentElement;
1880
- b && Ae(b, c, 24);
2346
+ const f = r.closest(".vui-section-list") ?? r.parentElement;
2347
+ f && ze(f, d, 24);
1881
2348
  }
1882
2349
  };
1883
- d.addEventListener("click", h);
1884
- const u = document.createElement("span");
1885
- u.className = "vui-lrow-block-name", u.textContent = n.blockName, u.title = n.blockName;
1886
- const v = document.createElement("span");
1887
- return v.className = "vui-lrow-block-count", v.textContent = `×${n.inserts.length}`, c.append(l, d, u, v), n.inserts.length === 1 && c.addEventListener("click", () => {
2350
+ h.addEventListener("click", u);
2351
+ const p = document.createElement("span");
2352
+ p.className = "vui-lrow-block-name", p.textContent = n.blockName, p.title = n.blockName;
2353
+ const b = document.createElement("span");
2354
+ return b.className = "vui-lrow-block-count", b.textContent = `×${n.inserts.length}`, d.append(l, h, p, b), n.inserts.length === 1 && d.addEventListener("click", () => {
1888
2355
  if (!n.canHighlight) return;
1889
- const f = n.inserts[0], p = `${n.layerIndex}:${n.variantId}:${f.instanceId}`;
1890
- e.markSelectionRevealed(p), t.selectInsert(f.insertId);
1891
- }), i.appendChild(c), r && i.appendChild(fe(n, e, t, l)), i;
1892
- }
1893
- function fe(n, e, t, i) {
1894
- const r = document.createElement("div");
1895
- r.className = "vui-lrow-inserts open";
1896
- for (const s of n.inserts) {
1897
- const o = document.createElement("div");
1898
- o.className = `vui-lrow-insert${Le(t.selection, n.layerIndex, n.variantId, s.instanceId) ? " active" : ""}${s.canHighlight === !1 ? " disabled" : ""}`, o.dataset.layerIndex = String(n.layerIndex), o.dataset.variantId = String(n.variantId), o.dataset.instanceId = String(s.instanceId), o.dataset.insertId = s.insertId, s.canHighlight === !1 && (o.title = "该 insert 无可高亮几何");
1899
- const c = document.createElement("button");
1900
- c.type = "button", c.className = "vui-lrow-insert-visibility", _(c, s.visible), c.addEventListener("click", (d) => {
1901
- d.stopPropagation();
1902
- const h = !s.visible;
1903
- _(c, h);
1904
- const u = r.querySelectorAll(".vui-lrow-insert-visibility");
1905
- let v = 0;
1906
- u.forEach((p) => {
1907
- p.dataset.visible === "1" && v++;
2356
+ const v = n.inserts[0], y = `${n.layerIndex}:${n.variantId}:${v.instanceId}`;
2357
+ e.markSelectionRevealed(y), t.selectInsert(v.insertId);
2358
+ }), r.appendChild(d), s && r.appendChild(ye(n, e, t, l, i)), r;
2359
+ }
2360
+ function ye(n, e, t, i, r) {
2361
+ const s = document.createElement("div");
2362
+ s.className = "vui-lrow-inserts open";
2363
+ for (const o of n.inserts) {
2364
+ const a = document.createElement("div");
2365
+ a.className = `vui-lrow-insert${Be(t.selection, n.layerIndex, n.variantId, o.instanceId) ? " active" : ""}${o.canHighlight === !1 ? " disabled" : ""}`, a.dataset.layerIndex = String(n.layerIndex), a.dataset.variantId = String(n.variantId), a.dataset.instanceId = String(o.instanceId), a.dataset.insertId = o.insertId, o.canHighlight === !1 && (a.title = r.t("layer.noHighlightInsert"));
2366
+ const d = document.createElement("button");
2367
+ d.type = "button", d.className = "vui-lrow-insert-visibility", X(d, o.visible, r), d.addEventListener("click", (h) => {
2368
+ h.stopPropagation();
2369
+ const u = !o.visible;
2370
+ X(d, u, r);
2371
+ const p = s.querySelectorAll(".vui-lrow-insert-visibility");
2372
+ let b = 0;
2373
+ p.forEach((y) => {
2374
+ y.dataset.visible === "1" && b++;
1908
2375
  });
1909
- const f = v === 0 ? "none" : v === u.length ? "all" : "mixed";
1910
- Y(i, f), t.toggleInsert(s.insertId, h);
2376
+ const v = b === 0 ? "none" : b === p.length ? "all" : "mixed";
2377
+ _(i, v, r), t.toggleInsert(o.insertId, u);
1911
2378
  });
1912
2379
  const l = document.createElement("span");
1913
- l.className = "vui-lrow-insert-label", l.textContent = s.label, l.title = s.label, o.append(c, l), o.addEventListener("click", () => {
1914
- if (s.canHighlight === !1) return;
1915
- const d = `${n.layerIndex}:${n.variantId}:${s.instanceId}`;
1916
- e.markSelectionRevealed(d), t.selectInsert(s.insertId);
1917
- }), r.appendChild(o);
2380
+ l.className = "vui-lrow-insert-label", l.textContent = o.label, l.title = o.label, a.append(d, l), a.addEventListener("click", () => {
2381
+ if (o.canHighlight === !1) return;
2382
+ const h = `${n.layerIndex}:${n.variantId}:${o.instanceId}`;
2383
+ e.markSelectionRevealed(h), t.selectInsert(o.insertId);
2384
+ }), s.appendChild(a);
1918
2385
  }
1919
- return r;
2386
+ return s;
1920
2387
  }
1921
- function di(n) {
2388
+ function Mi(n) {
1922
2389
  const e = document.createElement("div");
1923
2390
  return e.className = "vui-empty-note", e.textContent = n, e;
1924
2391
  }
1925
- function hi(n, e) {
2392
+ function Ti(n, e) {
1926
2393
  const t = () => {
1927
2394
  e(n.value);
1928
2395
  };
1929
2396
  return n.addEventListener("input", t), () => n.removeEventListener("input", t);
1930
2397
  }
1931
- function F(n) {
1932
- return n.replace(/[&<>"']/g, (e) => ({
1933
- "&": "&amp;",
1934
- "<": "&lt;",
1935
- ">": "&gt;",
1936
- '"': "&quot;",
1937
- "'": "&#39;"
1938
- })[e] ?? e);
1939
- }
1940
- function K(n) {
1941
- return n == null || !Number.isFinite(n) ? "—" : n.toFixed(4).replace(/\.0+$/, "").replace(/(\.\d*?)0+$/, "$1");
1942
- }
1943
- function I(n, e) {
1944
- const t = K(n);
1945
- return t === "—" ? t : `${t} ${e}`;
1946
- }
1947
- function be(n, e) {
2398
+ function xe(n, e, t = J, i = "mm") {
1948
2399
  if (n.body.replaceChildren(), e.textSelection && e.textDetails) {
1949
- D(n, !1), pi(n.body, e.textDetails), ge(n.body);
2400
+ D(n, !1), Ai(n.body, e.textDetails, t, i), we(n.body);
1950
2401
  return;
1951
2402
  }
1952
2403
  if (!e.selection || !e.details) {
1953
- D(n, !1), n.body.appendChild(mi("点击画布中的对象查看属性"));
2404
+ D(n, !1), n.body.appendChild(Li(t.t("property.empty")));
1954
2405
  return;
1955
2406
  }
1956
- ui(n.body, e.details), ge(n.body);
2407
+ Di(n.body, e.details, t, i), we(n.body);
1957
2408
  }
1958
2409
  function D(n, e) {
1959
2410
  if (!n.previewWrap || !n.previewCanvas || (n.previewWrap.hidden = !e, e)) return;
1960
2411
  const t = n.previewCanvas.getContext("2d");
1961
2412
  t == null || t.clearRect(0, 0, n.previewCanvas.width, n.previewCanvas.height);
1962
2413
  }
1963
- function ui(n, e) {
1964
- Ne(n, "INSERT", e.blockName), G(n, "基本", (t) => {
1965
- C(t, "Block", e.blockName), C(t, "图层", e.layerName), C(t, "Instance", `#${e.id.instanceId}`), C(t, "当前形态", "普通图形");
1966
- }), G(n, "变换", (t) => {
1967
- C(t, "X", I(e.tx, "mm")), C(t, "Y", I(e.ty, "mm")), C(t, "旋转", I(e.rotation, "°")), C(t, "Sx", K(e.scaleX)), C(t, "Sy", K(e.scaleY));
2414
+ function Di(n, e, t, i) {
2415
+ _e(n, t.t("property.insert"), e.blockName), G(n, t.t("property.basic"), (r) => {
2416
+ P(r, t.t("property.block"), e.blockName), P(r, t.t("property.layer"), e.layerName), P(r, t.t("property.instance"), `#${e.id.instanceId}`), P(r, t.t("property.currentShape"), t.t("property.normalShape"));
2417
+ }), G(n, t.t("property.transform"), (r) => {
2418
+ P(r, "X", t.formatUnit(e.tx, i)), P(r, "Y", t.formatUnit(e.ty, i)), P(r, t.t("property.rotation"), t.formatUnit(e.rotation, "°")), P(r, "Sx", t.formatNumber(e.scaleX)), P(r, "Sy", t.formatNumber(e.scaleY));
1968
2419
  });
1969
2420
  }
1970
- function pi(n, e) {
1971
- Ne(n, "文本", e.content), G(n, "基本", (t) => {
1972
- C(t, "图层", e.layerName), C(t, "内容", e.content), C(t, "高度", I(e.height, "mm")), C(t, "X", I(e.x, "mm")), C(t, "Y", I(e.y, "mm")), C(t, "旋转", I(e.rotation, "°"));
2421
+ function Ai(n, e, t, i) {
2422
+ _e(n, t.t("property.text"), e.content), G(n, t.t("property.basic"), (r) => {
2423
+ P(r, t.t("property.layer"), e.layerName), P(r, t.t("property.content"), e.content), P(r, t.t("property.height"), t.formatUnit(e.height, i)), P(r, "X", t.formatUnit(e.x, i)), P(r, "Y", t.formatUnit(e.y, i)), P(r, t.t("property.rotation"), t.formatUnit(e.rotation, "°"));
1973
2424
  });
1974
2425
  }
1975
- function Ne(n, e, t) {
2426
+ function _e(n, e, t) {
1976
2427
  const i = document.createElement("div");
1977
- i.className = "vui-pp-section vui-pp-title-row", i.innerHTML = `<strong>${F(e)}</strong><span>·</span><span>${F(t)}</span>`, n.appendChild(i);
2428
+ i.className = "vui-pp-section vui-pp-title-row", i.innerHTML = `<strong>${S(e)}</strong><span>·</span><span>${S(t)}</span>`, n.appendChild(i);
1978
2429
  }
1979
2430
  function G(n, e, t) {
1980
2431
  const i = document.createElement("section");
@@ -1982,15 +2433,15 @@ function G(n, e, t) {
1982
2433
  const r = document.createElement("div");
1983
2434
  r.className = "vui-pp-section-label", r.textContent = e, i.appendChild(r), t(i), n.appendChild(i);
1984
2435
  }
1985
- function C(n, e, t) {
2436
+ function P(n, e, t) {
1986
2437
  const i = document.createElement("div");
1987
- i.className = "vui-pp-row", i.innerHTML = `<span class="label">${F(e)}</span><span class="value" title="${F(t)}">${F(t)}</span>`, n.appendChild(i);
2438
+ i.className = "vui-pp-row", i.innerHTML = `<span class="label">${S(e)}</span><span class="value" title="${S(t)}">${S(t)}</span>`, n.appendChild(i);
1988
2439
  }
1989
- function mi(n) {
2440
+ function Li(n) {
1990
2441
  const e = document.createElement("div");
1991
2442
  return e.className = "vui-empty-note", e.textContent = n, e;
1992
2443
  }
1993
- function ge(n) {
2444
+ function we(n) {
1994
2445
  if (n.querySelector('input:not([type="color"])'))
1995
2446
  throw new Error("Property panel must not contain editable inputs");
1996
2447
  if (n.querySelector('[contenteditable=""], [contenteditable="true"]'))
@@ -1998,17 +2449,17 @@ function ge(n) {
1998
2449
  if (n.querySelector("textarea"))
1999
2450
  throw new Error("Property panel must not contain textarea elements");
2000
2451
  }
2001
- const vi = typeof requestAnimationFrame == "function" ? requestAnimationFrame.bind(globalThis) : (n) => globalThis.setTimeout(() => n(performance.now()), 16), fi = typeof cancelAnimationFrame == "function" ? cancelAnimationFrame.bind(globalThis) : (n) => {
2452
+ const Fi = typeof requestAnimationFrame == "function" ? requestAnimationFrame.bind(globalThis) : (n) => globalThis.setTimeout(() => n(performance.now()), 16), Oi = typeof cancelAnimationFrame == "function" ? cancelAnimationFrame.bind(globalThis) : (n) => {
2002
2453
  globalThis.clearTimeout(n);
2003
2454
  };
2004
- class bi {
2455
+ class Ni {
2005
2456
  constructor(e) {
2006
- a(this, "onFlush");
2007
- a(this, "requestFrame");
2008
- a(this, "cancelFrame");
2009
- a(this, "pending", /* @__PURE__ */ new Map());
2010
- a(this, "scheduledHandle", null);
2011
- this.onFlush = e.onFlush, this.requestFrame = e.requestFrame ?? vi, this.cancelFrame = e.cancelFrame ?? fi;
2457
+ c(this, "onFlush");
2458
+ c(this, "requestFrame");
2459
+ c(this, "cancelFrame");
2460
+ c(this, "pending", /* @__PURE__ */ new Map());
2461
+ c(this, "scheduledHandle", null);
2462
+ this.onFlush = e.onFlush, this.requestFrame = e.requestFrame ?? Fi, this.cancelFrame = e.cancelFrame ?? Oi;
2012
2463
  }
2013
2464
  enqueue(e, t) {
2014
2465
  this.pending.set(e, t), this.scheduledHandle === null && (this.scheduledHandle = this.requestFrame(() => {
@@ -2032,7 +2483,7 @@ class bi {
2032
2483
  this.pending.clear(), this.scheduledHandle !== null && (this.cancelFrame(this.scheduledHandle), this.scheduledHandle = null);
2033
2484
  }
2034
2485
  }
2035
- const gi = `
2486
+ const Vi = `
2036
2487
  :host {
2037
2488
  display: block;
2038
2489
  width: 100%;
@@ -2896,7 +3347,7 @@ button, input { font: inherit; }
2896
3347
  .vui-infobar-content { max-width: calc(100vw - 48px); }
2897
3348
  .vui-infobar-tools .vui-info-text { max-width: min(180px, 45vw); }
2898
3349
  }
2899
- `, yi = {
3350
+ `, Bi = {
2900
3351
  dark: `
2901
3352
  :host, .vui-root[data-theme="dark"] {
2902
3353
  --vui-bg: #0A0B0F;
@@ -3006,10 +3457,24 @@ button, input { font: inherit; }
3006
3457
  }
3007
3458
  `
3008
3459
  };
3009
- function xi(n = "dark") {
3010
- return `${yi[n]}${gi}`;
3011
- }
3012
- const wi = {
3460
+ function zi(n = "dark", e = {}) {
3461
+ const t = {
3462
+ accent: "--vui-accent",
3463
+ panelBackground: "--vui-bg2",
3464
+ background: "--vui-bg",
3465
+ text: "--vui-text",
3466
+ textDim: "--vui-text-dim",
3467
+ border: "--vui-border",
3468
+ hudBackground: "--vui-hud-bg"
3469
+ }, i = Object.entries(e).filter(([, r]) => typeof r == "string" && r.trim().length > 0).map(([r, s]) => `${t[r]}: ${s};`).join(`
3470
+ `);
3471
+ return `${Bi[n]}${i ? `
3472
+ :host, .vui-root[data-theme="${n}"] {
3473
+ ${i}
3474
+ }
3475
+ ` : ""}${Vi}`;
3476
+ }
3477
+ const Hi = {
3013
3478
  layerPanel: !0,
3014
3479
  propertyPanel: !0,
3015
3480
  hud: !0,
@@ -3019,7 +3484,8 @@ const wi = {
3019
3484
  infobarLineMode: !0,
3020
3485
  infobarPhase: !0,
3021
3486
  infobarDebug: !0
3022
- }, ye = "dxf-parser:reference-property-panel:open", xe = "dxf-parser:reference-layer-panel:open", we = 300, Ce = 180, Ci = 2;
3487
+ }, Ce = "property-panel:open", Pe = "layer-panel:open", Se = 300, Ee = 180, _i = 2;
3488
+ let Yi = 0;
3023
3489
  function T(n, ...e) {
3024
3490
  const t = document.createElement("div");
3025
3491
  t.className = "vui-debug-row";
@@ -3028,7 +3494,7 @@ function T(n, ...e) {
3028
3494
  const r = document.createElement("div");
3029
3495
  return r.className = "vui-debug-value", r.append(...e), t.append(i, r), t;
3030
3496
  }
3031
- function Pe(n, e, t) {
3497
+ function Ie(n, e, t) {
3032
3498
  const i = document.createElement("div");
3033
3499
  i.className = "vui-debug-spread";
3034
3500
  const r = document.createElement("b");
@@ -3040,131 +3506,190 @@ function Pe(n, e, t) {
3040
3506
  }
3041
3507
  return i;
3042
3508
  }
3043
- function Se(n) {
3509
+ function Re(n) {
3044
3510
  const e = document.createElement("div");
3045
3511
  return e.className = "vui-debug-spread-list", e.append(...n), e;
3046
3512
  }
3047
- function Pi(n) {
3513
+ function Xi(n, e) {
3048
3514
  switch (n) {
3049
3515
  case "created":
3050
- return "状态 创建";
3516
+ return e.t("status.created");
3051
3517
  case "header-ready":
3052
- return "状态 头部就绪";
3518
+ return e.t("status.headerReady");
3053
3519
  case "initial-loading":
3054
- return "状态 加载中";
3520
+ return e.t("status.initialLoading");
3055
3521
  case "interactive":
3056
- return "状态 就绪";
3522
+ return e.t("status.interactive");
3057
3523
  case "failed":
3058
- return "状态 失败";
3524
+ return e.t("status.failed");
3059
3525
  case "disposed":
3060
- return "状态 已关闭";
3526
+ return e.t("status.disposed");
3061
3527
  default:
3062
3528
  return "";
3063
3529
  }
3064
3530
  }
3065
- class Si {
3531
+ function ke(n) {
3532
+ return (typeof n.composedPath == "function" ? n.composedPath() : [n.target]).some((t) => {
3533
+ var o, a;
3534
+ if (!t || typeof t != "object") return !1;
3535
+ const i = t, r = (o = i.tagName) == null ? void 0 : o.toLowerCase();
3536
+ if (r === "input" || r === "textarea" || r === "select" || i.isContentEditable) return !0;
3537
+ const s = (a = i.getAttribute) == null ? void 0 : a.call(i, "contenteditable");
3538
+ return s === "" || s === "true" || s === "plaintext-only";
3539
+ });
3540
+ }
3541
+ class Ui {
3066
3542
  constructor(e, t) {
3067
- a(this, "parts");
3068
- a(this, "layerPanelState", new ii());
3069
- a(this, "shadow", null);
3070
- a(this, "layerPanelRefs", null);
3071
- a(this, "propertyPanelRefs", null);
3072
- a(this, "scalebarRefs", null);
3073
- a(this, "infobarRefs", null);
3074
- a(this, "btnFit", null);
3075
- a(this, "btnView2d", null);
3076
- a(this, "btnView3d", null);
3077
- a(this, "layerPanelShell", null);
3078
- a(this, "layerPanelToggle", null);
3079
- a(this, "infobar", null);
3080
- a(this, "infobarToggle", null);
3081
- a(this, "propertyPanelShell", null);
3082
- a(this, "propertyPanelToggle", null);
3083
- a(this, "propertyPanelAutoOpened", !1);
3084
- a(this, "propertyPreviewRenderHandle", null);
3085
- a(this, "propertyPreviewLayoutWaitAbort", null);
3086
- a(this, "propertyPreviewKey", null);
3087
- a(this, "toolbarInfoText", null);
3088
- a(this, "handleKeyDown", (e) => {
3089
- this.disposed || e.defaultPrevented || (e.key === "f" || e.key === "F") && this.host.fitView();
3543
+ c(this, "parts");
3544
+ c(this, "text");
3545
+ c(this, "layerPanelState", new pi());
3546
+ c(this, "shadow", null);
3547
+ c(this, "layerPanelRefs", null);
3548
+ c(this, "propertyPanelRefs", null);
3549
+ c(this, "scalebarRefs", null);
3550
+ c(this, "infobarRefs", null);
3551
+ c(this, "btnFit", null);
3552
+ c(this, "btnView2d", null);
3553
+ c(this, "btnView3d", null);
3554
+ c(this, "layerPanelShell", null);
3555
+ c(this, "layerPanelToggle", null);
3556
+ c(this, "infobar", null);
3557
+ c(this, "infobarToggle", null);
3558
+ c(this, "propertyPanelShell", null);
3559
+ c(this, "propertyPanelToggle", null);
3560
+ c(this, "propertyPanelAutoOpened", !1);
3561
+ c(this, "propertyPreviewRenderHandle", null);
3562
+ c(this, "propertyPreviewLayoutWaitAbort", null);
3563
+ c(this, "propertyPreviewKey", null);
3564
+ c(this, "layoutResizeObserver", null);
3565
+ c(this, "lastLayoutFingerprint", null);
3566
+ c(this, "toolbarInfoText", null);
3567
+ c(this, "keyboardTarget", null);
3568
+ c(this, "keyboardTargetTabIndexAdded", !1);
3569
+ c(this, "activeLayerColorPreview", null);
3570
+ c(this, "renderedLayerRows", null);
3571
+ c(this, "handleKeyDown", (e) => {
3572
+ if (this.disposed || e.defaultPrevented || e.altKey || e.ctrlKey || e.metaKey || ke(e)) return;
3573
+ const t = this.getFitShortcut();
3574
+ t && e.key.toLowerCase() === t.toLowerCase() && this.host.fitSelectionOrDocument();
3575
+ });
3576
+ c(this, "handleKeyboardTargetPointerDown", (e) => {
3577
+ var t, i;
3578
+ this.disposed || ke(e) || (i = (t = this.keyboardTarget) == null ? void 0 : t.focus) == null || i.call(t, { preventScroll: !0 });
3090
3579
  });
3091
- a(this, "unsubscribers", []);
3092
- a(this, "filterCleanup", null);
3093
- a(this, "disposed", !1);
3094
- a(this, "insertToggleScheduler", new bi({
3580
+ c(this, "unsubscribers", []);
3581
+ c(this, "filterCleanup", null);
3582
+ c(this, "disposed", !1);
3583
+ c(this, "persistenceNamespace");
3584
+ c(this, "insertToggleScheduler", new Ni({
3095
3585
  onFlush: (e) => {
3096
- var t, i;
3097
- (i = (t = this.host.cad.blocks).batchToggleInserts) == null || i.call(t, e);
3586
+ this.host.cad.blocks.batchToggleInserts(e);
3098
3587
  }
3099
3588
  }));
3100
- a(this, "refresh", () => {
3101
- this.disposed || (this.syncToolbarState(), this.layerPanelRefs && this.parts.layerPanel && pe(this.layerPanelRefs, this.layerPanelState, this.createLayerPanelActions()), this.propertyPanelRefs && this.parts.propertyPanel && (be(this.propertyPanelRefs, this.host.cad.inspector), this.syncPropertyPanelSelectionState(), this.syncPropertyPanelPreview()), this.syncHud());
3589
+ c(this, "refresh", () => {
3590
+ this.disposed || (this.syncToolbarState(), this.renderLayerPanel(), this.propertyPanelRefs && this.parts.propertyPanel && (xe(this.propertyPanelRefs, this.host.cad.inspector, this.text, this.getCadUnit()), this.syncPropertyPanelSelectionState(), this.syncPropertyPanelPreview()), this.syncHud());
3102
3591
  });
3103
- a(this, "syncHud", () => {
3592
+ c(this, "syncHud", () => {
3104
3593
  var e;
3105
3594
  if (!this.disposed) {
3106
3595
  if (this.infobarRefs && this.parts.hud) {
3107
3596
  const t = this.host.cad.hud;
3108
- this.infobarRefs.file.textContent = t.filename ?? "", this.infobarRefs.file.title = t.filename ?? "", this.infobarRefs.file.hidden = !t.filename, this.infobarRefs.zoom.textContent = t.zoomLabel ? `缩放 ${t.zoomLabel}` : "", this.infobarRefs.zoom.hidden = !t.zoomLabel, this.infobarRefs.vertices.textContent = t.viewportVertexCount > 0 ? `顶点 ${t.viewportVertexCount.toLocaleString()}` : "", this.infobarRefs.vertices.hidden = t.viewportVertexCount <= 0, this.infobarRefs.drawCalls.textContent = t.drawCalls > 0 ? `DrawCalls ${t.drawCalls}` : "", this.infobarRefs.drawCalls.hidden = t.drawCalls <= 0, this.infobarRefs.lineMode.textContent = this.parts.infobarLineMode && t.lineRenderMode ? `线模式 ${t.lineRenderMode.toUpperCase()}` : "", this.infobarRefs.lineMode.hidden = !this.infobarRefs.lineMode.textContent, this.infobarRefs.phase.textContent = this.parts.infobarPhase ? Pi(t.phase) : "", this.infobarRefs.phase.hidden = !this.infobarRefs.phase.textContent;
3597
+ this.infobarRefs.file.textContent = t.filename ?? "", this.infobarRefs.file.title = t.filename ?? "", this.infobarRefs.file.hidden = !t.filename, this.infobarRefs.zoom.textContent = t.zoomLabel ? this.text.t("toolbar.zoom", { value: t.zoomLabel }) : "", this.infobarRefs.zoom.hidden = !t.zoomLabel, this.infobarRefs.vertices.textContent = t.viewportVertexCount > 0 ? this.text.t("toolbar.vertices", { value: this.text.formatInteger(t.viewportVertexCount) }) : "", this.infobarRefs.vertices.hidden = t.viewportVertexCount <= 0, this.infobarRefs.drawCalls.textContent = t.drawCalls > 0 ? this.text.t("toolbar.drawCalls", { value: this.text.formatInteger(t.drawCalls) }) : "", this.infobarRefs.drawCalls.hidden = t.drawCalls <= 0, this.infobarRefs.lineMode.textContent = this.parts.infobarLineMode && t.lineRenderMode ? this.text.t("toolbar.lineMode", { value: t.lineRenderMode.toUpperCase() }) : "", this.infobarRefs.lineMode.hidden = !this.infobarRefs.lineMode.textContent, this.infobarRefs.phase.textContent = this.parts.infobarPhase ? Xi(t.phase, this.text) : "", this.infobarRefs.phase.hidden = !this.infobarRefs.phase.textContent;
3109
3598
  const i = Math.round(t.fps);
3110
- this.infobarRefs.fps.textContent = i > 0 ? `${i} FPS` : "— FPS", this.infobarRefs.fps.classList.toggle("hi", i >= 55), this.infobarRefs.fps.classList.toggle("mid", i >= 30 && i < 55), this.infobarRefs.fps.classList.toggle("low", i < 30);
3599
+ this.infobarRefs.fps.textContent = i > 0 ? this.text.t("toolbar.fps", { value: i }) : this.text.t("toolbar.fpsEmpty"), this.infobarRefs.fps.classList.toggle("hi", i >= 55), this.infobarRefs.fps.classList.toggle("mid", i >= 30 && i < 55), this.infobarRefs.fps.classList.toggle("low", i < 30);
3111
3600
  const r = t.blockVariantCount > 0 || t.splitBlockLayerGroupCount > 0 || t.entityCount > 0;
3112
3601
  if (this.infobarRefs.debugCard.hidden = !this.parts.infobarDebug || !r, this.infobarRefs.debugCard.hidden)
3113
3602
  this.infobarRefs.debugCard.open = !1, this.infobarRefs.debugSummary.textContent = "", this.infobarRefs.debugBody.replaceChildren();
3114
3603
  else {
3115
- this.infobarRefs.debugSummary.textContent = `Debug · Block ${t.blockVariantCount} · 跨层 ${t.splitBlockLayerGroupCount}`;
3116
- const s = t.renderDebugBreakdown.map((d) => Pe(
3117
- d.label,
3118
- `${d.renderables.toLocaleString()} call-ish / ${d.submittedVertexRefs.toLocaleString()} vertices`
3604
+ this.infobarRefs.debugSummary.textContent = this.text.t("toolbar.debugSummary", {
3605
+ blocks: this.text.formatInteger(t.blockVariantCount),
3606
+ split: this.text.formatInteger(t.splitBlockLayerGroupCount)
3607
+ });
3608
+ const s = t.renderDebugBreakdown.map((l) => Ie(
3609
+ l.label,
3610
+ this.text.t("toolbar.debug.breakdown", {
3611
+ renderables: this.text.formatInteger(l.renderables),
3612
+ vertices: this.text.formatInteger(l.submittedVertexRefs)
3613
+ })
3119
3614
  )), o = [
3120
- `${t.renderableCount.toLocaleString()} renderables / ${t.drawCalls.toLocaleString()} calls`
3615
+ this.text.t("toolbar.debug.renderables", {
3616
+ renderables: this.text.formatInteger(t.renderableCount),
3617
+ calls: this.text.formatInteger(t.drawCalls)
3618
+ })
3121
3619
  ];
3122
- s.length > 0 && o.push(Se(s));
3123
- const c = t.splitBlockLayerDetails.map((d) => Pe(
3124
- `${d.blockName} #${d.variantId}`,
3125
- `${d.layerCount.toLocaleString()} layer / ${d.instanceCount.toLocaleString()} insert`,
3126
- d.layers.join(", ")
3620
+ s.length > 0 && o.push(Re(s));
3621
+ const a = t.splitBlockLayerDetails.map((l) => Ie(
3622
+ `${l.blockName} #${l.variantId}`,
3623
+ this.text.t("toolbar.debug.spreadMeta", {
3624
+ layers: this.text.formatInteger(l.layerCount),
3625
+ instances: this.text.formatInteger(l.instanceCount)
3626
+ }),
3627
+ l.layers.join(", ")
3127
3628
  ));
3128
3629
  if (t.splitBlockLayerDetails.length < t.splitBlockLayerGroupCount) {
3129
- const d = document.createElement("div");
3130
- d.className = "vui-debug-spread vui-debug-spread-muted", d.textContent = `另有 ${(t.splitBlockLayerGroupCount - t.splitBlockLayerDetails.length).toLocaleString()} 个跨层 block`, c.push(d);
3630
+ const l = document.createElement("div");
3631
+ l.className = "vui-debug-spread vui-debug-spread-muted", l.textContent = this.text.t("toolbar.debug.moreSplitLayers", {
3632
+ count: this.text.formatInteger(t.splitBlockLayerGroupCount - t.splitBlockLayerDetails.length)
3633
+ }), a.push(l);
3131
3634
  }
3132
- const l = [`跨层 ${t.splitBlockLayerGroupCount.toLocaleString()}`];
3133
- c.length > 0 && l.push(Se(c)), this.infobarRefs.debugBody.replaceChildren(
3134
- T("提交", t.submittedVertexRefs.toLocaleString()),
3135
- ...t.lineRenderMode ? [T("线模式", t.lineRenderMode.toUpperCase())] : [],
3136
- T("图层", `${t.visibleLayerCount.toLocaleString()} / ${t.totalLayerCount.toLocaleString()}`),
3137
- T("DrawCall 来源", ...o),
3138
- T("Block", `${t.blockVariantCount.toLocaleString()} / INSERT ${t.blockInstanceCount.toLocaleString()}`),
3139
- T("分散 layer", ...l)
3635
+ const d = [this.text.t("toolbar.debug.splitLayerCount", {
3636
+ count: this.text.formatInteger(t.splitBlockLayerGroupCount)
3637
+ })];
3638
+ a.length > 0 && d.push(Re(a)), this.infobarRefs.debugBody.replaceChildren(
3639
+ T("" + this.text.t("toolbar.debug.submitted"), this.text.formatInteger(t.submittedVertexRefs)),
3640
+ ...t.lineRenderMode ? [T(this.text.t("toolbar.debug.lineMode"), t.lineRenderMode.toUpperCase())] : [],
3641
+ T(this.text.t("toolbar.debug.layers"), this.text.t("toolbar.debug.layerCount", {
3642
+ visible: this.text.formatInteger(t.visibleLayerCount),
3643
+ total: this.text.formatInteger(t.totalLayerCount)
3644
+ })),
3645
+ T(this.text.t("toolbar.debug.drawCallSource"), ...o),
3646
+ T(this.text.t("toolbar.debug.block"), this.text.t("toolbar.debug.blockCount", {
3647
+ variants: this.text.formatInteger(t.blockVariantCount),
3648
+ instances: this.text.formatInteger(t.blockInstanceCount)
3649
+ })),
3650
+ T(this.text.t("toolbar.debug.splitLayer"), ...d)
3140
3651
  );
3141
3652
  }
3142
3653
  }
3143
3654
  if (this.toolbarInfoText) {
3144
- const t = this.host.cad.hud, i = t.fileCount > 0 ? `${t.visibleLayerCount.toLocaleString()} / ${t.totalLayerCount.toLocaleString()} 图层` : "", r = t.statusMessage.trim();
3655
+ const t = this.host.cad.hud, i = t.fileCount > 0 ? this.text.t("toolbar.layerSummary", {
3656
+ visible: this.text.formatInteger(t.visibleLayerCount),
3657
+ total: this.text.formatInteger(t.totalLayerCount)
3658
+ }) : "", r = xi(t.statusMessage, this.text);
3145
3659
  this.toolbarInfoText.textContent = i && r ? `${i} | ${r}` : i || r;
3146
3660
  }
3147
- this.scalebarRefs && (this.host.viewMode === "2d" && ((e = this.host.cad.hud.scaleRuler) != null && e.visible) ? (this.scalebarRefs.scaleBar.hidden = !1, this.scalebarRefs.scaleLabel.textContent = this.host.cad.hud.scaleRuler.lengthLabel) : this.scalebarRefs.scaleBar.hidden = !0);
3661
+ this.scalebarRefs && (this.host.viewMode === "2d" && ((e = this.host.cad.hud.scaleRuler) != null && e.visible) ? (this.scalebarRefs.scaleBar.hidden = !1, this.scalebarRefs.scaleLabel.textContent = this.text.formatScaleLabel(
3662
+ this.host.cad.hud.scaleRuler.worldLength,
3663
+ this.getCadUnit(),
3664
+ this.host.viewMode
3665
+ )) : this.scalebarRefs.scaleBar.hidden = !0);
3148
3666
  }
3149
3667
  });
3150
- this.host = e, this.options = t, this.parts = { ...wi, ...t.parts };
3668
+ var i;
3669
+ this.host = e, this.options = t, this.parts = { ...Hi, ...t.parts }, this.text = Ve(t), this.persistenceNamespace = ((i = t.persistenceKey) == null ? void 0 : i.trim()) || t.root.id.trim() || `instance-${++Yi}`;
3151
3670
  }
3152
3671
  mount() {
3153
3672
  if (this.disposed) return;
3154
3673
  this.shadow = this.options.root.attachShadow({ mode: "open" });
3155
3674
  const e = this.options.theme ?? "dark", t = document.createElement("style");
3156
- t.textContent = xi(e);
3675
+ t.textContent = zi(e, this.options.tokens);
3157
3676
  const i = document.createElement("div");
3158
3677
  i.className = "vui-root", i.dataset.theme = e, i.dataset.preset = this.options.preset ?? "cad-readonly";
3159
3678
  const r = document.createElement("div");
3160
3679
  r.className = "vui-main", this.parts.layerPanel && r.appendChild(this.buildLayerPanel());
3161
3680
  const s = document.createElement("div");
3162
- s.className = "vui-canvas-space", this.parts.scaleRuler && s.appendChild(this.buildScalebar()), this.parts.hud && s.appendChild(this.buildInfobar()), r.appendChild(s), this.parts.propertyPanel && r.appendChild(this.buildPropertyPanel()), i.appendChild(r), this.shadow.append(t, i), this.bindEvents(), this.setLayerPanelOpen(this.readLayerPanelOpen(), !1), this.setPropertyPanelOpen(this.readPropertyPanelOpen(), !1), this.setInfobarOpen(!0), this.refresh();
3681
+ if (s.className = "vui-canvas-space", this.parts.scaleRuler && s.appendChild(this.buildScalebar()), this.parts.hud && s.appendChild(this.buildInfobar()), r.appendChild(s), this.parts.propertyPanel && r.appendChild(this.buildPropertyPanel()), i.appendChild(r), this.shadow.append(t, i), this.options.style)
3682
+ if (typeof this.options.style == "string") {
3683
+ const o = document.createElement("style");
3684
+ o.textContent = this.options.style, this.shadow.append(o);
3685
+ } else
3686
+ this.options.style(this.shadow);
3687
+ this.bindEvents(), this.setLayerPanelOpen(this.readLayerPanelOpen(), !1), this.setPropertyPanelOpen(this.readPropertyPanelOpen(), !1), this.setInfobarOpen(!0), this.refresh(), this.observeLayoutChanges(), typeof queueMicrotask == "function" ? queueMicrotask(() => this.emitUiLayoutChange()) : this.emitUiLayoutChange();
3163
3688
  }
3164
3689
  dispose() {
3165
3690
  var e, t;
3166
3691
  if (!this.disposed) {
3167
- this.disposed = !0, this.insertToggleScheduler.clear(), (e = this.filterCleanup) == null || e.call(this), this.filterCleanup = null, (t = globalThis.removeEventListener) == null || t.call(globalThis, "keydown", this.handleKeyDown), this.cancelPropertyPreviewRender();
3692
+ this.disposed = !0, this.insertToggleScheduler.clear(), (e = this.layoutResizeObserver) == null || e.disconnect(), this.layoutResizeObserver = null, (t = this.filterCleanup) == null || t.call(this), this.filterCleanup = null, this.unbindKeyboardShortcuts(), this.cancelPropertyPreviewRender(), this.activeLayerColorPreview = null, this.renderedLayerRows = null;
3168
3693
  for (const i of this.unsubscribers) i();
3169
3694
  this.unsubscribers = [], this.shadow && (this.shadow.replaceChildren(), this.shadow = null);
3170
3695
  }
@@ -3174,45 +3699,45 @@ class Si {
3174
3699
  }
3175
3700
  buildLayerPanel() {
3176
3701
  const e = document.createElement("aside");
3177
- e.className = "vui-layer-panel-shell", e.setAttribute("aria-label", "图层面板");
3702
+ e.className = "vui-layer-panel-shell", e.setAttribute("aria-label", this.text.t("panel.layers.aria"));
3178
3703
  const t = document.createElement("div");
3179
3704
  t.className = "vui-sidebar", t.dataset.part = "layer-panel";
3180
3705
  const i = document.createElement("div");
3181
3706
  i.className = "vui-section";
3182
3707
  const r = document.createElement("div");
3183
- r.className = "vui-section-head", r.innerHTML = '<span class="vui-section-title">图层</span><span class="vui-section-count">—</span>';
3708
+ r.className = "vui-section-head", r.innerHTML = `<span class="vui-section-title">${S(this.text.t("panel.layers"))}</span><span class="vui-section-count">—</span>`;
3184
3709
  const s = document.createElement("div");
3185
3710
  s.className = "vui-section-filter-wrap";
3186
3711
  const o = document.createElement("input");
3187
- o.className = "vui-section-filter", o.type = "text", o.placeholder = "搜索图层…", o.autocomplete = "off", s.appendChild(o);
3188
- const c = document.createElement("div");
3189
- c.className = "vui-layer-quick";
3190
- const l = document.createElement("button");
3191
- l.type = "button", l.className = "vui-btn", l.textContent = "全显", l.addEventListener("click", () => this.host.cad.layers.showAll());
3712
+ o.className = "vui-section-filter", o.type = "text", o.placeholder = this.text.t("layer.searchPlaceholder"), o.autocomplete = "off", s.appendChild(o);
3713
+ const a = document.createElement("div");
3714
+ a.className = "vui-layer-quick";
3192
3715
  const d = document.createElement("button");
3193
- d.type = "button", d.className = "vui-btn", d.textContent = "全隐", d.addEventListener("click", () => this.host.cad.layers.hideAll());
3716
+ d.type = "button", d.className = "vui-btn", d.textContent = this.text.t("layer.showAll"), d.addEventListener("click", () => this.host.cad.layers.showAll());
3717
+ const l = document.createElement("button");
3718
+ l.type = "button", l.className = "vui-btn", l.textContent = this.text.t("layer.hideAll"), l.addEventListener("click", () => this.host.cad.layers.hideAll());
3194
3719
  const h = document.createElement("button");
3195
- h.type = "button", h.className = "vui-btn", h.textContent = "折叠", h.title = "折叠全部已展开层级", h.addEventListener("click", () => {
3196
- var b;
3197
- const p = (b = this.host.cad.inspector.selection) == null ? void 0 : b.id, m = p ? `${p.layerIndex}:${p.variantId}:${p.instanceId}` : null;
3198
- this.layerPanelState.collapseAll(m), this.refresh();
3199
- }), c.append(l, d, h);
3720
+ h.type = "button", h.className = "vui-btn", h.textContent = this.text.t("layer.collapse"), h.title = this.text.t("layer.collapseTitle"), h.addEventListener("click", () => {
3721
+ var m;
3722
+ const v = (m = this.host.cad.inspector.selection) == null ? void 0 : m.id, y = v ? `${v.layerIndex}:${v.variantId}:${v.instanceId}` : null;
3723
+ this.layerPanelState.collapseAll(y), this.refresh();
3724
+ }), a.append(d, l, h);
3200
3725
  const u = document.createElement("div");
3201
- u.className = "vui-section-list", i.append(r, s, c, u), t.appendChild(i), this.layerPanelRefs = {
3726
+ u.className = "vui-section-list", i.append(r, s, a, u), t.appendChild(i), this.layerPanelRefs = {
3202
3727
  list: u,
3203
3728
  count: r.querySelector(".vui-section-count"),
3204
3729
  filterInput: o
3205
3730
  };
3206
- const v = document.createElement("div");
3207
- v.className = "vui-layer-panel-toggle-zone";
3208
- const f = document.createElement("button");
3209
- return f.type = "button", f.className = "vui-layer-panel-toggle", f.addEventListener("click", () => this.setLayerPanelOpen(e.classList.contains("closed"))), v.appendChild(f), e.append(t, v), this.layerPanelShell = e, this.layerPanelToggle = f, e;
3731
+ const p = document.createElement("div");
3732
+ p.className = "vui-layer-panel-toggle-zone";
3733
+ const b = document.createElement("button");
3734
+ return b.type = "button", b.className = "vui-layer-panel-toggle", b.addEventListener("click", () => this.setLayerPanelOpen(e.classList.contains("closed"))), p.appendChild(b), e.append(t, p), this.layerPanelShell = e, this.layerPanelToggle = b, e;
3210
3735
  }
3211
3736
  buildScalebar() {
3212
3737
  const e = document.createElement("div");
3213
- e.className = "vui-scalebar", e.title = "当前视图比例尺(按图纸单位)", e.hidden = !this.parts.scaleRuler;
3738
+ e.className = "vui-scalebar", e.title = this.text.t("scale.title"), e.hidden = !this.parts.scaleRuler;
3214
3739
  const t = document.createElement("div");
3215
- t.className = "vui-scalebar-label", t.textContent = "100 mm";
3740
+ t.className = "vui-scalebar-label", t.textContent = this.text.formatScaleLabel(100);
3216
3741
  const i = document.createElement("div");
3217
3742
  return i.className = "vui-scalebar-line", e.append(t, i), this.scalebarRefs = { scaleBar: e, scaleLabel: t, scaleLine: i }, e;
3218
3743
  }
@@ -3226,83 +3751,87 @@ class Si {
3226
3751
  const r = document.createElement("span");
3227
3752
  r.className = "vui-seg vui-info-file";
3228
3753
  const s = document.createElement("div");
3229
- s.className = "vui-infobar-tools", s.setAttribute("role", "toolbar"), s.setAttribute("aria-label", "视图控制");
3754
+ s.className = "vui-infobar-tools", s.setAttribute("role", "toolbar"), s.setAttribute("aria-label", this.text.t("toolbar.viewControls"));
3230
3755
  const o = document.createElement("span");
3231
- if (o.className = "vui-info-text", this.toolbarInfoText = o, s.appendChild(o), this.parts.fit && (this.btnFit = document.createElement("button"), this.btnFit.type = "button", this.btnFit.className = "vui-btn", this.btnFit.innerHTML = '适应 <span class="vui-kbd">F</span>', this.btnFit.addEventListener("click", () => this.host.fitView()), s.appendChild(this.btnFit)), this.parts.viewMode) {
3232
- const b = document.createElement("div");
3233
- b.className = "vui-view-toggle", b.setAttribute("role", "group"), b.setAttribute("aria-label", "视图模式"), this.btnView2d = document.createElement("button"), this.btnView2d.type = "button", this.btnView2d.className = "vui-btn", this.btnView2d.textContent = "2D", this.btnView2d.setAttribute("aria-pressed", "false"), this.btnView2d.addEventListener("click", () => this.host.setViewMode("2d")), this.btnView3d = document.createElement("button"), this.btnView3d.type = "button", this.btnView3d.className = "vui-btn", this.btnView3d.textContent = "3D", this.btnView3d.setAttribute("aria-pressed", "false"), this.btnView3d.addEventListener("click", () => this.host.setViewMode("3d")), b.append(this.btnView2d, this.btnView3d), s.appendChild(b);
3756
+ if (o.className = "vui-info-text", this.toolbarInfoText = o, s.appendChild(o), this.parts.fit) {
3757
+ this.btnFit = document.createElement("button"), this.btnFit.type = "button", this.btnFit.className = "vui-btn";
3758
+ const m = this.getFitShortcut();
3759
+ this.btnFit.innerHTML = m ? `${S(this.text.t("toolbar.fit"))} <span class="vui-kbd">${S(m.toUpperCase())}</span>` : S(this.text.t("toolbar.fit")), this.btnFit.addEventListener("click", () => this.host.fitSelectionOrDocument()), s.appendChild(this.btnFit);
3234
3760
  }
3235
- const c = document.createElement("span");
3236
- c.className = "vui-seg";
3237
- const l = document.createElement("span");
3238
- l.className = "vui-seg";
3761
+ if (this.parts.viewMode) {
3762
+ const m = document.createElement("div");
3763
+ m.className = "vui-view-toggle", m.setAttribute("role", "group"), m.setAttribute("aria-label", this.text.t("toolbar.viewMode")), this.btnView2d = document.createElement("button"), this.btnView2d.type = "button", this.btnView2d.className = "vui-btn", this.btnView2d.textContent = "2D", this.btnView2d.setAttribute("aria-pressed", "false"), this.btnView2d.addEventListener("click", () => this.host.setViewMode("2d")), this.btnView3d = document.createElement("button"), this.btnView3d.type = "button", this.btnView3d.className = "vui-btn", this.btnView3d.textContent = "3D", this.btnView3d.setAttribute("aria-pressed", "false"), this.btnView3d.addEventListener("click", () => this.host.setViewMode("3d")), m.append(this.btnView2d, this.btnView3d), s.appendChild(m);
3764
+ }
3765
+ const a = document.createElement("span");
3766
+ a.className = "vui-seg";
3239
3767
  const d = document.createElement("span");
3240
3768
  d.className = "vui-seg";
3769
+ const l = document.createElement("span");
3770
+ l.className = "vui-seg";
3241
3771
  const h = document.createElement("span");
3242
3772
  h.className = "vui-seg", h.hidden = !0;
3243
3773
  const u = document.createElement("span");
3244
3774
  u.className = "vui-seg";
3245
- const v = document.createElement("span");
3246
- v.className = "vui-fps";
3247
- const f = document.createElement("details");
3248
- f.className = "vui-debug-card";
3249
- const p = document.createElement("summary");
3250
- p.className = "vui-debug-summary", p.textContent = "详细";
3251
- const m = document.createElement("div");
3252
- return m.className = "vui-debug-body", f.append(p, m), i.append(r, s, c, l, d, h, u, v, f), e.append(t, i), this.infobarRefs = {
3775
+ const p = document.createElement("span");
3776
+ p.className = "vui-fps";
3777
+ const b = document.createElement("details");
3778
+ b.className = "vui-debug-card";
3779
+ const v = document.createElement("summary");
3780
+ v.className = "vui-debug-summary", v.textContent = this.text.t("toolbar.details");
3781
+ const y = document.createElement("div");
3782
+ return y.className = "vui-debug-body", b.append(v, y), i.append(r, s, a, d, l, h, u, p, b), e.append(t, i), this.infobarRefs = {
3253
3783
  infobar: e,
3254
3784
  file: r,
3255
3785
  tools: s,
3256
- zoom: c,
3257
- vertices: l,
3258
- drawCalls: d,
3786
+ zoom: a,
3787
+ vertices: d,
3788
+ drawCalls: l,
3259
3789
  lineMode: h,
3260
3790
  phase: u,
3261
- fps: v,
3262
- debugCard: f,
3263
- debugSummary: p,
3264
- debugBody: m
3791
+ fps: p,
3792
+ debugCard: b,
3793
+ debugSummary: v,
3794
+ debugBody: y
3265
3795
  }, this.infobar = e, this.infobarToggle = t, e;
3266
3796
  }
3267
3797
  buildPropertyPanel() {
3268
3798
  const e = document.createElement("aside");
3269
- e.className = "vui-property-panel-shell", e.setAttribute("aria-label", "属性面板");
3799
+ e.className = "vui-property-panel-shell", e.setAttribute("aria-label", this.text.t("panel.properties.aria"));
3270
3800
  const t = document.createElement("div");
3271
3801
  t.className = "vui-property-panel", t.dataset.part = "property-panel";
3272
3802
  const i = document.createElement("div");
3273
- i.className = "vui-pp-head", i.innerHTML = '<span class="vui-pp-title-text">属性</span>';
3803
+ i.className = "vui-pp-head", i.innerHTML = `<span class="vui-pp-title-text">${S(this.text.t("panel.properties"))}</span>`;
3274
3804
  const r = document.createElement("div");
3275
3805
  r.className = "vui-pp-preview-wrap", r.hidden = !0;
3276
3806
  const s = document.createElement("canvas");
3277
3807
  s.className = "vui-pp-preview", s.width = 256, s.height = 256, r.appendChild(s);
3278
3808
  const o = document.createElement("div");
3279
3809
  o.className = "vui-pp-body", t.append(i, r, o);
3280
- const c = document.createElement("div");
3281
- c.className = "vui-property-panel-toggle-zone";
3282
- const l = document.createElement("button");
3283
- return l.type = "button", l.className = "vui-property-panel-toggle", l.addEventListener("click", () => this.setPropertyPanelOpen(e.classList.contains("closed"))), c.appendChild(l), e.append(c, t), this.propertyPanelShell = e, this.propertyPanelToggle = l, this.propertyPanelRefs = { body: o, previewWrap: r, previewCanvas: s }, e;
3810
+ const a = document.createElement("div");
3811
+ a.className = "vui-property-panel-toggle-zone";
3812
+ const d = document.createElement("button");
3813
+ return d.type = "button", d.className = "vui-property-panel-toggle", d.addEventListener("click", () => this.setPropertyPanelOpen(e.classList.contains("closed"))), a.appendChild(d), e.append(a, t), this.propertyPanelShell = e, this.propertyPanelToggle = d, this.propertyPanelRefs = { body: o, previewWrap: r, previewCanvas: s }, e;
3284
3814
  }
3285
3815
  bindEvents() {
3286
- var e;
3287
- this.layerPanelRefs && (this.filterCleanup = hi(this.layerPanelRefs.filterInput, (t) => {
3288
- this.layerPanelState.filterText = t, this.layerPanelRefs && oi(this.layerPanelRefs.list, t);
3816
+ this.layerPanelRefs && (this.filterCleanup = Ti(this.layerPanelRefs.filterInput, (e) => {
3817
+ this.layerPanelState.filterText = e, this.layerPanelRefs && Si(this.layerPanelRefs.list, e);
3289
3818
  })), this.unsubscribers.push(
3290
3819
  this.host.cad.on("document-change", () => this.refresh()),
3291
- this.host.cad.on("layer-change", () => this.refresh()),
3820
+ this.host.cad.on("layer-change", () => this.syncLayerChange()),
3292
3821
  this.host.cad.on("block-change", () => this.refresh()),
3293
3822
  this.host.cad.on("inspector-change", () => {
3294
3823
  if (this.layerPanelRefs && this.parts.layerPanel) {
3295
- const t = this.host.cad.inspector.selection, i = t == null ? void 0 : t.id, r = i ? `${i.layerIndex}:${i.variantId}:${i.instanceId}` : null;
3296
- r && this.layerPanelState.needsSelectionReveal(r) ? pe(this.layerPanelRefs, this.layerPanelState, this.createLayerPanelActions()) : ai(this.layerPanelRefs.list, t);
3824
+ const e = this.host.cad.inspector.selection, t = e == null ? void 0 : e.id, i = t ? `${t.layerIndex}:${t.variantId}:${t.instanceId}` : null;
3825
+ i && this.layerPanelState.needsSelectionReveal(i) ? this.renderLayerPanel() : Ei(this.layerPanelRefs.list, e);
3297
3826
  }
3298
- this.propertyPanelRefs && this.parts.propertyPanel && (be(this.propertyPanelRefs, this.host.cad.inspector), this.syncPropertyPanelSelectionState(), this.syncPropertyPanelPreview());
3827
+ this.propertyPanelRefs && this.parts.propertyPanel && (xe(this.propertyPanelRefs, this.host.cad.inspector, this.text, this.getCadUnit()), this.syncPropertyPanelSelectionState(), this.syncPropertyPanelPreview());
3299
3828
  }),
3300
3829
  this.host.cad.on("hud-change", () => this.syncHud()),
3301
3830
  this.host.on("view-mode-change", () => {
3302
3831
  this.syncToolbarState(), this.syncHud();
3303
3832
  }),
3304
3833
  this.host.on("interaction-change", () => this.syncHud())
3305
- ), (e = globalThis.addEventListener) == null || e.call(globalThis, "keydown", this.handleKeyDown);
3834
+ ), this.bindKeyboardShortcuts();
3306
3835
  }
3307
3836
  createLayerPanelActions() {
3308
3837
  var e;
@@ -3311,66 +3840,170 @@ class Si {
3311
3840
  blocks: this.host.cad.blocks,
3312
3841
  selection: this.host.cad.inspector.selection,
3313
3842
  scopeKey: ((e = this.host.cad.document) == null ? void 0 : e.documentKey) ?? null,
3843
+ text: this.text,
3314
3844
  toggleLayer: (t) => this.host.cad.layers.toggle(t),
3315
3845
  showAllLayers: () => this.host.cad.layers.showAll(),
3316
3846
  hideAllLayers: () => this.host.cad.layers.hideAll(),
3317
3847
  setLayerColor: (t, i) => this.host.cad.layers.setColor(t, i),
3318
- setAllLayerColor: (t) => {
3319
- var i, r;
3320
- return (r = (i = this.host.cad.layers).setAllColor) == null ? void 0 : r.call(i, t);
3848
+ setAllLayerColor: (t) => this.host.cad.layers.setAllColor(t),
3849
+ beginLayerColorPreview: (t) => {
3850
+ this.activeLayerColorPreview = t;
3851
+ },
3852
+ endLayerColorPreview: (t) => {
3853
+ this.activeLayerColorPreview === t && (this.activeLayerColorPreview = null);
3321
3854
  },
3322
3855
  toggleInsert: (t, i) => this.host.cad.blocks.toggleInsert(t, i),
3323
3856
  batchToggleInserts: (t) => this.insertToggleScheduler.enqueueMany(t),
3324
3857
  selectInsert: (t) => {
3325
- var i, r;
3326
- return (r = (i = this.host.cad).selectInsert) == null ? void 0 : r.call(i, t);
3858
+ var r;
3859
+ const i = this.host.cad.blocks.usages.find((s) => s.insertId === t);
3860
+ if (!i) {
3861
+ this.host.cad.clearSelection();
3862
+ return;
3863
+ }
3864
+ this.host.cad.select({
3865
+ kind: "insert",
3866
+ selection: {
3867
+ documentKey: ((r = this.host.cad.document) == null ? void 0 : r.documentKey) ?? null,
3868
+ id: {
3869
+ kind: "insert",
3870
+ layerIndex: i.layerIndex,
3871
+ variantId: i.variantId,
3872
+ instanceId: i.instanceId
3873
+ }
3874
+ }
3875
+ });
3327
3876
  },
3328
3877
  refresh: this.refresh
3329
3878
  };
3330
3879
  }
3880
+ isLayerColorPreviewActive() {
3881
+ var t;
3882
+ const e = this.activeLayerColorPreview;
3883
+ return !!(e && e.isConnected && ((t = this.layerPanelRefs) != null && t.list.contains(e)));
3884
+ }
3885
+ renderLayerPanel() {
3886
+ !this.layerPanelRefs || !this.parts.layerPanel || (Ri(this.layerPanelRefs, this.layerPanelState, this.createLayerPanelActions()), this.renderedLayerRows = this.host.cad.layers.rows);
3887
+ }
3888
+ syncLayerChange() {
3889
+ if (!this.isLayerColorPreviewActive()) {
3890
+ if (!this.layerPanelRefs || !this.parts.layerPanel || this.renderedLayerRows !== this.host.cad.layers.rows) {
3891
+ this.refresh();
3892
+ return;
3893
+ }
3894
+ Ii(
3895
+ this.layerPanelRefs.list,
3896
+ this.host.cad.layers.rows,
3897
+ this.host.cad.layers.allColor,
3898
+ this.text
3899
+ );
3900
+ }
3901
+ }
3902
+ getCadUnit() {
3903
+ var t, i;
3904
+ const e = (i = (t = this.host.cad.document) == null ? void 0 : t.units.source) == null ? void 0 : i.trim();
3905
+ return e && e !== "unitless" ? e : "";
3906
+ }
3331
3907
  syncToolbarState() {
3332
3908
  var t, i, r, s, o;
3333
3909
  const e = this.host.viewMode;
3334
3910
  (t = this.btnView2d) == null || t.classList.toggle("active", e === "2d"), (i = this.btnView3d) == null || i.classList.toggle("active", e === "3d"), (r = this.btnView2d) == null || r.setAttribute("aria-pressed", String(e === "2d")), (s = this.btnView3d) == null || s.setAttribute("aria-pressed", String(e === "3d")), this.btnFit && (this.btnFit.disabled = !((o = this.host.cad.document) != null && o.headerBounds));
3335
3911
  }
3336
3912
  readPropertyPanelOpen() {
3337
- var e;
3913
+ if (this.options.persistence === !1) return !1;
3338
3914
  try {
3339
- return ((e = globalThis.localStorage) == null ? void 0 : e.getItem(ye)) === "1";
3915
+ return this.readState(Ce) === "1";
3340
3916
  } catch {
3341
3917
  return !1;
3342
3918
  }
3343
3919
  }
3344
3920
  readLayerPanelOpen() {
3345
- var e;
3921
+ if (this.options.persistence === !1) return !0;
3346
3922
  try {
3347
- return ((e = globalThis.localStorage) == null ? void 0 : e.getItem(xe)) !== "0";
3923
+ return this.readState(Pe) !== "0";
3348
3924
  } catch {
3349
3925
  return !0;
3350
3926
  }
3351
3927
  }
3352
3928
  setLayerPanelOpen(e, t = !0) {
3353
- var s;
3354
3929
  const i = this.layerPanelShell, r = this.layerPanelToggle;
3355
- if (!(!i || !r) && (i.classList.toggle("closed", !e), r.textContent = e ? "‹" : "›", r.setAttribute("aria-expanded", String(e)), r.setAttribute("aria-label", e ? "收起图层面板" : "展开图层面板"), !!t))
3930
+ if (!(!i || !r) && (i.classList.toggle("closed", !e), r.textContent = e ? "‹" : "›", r.setAttribute("aria-expanded", String(e)), r.setAttribute("aria-label", this.text.t("panel.toggle", {
3931
+ action: e ? this.text.t("panel.collapse") : this.text.t("panel.expand"),
3932
+ panel: this.text.t("panel.layers")
3933
+ })), !!t && (this.emitUiLayoutChange(), this.options.persistence !== !1)))
3356
3934
  try {
3357
- (s = globalThis.localStorage) == null || s.setItem(xe, e ? "1" : "0");
3935
+ this.writeState(Pe, e ? "1" : "0");
3358
3936
  } catch {
3359
3937
  }
3360
3938
  }
3361
3939
  setInfobarOpen(e) {
3362
3940
  const t = this.infobar, i = this.infobarToggle;
3363
- !t || !i || (t.classList.toggle("collapsed", !e), i.textContent = e ? "›" : "‹", i.setAttribute("aria-expanded", String(e)), i.setAttribute("aria-label", e ? "收起信息栏" : "展开信息栏"));
3941
+ !t || !i || (t.classList.toggle("collapsed", !e), i.textContent = e ? "›" : "‹", i.setAttribute("aria-expanded", String(e)), i.setAttribute("aria-label", e ? this.text.t("infobar.collapse") : this.text.t("infobar.expand")));
3364
3942
  }
3365
3943
  setPropertyPanelOpen(e, t = !0) {
3366
- var s, o;
3944
+ var s;
3367
3945
  const i = this.propertyPanelShell, r = this.propertyPanelToggle;
3368
- if (!(!i || !r) && (i.classList.toggle("closed", !e), r.textContent = e ? "›" : "‹", r.setAttribute("aria-expanded", String(e)), (s = i.querySelector(".vui-property-panel")) == null || s.setAttribute("aria-hidden", String(!e)), e ? this.syncPropertyPanelPreview(!0) : (this.cancelPropertyPreviewRender(), this.propertyPanelRefs && D(this.propertyPanelRefs, !1)), !!t))
3946
+ if (!(!i || !r) && (i.classList.toggle("closed", !e), r.textContent = e ? "›" : "‹", r.setAttribute("aria-expanded", String(e)), r.setAttribute("aria-label", this.text.t("panel.toggle", {
3947
+ action: e ? this.text.t("panel.collapse") : this.text.t("panel.expand"),
3948
+ panel: this.text.t("panel.properties")
3949
+ })), (s = i.querySelector(".vui-property-panel")) == null || s.setAttribute("aria-hidden", String(!e)), e ? this.syncPropertyPanelPreview(!0) : (this.cancelPropertyPreviewRender(), this.propertyPanelRefs && D(this.propertyPanelRefs, !1)), !!t && (this.emitUiLayoutChange(), this.options.persistence !== !1)))
3369
3950
  try {
3370
- (o = globalThis.localStorage) == null || o.setItem(ye, e ? "1" : "0");
3951
+ this.writeState(Ce, e ? "1" : "0");
3371
3952
  } catch {
3372
3953
  }
3373
3954
  }
3955
+ persistenceKey(e) {
3956
+ return `nebula-viewer:${this.persistenceNamespace}:${e}`;
3957
+ }
3958
+ readState(e) {
3959
+ var i;
3960
+ const t = this.persistenceKey(e);
3961
+ return this.options.stateStore ? this.options.stateStore.read(t) : ((i = globalThis.localStorage) == null ? void 0 : i.getItem(t)) ?? null;
3962
+ }
3963
+ writeState(e, t) {
3964
+ var r;
3965
+ const i = this.persistenceKey(e);
3966
+ this.options.stateStore ? this.options.stateStore.write(i, t) : (r = globalThis.localStorage) == null || r.setItem(i, t);
3967
+ }
3968
+ getKeyboardTarget() {
3969
+ var e;
3970
+ return ((e = this.options.keyboard) == null ? void 0 : e.target) ?? this.host.keyboardTarget;
3971
+ }
3972
+ bindKeyboardShortcuts() {
3973
+ var t, i, r;
3974
+ if (((t = this.options.keyboard) == null ? void 0 : t.enabled) === !1) return;
3975
+ const e = this.getKeyboardTarget();
3976
+ this.keyboardTarget = e, typeof e.hasAttribute == "function" && !e.hasAttribute("tabindex") && e.tabIndex < 0 && (e.tabIndex = 0, this.keyboardTargetTabIndexAdded = !0), (i = e.addEventListener) == null || i.call(e, "keydown", this.handleKeyDown), (r = e.addEventListener) == null || r.call(e, "pointerdown", this.handleKeyboardTargetPointerDown);
3977
+ }
3978
+ unbindKeyboardShortcuts() {
3979
+ var t, i, r, s;
3980
+ const e = this.keyboardTarget;
3981
+ e && ((t = e.removeEventListener) == null || t.call(e, "keydown", this.handleKeyDown), (i = e.removeEventListener) == null || i.call(e, "pointerdown", this.handleKeyboardTargetPointerDown), this.keyboardTargetTabIndexAdded && ((r = e.getAttribute) == null ? void 0 : r.call(e, "tabindex")) === "0" && ((s = e.removeAttribute) == null || s.call(e, "tabindex")), this.keyboardTarget = null, this.keyboardTargetTabIndexAdded = !1);
3982
+ }
3983
+ getFitShortcut() {
3984
+ var t, i, r, s, o;
3985
+ if (((t = this.options.keyboard) == null ? void 0 : t.enabled) === !1 || ((r = (i = this.options.keyboard) == null ? void 0 : i.shortcuts) == null ? void 0 : r.fit) === !1) return null;
3986
+ const e = (o = (s = this.options.keyboard) == null ? void 0 : s.shortcuts) == null ? void 0 : o.fit;
3987
+ return typeof e == "string" && e.trim() ? e.trim() : "f";
3988
+ }
3989
+ emitUiLayoutChange() {
3990
+ var s, o;
3991
+ if (this.disposed) return;
3992
+ const e = !!(this.layerPanelShell && !this.layerPanelShell.classList.contains("closed")), t = !!(this.propertyPanelShell && !this.propertyPanelShell.classList.contains("closed")), i = {
3993
+ contentInsets: {
3994
+ top: 0,
3995
+ right: t ? ((s = this.propertyPanelShell) == null ? void 0 : s.getBoundingClientRect().width) ?? 0 : 0,
3996
+ bottom: 0,
3997
+ left: e ? ((o = this.layerPanelShell) == null ? void 0 : o.getBoundingClientRect().width) ?? 0 : 0
3998
+ },
3999
+ layerPanelOpen: e,
4000
+ propertyPanelOpen: t
4001
+ }, r = `${i.contentInsets.top}:${i.contentInsets.right}:${i.contentInsets.bottom}:${i.contentInsets.left}:${Number(e)}:${Number(t)}`;
4002
+ r !== this.lastLayoutFingerprint && (this.lastLayoutFingerprint = r, this.host.emitUiLayoutChange(i));
4003
+ }
4004
+ observeLayoutChanges() {
4005
+ typeof globalThis.ResizeObserver == "function" && (this.layoutResizeObserver = new globalThis.ResizeObserver(() => this.emitUiLayoutChange()), this.layoutResizeObserver.observe(this.options.root), this.layerPanelShell && this.layoutResizeObserver.observe(this.layerPanelShell), this.propertyPanelShell && this.layoutResizeObserver.observe(this.propertyPanelShell));
4006
+ }
3374
4007
  syncPropertyPanelSelectionState() {
3375
4008
  const e = this.propertyPanelShell;
3376
4009
  if (!e) return;
@@ -3390,7 +4023,7 @@ class Si {
3390
4023
  const s = i.id, o = `${i.documentKey ?? ""}:${s.layerIndex}:${s.variantId}:${s.instanceId}`;
3391
4024
  if (!e && o === this.propertyPreviewKey) return;
3392
4025
  this.cancelPropertyPreviewRender(), this.propertyPreviewKey = o, D(t, !0), this.clearPropertyPreviewCanvas(r);
3393
- const c = () => {
4026
+ const a = () => {
3394
4027
  this.disposed || this.propertyPreviewKey !== o || !this.isPropertyPreviewLayoutReady(r) || (this.propertyPreviewRenderHandle = requestAnimationFrame(() => {
3395
4028
  this.propertyPreviewRenderHandle = requestAnimationFrame(() => {
3396
4029
  this.propertyPreviewRenderHandle = null, !(this.disposed || this.propertyPreviewKey !== o) && D(t, this.host.cad.renderInsertPreview(r));
@@ -3398,57 +4031,57 @@ class Si {
3398
4031
  }));
3399
4032
  };
3400
4033
  if (this.shouldWaitForPropertyPreviewLayout(r)) {
3401
- this.waitForPropertyPreviewLayout(r).then(c);
4034
+ this.waitForPropertyPreviewLayout(r).then(a);
3402
4035
  return;
3403
4036
  }
3404
- c();
4037
+ a();
3405
4038
  }
3406
4039
  shouldWaitForPropertyPreviewLayout(e) {
3407
4040
  var t;
3408
4041
  return (t = this.propertyPanelShell) != null && t.classList.contains("closed") ? !0 : !this.isPropertyPreviewLayoutReady(e);
3409
4042
  }
3410
4043
  isPropertyPreviewLayoutReady(e) {
3411
- return e.clientWidth >= Ce && e.clientHeight >= Ce;
4044
+ return e.clientWidth >= Ee && e.clientHeight >= Ee;
3412
4045
  }
3413
4046
  waitForPropertyPreviewLayout(e) {
3414
4047
  if (this.isPropertyPreviewLayoutReady(e)) return Promise.resolve();
3415
4048
  const t = this.propertyPanelShell, i = (t == null ? void 0 : t.querySelector(".vui-property-panel")) ?? null;
3416
4049
  return !t || !i ? Promise.resolve() : new Promise((r) => {
3417
- let s = !1, o = 0, c = -1;
3418
- const l = [], d = [];
4050
+ let s = !1, o = 0, a = -1;
4051
+ const d = [], l = [];
3419
4052
  let h = 0;
3420
4053
  const u = () => {
3421
- for (const g of l) window.clearTimeout(g);
3422
- for (const g of d) g();
3423
- window.clearTimeout(b), h !== 0 && cancelAnimationFrame(h), this.propertyPreviewLayoutWaitAbort = null;
3424
- }, v = () => {
4054
+ for (const f of d) window.clearTimeout(f);
4055
+ for (const f of l) f();
4056
+ window.clearTimeout(m), h !== 0 && cancelAnimationFrame(h), this.propertyPreviewLayoutWaitAbort = null;
4057
+ }, p = () => {
3425
4058
  s || (s = !0, u(), r());
3426
- }, f = () => {
3427
- const g = e.clientWidth;
4059
+ }, b = () => {
4060
+ const f = e.clientWidth;
3428
4061
  if (!this.isPropertyPreviewLayoutReady(e)) {
3429
- o = 0, c = -1;
4062
+ o = 0, a = -1;
3430
4063
  return;
3431
4064
  }
3432
- if (g === c) {
3433
- o += 1, o >= Ci && v();
4065
+ if (f === a) {
4066
+ o += 1, o >= _i && p();
3434
4067
  return;
3435
4068
  }
3436
- c = g, o = 0;
3437
- }, p = (g) => {
3438
- if (!Ri(g)) return;
3439
- let y = !1;
3440
- const P = (E) => {
3441
- E.target !== g || E.propertyName !== "width" || x();
4069
+ a = f, o = 0;
4070
+ }, v = (f) => {
4071
+ if (!$i(f)) return;
4072
+ let g = !1;
4073
+ const w = (E) => {
4074
+ E.target !== f || E.propertyName !== "width" || x();
3442
4075
  }, x = () => {
3443
- y || (y = !0, g.removeEventListener("transitionend", P), requestAnimationFrame(f));
4076
+ g || (g = !0, f.removeEventListener("transitionend", w), requestAnimationFrame(b));
3444
4077
  };
3445
- g.addEventListener("transitionend", P), l.push(window.setTimeout(x, we)), d.push(() => {
3446
- y || (y = !0, g.removeEventListener("transitionend", P));
4078
+ f.addEventListener("transitionend", w), d.push(window.setTimeout(x, Se)), l.push(() => {
4079
+ g || (g = !0, f.removeEventListener("transitionend", w));
3447
4080
  });
3448
- }, m = () => {
3449
- f(), s || (h = requestAnimationFrame(m));
3450
- }, b = window.setTimeout(v, we);
3451
- p(i), p(t), h = requestAnimationFrame(m), this.propertyPreviewLayoutWaitAbort = () => {
4081
+ }, y = () => {
4082
+ b(), s || (h = requestAnimationFrame(y));
4083
+ }, m = window.setTimeout(p, Se);
4084
+ v(i), v(t), h = requestAnimationFrame(y), this.propertyPreviewLayoutWaitAbort = () => {
3452
4085
  s = !0, u();
3453
4086
  };
3454
4087
  });
@@ -3465,7 +4098,7 @@ class Si {
3465
4098
  this.propertyPreviewRenderHandle !== null && (cancelAnimationFrame(this.propertyPreviewRenderHandle), this.propertyPreviewRenderHandle = null), (e = this.propertyPreviewLayoutWaitAbort) == null || e.call(this), this.propertyPreviewLayoutWaitAbort = null;
3466
4099
  }
3467
4100
  }
3468
- function Ri(n) {
4101
+ function $i(n) {
3469
4102
  const e = getComputedStyle(n), t = e.transitionDuration.split(",").map((r) => r.trim()), i = e.transitionProperty.split(",").map((r) => r.trim());
3470
4103
  for (let r = 0; r < i.length; r += 1) {
3471
4104
  const s = i[r] ?? i[0] ?? "all";
@@ -3474,7 +4107,228 @@ function Ri(n) {
3474
4107
  }
3475
4108
  return !1;
3476
4109
  }
3477
- const B = "viewer:highlight", z = "viewer:cad-selection", H = "viewer:cad-hover", Re = {
4110
+ class Ki {
4111
+ constructor(e, t, i, r, s) {
4112
+ c(this, "pluginsById", /* @__PURE__ */ new Map());
4113
+ c(this, "contributions", []);
4114
+ c(this, "commandContributions", /* @__PURE__ */ new Map());
4115
+ c(this, "refreshingInspectors", !1);
4116
+ c(this, "disposed", !1);
4117
+ this.readCad = e, this.readState = t, this.subscribe = i, this.commands = r, this.hostElement = s;
4118
+ }
4119
+ register(e) {
4120
+ if (this.assertActive(), !e || !e.id || typeof e.activate != "function") throw new TypeError("Invalid viewer plugin.");
4121
+ if (this.pluginsById.has(e.id)) throw new Error(`Viewer plugin already registered: ${e.id}`);
4122
+ const t = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set();
4123
+ let s = !1;
4124
+ const o = () => {
4125
+ if (s) throw new Error(`Viewer plugin context is disposed: ${e.id}`);
4126
+ }, a = {
4127
+ cad: {
4128
+ $read: () => (o(), this.readCad())
4129
+ },
4130
+ viewer: {
4131
+ $getState: () => (o(), this.readState())
4132
+ },
4133
+ commands: {
4134
+ setLayerVisible: (d, l) => (o(), this.commands.setLayerVisible(d, l)),
4135
+ setSelection: (d) => {
4136
+ o(), this.commands.setSelection(d);
4137
+ },
4138
+ fitDocument: () => (o(), this.commands.fitDocument()),
4139
+ setViewMode: (d) => {
4140
+ o(), this.commands.setViewMode(d);
4141
+ }
4142
+ },
4143
+ events: {
4144
+ on: (d, l) => {
4145
+ o();
4146
+ const h = this.subscribe(d, l);
4147
+ return i.add(h), () => {
4148
+ i.delete(h) && h();
4149
+ };
4150
+ }
4151
+ },
4152
+ layout: {
4153
+ mount: (d, l = {}) => {
4154
+ o();
4155
+ const h = document.createElement("div");
4156
+ return h.dataset.viewerLayoutPosition = l.position ?? "overlay", h.append(d), this.hostElement.append(h), r.add(h), {
4157
+ dispose: () => {
4158
+ r.delete(h) && h.remove();
4159
+ }
4160
+ };
4161
+ },
4162
+ onInsetsChange: (d) => {
4163
+ o();
4164
+ const l = this.subscribe("ui-layout-change", (h) => d(h.contentInsets));
4165
+ return i.add(l), () => {
4166
+ i.delete(l) && l();
4167
+ };
4168
+ }
4169
+ },
4170
+ contribute: (d) => {
4171
+ if (s) throw new Error(`Viewer plugin is disposed: ${e.id}`);
4172
+ if (!d.id || this.contributions.some((h) => h.point.id === d.id))
4173
+ throw new Error(`Viewer contribution already registered: ${d.id}`);
4174
+ const l = { pluginId: e.id, point: d, context: a };
4175
+ t.add(l), this.contributions.push(l);
4176
+ try {
4177
+ this.mountContribution(l);
4178
+ } catch (h) {
4179
+ throw this.removeContribution(l), h;
4180
+ }
4181
+ return {
4182
+ dispose: () => this.removeContribution(l)
4183
+ };
4184
+ },
4185
+ dispose: () => {
4186
+ if (!s) {
4187
+ s = !0;
4188
+ for (const d of [...t]) this.removeContribution(d);
4189
+ t.clear();
4190
+ for (const d of i) d();
4191
+ i.clear();
4192
+ for (const d of r) d.remove();
4193
+ r.clear();
4194
+ }
4195
+ }
4196
+ };
4197
+ this.pluginsById.set(e.id, { plugin: e, context: a, contributions: t });
4198
+ try {
4199
+ const d = e.activate(a);
4200
+ d && typeof d.catch == "function" && d.catch((l) => {
4201
+ console.error(`[viewer] plugin ${e.id} activation failed`, l), this.deactivate(e.id, a);
4202
+ });
4203
+ } catch (d) {
4204
+ throw this.deactivate(e.id, a), d;
4205
+ }
4206
+ return { dispose: () => this.deactivate(e.id, a) };
4207
+ }
4208
+ use(e, t = {}) {
4209
+ this.assertActive(), t.replace && this.disposeAll();
4210
+ for (const i of e) this.register(i);
4211
+ }
4212
+ deactivate(e, t) {
4213
+ var r, s;
4214
+ const i = this.pluginsById.get(e);
4215
+ if (!(!i || t && i.context !== t)) {
4216
+ this.pluginsById.delete(e), i.context.dispose();
4217
+ try {
4218
+ const o = (s = (r = i.plugin).deactivate) == null ? void 0 : s.call(r);
4219
+ o && typeof o.catch == "function" && o.catch((a) => console.error(`[viewer] plugin ${e} deactivation failed`, a));
4220
+ } catch (o) {
4221
+ console.error(`[viewer] plugin ${e} deactivation failed`, o);
4222
+ }
4223
+ }
4224
+ }
4225
+ disposeAll() {
4226
+ for (const e of Array.from(this.pluginsById.keys()).reverse()) this.deactivate(e);
4227
+ }
4228
+ dispose() {
4229
+ this.disposed || (this.disposed = !0, this.disposeAll());
4230
+ }
4231
+ dispatchInteraction(e, t) {
4232
+ for (const i of this.contributions) {
4233
+ if (i.point.kind !== "interaction") continue;
4234
+ const r = i.point.hooks[e];
4235
+ if (!r) continue;
4236
+ const s = r(e === "onClear" ? void 0 : t);
4237
+ if (e === "onPick" && s === !1) return !0;
4238
+ }
4239
+ return !1;
4240
+ }
4241
+ findFitPolicy() {
4242
+ for (const e of this.contributions) {
4243
+ if (e.point.kind !== "fit-policy") continue;
4244
+ const t = e.point.resolve(e.context);
4245
+ if (t) return t;
4246
+ }
4247
+ return null;
4248
+ }
4249
+ executeCommand(e, t) {
4250
+ this.assertActive();
4251
+ const i = this.commandContributions.get(e);
4252
+ return !i || i.point.kind !== "command" ? !1 : (i.point.handler(i.context, t), !0);
4253
+ }
4254
+ hasCommand(e) {
4255
+ return this.assertActive(), this.commandContributions.has(e);
4256
+ }
4257
+ removeContribution(e) {
4258
+ var r;
4259
+ const t = this.contributions.indexOf(e);
4260
+ if (t < 0) return;
4261
+ this.contributions.splice(t, 1);
4262
+ const i = this.pluginsById.get(e.pluginId);
4263
+ i == null || i.contributions.delete(e), e.point.kind === "command" && this.commandContributions.get(e.point.id) === e && this.commandContributions.delete(e.point.id), (r = e.cleanup) == null || r.call(e), e.cleanup = void 0, e.point.kind === "inspector" && this.refreshInspectorContributions();
4264
+ }
4265
+ mountContribution(e) {
4266
+ const t = e.point;
4267
+ if (t.kind === "command" && this.commandContributions.set(t.id, e), t.kind === "toolbar") {
4268
+ const s = document.createElement("div");
4269
+ s.dataset.viewerContribution = "toolbar", s.dataset.viewerContributionId = t.id;
4270
+ for (const o of t.items) {
4271
+ const a = document.createElement("button");
4272
+ a.type = "button", a.textContent = o.label, o.title && (a.title = o.title), a.disabled = o.disabled === !0, a.addEventListener("click", o.onClick), s.append(a);
4273
+ }
4274
+ this.hostElement.append(s), e.cleanup = () => s.remove();
4275
+ return;
4276
+ }
4277
+ if (t.kind === "inspector") {
4278
+ const s = document.createElement("div");
4279
+ s.dataset.viewerContribution = "inspector", s.dataset.viewerContributionId = t.id;
4280
+ const o = () => {
4281
+ const d = this.readCad(), l = d.inspector.selection ? { kind: "insert", selection: d.inspector.selection } : d.inspector.textSelection ? { kind: "text", selection: d.inspector.textSelection } : null;
4282
+ if (!l || !t.matcher(l) || !this.isFirstMatchingInspector(e, l)) {
4283
+ s.replaceChildren();
4284
+ return;
4285
+ }
4286
+ s.replaceChildren(t.render(e.context, l));
4287
+ }, a = this.subscribe("inspector-change", o);
4288
+ this.hostElement.append(s), e.cleanup = () => {
4289
+ a(), s.remove();
4290
+ }, o();
4291
+ return;
4292
+ }
4293
+ if (t.kind !== "panel" && t.kind !== "hud" && t.kind !== "statusbar") return;
4294
+ const i = t.factory(e.context);
4295
+ if (!i || typeof Node < "u" && !(i instanceof Node))
4296
+ throw new TypeError(`Contribution ${t.id} factory must return a Node.`);
4297
+ const r = document.createElement("div");
4298
+ r.dataset.viewerContribution = t.kind, r.dataset.viewerContributionId = t.id, r.append(i), this.hostElement.append(r), e.cleanup = () => r.remove();
4299
+ }
4300
+ isFirstMatchingInspector(e, t) {
4301
+ for (const i of this.contributions)
4302
+ if (i.point.kind === "inspector") {
4303
+ if (i === e) return !0;
4304
+ if (i.point.matcher(t)) return !1;
4305
+ }
4306
+ return !1;
4307
+ }
4308
+ refreshInspectorContributions() {
4309
+ var e;
4310
+ if (!this.refreshingInspectors) {
4311
+ this.refreshingInspectors = !0;
4312
+ try {
4313
+ for (const t of [...this.contributions])
4314
+ if (t.point.kind === "inspector") {
4315
+ (e = t.cleanup) == null || e.call(t), t.cleanup = void 0;
4316
+ try {
4317
+ this.mountContribution(t);
4318
+ } catch (i) {
4319
+ console.error(`[viewer] inspector contribution ${t.point.id} refresh failed`, i), this.removeContribution(t);
4320
+ }
4321
+ }
4322
+ } finally {
4323
+ this.refreshingInspectors = !1;
4324
+ }
4325
+ }
4326
+ }
4327
+ assertActive() {
4328
+ if (this.disposed) throw new Error("Viewer plugin manager has been disposed.");
4329
+ }
4330
+ }
4331
+ const B = "viewer:highlight", z = "viewer:cad-selection", H = "viewer:cad-hover", Me = {
3478
4332
  dark: {
3479
4333
  hover: { color: 3528703, fillOpacity: 0, edgeOpacity: 0.85 },
3480
4334
  selected: { color: 5999871, fillOpacity: 0.24, edgeOpacity: 1 }
@@ -3483,35 +4337,41 @@ const B = "viewer:highlight", z = "viewer:cad-selection", H = "viewer:cad-hover"
3483
4337
  hover: { color: 24524, fillOpacity: 0, edgeOpacity: 0.95 },
3484
4338
  selected: { color: 24524, fillOpacity: 0.2, edgeOpacity: 1 }
3485
4339
  }
3486
- }, Ei = 6, Ii = 12, Mi = 160, ki = 160, Ti = 50, Ee = 5e3;
3487
- class Di {
4340
+ }, qi = 6, ji = 12, Wi = 160, Gi = 160, Zi = 50;
4341
+ class Ji {
3488
4342
  constructor(e, t) {
3489
- a(this, "cad");
3490
- a(this, "mountedObjects", /* @__PURE__ */ new Set());
3491
- a(this, "listeners", /* @__PURE__ */ new Map());
3492
- a(this, "selectedObjectValue", null);
3493
- a(this, "highlightedObjectValue", null);
3494
- a(this, "pointerStart", null);
3495
- a(this, "disposed", !1);
3496
- a(this, "cadRenderRoot", null);
3497
- a(this, "interaction", "idle");
3498
- a(this, "interactionIdleTimer", null);
3499
- a(this, "interactionRenderLastTs", null);
3500
- a(this, "cadHoveredInsert", null);
3501
- a(this, "cadPointerPosition", null);
3502
- a(this, "pointerDragTracker", new ti({
3503
- distancePx: Ei,
3504
- pathPx: Ii
4343
+ c(this, "cad");
4344
+ c(this, "mountedObjects", /* @__PURE__ */ new Set());
4345
+ c(this, "listeners", /* @__PURE__ */ new Map());
4346
+ c(this, "selectedObjectValue", null);
4347
+ c(this, "highlightedObjectValue", null);
4348
+ c(this, "pointerStart", null);
4349
+ c(this, "disposed", !1);
4350
+ c(this, "cadRenderRoot", null);
4351
+ c(this, "interaction", "idle");
4352
+ c(this, "interactionIdleTimer", null);
4353
+ c(this, "interactionRenderLastTs", null);
4354
+ c(this, "cadHoveredInsert", null);
4355
+ c(this, "cadPointerPosition", null);
4356
+ c(this, "pointerDragTracker", new ui({
4357
+ distancePx: qi,
4358
+ pathPx: ji
3505
4359
  }));
3506
- a(this, "cadCapability");
3507
- a(this, "cadHost");
3508
- a(this, "ui");
3509
- a(this, "cameraStateStore");
3510
- a(this, "cadInspectorUnsubscribe");
3511
- a(this, "cadDocumentUnsubscribe");
3512
- a(this, "handlePointerDown", (e) => {
4360
+ c(this, "cadCapability");
4361
+ c(this, "cadHost");
4362
+ c(this, "ui", null);
4363
+ c(this, "cameraStateStore");
4364
+ c(this, "initialCameraSnapshot");
4365
+ c(this, "pluginManager");
4366
+ c(this, "interactionMode");
4367
+ c(this, "lastCadSelectionFingerprint", null);
4368
+ c(this, "lastCameraFingerprint", null);
4369
+ c(this, "pendingCameraReason", "api");
4370
+ c(this, "cadInspectorUnsubscribe");
4371
+ c(this, "cadDocumentUnsubscribe");
4372
+ c(this, "handlePointerDown", (e) => {
3513
4373
  if (this.disposed) return;
3514
- if (this.rememberCadPointer(e.clientX, e.clientY), !(e.isPrimary !== !1) || this.pointerStart !== null) {
4374
+ if (this.rememberCadPointer(e.clientX, e.clientY), this.pendingCameraReason = "pointer", !(e.isPrimary !== !1) || this.pointerStart !== null) {
3515
4375
  this.pointerStart = null, this.pointerDragTracker.reset(), this.markInteractionActive();
3516
4376
  return;
3517
4377
  }
@@ -3522,21 +4382,21 @@ class Di {
3522
4382
  button: e.button
3523
4383
  }, this.pointerDragTracker.begin(e.clientX, e.clientY), this.markInteractionActive();
3524
4384
  });
3525
- a(this, "handleWheel", (e) => {
4385
+ c(this, "handleWheel", (e) => {
3526
4386
  if (this.disposed) return;
3527
4387
  const t = e.clientX === 0 && e.clientY === 0 ? this.cadPointerPosition : { clientX: e.clientX, clientY: e.clientY };
3528
- t && this.rememberCadPointer(t.clientX, t.clientY), this.markInteractionActive(), this.scheduleInteractionIdle();
4388
+ t && this.rememberCadPointer(t.clientX, t.clientY), this.markInteractionActive(), this.pendingCameraReason = "wheel", this.scheduleInteractionIdle();
3529
4389
  });
3530
- a(this, "handlePointerMove", (e) => {
3531
- if (!this.disposed) {
3532
- if (this.rememberCadPointer(e.clientX, e.clientY), e.buttons > 0) {
3533
- this.pointerDragTracker.update(e.clientX, e.clientY, e.buttons), this.markInteractionActive(), this.setCadHoveredInsert(null), this.emit("pointer-move", this.toPointerEvent(e));
3534
- return;
3535
- }
3536
- this.updateCadHoveredInsert(e.clientX, e.clientY), this.emit("pointer-move", this.toPointerEvent(e));
4390
+ c(this, "handlePointerMove", (e) => {
4391
+ if (this.disposed) return;
4392
+ if (this.rememberCadPointer(e.clientX, e.clientY), e.buttons > 0) {
4393
+ this.pointerDragTracker.update(e.clientX, e.clientY, e.buttons), this.markInteractionActive(), this.setCadHoveredInsert(null), this.emit("pointer-move", this.toPointerEvent(e));
4394
+ return;
3537
4395
  }
4396
+ const t = this.interactionMode === "disabled" ? null : this.cadCapability.hitTest(e.clientX, e.clientY);
4397
+ this.interactionMode !== "disabled" && this.pluginManager.dispatchInteraction("onHover", t), this.interactionMode === "managed" ? this.updateCadHoveredInsert(e.clientX, e.clientY) : this.setCadHoveredInsert(null), this.emit("pointer-move", this.toPointerEvent(e));
3538
4398
  });
3539
- a(this, "handlePointerUp", (e) => {
4399
+ c(this, "handlePointerUp", (e) => {
3540
4400
  const t = this.pointerStart;
3541
4401
  this.pointerStart = null, this.pointerDragTracker.update(e.clientX, e.clientY, e.buttons);
3542
4402
  const i = this.pointerDragTracker.hasExceededDragThreshold;
@@ -3544,8 +4404,15 @@ class Di {
3544
4404
  return;
3545
4405
  const r = this.toPointerEvent(e);
3546
4406
  this.emit("pointer-click", r);
3547
- const s = this.cadCapability.pickInsertAtScreen(e.clientX, e.clientY);
3548
- if (s) {
4407
+ const s = this.interactionMode === "disabled" ? null : this.cadCapability.hitTest(e.clientX, e.clientY);
4408
+ if (this.interactionMode !== "disabled" && this.pluginManager.dispatchInteraction("onPick", s)) return;
4409
+ if (this.interactionMode !== "managed") {
4410
+ if (this.options.pointerPick === !1) return;
4411
+ const a = this.pick(e.clientX, e.clientY);
4412
+ this.emit("pick", { ...r, result: a }), this.options.autoSelectOnPick !== !1 && this.setSelection((a == null ? void 0 : a.object) ?? null);
4413
+ return;
4414
+ }
4415
+ if ((s == null ? void 0 : s.kind) === "insert") {
3549
4416
  if (this.isSameCadInsertSelection(s.selection, this.cad.inspector.selection)) {
3550
4417
  this.cadCapability.setInsertSelection(null, null), this.setCadHoveredInsert(s), this.setSelection(null);
3551
4418
  return;
@@ -3553,44 +4420,67 @@ class Di {
3553
4420
  this.cadCapability.setInsertSelection(s.selection, s.details), this.setCadHoveredInsert(s), this.setSelection(null);
3554
4421
  return;
3555
4422
  }
3556
- this.setCadHoveredInsert(null), this.cadCapability.setInsertSelection(null, null);
3557
- const o = this.cadCapability.pickTextAtScreen(e.clientX, e.clientY);
3558
- if (o) {
3559
- this.cadCapability.setTextSelection(o.selection, o.details), this.setSelection(null);
4423
+ if (this.setCadHoveredInsert(null), this.cadCapability.setInsertSelection(null, null), (s == null ? void 0 : s.kind) === "text") {
4424
+ this.cadCapability.setTextSelectionInternal(s.selection, s.details), this.setSelection(null);
3560
4425
  return;
3561
4426
  }
3562
- if (this.cadCapability.setTextSelection(null, null), this.options.pointerPick === !1) return;
3563
- const c = this.pick(e.clientX, e.clientY);
4427
+ if (this.cadCapability.setTextSelectionInternal(null, null), this.options.pointerPick === !1) return;
4428
+ const o = this.pick(e.clientX, e.clientY);
3564
4429
  this.emit("pick", {
3565
4430
  ...r,
3566
- result: c
3567
- }), this.options.autoSelectOnPick !== !1 && this.setSelection((c == null ? void 0 : c.object) ?? null);
4431
+ result: o
4432
+ }), this.options.autoSelectOnPick !== !1 && this.setSelection((o == null ? void 0 : o.object) ?? null);
3568
4433
  });
3569
- a(this, "handlePointerCancel", () => {
3570
- this.pointerStart = null, this.cadPointerPosition = null, this.pointerDragTracker.reset(), this.setCadHoveredInsert(null), this.scheduleInteractionIdle();
4434
+ c(this, "handlePointerCancel", () => {
4435
+ this.pointerStart = null, this.cadPointerPosition = null, this.pointerDragTracker.reset(), this.setCadHoveredInsert(null), this.interactionMode !== "disabled" && this.pluginManager.dispatchInteraction("onHover", null), this.scheduleInteractionIdle();
3571
4436
  });
3572
- a(this, "handleLostPointerCapture", (e) => {
4437
+ c(this, "handleLostPointerCapture", (e) => {
3573
4438
  var t;
3574
- ((t = this.pointerStart) == null ? void 0 : t.pointerId) === e.pointerId && (this.pointerStart = null, this.cadPointerPosition = null, this.pointerDragTracker.reset(), this.setCadHoveredInsert(null), this.scheduleInteractionIdle());
4439
+ ((t = this.pointerStart) == null ? void 0 : t.pointerId) === e.pointerId && (this.pointerStart = null, this.cadPointerPosition = null, this.pointerDragTracker.reset(), this.setCadHoveredInsert(null), this.interactionMode !== "disabled" && this.pluginManager.dispatchInteraction("onHover", null), this.scheduleInteractionIdle());
3575
4440
  });
3576
- a(this, "handleWindowBlur", () => {
3577
- this.pointerStart = null, this.cadPointerPosition = null, this.pointerDragTracker.reset(), this.setCadHoveredInsert(null), this.scheduleInteractionIdle();
4441
+ c(this, "handleWindowBlur", () => {
4442
+ this.pointerStart = null, this.cadPointerPosition = null, this.pointerDragTracker.reset(), this.setCadHoveredInsert(null), this.interactionMode !== "disabled" && this.pluginManager.dispatchInteraction("onHover", null), this.scheduleInteractionIdle();
3578
4443
  });
3579
- a(this, "handlePointerLeave", (e) => {
3580
- this.pointerStart = null, this.cadPointerPosition = null, this.pointerDragTracker.reset(), this.setCadHoveredInsert(null), this.scheduleInteractionIdle(), !this.disposed && this.emit("pointer-leave", this.toPointerEvent(e));
4444
+ c(this, "handlePointerLeave", (e) => {
4445
+ this.pointerStart = null, this.cadPointerPosition = null, this.pointerDragTracker.reset(), this.setCadHoveredInsert(null), this.interactionMode !== "disabled" && this.pluginManager.dispatchInteraction("onHover", null), this.scheduleInteractionIdle(), !this.disposed && this.emit("pointer-leave", this.toPointerEvent(e));
3581
4446
  });
3582
- var i, r, s, o, c, l, d, h, u, v, f, p, m, b, g;
3583
- this.options = e, this.runtime = t, this.cameraStateStore = e.cameraStateStore === !1 ? void 0 : e.cameraStateStore ?? Xt(), this.cadHost = this.createCadHost(), this.cadCapability = new Qt(this.cadHost), this.cad = this.cadCapability, this.cadInspectorUnsubscribe = this.cad.on("inspector-change", () => {
3584
- this.syncCadSelectionOverlay(), this.syncCadHoverOverlay();
4447
+ var i, r, s, o, a, d, l, h, u, p, b, v, y, m;
4448
+ this.options = e, this.runtime = t, this.cameraStateStore = e.cameraStateStore === !1 ? void 0 : e.cameraStateStore ?? qt(), this.interactionMode = e.cadInteraction ?? "managed", this.cadHost = this.createCadHost(), this.cadCapability = new oi(this.cadHost), this.cad = this.cadCapability, this.initialCameraSnapshot = t.captureCameraSnapshot(), this.lastCameraFingerprint = j(this.initialCameraSnapshot), this.pluginManager = new Ki(
4449
+ () => this.cadCapability.getSnapshot(),
4450
+ () => ({
4451
+ viewMode: this.runtime.viewMode,
4452
+ selectedObject: this.selectedObjectValue,
4453
+ highlightedObject: this.highlightedObjectValue,
4454
+ isDisposed: this.disposed
4455
+ }),
4456
+ (f, g) => this.subscribePluginEvent(f, g),
4457
+ {
4458
+ setLayerVisible: (f, g) => this.cad.layers.setVisible(f, g),
4459
+ setSelection: (f) => this.cad.select(f),
4460
+ fitDocument: () => this.cad.fitDocument(),
4461
+ setViewMode: (f) => this.setViewMode(f)
4462
+ },
4463
+ e.viewport
4464
+ ), this.cadInspectorUnsubscribe = this.cad.on("inspector-change", () => {
4465
+ this.interactionMode === "managed" && (this.syncCadSelectionOverlay(), this.syncCadHoverOverlay()), this.dispatchCadSelectionChange();
3585
4466
  }), this.cadDocumentUnsubscribe = this.cad.on("document-change", () => {
3586
- this.setCadHoveredInsert(null), this.syncCadSelectionOverlay();
3587
- }), this.ui = e.ui ? new Si(this.createUiHost(), e.ui) : null, (i = this.ui) == null || i.mount(), (s = (r = this.options.canvas).addEventListener) == null || s.call(r, "pointerdown", this.handlePointerDown), (c = (o = this.options.canvas).addEventListener) == null || c.call(o, "pointermove", this.handlePointerMove), (d = (l = this.options.canvas).addEventListener) == null || d.call(l, "pointerup", this.handlePointerUp), (u = (h = this.options.canvas).addEventListener) == null || u.call(h, "pointercancel", this.handlePointerCancel), (f = (v = this.options.canvas).addEventListener) == null || f.call(v, "pointerleave", this.handlePointerLeave), (m = (p = this.options.canvas).addEventListener) == null || m.call(p, "lostpointercapture", this.handleLostPointerCapture), (g = (b = this.options.canvas).addEventListener) == null || g.call(b, "wheel", this.handleWheel, { passive: !0 }), typeof globalThis.window < "u" && globalThis.window.addEventListener("blur", this.handleWindowBlur), this.runtime.startAnimation({
3588
- shouldRender: (y) => this.shouldRenderCurrentFrame(y),
3589
- beforeRender: (y) => {
3590
- this.cadCapability.onBeforeRender(), this.interaction === "active" && (this.interactionRenderLastTs = y);
4467
+ this.setCadHoveredInsert(null), this.interactionMode === "managed" && this.syncCadSelectionOverlay();
4468
+ }), e.ui && this.interactionMode === "managed" && this.pluginManager.register({
4469
+ id: "nebula-cad-readonly",
4470
+ activate: () => {
4471
+ this.ui = new Ui(this.createUiHost(), e.ui), this.ui.mount();
4472
+ },
4473
+ deactivate: () => {
4474
+ var f;
4475
+ (f = this.ui) == null || f.dispose(), this.ui = null;
4476
+ }
4477
+ }), (r = (i = this.options.canvas).addEventListener) == null || r.call(i, "pointerdown", this.handlePointerDown), (o = (s = this.options.canvas).addEventListener) == null || o.call(s, "pointermove", this.handlePointerMove), (d = (a = this.options.canvas).addEventListener) == null || d.call(a, "pointerup", this.handlePointerUp), (h = (l = this.options.canvas).addEventListener) == null || h.call(l, "pointercancel", this.handlePointerCancel), (p = (u = this.options.canvas).addEventListener) == null || p.call(u, "pointerleave", this.handlePointerLeave), (v = (b = this.options.canvas).addEventListener) == null || v.call(b, "lostpointercapture", this.handleLostPointerCapture), (m = (y = this.options.canvas).addEventListener) == null || m.call(y, "wheel", this.handleWheel, { passive: !0 }), typeof globalThis.window < "u" && globalThis.window.addEventListener("blur", this.handleWindowBlur), this.runtime.startAnimation({
4478
+ shouldRender: (f) => this.shouldRenderCurrentFrame(f),
4479
+ beforeRender: (f) => {
4480
+ this.detectCameraChange() || this.cadCapability.onBeforeRender(), this.interaction === "active" && (this.interactionRenderLastTs = f);
3591
4481
  },
3592
4482
  onInfoUpdate: () => {
3593
- this.cadCapability.onViewportChanged();
4483
+ this.detectCameraChange() || this.cadCapability.onRuntimeStatsChanged();
3594
4484
  }
3595
4485
  });
3596
4486
  }
@@ -3612,27 +4502,58 @@ class Di {
3612
4502
  get isDisposed() {
3613
4503
  return this.disposed;
3614
4504
  }
3615
- addObject(e) {
3616
- this.assertActive(), !this.mountedObjects.has(e) && (this.runtime.addObject(e), this.mountedObjects.add(e));
4505
+ get overlays() {
4506
+ return {
4507
+ set: (e, t, i) => {
4508
+ this.assertActive(), this.runtime.mountOverlay(e, t, { owned: (i == null ? void 0 : i.owned) ?? !1 });
4509
+ },
4510
+ remove: (e, t) => (this.assertActive(), this.runtime.removeOverlay(e, t))
4511
+ };
4512
+ }
4513
+ get camera() {
4514
+ return {
4515
+ getState: () => (this.assertActive(), this.runtime.captureCameraSnapshot()),
4516
+ setState: (e) => (this.assertActive(), this.applyCameraSnapshot(e, "api")),
4517
+ reset: () => (this.assertActive(), this.initialCameraSnapshot ? this.applyCameraSnapshot(this.initialCameraSnapshot, "restore") : !1)
4518
+ };
4519
+ }
4520
+ get plugins() {
4521
+ return this.assertActive(), this.pluginManager;
4522
+ }
4523
+ get commands() {
4524
+ return {
4525
+ execute: (e, t) => (this.assertActive(), this.pluginManager.executeCommand(e, t)),
4526
+ has: (e) => this.pluginManager.hasCommand(e)
4527
+ };
4528
+ }
4529
+ addObject(e, t) {
4530
+ this.assertActive(), !this.mountedObjects.has(e) && (this.runtime.addObject(e), this.mountedObjects.add(e), this.emit("content-change", { source: "object" }));
3617
4531
  }
3618
4532
  removeObject(e) {
3619
4533
  if (this.assertActive(), !this.mountedObjects.has(e)) return !1;
3620
4534
  this.selectedObjectValue && this.isObjectWithinRoot(this.selectedObjectValue, e) && this.setSelection(null), this.highlightedObjectValue && this.isObjectWithinRoot(this.highlightedObjectValue, e) && this.setHighlight(null);
3621
4535
  const t = this.runtime.removeObject(e, { dispose: !1 });
3622
- return t && this.mountedObjects.delete(e), t;
4536
+ return t && (this.mountedObjects.delete(e), this.emit("content-change", { source: "object" })), t;
3623
4537
  }
3624
4538
  setVisible(e, t) {
3625
- this.assertActive(), this.assertMounted(e), this.runtime.setObjectVisible(e, t);
4539
+ this.assertActive(), this.assertMounted(e);
4540
+ const i = e.visible !== t;
4541
+ this.runtime.setObjectVisible(e, t), i && this.emit("content-change", { source: "object" });
3626
4542
  }
3627
4543
  setViewMode(e, t) {
3628
- this.assertActive(), e !== this.runtime.viewMode && (t ? this.runtime.setViewMode(e, t) : this.runtime.setViewMode(e), this.emit("view-mode-change", { viewMode: e }), this.cadCapability.onCameraChanged(), this.cadCapability.onViewportChanged(), this.refreshCadPointerHover());
4544
+ this.assertActive(), e !== this.runtime.viewMode && (t ? this.runtime.setViewMode(e, t) : this.runtime.setViewMode(e), this.emit("view-mode-change", { viewMode: e }), this.pendingCameraReason = "view-mode", this.cadCapability.onCameraChanged("view-mode"), this.refreshCadPointerHover());
3629
4545
  }
3630
4546
  fitView(e, t) {
3631
- this.assertActive(), e && !(e instanceof S) && this.assertMounted(e);
3632
- const i = e ?? this.resolveFocusedCadBounds() ?? this.resolveMixedBounds();
4547
+ this.assertActive(), e && !(e instanceof R) && this.assertMounted(e);
4548
+ const i = e ?? this.pluginManager.findFitPolicy() ?? this.resolveMixedBounds();
3633
4549
  if (!i) return !1;
3634
4550
  const r = this.runtime.fitView(i, t);
3635
- return r && (this.cadCapability.onCameraChanged(), this.cadCapability.onViewportChanged(), this.refreshCadPointerHover()), r;
4551
+ return r && (this.pendingCameraReason = "fit", this.cadCapability.onCameraChanged("fit"), this.refreshCadPointerHover()), r;
4552
+ }
4553
+ fitAll(e) {
4554
+ this.assertActive();
4555
+ const t = this.resolveMixedBounds();
4556
+ return t ? this.fitView(t, e) : !1;
3636
4557
  }
3637
4558
  screenToWorldOnPlane(e, t, i = 0) {
3638
4559
  var r;
@@ -3657,7 +4578,7 @@ class Di {
3657
4578
  setHighlight(e, t = {}) {
3658
4579
  if (this.assertActive(), e && this.assertMounted(e), !(this.highlightedObjectValue === null && e === null)) {
3659
4580
  if (this.runtime.removeOverlay(B), this.highlightedObjectValue = e, e) {
3660
- const i = new Qe(e, t.color ?? 6000111);
4581
+ const i = new st(e, t.color ?? 6000111);
3661
4582
  i.name = B, this.runtime.mountOverlay(B, i, { owned: !0 });
3662
4583
  }
3663
4584
  this.emit("highlight-change", { object: e });
@@ -3675,18 +4596,21 @@ class Di {
3675
4596
  resize() {
3676
4597
  this.assertActive();
3677
4598
  const e = this.runtime.resize();
3678
- return this.emit("resize", { resized: e }), e && (this.cadCapability.onViewportChanged(), this.refreshCadPointerHover()), e;
4599
+ return this.emit("resize", { resized: e }), e && (this.emitViewportChange(), this.cadCapability.onViewportChanged(), this.refreshCadPointerHover()), e;
3679
4600
  }
3680
4601
  requestRender() {
3681
4602
  this.assertActive(), this.runtime.requestRender();
3682
4603
  }
4604
+ use(e, t) {
4605
+ this.assertActive(), this.pluginManager.use(e, t);
4606
+ }
3683
4607
  dispose() {
3684
- var e, t, i, r, s, o, c, l, d, h, u, v, f, p, m;
4608
+ var e, t, i, r, s, o, a, d, l, h, u, p, b, v;
3685
4609
  if (!this.disposed) {
3686
- this.disposed = !0, this.clearInteractionIdleTimer(), this.pointerDragTracker.reset(), (t = (e = this.options.canvas).removeEventListener) == null || t.call(e, "pointerdown", this.handlePointerDown), (r = (i = this.options.canvas).removeEventListener) == null || r.call(i, "pointermove", this.handlePointerMove), (o = (s = this.options.canvas).removeEventListener) == null || o.call(s, "pointerup", this.handlePointerUp), (l = (c = this.options.canvas).removeEventListener) == null || l.call(c, "pointercancel", this.handlePointerCancel), (h = (d = this.options.canvas).removeEventListener) == null || h.call(d, "pointerleave", this.handlePointerLeave), (v = (u = this.options.canvas).removeEventListener) == null || v.call(u, "lostpointercapture", this.handleLostPointerCapture), (p = (f = this.options.canvas).removeEventListener) == null || p.call(f, "wheel", this.handleWheel), typeof globalThis.window < "u" && globalThis.window.removeEventListener("blur", this.handleWindowBlur), this.pointerStart = null, this.cadPointerPosition = null, this.setCadHoveredInsert(null), this.setCanvasCursor(""), this.highlightedObjectValue && this.runtime.removeOverlay(B), this.runtime.removeOverlay(z), this.runtime.removeOverlay(H), this.cadInspectorUnsubscribe(), this.cadDocumentUnsubscribe(), this.highlightedObjectValue = null, this.selectedObjectValue = null;
3687
- for (const b of this.mountedObjects)
3688
- this.runtime.removeObject(b, { dispose: !1 });
3689
- this.mountedObjects.clear(), (m = this.ui) == null || m.dispose(), this.cadCapability.dispose(), this.listeners.clear(), this.runtime.dispose();
4610
+ this.disposed = !0, this.pluginManager.dispose(), this.clearInteractionIdleTimer(), this.pointerDragTracker.reset(), (t = (e = this.options.canvas).removeEventListener) == null || t.call(e, "pointerdown", this.handlePointerDown), (r = (i = this.options.canvas).removeEventListener) == null || r.call(i, "pointermove", this.handlePointerMove), (o = (s = this.options.canvas).removeEventListener) == null || o.call(s, "pointerup", this.handlePointerUp), (d = (a = this.options.canvas).removeEventListener) == null || d.call(a, "pointercancel", this.handlePointerCancel), (h = (l = this.options.canvas).removeEventListener) == null || h.call(l, "pointerleave", this.handlePointerLeave), (p = (u = this.options.canvas).removeEventListener) == null || p.call(u, "lostpointercapture", this.handleLostPointerCapture), (v = (b = this.options.canvas).removeEventListener) == null || v.call(b, "wheel", this.handleWheel), typeof globalThis.window < "u" && globalThis.window.removeEventListener("blur", this.handleWindowBlur), this.pointerStart = null, this.cadPointerPosition = null, this.setCadHoveredInsert(null), this.setCanvasCursor(""), this.highlightedObjectValue && this.runtime.removeOverlay(B), this.runtime.removeOverlay(z), this.runtime.removeOverlay(H), this.cadInspectorUnsubscribe(), this.cadDocumentUnsubscribe(), this.highlightedObjectValue = null, this.selectedObjectValue = null;
4611
+ for (const y of this.mountedObjects)
4612
+ this.runtime.removeObject(y, { dispose: !1 });
4613
+ this.mountedObjects.clear(), this.cadCapability.dispose(), this.listeners.clear(), this.runtime.dispose();
3690
4614
  }
3691
4615
  }
3692
4616
  createCadHost() {
@@ -3708,7 +4632,7 @@ class Di {
3708
4632
  return e.cadCapability.getVisibilityRevision();
3709
4633
  },
3710
4634
  get viewportDemandCoalesceMs() {
3711
- return e.options.viewportDemandCoalesceMs ?? ki;
4635
+ return e.options.viewportDemandCoalesceMs ?? Gi;
3712
4636
  },
3713
4637
  mountCadObject(t) {
3714
4638
  e.unmountCadObject(), e.runtime.addObject(t, { owned: !0 }), e.cadRenderRoot = t;
@@ -3722,14 +4646,19 @@ class Di {
3722
4646
  emitContentChange() {
3723
4647
  e.emit("content-change", { source: "cad" });
3724
4648
  },
3725
- emitViewportChange(t) {
3726
- e.emit("viewport-change", t);
4649
+ emitCameraChange(t = e.pendingCameraReason) {
4650
+ e.lastCameraFingerprint = j(e.runtime.captureCameraSnapshot()), e.emit("camera-change", {
4651
+ viewMode: e.runtime.viewMode,
4652
+ reason: t,
4653
+ interaction: e.interaction
4654
+ }), e.emitViewportChange();
3727
4655
  },
3728
- emitCameraChange() {
3729
- e.emit("camera-change", { viewMode: e.runtime.viewMode });
4656
+ applyCameraSnapshot(t, i) {
4657
+ return e.applyCameraSnapshot(t, i);
3730
4658
  },
3731
4659
  fitBox3(t, i) {
3732
- return e.runtime.fitView(t, i);
4660
+ const r = e.runtime.fitView(t, i);
4661
+ return r && (e.pendingCameraReason = "fit", e.cadCapability.onCameraChanged("fit")), r;
3733
4662
  },
3734
4663
  resolveMixedBounds() {
3735
4664
  return e.resolveMixedBounds();
@@ -3742,10 +4671,10 @@ class Di {
3742
4671
  return ((s = e.runtime.screenToWorldOnPlane(t, i, r)) == null ? void 0 : s.clone()) ?? null;
3743
4672
  },
3744
4673
  readCameraSnapshot(t) {
3745
- return qt(e.cameraStateStore, t);
4674
+ return Wt(e.cameraStateStore, t);
3746
4675
  },
3747
4676
  persistCameraSnapshot(t, i) {
3748
- Wt(e.cameraStateStore, t, i);
4677
+ Gt(e.cameraStateStore, t, i);
3749
4678
  },
3750
4679
  getViewportSize() {
3751
4680
  return {
@@ -3759,73 +4688,83 @@ class Di {
3759
4688
  };
3760
4689
  }
3761
4690
  syncCadSelectionOverlay() {
3762
- var o, c;
4691
+ var o, a, d, l, h, u;
3763
4692
  this.runtime.removeOverlay(z);
3764
4693
  const e = this.cad.inspector, t = (o = e.details) != null && o.bbox && [
3765
4694
  e.details.bbox.minX,
3766
4695
  e.details.bbox.minY,
3767
4696
  e.details.bbox.maxX,
3768
4697
  e.details.bbox.maxY
3769
- ].every(Number.isFinite) ? e.details.bbox : null, i = t ? new S(
3770
- new w(t.minX, t.minY, -0.01),
3771
- new w(t.maxX, t.maxY, 0.01)
3772
- ) : e.textDetails ? new S(
3773
- new w(e.textDetails.x, e.textDetails.y, -0.01),
3774
- new w(
4698
+ ].every(Number.isFinite) ? e.details.bbox : null, i = t ? new R(
4699
+ new C(t.minX, t.minY, -0.01),
4700
+ new C(t.maxX, t.maxY, 0.01)
4701
+ ) : e.textDetails ? new R(
4702
+ new C(e.textDetails.x, e.textDetails.y, -0.01),
4703
+ new C(
3775
4704
  e.textDetails.x + e.textDetails.content.length * e.textDetails.height * 0.6,
3776
4705
  e.textDetails.y + e.textDetails.height,
3777
4706
  0.01
3778
4707
  )
3779
4708
  ) : null;
3780
4709
  if (!i || i.isEmpty()) return;
3781
- const s = !!((c = e.details) != null && c.bbox) ? this.createCadInteractionOverlay(i, "selected") : new et(i, Re.dark.selected.color);
4710
+ const r = !!((a = e.details) != null && a.bbox);
4711
+ if (((l = (d = this.options.cadInteractionStyle) == null ? void 0 : d.selected) == null ? void 0 : l.enabled) === !1) return;
4712
+ const s = r ? this.createCadInteractionOverlay(i, "selected") : new ot(i, ((u = (h = this.options.cadInteractionStyle) == null ? void 0 : h.selected) == null ? void 0 : u.color) ?? Me.dark.selected.color);
3782
4713
  s.name = z, this.runtime.mountOverlay(z, s, { owned: !0 });
3783
4714
  }
4715
+ dispatchCadSelectionChange() {
4716
+ const e = this.cad.inspector, t = e.selection ? { kind: "insert", selection: e.selection } : e.textSelection ? { kind: "text", selection: e.textSelection } : null, i = (t == null ? void 0 : t.kind) === "insert" ? `${t.selection.documentKey ?? ""}:insert:${t.selection.id.layerIndex}:${t.selection.id.variantId}:${t.selection.id.instanceId}` : t ? `${t.selection.documentKey ?? ""}:text:${t.selection.id.textId}` : null;
4717
+ i !== this.lastCadSelectionFingerprint && (this.lastCadSelectionFingerprint = i, this.interactionMode !== "disabled" && (t ? this.pluginManager.dispatchInteraction("onSelect", t) : this.pluginManager.dispatchInteraction("onClear", null)));
4718
+ }
3784
4719
  syncCadHoverOverlay() {
3785
- var s;
4720
+ var s, o, a;
3786
4721
  this.runtime.removeOverlay(H);
3787
4722
  const e = this.cadHoveredInsert, t = this.cad.inspector.selection;
3788
4723
  if (!((s = e == null ? void 0 : e.details) != null && s.bbox) || this.isSameCadInsertSelection(e.selection, t)) return;
3789
4724
  const i = this.cadInsertDetailsToBox(e.details);
3790
- if (!i || i.isEmpty()) return;
4725
+ if (!i || i.isEmpty() || ((a = (o = this.options.cadInteractionStyle) == null ? void 0 : o.hover) == null ? void 0 : a.enabled) === !1) return;
3791
4726
  const r = this.createCadInteractionOverlay(i, "hover");
3792
4727
  r.name = H, this.runtime.mountOverlay(H, r, { owned: !0 });
3793
4728
  }
3794
4729
  createCadInteractionOverlay(e, t) {
3795
- var h;
3796
- const i = ((h = this.options.ui) == null ? void 0 : h.theme) === "light" ? "light" : "dark", r = Re[i][t], s = new Ie();
3797
- s.name = t === "hover" ? "cad-insert-hover" : "cad-insert-selected", s.renderOrder = t === "hover" ? 1300 : 1310;
3798
- const o = e.getSize(new w()), c = e.getCenter(new w()), l = new tt(Math.max(o.x, 1e-6), Math.max(o.y, 1e-6), Math.max(o.z, 1e-3));
3799
- if (r.fillOpacity > 0) {
3800
- const u = new it(
3801
- l.clone(),
3802
- new rt({
3803
- color: r.color,
4730
+ var p, b;
4731
+ const i = ((p = this.options.ui) == null ? void 0 : p.theme) === "light" ? "light" : "dark", r = Me[i][t], s = (b = this.options.cadInteractionStyle) == null ? void 0 : b[t], o = {
4732
+ color: (s == null ? void 0 : s.color) ?? r.color,
4733
+ fillOpacity: (s == null ? void 0 : s.fillOpacity) ?? r.fillOpacity,
4734
+ edgeOpacity: (s == null ? void 0 : s.edgeOpacity) ?? r.edgeOpacity
4735
+ }, a = new Te();
4736
+ a.name = t === "hover" ? "cad-insert-hover" : "cad-insert-selected", a.renderOrder = t === "hover" ? 1300 : 1310;
4737
+ const d = e.getSize(new C()), l = e.getCenter(new C()), h = new at(Math.max(d.x, 1e-6), Math.max(d.y, 1e-6), Math.max(d.z, 1e-3));
4738
+ if (o.fillOpacity > 0) {
4739
+ const v = new lt(
4740
+ h.clone(),
4741
+ new ct({
4742
+ color: o.color,
3804
4743
  transparent: !0,
3805
- opacity: r.fillOpacity,
4744
+ opacity: o.fillOpacity,
3806
4745
  depthTest: !0,
3807
4746
  depthWrite: !1
3808
4747
  })
3809
4748
  );
3810
- u.name = `${s.name}:fill`, u.position.copy(c), u.renderOrder = 1305, s.add(u);
4749
+ v.name = `${a.name}:fill`, v.position.copy(l), v.renderOrder = 1305, a.add(v);
3811
4750
  }
3812
- const d = new nt(
3813
- new st(l),
3814
- new ot({
3815
- color: r.color,
4751
+ const u = new dt(
4752
+ new ht(h),
4753
+ new ut({
4754
+ color: o.color,
3816
4755
  transparent: !0,
3817
- opacity: r.edgeOpacity,
4756
+ opacity: o.edgeOpacity,
3818
4757
  depthTest: !0,
3819
4758
  depthWrite: !1
3820
4759
  })
3821
4760
  );
3822
- return d.name = `${s.name}:edges`, d.position.copy(c), d.renderOrder = t === "hover" ? 1300 : 1310, s.add(d), l.dispose(), s;
4761
+ return u.name = `${a.name}:edges`, u.position.copy(l), u.renderOrder = t === "hover" ? 1300 : 1310, a.add(u), h.dispose(), a;
3823
4762
  }
3824
4763
  cadInsertDetailsToBox(e) {
3825
4764
  const t = e == null ? void 0 : e.bbox;
3826
- return !t || ![t.minX, t.minY, t.maxX, t.maxY].every(Number.isFinite) ? null : new S(
3827
- new w(t.minX, t.minY, -0.01),
3828
- new w(t.maxX, t.maxY, 0.01)
4765
+ return !t || ![t.minX, t.minY, t.maxX, t.maxY].every(Number.isFinite) ? null : new R(
4766
+ new C(t.minX, t.minY, -0.01),
4767
+ new C(t.maxX, t.maxY, 0.01)
3829
4768
  );
3830
4769
  }
3831
4770
  isSameCadInsertSelection(e, t) {
@@ -3862,14 +4801,20 @@ class Di {
3862
4801
  get viewMode() {
3863
4802
  return e.runtime.viewMode;
3864
4803
  },
3865
- fitView() {
3866
- return e.fitView();
4804
+ get keyboardTarget() {
4805
+ return e.options.viewport;
4806
+ },
4807
+ fitSelectionOrDocument() {
4808
+ return e.cad.fitSelection() || e.cad.fitDocument() || e.fitView();
3867
4809
  },
3868
4810
  setViewMode(t) {
3869
4811
  e.setViewMode(t);
3870
4812
  },
3871
4813
  on(t, i) {
3872
4814
  return e.on(t, i);
4815
+ },
4816
+ emitUiLayoutChange(t) {
4817
+ e.emit("ui-layout-change", t);
3873
4818
  }
3874
4819
  };
3875
4820
  }
@@ -3877,35 +4822,40 @@ class Di {
3877
4822
  this.cadHost.unmountCadObject();
3878
4823
  }
3879
4824
  resolveMixedBounds() {
3880
- const e = new S();
4825
+ const e = new R();
3881
4826
  let t = !1;
3882
4827
  for (const r of this.mountedObjects)
3883
4828
  r.visible && (e.expandByObject(r), t = !0);
3884
4829
  const i = this.cadHost.resolveCadFitBounds();
3885
4830
  return i && (e.union(i), t = !0), t && !e.isEmpty() ? e : null;
3886
4831
  }
3887
- resolveFocusedCadBounds() {
3888
- var d;
3889
- const e = (d = this.cad.inspector.details) == null ? void 0 : d.bbox;
3890
- if (!e || ![e.minX, e.minY, e.maxX, e.maxY].every(Number.isFinite)) return null;
3891
- let t = e.minX, i = e.minY, r = e.maxX, s = e.maxY;
3892
- const o = r - t, c = s - i, l = Math.max(o, c);
3893
- if (o > 0 && c > 0 && l < Ee) {
3894
- const h = (t + r) / 2, u = (i + s) / 2, v = Ee / 2;
3895
- t = h - v, i = u - v, r = h + v, s = u + v;
3896
- }
3897
- return new S(
3898
- new w(t, i, -0.01),
3899
- new w(r, s, 0.01)
3900
- );
3901
- }
3902
4832
  setInteraction(e) {
3903
- this.interaction !== e && (this.interaction = e, this.interactionRenderLastTs = null, this.emit("interaction-change", { interaction: e }), this.cadCapability.onInteractionChanged(), e === "idle" && this.runtime.requestRender());
4833
+ this.interaction !== e && (this.interaction = e, this.interactionRenderLastTs = null, this.emit("interaction-change", { interaction: e }), this.emitViewportChange(), this.cadCapability.onInteractionChanged(), e === "idle" && (this.pendingCameraReason = "api"), e === "idle" && this.runtime.requestRender());
4834
+ }
4835
+ applyCameraSnapshot(e, t) {
4836
+ if (!Fe(e)) return !1;
4837
+ const i = this.runtime.viewMode;
4838
+ return this.runtime.applyCameraSnapshot(e) ? (this.runtime.viewMode !== i && this.emit("view-mode-change", { viewMode: this.runtime.viewMode }), this.pendingCameraReason = t, this.cadCapability.onCameraChanged(t), this.refreshCadPointerHover(), !0) : !1;
4839
+ }
4840
+ detectCameraChange(e = !1) {
4841
+ const t = j(this.runtime.captureCameraSnapshot());
4842
+ return !e && t === this.lastCameraFingerprint ? !1 : (this.lastCameraFingerprint = t, this.cadCapability.onCameraChanged(this.pendingCameraReason), !0);
4843
+ }
4844
+ emitViewportChange() {
4845
+ this.emit("viewport-change", {
4846
+ viewportWidthPx: Math.max(1, this.options.viewport.clientWidth || 1),
4847
+ viewportHeightPx: Math.max(1, this.options.viewport.clientHeight || 1),
4848
+ worldUnitsPerPixel: this.runtime.getWorldUnitsPerPixel(),
4849
+ interaction: this.interaction
4850
+ });
4851
+ }
4852
+ subscribePluginEvent(e, t) {
4853
+ return (/* @__PURE__ */ new Set(["document-change", "layer-change", "block-change", "inspector-change", "hud-change", "load-timing", "load-progress", "error"])).has(String(e)) ? this.cad.on(e, t) : this.on(e, t);
3904
4854
  }
3905
4855
  shouldRenderCurrentFrame(e) {
3906
4856
  if (this.interaction !== "active" || this.interactionRenderLastTs === null) return !0;
3907
4857
  const t = e - this.interactionRenderLastTs;
3908
- return t < 0 || t >= Ti;
4858
+ return t < 0 || t >= Zi;
3909
4859
  }
3910
4860
  markInteractionActive() {
3911
4861
  this.clearInteractionIdleTimer(), this.setInteraction("active");
@@ -3913,7 +4863,7 @@ class Di {
3913
4863
  scheduleInteractionIdle() {
3914
4864
  this.clearInteractionIdleTimer(), this.interactionIdleTimer = globalThis.setTimeout(() => {
3915
4865
  this.interactionIdleTimer = null, this.setInteraction("idle"), this.refreshCadPointerHover();
3916
- }, Mi);
4866
+ }, Wi);
3917
4867
  }
3918
4868
  clearInteractionIdleTimer() {
3919
4869
  this.interactionIdleTimer !== null && (globalThis.clearTimeout(this.interactionIdleTimer), this.interactionIdleTimer = null);
@@ -3950,8 +4900,8 @@ class Di {
3950
4900
  for (const i of this.listeners.get(e) ?? []) i(t);
3951
4901
  }
3952
4902
  }
3953
- function Hi(n) {
3954
- const e = new Bt({
4903
+ function ar(n) {
4904
+ const e = new Xt({
3955
4905
  canvasArea: n.viewport,
3956
4906
  canvas: n.canvas,
3957
4907
  clearColor: n.clearColor,
@@ -3962,12 +4912,15 @@ function Hi(n) {
3962
4912
  environment: n.environment ?? "room",
3963
4913
  navigationPolicy: "viewer"
3964
4914
  });
3965
- return Li(n, e);
4915
+ return Qi(n, e);
4916
+ }
4917
+ function Qi(n, e) {
4918
+ return e.initialize(), new Ji(n, e);
3966
4919
  }
3967
- function Li(n, e) {
3968
- return e.initialize(), new Di(n, e);
4920
+ function j(n) {
4921
+ return n ? JSON.stringify(n) : null;
3969
4922
  }
3970
4923
  export {
3971
- _i as configureViewerText,
3972
- Hi as createViewer
4924
+ dr as configureViewerText,
4925
+ ar as createViewer
3973
4926
  };