@harpern/edu-modelhub-viewer-core 0.1.0-beta.0 → 0.1.0-beta.2

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,29 +1,476 @@
1
- import { parseGlb as B, validate as S, adaptSidecar as R } from "@osuecampus/edu-modelhub-extractor";
2
- import { GlbParseError as ze } from "@osuecampus/edu-modelhub-extractor";
3
- import { SpriteMaterial as _, CanvasTexture as N, Sprite as D, Vector3 as h, Raycaster as C, AmbientLight as L, SpotLight as U, Color as I, DirectionalLight as F, Box3 as g } from "three";
4
- function W(e) {
1
+ import { SpriteMaterial as V, CanvasTexture as E, Sprite as W, Vector3 as b, Raycaster as q, AmbientLight as Y, SpotLight as H, Color as T, DirectionalLight as X, Box3 as v } from "three";
2
+ const C = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
3
+ function _(e, t) {
4
+ const n = /* @__PURE__ */ new WeakSet(), o = [
5
+ { value: e, path: "" }
6
+ ], r = (i, s) => {
7
+ o.push({ value: i, path: s });
8
+ };
9
+ for (; o.length > 0; ) {
10
+ const { value: i, path: s } = o.pop();
11
+ if (!(typeof i != "object" || i === null || n.has(i)))
12
+ if (n.add(i), Array.isArray(i))
13
+ for (let c = 0; c < i.length; c++)
14
+ r(i[c], `${s}[${c}]`);
15
+ else
16
+ t(i, s, r);
17
+ }
18
+ }
19
+ function K(e) {
20
+ const t = [];
21
+ return _(e, (n, o, r) => {
22
+ for (const i of Object.keys(n)) {
23
+ const s = o === "" ? i : `${o}.${i}`;
24
+ C.has(i) ? t.push({ path: s, key: i }) : r(n[i], s);
25
+ }
26
+ }), t;
27
+ }
28
+ function Z(e) {
29
+ return _(e, (t, n, o) => {
30
+ for (const r of Object.keys(t))
31
+ C.has(r) ? delete t[r] : o(t[r], n);
32
+ }), e;
33
+ }
34
+ const N = 1179937895, k = 2, Q = 1313821514, J = 21;
35
+ class g extends Error {
36
+ constructor(t) {
37
+ super(t), this.name = "GlbParseError";
38
+ }
39
+ }
40
+ function ee(e) {
41
+ return e instanceof ArrayBuffer ? new DataView(e) : new DataView(e.buffer, e.byteOffset, e.byteLength);
42
+ }
43
+ function te(e) {
44
+ return e === null ? "null" : Array.isArray(e) ? "an array" : typeof e;
45
+ }
46
+ function ne(e) {
47
+ const t = ee(e);
48
+ if (t.byteLength < J)
49
+ throw new g(
50
+ `Input too short to be a GLB file (${t.byteLength} bytes).`
51
+ );
52
+ const n = t.getUint32(
53
+ 0,
54
+ !0
55
+ /* littleEndian */
56
+ );
57
+ if (n !== N)
58
+ throw new g(
59
+ `Invalid GLB magic: expected 0x${N.toString(16)}, got 0x${n.toString(16)}.`
60
+ );
61
+ const o = t.getUint32(4, !0);
62
+ if (o !== k)
63
+ throw new g(
64
+ `Unsupported GLB version: expected ${k}, got ${o}.`
65
+ );
66
+ const r = t.getUint32(8, !0);
67
+ if (r > t.byteLength)
68
+ throw new g(
69
+ `GLB header reports ${r} bytes but only ${t.byteLength} bytes were supplied.`
70
+ );
71
+ if (t.byteLength < 20)
72
+ throw new g("GLB file truncated before first chunk header.");
73
+ const i = t.getUint32(12, !0), s = t.getUint32(16, !0);
74
+ if (s !== Q)
75
+ throw new g(
76
+ `First GLB chunk is not JSON (type 0x${s.toString(16)}).`
77
+ );
78
+ if (20 + i > r)
79
+ throw new g(
80
+ `JSON chunk claims ${i} bytes but the declared GLB length is only ${r} bytes.`
81
+ );
82
+ if (20 + i > t.byteLength)
83
+ throw new g(
84
+ `JSON chunk claims ${i} bytes but only ${t.byteLength - 20} bytes remain in the buffer.`
85
+ );
86
+ const c = new Uint8Array(
87
+ t.buffer,
88
+ t.byteOffset + 20,
89
+ i
90
+ ), l = new TextDecoder("utf-8").decode(c);
91
+ let a;
92
+ try {
93
+ a = JSON.parse(l);
94
+ } catch (u) {
95
+ throw new g(
96
+ `Failed to parse GLB JSON chunk: ${u.message}`
97
+ );
98
+ }
99
+ if (a === null || typeof a != "object" || Array.isArray(a))
100
+ throw new g(
101
+ `GLB JSON chunk root must be an object, got ${te(a)}.`
102
+ );
103
+ return a;
104
+ }
105
+ function oe(e) {
106
+ const t = ne(e).extensions;
107
+ if (t === null || typeof t != "object" || Array.isArray(t))
108
+ return null;
109
+ const n = t.EDU_modelhub;
110
+ return n === void 0 ? null : Z(n);
111
+ }
112
+ const re = /^[a-z][a-z0-9_]*$/, ie = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/, se = /^[a-z]{2}$/, ae = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
113
+ function d(e, t) {
114
+ return { field: e, message: t, severity: "error" };
115
+ }
116
+ function $(e, t) {
117
+ return { field: e, message: t, severity: "warning" };
118
+ }
119
+ function x(e) {
120
+ return typeof e == "object" && e !== null && !Array.isArray(e);
121
+ }
122
+ function w(e) {
123
+ return typeof e == "string" && e.trim() !== "";
124
+ }
125
+ function U(e) {
126
+ return typeof e == "number" && Number.isInteger(e) && e >= 0;
127
+ }
128
+ function h(e) {
129
+ if (e === void 0) return "undefined";
130
+ let t;
131
+ if (typeof e == "string")
132
+ t = `"${e}"`;
133
+ else
134
+ try {
135
+ const n = JSON.stringify(e);
136
+ if (n === void 0) return typeof e;
137
+ t = n;
138
+ } catch {
139
+ return Array.isArray(e) ? "an array" : typeof e;
140
+ }
141
+ return t.length > 60 ? `${t.slice(0, 57)}...` : t;
142
+ }
143
+ function F(e) {
144
+ const t = [], n = e;
145
+ if (!x(n))
146
+ return [d("", `Payload must be a JSON object, got ${h(n)}.`)];
147
+ ce(n, t), ue(n.specVersion, t), le(n.coordinateSpace, t), de(n.model, t);
148
+ const o = pe(n.regions, t);
149
+ return ye(n.annotations, o, t), t;
150
+ }
151
+ function ce(e, t) {
152
+ for (const n of K(e))
153
+ t.push(
154
+ d(
155
+ n.path,
156
+ `Disallowed key "${n.key}" at ${n.path} (prototype-pollution vector).`
157
+ )
158
+ );
159
+ }
160
+ function ue(e, t) {
161
+ (typeof e != "string" || !ae.test(e)) && t.push(
162
+ d(
163
+ "specVersion",
164
+ `specVersion must be a semver string (e.g. "0.1.0"), got ${h(e)}.`
165
+ )
166
+ );
167
+ }
168
+ function le(e, t) {
169
+ e !== void 0 && e !== "gltf" && e !== "blender" && t.push(
170
+ d(
171
+ "coordinateSpace",
172
+ `coordinateSpace must be "gltf" or "blender" when present, got ${h(e)}.`
173
+ )
174
+ );
175
+ }
176
+ function de(e, t) {
177
+ if (!x(e)) {
178
+ t.push(
179
+ d(
180
+ "model",
181
+ `model is required and must be an object, got ${h(e)}.`
182
+ )
183
+ );
184
+ return;
185
+ }
186
+ const n = e, o = n.title;
187
+ w(o) || t.push(
188
+ d(
189
+ "model.title",
190
+ `model.title is required and must be a non-empty string, got ${h(o)}.`
191
+ )
192
+ );
193
+ const r = n.altText;
194
+ w(r) ? r.length > 300 && t.push(
195
+ d(
196
+ "model.altText",
197
+ `model.altText exceeds 300 characters (${r.length} chars).`
198
+ )
199
+ ) : t.push(
200
+ d(
201
+ "model.altText",
202
+ `model.altText is required and must be a non-empty string, got ${h(r)}.`
203
+ )
204
+ );
205
+ const i = n.language;
206
+ i !== void 0 && (typeof i != "string" || !se.test(i)) && t.push(
207
+ $(
208
+ "model.language",
209
+ `model.language should be an ISO 639-1 two-letter code (e.g. "en"), got ${h(i)}.`
210
+ )
211
+ ), fe(n, t), me(n.source, t), he(n, t), w(n.longDescription) || t.push(
212
+ $("model.longDescription", "model.longDescription is recommended.")
213
+ );
214
+ }
215
+ function fe(e, t) {
216
+ const n = ["CC0", "CC BY", "CC BY-SA", "All Rights Reserved"], o = e.license;
217
+ o !== void 0 && (typeof o != "string" || !n.includes(o)) && t.push(
218
+ d(
219
+ "model.license",
220
+ `model.license must be one of ${n.map((r) => `"${r}"`).join(", ")}, got ${h(o)}.`
221
+ )
222
+ ), (o === "CC BY" || o === "CC BY-SA") && !w(e.attribution) && t.push(
223
+ $(
224
+ "model.attribution",
225
+ 'model.attribution is recommended when license is "CC BY" or "CC BY-SA".'
226
+ )
227
+ );
228
+ }
229
+ function me(e, t) {
230
+ if (e === void 0) return;
231
+ const n = ["scan", "photogrammetry", "manual", "other"];
232
+ if (typeof e != "string" || !n.includes(e)) {
233
+ const o = n.map((r) => `"${r}"`).join(", ");
234
+ t.push(
235
+ d(
236
+ "model.source",
237
+ `model.source must be one of ${o}, got ${h(e)}.`
238
+ )
239
+ );
240
+ }
241
+ }
242
+ function he(e, t) {
243
+ for (const n of ["created", "modified"]) {
244
+ const o = e[n];
245
+ o !== void 0 && (typeof o != "string" || !ie.test(o)) && t.push(
246
+ $(
247
+ `model.${n}`,
248
+ `model.${n} should be ISO 8601 UTC (YYYY-MM-DDTHH:MM:SSZ), got ${h(o)}.`
249
+ )
250
+ );
251
+ }
252
+ }
253
+ function pe(e, t) {
254
+ const n = /* @__PURE__ */ new Set();
255
+ if (!Array.isArray(e) || e.length === 0)
256
+ return t.push(d("regions", "At least one region is required.")), n;
257
+ for (let o = 0; o < e.length; o++) {
258
+ const r = e[o], i = `regions[${o}]`;
259
+ if (!x(r)) {
260
+ t.push(
261
+ d(i, `${i} must be an object, got ${h(r)}.`)
262
+ );
263
+ continue;
264
+ }
265
+ ge(r, i, n, t);
266
+ }
267
+ return n;
268
+ }
269
+ function ge(e, t, n, o) {
270
+ const r = e.id;
271
+ typeof r != "string" || !re.test(r) ? o.push(
272
+ d(
273
+ `${t}.id`,
274
+ `${t}.id must be a non-empty snake_case string (lowercase letters, digits, underscores; must start with a letter), got ${h(r)}.`
275
+ )
276
+ ) : n.has(r) ? o.push(
277
+ d(`${t}.id`, `Duplicate region id "${r}" at ${t}.`)
278
+ ) : n.add(r);
279
+ const i = e.visibilityDefault;
280
+ i !== void 0 && i !== "shown" && i !== "hidden" && o.push(
281
+ d(
282
+ `${t}.visibilityDefault`,
283
+ `${t}.visibilityDefault must be "shown" or "hidden", got ${h(i)}.`
284
+ )
285
+ );
286
+ const s = e.order;
287
+ s !== void 0 && !U(s) && o.push(
288
+ $(
289
+ `${t}.order`,
290
+ `${t}.order should be a non-negative integer, got ${h(s)}.`
291
+ )
292
+ );
293
+ }
294
+ function ye(e, t, n) {
295
+ if (!Array.isArray(e)) {
296
+ n.push(d("annotations", "annotations must be an array."));
297
+ return;
298
+ }
299
+ e.length < 3 && n.push(
300
+ $(
301
+ "annotations",
302
+ `Only ${e.length} annotation(s) defined (3–8 recommended).`
303
+ )
304
+ ), e.length > 8 && n.push(
305
+ $(
306
+ "annotations",
307
+ `${e.length} annotations defined (3–8 recommended).`
308
+ )
309
+ );
310
+ const o = {
311
+ seenRegionIds: t,
312
+ seenAnnotationIds: /* @__PURE__ */ new Set(),
313
+ seenReadingOrders: /* @__PURE__ */ new Set()
314
+ };
315
+ for (let r = 0; r < e.length; r++) {
316
+ const i = e[r], s = `annotations[${r}]`;
317
+ if (!x(i)) {
318
+ n.push(
319
+ d(s, `${s} must be an object, got ${h(i)}.`)
320
+ );
321
+ continue;
322
+ }
323
+ be(i, s, o, n);
324
+ }
325
+ ve(o.seenReadingOrders, n);
326
+ }
327
+ function be(e, t, n, o) {
328
+ const r = e.id;
329
+ w(r) ? n.seenAnnotationIds.has(r) ? o.push(
330
+ d(`${t}.id`, `Duplicate annotation id "${r}" at ${t}.`)
331
+ ) : n.seenAnnotationIds.add(r) : o.push(
332
+ d(
333
+ `${t}.id`,
334
+ `${t}.id is required and must be a non-empty string, got ${h(r)}.`
335
+ )
336
+ );
337
+ const i = e.regionId;
338
+ i !== void 0 && i !== "" && (typeof i != "string" || !n.seenRegionIds.has(i)) && o.push(
339
+ d(
340
+ `${t}.regionId`,
341
+ `${t}.regionId ${h(i)} does not match any region id.`
342
+ )
343
+ ), $e(e.readingOrder, t, n, o), we(e.anchor, t, o), xe(e.camera, t, o);
344
+ }
345
+ function $e(e, t, n, o) {
346
+ e !== void 0 && (U(e) ? n.seenReadingOrders.has(e) ? o.push(
347
+ d(
348
+ `${t}.readingOrder`,
349
+ `Duplicate readingOrder value ${e} at ${t}.`
350
+ )
351
+ ) : n.seenReadingOrders.add(e) : o.push(
352
+ d(
353
+ `${t}.readingOrder`,
354
+ `${t}.readingOrder must be a non-negative integer, got ${h(e)}.`
355
+ )
356
+ ));
357
+ }
358
+ function we(e, t, n) {
359
+ if (!x(e)) {
360
+ n.push(
361
+ d(
362
+ `${t}.anchor`,
363
+ `${t}.anchor is required and must be an object, got ${h(e)}.`
364
+ )
365
+ );
366
+ return;
367
+ }
368
+ const o = e, r = o.type;
369
+ if (r === "marker") {
370
+ const i = o.position;
371
+ (!Array.isArray(i) || i.length !== 3 || !i.every((s) => typeof s == "number")) && n.push(
372
+ d(
373
+ `${t}.anchor.position`,
374
+ `${t}.anchor.position must be an array of exactly 3 numbers for type "marker".`
375
+ )
376
+ );
377
+ } else r === "node" || r === "primitive" || r === "aabb" ? w(o.ref) || n.push(
378
+ d(
379
+ `${t}.anchor.ref`,
380
+ `${t}.anchor.ref is required for anchor type "${r}".`
381
+ )
382
+ ) : n.push(
383
+ d(
384
+ `${t}.anchor.type`,
385
+ `${t}.anchor.type must be "marker", "node", "primitive", or "aabb", got ${h(r)}.`
386
+ )
387
+ );
388
+ }
389
+ function xe(e, t, n) {
390
+ if (e === void 0) return;
391
+ if (!x(e)) {
392
+ n.push(
393
+ d(
394
+ `${t}.camera`,
395
+ `${t}.camera must be an object when present, got ${h(e)}.`
396
+ )
397
+ );
398
+ return;
399
+ }
400
+ for (const r of ["eye", "target"]) {
401
+ const i = e[r];
402
+ (!Array.isArray(i) || i.length !== 3 || !i.every((s) => typeof s == "number" && Number.isFinite(s))) && n.push(
403
+ d(
404
+ `${t}.camera.${r}`,
405
+ `${t}.camera.${r} must be an array of exactly 3 finite numbers.`
406
+ )
407
+ );
408
+ }
409
+ const o = e.fov;
410
+ o !== void 0 && (typeof o != "number" || !(o > 0)) && n.push(
411
+ d(
412
+ `${t}.camera.fov`,
413
+ `${t}.camera.fov must be a number greater than 0 when present, got ${h(o)}.`
414
+ )
415
+ );
416
+ }
417
+ function ve(e, t) {
418
+ if (e.size === 0) return;
419
+ const n = [...e].sort((o, r) => o - r);
420
+ for (let o = 0; o < n.length; o++)
421
+ if (n[o] !== o) {
422
+ t.push(
423
+ $(
424
+ "annotations[*].readingOrder",
425
+ `readingOrder values are not sequential from 0. Expected 0–${n.length - 1} but found gaps or wrong start.`
426
+ )
427
+ );
428
+ break;
429
+ }
430
+ }
431
+ class B extends Error {
432
+ constructor(t) {
433
+ super(t), this.name = "AdaptError";
434
+ }
435
+ }
436
+ class Ae {
437
+ adapt(t) {
438
+ var n, o;
439
+ const r = t.model, i = ((n = r == null ? void 0 : r.title) == null ? void 0 : n.trim()) ?? "", s = ((o = r == null ? void 0 : r.altText) == null ? void 0 : o.trim()) ?? "";
440
+ if (!i)
441
+ throw new B("Sidecar is missing required field: model.title");
442
+ if (!s)
443
+ throw new B("Sidecar is missing required field: model.altText");
444
+ return t;
445
+ }
446
+ }
447
+ const Se = new Ae();
448
+ function Ie(e) {
449
+ return Se.adapt(e);
450
+ }
451
+ function Me(e) {
5
452
  return e.filter((t) => t.severity === "error");
6
453
  }
7
- function z(e) {
8
- const [t, i = ""] = e.split("?", 2);
454
+ function Oe(e) {
455
+ const [t, n = ""] = e.split("?", 2);
9
456
  if (!/\.glb$/i.test(t)) return null;
10
- const n = t.replace(/\.glb$/i, ".modelhub.json");
11
- return i ? `${n}?${i}` : n;
457
+ const o = t.replace(/\.glb$/i, ".modelhub.json");
458
+ return n ? `${o}?${n}` : o;
12
459
  }
13
- function le(e, t) {
14
- var r;
460
+ function Ke(e, t) {
461
+ var i;
15
462
  if (!e || e.startsWith("blob:") || e.startsWith("data:")) return "";
16
- const i = t ?? ((r = globalThis.location) == null ? void 0 : r.href), n = i ? new URL(e, i).href : e, o = n.lastIndexOf("/");
17
- return o === -1 ? "" : n.slice(0, o + 1);
463
+ const n = t ?? ((i = globalThis.location) == null ? void 0 : i.href), o = n ? new URL(e, n).href : e, r = o.lastIndexOf("/");
464
+ return r === -1 ? "" : o.slice(0, r + 1);
18
465
  }
19
- async function P(e, t = fetch) {
20
- const i = await t(e);
21
- if (!i.ok)
22
- throw new Error(`Failed to fetch ${e} (HTTP ${i.status}).`);
23
- return i.arrayBuffer();
466
+ async function Te(e, t = fetch) {
467
+ const n = await t(e);
468
+ if (!n.ok)
469
+ throw new Error(`Failed to fetch ${e} (HTTP ${n.status}).`);
470
+ return n.arrayBuffer();
24
471
  }
25
- function G(e) {
26
- const t = B(e);
472
+ function Ne(e) {
473
+ const t = oe(e);
27
474
  if (!t)
28
475
  return {
29
476
  payload: null,
@@ -31,25 +478,25 @@ function G(e) {
31
478
  findings: [],
32
479
  problem: "This model carries no EDU_modelhub metadata."
33
480
  };
34
- const i = S(t);
35
- return { payload: t, source: "embedded", findings: i, problem: null };
36
- }
37
- async function ue(e, t = {}) {
38
- const i = t.fetchImpl ?? fetch, n = await P(e, i), o = G(n);
39
- if (o.payload) return { ...o, bytes: n };
40
- if (t.sidecar === !1) return { ...o, bytes: n };
41
- const s = (t.sidecarUrl ?? z)(e);
42
- if (!s) return { ...o, bytes: n };
481
+ const n = F(t);
482
+ return { payload: t, source: "embedded", findings: n, problem: null };
483
+ }
484
+ async function Ze(e, t = {}) {
485
+ const n = t.fetchImpl ?? fetch, o = await Te(e, n), r = Ne(o);
486
+ if (r.payload) return { ...r, bytes: o };
487
+ if (t.sidecar === !1) return { ...r, bytes: o };
488
+ const s = (t.sidecarUrl ?? Oe)(e);
489
+ if (!s) return { ...r, bytes: o };
43
490
  try {
44
- const c = await i(s);
491
+ const c = await n(s);
45
492
  if (c.ok) {
46
- const u = R(await c.json());
493
+ const l = Ie(await c.json());
47
494
  return {
48
- payload: u,
495
+ payload: l,
49
496
  source: "sidecar",
50
- findings: S(u),
497
+ findings: F(l),
51
498
  problem: null,
52
- bytes: n
499
+ bytes: o
53
500
  };
54
501
  }
55
502
  } catch {
@@ -59,238 +506,255 @@ async function ue(e, t = {}) {
59
506
  source: "none",
60
507
  findings: [],
61
508
  problem: "This model has no EDU_modelhub metadata, either embedded in the file or in a sidecar beside it.",
62
- bytes: n
509
+ bytes: o
63
510
  };
64
511
  }
65
- function de(e, t = "EDU_modelhub", i = console) {
512
+ function Qe(e, t = "EDU_modelhub", n = console) {
66
513
  if (!(e != null && e.length)) return;
67
- const n = W(e), o = e.filter((r) => r.severity !== "error");
68
- n.length && i.warn(`${t}: ${n.length} validation error(s)`, n), o.length && i.info(
69
- `${t}: ${o.length} validation warning(s)`,
70
- o
514
+ const o = Me(e), r = e.filter((i) => i.severity !== "error");
515
+ o.length && n.warn(`${t}: ${o.length} validation error(s)`, o), r.length && n.info(
516
+ `${t}: ${r.length} validation warning(s)`,
517
+ r
71
518
  );
72
519
  }
73
- function v(e) {
520
+ function Je(e) {
521
+ return (e == null ? void 0 : e.name) === "GlbParseError";
522
+ }
523
+ function G(e) {
74
524
  return Array.isArray(e) && e.length === 3 && e.every((t) => typeof t == "number" && Number.isFinite(t));
75
525
  }
76
- function O(e) {
526
+ function P(e) {
77
527
  return e === "blender";
78
528
  }
79
- function x(e, t) {
80
- if (!v(e)) return null;
81
- const [i, n, o] = e;
82
- return O(t) ? [i, o, -n] : [i, n, o];
529
+ function A(e, t) {
530
+ if (!G(e)) return null;
531
+ const [n, o, r] = e;
532
+ return P(t) ? [n, r, -o] : [n, o, r];
83
533
  }
84
- function fe(e, t) {
85
- if (!v(e)) return null;
86
- const [i, n, o] = e;
87
- return O(t) ? [i, -o, n] : [i, n, o];
534
+ function et(e, t) {
535
+ if (!G(e)) return null;
536
+ const [n, o, r] = e;
537
+ return P(t) ? [n, -r, o] : [n, o, r];
88
538
  }
89
- function V(e) {
539
+ function ke(e) {
90
540
  if (!Array.isArray(e)) return [];
91
541
  const t = /* @__PURE__ */ new Set();
92
- return e.map((i, n) => {
93
- const r = (typeof (i == null ? void 0 : i.id) == "string" ? i.id.trim() : "") || `annotation-${n + 1}`;
94
- let s = r, c = 2;
95
- for (; t.has(s); ) s = `${r}-${c++}`;
96
- return t.add(s), { ...i ?? {}, id: s };
542
+ return e.map((n, o) => {
543
+ const i = (typeof (n == null ? void 0 : n.id) == "string" ? n.id.trim() : "") || `annotation-${o + 1}`;
544
+ let s = i, c = 2;
545
+ for (; t.has(s); ) s = `${i}-${c++}`;
546
+ return t.add(s), { ...n ?? {}, id: s };
97
547
  });
98
548
  }
99
- function w(e) {
100
- const t = V(e == null ? void 0 : e.annotations), i = (n) => Number.isFinite(n.readingOrder) ? n.readingOrder : Number.MAX_SAFE_INTEGER;
101
- return t.map((n, o) => ({ annotation: n, index: o })).sort(
102
- (n, o) => i(n.annotation) - i(o.annotation) || n.index - o.index
103
- ).map((n) => n.annotation);
549
+ function M(e) {
550
+ const t = ke(e == null ? void 0 : e.annotations), n = (o) => Number.isFinite(o.readingOrder) ? o.readingOrder : Number.MAX_SAFE_INTEGER;
551
+ return t.map((o, r) => ({ annotation: o, index: r })).sort(
552
+ (o, r) => n(o.annotation) - n(r.annotation) || o.index - r.index
553
+ ).map((o) => o.annotation);
554
+ }
555
+ function z(e) {
556
+ return (Array.isArray(e == null ? void 0 : e.regions) ? e.regions : []).map((n, o) => ({ region: n, index: o })).sort(
557
+ (n, o) => (n.region.order ?? Number.MAX_SAFE_INTEGER) - (o.region.order ?? Number.MAX_SAFE_INTEGER) || n.index - o.index
558
+ ).map((n) => n.region);
559
+ }
560
+ const Be = "Auto-created from object ";
561
+ function Le(e) {
562
+ var n;
563
+ const t = (n = e == null ? void 0 : e.description) == null ? void 0 : n.trim();
564
+ return t ? !t.startsWith(Be) : !1;
104
565
  }
105
- function k(e) {
106
- return (Array.isArray(e == null ? void 0 : e.regions) ? e.regions : []).map((i, n) => ({ region: i, index: n })).sort(
107
- (i, n) => (i.region.order ?? Number.MAX_SAFE_INTEGER) - (n.region.order ?? Number.MAX_SAFE_INTEGER) || i.index - n.index
108
- ).map((i) => i.region);
566
+ function tt(e) {
567
+ return Array.isArray(e) ? e.filter(
568
+ (t) => {
569
+ var n;
570
+ return Le(t) || !((n = t.description) != null && n.trim());
571
+ }
572
+ ) : [];
109
573
  }
110
- function T(e) {
574
+ function L(e) {
111
575
  var t;
112
576
  return e ? ((t = e.label) == null ? void 0 : t.trim()) || e.id || "Unnamed region" : "Unknown region";
113
577
  }
114
- function me(e) {
578
+ function nt(e) {
115
579
  if (!e) return [];
116
- const t = [], i = /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g;
117
- let n = 0, o;
118
- for (; (o = i.exec(e)) !== null; )
119
- o.index > n && t.push({ text: e.slice(n, o.index) }), t.push({ text: o[1], url: o[2] }), n = o.index + o[0].length;
120
- return n < e.length && t.push({ text: e.slice(n) }), t.filter((r) => r.text.trim() || r.url);
121
- }
122
- function pe(e) {
123
- const t = e == null ? void 0 : e.coordinateSpace, i = k(e), n = w(e), o = new Map(i.map((a) => [a.id, a])), r = new Map(
124
- n.map((a) => [a.id, a])
580
+ const t = [], n = /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g;
581
+ let o = 0, r;
582
+ for (; (r = n.exec(e)) !== null; )
583
+ r.index > o && t.push({ text: e.slice(o, r.index) }), t.push({ text: r[1], url: r[2] }), o = r.index + r[0].length;
584
+ return o < e.length && t.push({ text: e.slice(o) }), t.filter((i) => i.text.trim() || i.url);
585
+ }
586
+ function ot(e) {
587
+ const t = e == null ? void 0 : e.coordinateSpace, n = z(e), o = M(e), r = new Map(n.map((a) => [a.id, a])), i = new Map(
588
+ o.map((a) => [a.id, a])
125
589
  ), s = /* @__PURE__ */ new Map();
126
- for (const a of n) {
127
- const l = a.regionId;
128
- if (!l) continue;
129
- const d = s.get(l);
130
- d ? d.push(a) : s.set(l, [a]);
590
+ for (const a of o) {
591
+ const u = a.regionId;
592
+ if (!u) continue;
593
+ const f = s.get(u);
594
+ f ? f.push(a) : s.set(u, [a]);
131
595
  }
132
596
  const c = [];
133
- for (const a of n) {
134
- const l = a.anchor;
135
- if (!l || l.type !== "marker") continue;
136
- const d = x(l.position, t);
137
- if (!d) continue;
138
- const f = a.camera, m = f ? x(f.eye, t) : null, p = f ? x(f.target, t) : null;
597
+ for (const a of o) {
598
+ const u = a.anchor;
599
+ if (!u || u.type !== "marker") continue;
600
+ const f = A(u.position, t);
601
+ if (!f) continue;
602
+ const m = a.camera, p = m ? A(m.eye, t) : null, y = m ? A(m.target, t) : null;
139
603
  c.push({
140
604
  annotation: a,
141
- position: d,
142
- ...m && p ? {
605
+ position: f,
606
+ ...p && y ? {
143
607
  camera: {
144
- eye: m,
145
- target: p,
146
- ...f != null && f.fov ? { fov: f.fov } : {}
608
+ eye: p,
609
+ target: y,
610
+ ...m != null && m.fov ? { fov: m.fov } : {}
147
611
  }
148
612
  } : {}
149
613
  });
150
614
  }
151
- const u = new Set(
152
- i.filter((a) => a.visibilityDefault === "hidden").map((a) => a.id)
615
+ const l = new Set(
616
+ n.filter((a) => a.visibilityDefault === "hidden").map((a) => a.id)
153
617
  );
154
618
  return {
155
619
  payload: e,
156
- regions: i,
157
- regionsById: o,
158
- annotations: n,
159
- annotationsById: r,
620
+ regions: n,
621
+ regionsById: r,
622
+ annotations: o,
623
+ annotationsById: i,
160
624
  annotationsByRegion: s,
161
625
  markerAnchors: c,
162
- hiddenRegionIds: u
626
+ hiddenRegionIds: l
163
627
  };
164
628
  }
165
- function H(e) {
629
+ function De(e) {
166
630
  return e.isMesh === !0;
167
631
  }
168
- function he(e, t, i = []) {
169
- var u;
170
- const n = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map();
171
- for (const [a, l] of ((t == null ? void 0 : t.meshes) ?? []).entries())
172
- for (const d of l.primitives ?? []) {
173
- const f = (u = d.extras) == null ? void 0 : u.modelhubRegionId;
174
- typeof f == "string" && f && (s.set(a, f), l.name && o.set(l.name, f));
632
+ function rt(e, t, n = []) {
633
+ var l;
634
+ const o = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map();
635
+ for (const [a, u] of ((t == null ? void 0 : t.meshes) ?? []).entries())
636
+ for (const f of u.primitives ?? []) {
637
+ const m = (l = f.extras) == null ? void 0 : l.modelhubRegionId;
638
+ typeof m == "string" && m && (s.set(a, m), u.name && r.set(u.name, m));
175
639
  }
176
640
  for (const a of (t == null ? void 0 : t.nodes) ?? []) {
177
641
  if (a.mesh === void 0 || !a.name) continue;
178
- const l = s.get(a.mesh);
179
- l && r.set(a.name, l);
642
+ const u = s.get(a.mesh);
643
+ u && i.set(a.name, u);
180
644
  }
181
- const c = new Set(i.map((a) => a.id));
645
+ const c = new Set(n.map((a) => a.id));
182
646
  return e.traverse((a) => {
183
- var m, p;
184
- if (!H(a)) return;
185
- const l = (p = (m = a.geometry) == null ? void 0 : m.userData) == null ? void 0 : p.modelhubRegionId, d = typeof l == "string" && l || r.get(a.name) || o.get(a.name) || (c.has(a.name) ? a.name : void 0);
186
- if (!d) return;
187
- const f = n.get(d);
188
- f ? f.push(a) : n.set(d, [a]), a.userData.modelhubOriginalMaterial === void 0 && (a.userData.modelhubOriginalMaterial = a.material);
189
- }), n;
190
- }
191
- function ge(e) {
647
+ var p, y;
648
+ if (!De(a)) return;
649
+ const u = (y = (p = a.geometry) == null ? void 0 : p.userData) == null ? void 0 : y.modelhubRegionId, f = typeof u == "string" && u || i.get(a.name) || r.get(a.name) || (c.has(a.name) ? a.name : void 0);
650
+ if (!f) return;
651
+ const m = o.get(f);
652
+ m ? m.push(a) : o.set(f, [a]), a.userData.modelhubOriginalMaterial === void 0 && (a.userData.modelhubOriginalMaterial = a.material);
653
+ }), o;
654
+ }
655
+ function it(e) {
192
656
  const t = {};
193
- for (const [i, n] of e) t[i] = n.length;
657
+ for (const [n, o] of e) t[n] = o.length;
194
658
  return t;
195
659
  }
196
- function q(e, t, i) {
197
- for (const n of e.get(t) ?? []) n.visible = i;
660
+ function Re(e, t, n) {
661
+ for (const o of e.get(t) ?? []) o.visible = n;
198
662
  }
199
- function xe(e, t) {
200
- for (const i of e.keys())
201
- q(e, i, !t.has(i));
663
+ function st(e, t) {
664
+ for (const n of e.keys())
665
+ Re(e, n, !t.has(n));
202
666
  }
203
- function be(e, t, i) {
204
- for (const n of e.get(t) ?? []) n.material = i;
667
+ function at(e, t, n) {
668
+ for (const o of e.get(t) ?? []) o.material = n;
205
669
  }
206
- function ye(e, t) {
207
- for (const i of e.get(t) ?? []) {
208
- const n = i.userData.modelhubOriginalMaterial;
209
- n && (i.material = n);
670
+ function ct(e, t) {
671
+ for (const n of e.get(t) ?? []) {
672
+ const o = n.userData.modelhubOriginalMaterial;
673
+ o && (n.material = o);
210
674
  }
211
675
  }
212
- const K = "#2196f3", we = "#ff5722";
213
- function E(e, t = {}) {
676
+ const Ee = "#2196f3", ut = "#ff5722";
677
+ function j(e, t = {}) {
214
678
  const {
215
- fill: i = K,
216
- text: n = "#ffffff",
217
- textStroke: o = "rgba(0, 0, 0, 0.45)"
218
- } = t, r = 256, s = document.createElement("canvas");
219
- s.width = r, s.height = r;
679
+ fill: n = Ee,
680
+ text: o = "#ffffff",
681
+ textStroke: r = "rgba(0, 0, 0, 0.45)"
682
+ } = t, i = 256, s = document.createElement("canvas");
683
+ s.width = i, s.height = i;
220
684
  const c = s.getContext("2d");
221
- return c && (c.beginPath(), c.arc(r / 2, r / 2, r / 2 - 4, 0, Math.PI * 2), c.fillStyle = i, c.fill(), c.strokeStyle = "#ffffff", c.lineWidth = 8, c.stroke(), c.fillStyle = n, c.strokeStyle = o, c.lineWidth = 10, c.font = "bold 132px Arial, sans-serif", c.textAlign = "center", c.textBaseline = "middle", c.strokeText(String(e), r / 2, r / 2), c.fillText(String(e), r / 2, r / 2)), s;
685
+ return c && (c.beginPath(), c.arc(i / 2, i / 2, i / 2 - 4, 0, Math.PI * 2), c.fillStyle = n, c.fill(), c.strokeStyle = "#ffffff", c.lineWidth = 8, c.stroke(), c.fillStyle = o, c.strokeStyle = r, c.lineWidth = 10, c.font = "bold 132px Arial, sans-serif", c.textAlign = "center", c.textBaseline = "middle", c.strokeText(String(e), i / 2, i / 2), c.fillText(String(e), i / 2, i / 2)), s;
222
686
  }
223
- function X(e, t = 0.2, i) {
224
- const n = new _({
225
- map: new N(E(e, i)),
687
+ function Ce(e, t = 0.2, n) {
688
+ const o = new V({
689
+ map: new E(j(e, n)),
226
690
  transparent: !0,
227
691
  depthTest: !1
228
- }), o = new D(n);
229
- return o.scale.set(t, t, 1), o.renderOrder = 999, o;
230
- }
231
- function Me(e, t, i) {
232
- var o;
233
- const n = e.material;
234
- (o = n.map) == null || o.dispose(), n.map = new N(E(t, { fill: i })), n.needsUpdate = !0;
235
- }
236
- function Ie(e, t, i = 0.2, n) {
237
- return t.map((o, r) => {
238
- const s = X(r + 1, i, n);
239
- return s.position.set(...o.position), s.name = `modelhub_marker_${o.annotation.id}`, s.userData.annotationId = o.annotation.id, s.userData.displayNumber = r + 1, e.add(s), s;
692
+ }), r = new W(o);
693
+ return r.scale.set(t, t, 1), r.renderOrder = 999, r;
694
+ }
695
+ function lt(e, t, n) {
696
+ var r;
697
+ const o = e.material;
698
+ (r = o.map) == null || r.dispose(), o.map = new E(j(t, { fill: n })), o.needsUpdate = !0;
699
+ }
700
+ function dt(e, t, n = 0.2, o) {
701
+ return t.map((r, i) => {
702
+ const s = Ce(i + 1, n, o);
703
+ return s.position.set(...r.position), s.name = `modelhub_marker_${r.annotation.id}`, s.userData.annotationId = r.annotation.id, s.userData.displayNumber = i + 1, e.add(s), s;
240
704
  });
241
705
  }
242
- function Te(e) {
243
- const { camera: t, model: i, anchors: n, width: o, height: r, isOccluded: s } = e, c = e.referenceDistance ?? 1, u = new h(), a = {};
244
- i.updateMatrixWorld();
245
- for (const l of n) {
246
- u.set(...l.position).applyMatrix4(i.matrixWorld);
247
- const d = u.distanceTo(t.position), f = s ? s(u, d) : !1, m = u.clone().project(t);
248
- a[l.annotation.id] = {
249
- x: (m.x * 0.5 + 0.5) * o,
250
- y: (-m.y * 0.5 + 0.5) * r,
706
+ function ft(e) {
707
+ const { camera: t, model: n, anchors: o, width: r, height: i, isOccluded: s } = e, c = e.referenceDistance ?? 1, l = new b(), a = {};
708
+ n.updateMatrixWorld();
709
+ for (const u of o) {
710
+ l.set(...u.position).applyMatrix4(n.matrixWorld);
711
+ const f = l.distanceTo(t.position), m = s ? s(l, f) : !1, p = l.clone().project(t);
712
+ a[u.annotation.id] = {
713
+ x: (p.x * 0.5 + 0.5) * r,
714
+ y: (-p.y * 0.5 + 0.5) * i,
251
715
  scale: Math.min(
252
716
  1.6,
253
- Math.max(0.55, c / Math.max(d, 1e-3))
717
+ Math.max(0.55, c / Math.max(f, 1e-3))
254
718
  ),
255
- zIndex: Math.max(1, Math.round((1 - m.z) * 1e5)) + (f ? 0 : 2e5),
256
- inView: m.z < 1 && m.x > -1.05 && m.x < 1.05 && m.y > -1.05 && m.y < 1.05,
257
- occluded: f
719
+ zIndex: Math.max(1, Math.round((1 - p.z) * 1e5)) + (m ? 0 : 2e5),
720
+ inView: p.z < 1 && p.x > -1.05 && p.x < 1.05 && p.y > -1.05 && p.y < 1.05,
721
+ occluded: m
258
722
  };
259
723
  }
260
724
  return a;
261
725
  }
262
- const j = 0.03, Z = {
726
+ const _e = 0.03, Ue = {
263
727
  enabled: !1,
264
728
  isOccluded: () => !1,
265
729
  dispose: () => {
266
730
  }
267
731
  };
268
- async function $e(e) {
269
- var r;
270
- let t = [], i = [];
732
+ async function mt(e) {
733
+ var i;
734
+ let t = [], n = [];
271
735
  if (e.traverse((s) => {
272
736
  if (!s.isMesh) return;
273
737
  const c = s.geometry;
274
- c != null && c.computeBoundsTree && (t.push(c), i.push(s));
275
- }), !t.length) return Z;
738
+ c != null && c.computeBoundsTree && (t.push(c), n.push(s));
739
+ }), !t.length) return Ue;
276
740
  for (const s of t)
277
- s.boundsTree || (r = s.computeBoundsTree) == null || r.call(s, { maxLeafTris: 8 });
278
- const n = new C();
279
- n.firstHitOnly = !0;
280
- const o = new h();
741
+ s.boundsTree || (i = s.computeBoundsTree) == null || i.call(s, { maxLeafTris: 8 });
742
+ const o = new q();
743
+ o.firstHitOnly = !0;
744
+ const r = new b();
281
745
  return {
282
746
  enabled: !0,
283
- isOccluded(s, c, u) {
284
- return o.subVectors(c, s.position).normalize(), n.set(s.position, o), n.near = 0, n.far = Math.max(0, u - j), n.camera = s, n.intersectObjects(i, !1).length > 0;
747
+ isOccluded(s, c, l) {
748
+ return r.subVectors(c, s.position).normalize(), o.set(s.position, r), o.near = 0, o.far = Math.max(0, l - _e), o.camera = s, o.intersectObjects(n, !1).length > 0;
285
749
  },
286
750
  dispose() {
287
751
  var s;
288
752
  for (const c of t) (s = c.disposeBoundsTree) == null || s.call(c);
289
- t = [], i = [];
753
+ t = [], n = [];
290
754
  }
291
755
  };
292
756
  }
293
- const y = {
757
+ const I = {
294
758
  headlight: {
295
759
  ambient: 0.7,
296
760
  lights: [
@@ -347,216 +811,216 @@ const y = {
347
811
  { color: [0.42, 0.74, 1], intensity: 0.25, position: [7.23, 6.78, 1.29] }
348
812
  ]
349
813
  }
350
- }, Q = "headlight";
351
- function Ae() {
352
- return Object.keys(y);
814
+ }, Fe = "headlight";
815
+ function ht() {
816
+ return Object.keys(I);
353
817
  }
354
- function Y(e) {
818
+ function Ge(e) {
355
819
  var t;
356
820
  (t = e.parent) == null || t.remove(e);
357
821
  }
358
- function Se(e) {
822
+ function pt(e) {
359
823
  var c;
360
- const { scene: t, camera: i, exposure: n = 1 } = e;
824
+ const { scene: t, camera: n, exposure: o = 1 } = e;
361
825
  (c = e.previous) == null || c.remove();
362
- const o = y[e.preset ?? ""] ?? y[Q], r = [], s = new L(16777215, o.ambient * n);
363
- t.add(s), r.push(s);
364
- for (const u of o.lights) {
826
+ const r = I[e.preset ?? ""] ?? I[Fe], i = [], s = new Y(16777215, r.ambient * o);
827
+ t.add(s), i.push(s);
828
+ for (const l of r.lights) {
365
829
  let a;
366
- if (u.spot) {
367
- const d = new U(new I(...u.color));
368
- d.angle = 0.5, d.penumbra = 0.9, d.decay = 0, a = d;
830
+ if (l.spot) {
831
+ const f = new H(new T(...l.color));
832
+ f.angle = 0.5, f.penumbra = 0.9, f.decay = 0, a = f;
369
833
  } else
370
- a = new F(new I(...u.color));
371
- a.intensity = u.intensity, a.position.set(...u.position);
372
- const l = a.target;
373
- u.attach ? (l == null || l.position.set(0, 0, u.spot ? -1 : 0), i.add(a), l && i.add(l)) : (t.add(a), l && t.add(l)), r.push(a), l && r.push(l);
834
+ a = new X(new T(...l.color));
835
+ a.intensity = l.intensity, a.position.set(...l.position);
836
+ const u = a.target;
837
+ l.attach ? (u == null || u.position.set(0, 0, l.spot ? -1 : 0), n.add(a), u && n.add(u)) : (t.add(a), u && t.add(u)), i.push(a), u && i.push(u);
374
838
  }
375
839
  return {
376
- lights: r,
840
+ lights: i,
377
841
  remove() {
378
- for (const u of r) Y(u);
379
- r.length = 0;
842
+ for (const l of i) Ge(l);
843
+ i.length = 0;
380
844
  }
381
845
  };
382
846
  }
383
- const b = [
847
+ const S = [
384
848
  { id: "white", label: "White", hex: "#ffffff", light: !0 },
385
849
  { id: "light-grey", label: "Light grey", hex: "#d4d4d4", light: !0 },
386
850
  { id: "medium-grey", label: "Medium grey", hex: "#808080", light: !1 },
387
851
  { id: "dark-grey", label: "Dark grey", hex: "#252525", light: !1 },
388
852
  { id: "black", label: "Black", hex: "#000000", light: !1 }
389
- ], J = "dark-grey";
390
- function ee(e) {
853
+ ], Pe = "dark-grey";
854
+ function ze(e) {
391
855
  if (typeof e != "string") return "";
392
856
  const t = e.trim().replace(/^#/, "");
393
- return /^[0-9a-f]{6}$/i.test(t) ? `#${t.toLowerCase()}` : /^[0-9a-f]{3}$/i.test(t) ? `#${[...t].map((i) => i + i).join("").toLowerCase()}` : "";
857
+ return /^[0-9a-f]{6}$/i.test(t) ? `#${t.toLowerCase()}` : /^[0-9a-f]{3}$/i.test(t) ? `#${[...t].map((n) => n + n).join("").toLowerCase()}` : "";
394
858
  }
395
- function te(e) {
859
+ function je(e) {
396
860
  const t = Number.parseInt(e.replace("#", ""), 16);
397
861
  return Number.isFinite(t) ? (0.299 * (t >> 16 & 255) + 0.587 * (t >> 8 & 255) + 0.114 * (t & 255)) / 255 : 0;
398
862
  }
399
- function Ne(e, t) {
400
- const i = ee(t);
401
- return i ? {
863
+ function gt(e, t) {
864
+ const n = ze(t);
865
+ return n ? {
402
866
  id: "custom",
403
867
  label: "Custom",
404
- hex: i,
405
- light: te(i) > 0.5
406
- } : b.find((n) => n.id === e) ?? b.find((n) => n.id === J) ?? b[0];
868
+ hex: n,
869
+ light: je(n) > 0.5
870
+ } : S.find((o) => o.id === e) ?? S.find((o) => o.id === Pe) ?? S[0];
407
871
  }
408
- const ne = 2;
409
- function $(e) {
872
+ const Ve = 2;
873
+ function D(e) {
410
874
  e.updateMatrixWorld(!0);
411
- const t = new g(), i = new g();
412
- return e.traverse((n) => {
413
- const o = n, r = n;
414
- o.isSkinnedMesh ? (o.computeBoundingBox(), o.boundingBox && (i.copy(o.boundingBox).applyMatrix4(o.matrixWorld), t.union(i))) : r.isMesh && r.geometry && (r.geometry.boundingBox || r.geometry.computeBoundingBox(), r.geometry.boundingBox && (i.copy(r.geometry.boundingBox).applyMatrix4(r.matrixWorld), t.union(i)));
415
- }), t.isEmpty() ? new g().setFromObject(e) : t;
416
- }
417
- function ve(e, t = ne) {
418
- const n = $(e).getSize(new h()), o = Math.max(n.x, n.y, n.z) || 1, r = t / o;
419
- e.scale.multiplyScalar(r);
420
- const s = $(e);
421
- return e.position.sub(s.getCenter(new h())), r;
422
- }
423
- function Oe(e, t = 1.3) {
875
+ const t = new v(), n = new v();
876
+ return e.traverse((o) => {
877
+ const r = o, i = o;
878
+ r.isSkinnedMesh ? (r.computeBoundingBox(), r.boundingBox && (n.copy(r.boundingBox).applyMatrix4(r.matrixWorld), t.union(n))) : i.isMesh && i.geometry && (i.geometry.boundingBox || i.geometry.computeBoundingBox(), i.geometry.boundingBox && (n.copy(i.geometry.boundingBox).applyMatrix4(i.matrixWorld), t.union(n)));
879
+ }), t.isEmpty() ? new v().setFromObject(e) : t;
880
+ }
881
+ function yt(e, t = Ve) {
882
+ const o = D(e).getSize(new b()), r = Math.max(o.x, o.y, o.z) || 1, i = t / r;
883
+ e.scale.multiplyScalar(i);
884
+ const s = D(e);
885
+ return e.position.sub(s.getCenter(new b())), i;
886
+ }
887
+ function bt(e, t = 1.3) {
424
888
  return t / Math.tan(e * Math.PI / 360);
425
889
  }
426
- const ie = 0.5, oe = 1.5;
427
- function ke(e, t, i = {}) {
890
+ const We = 0.5, qe = 1.5;
891
+ function $t(e, t, n = {}) {
428
892
  t.updateMatrixWorld();
429
- const n = new h(...e.position).applyMatrix4(
893
+ const o = new b(...e.position).applyMatrix4(
430
894
  t.matrixWorld
431
895
  );
432
896
  if (e.camera) {
433
- const u = new h(...e.camera.eye).applyMatrix4(
897
+ const l = new b(...e.camera.eye).applyMatrix4(
434
898
  t.matrixWorld
435
- ), l = new h(...e.camera.target).applyMatrix4(
899
+ ), u = new b(...e.camera.target).applyMatrix4(
436
900
  t.matrixWorld
437
- ).clone().sub(u);
438
- l.lengthSq() < 1e-10 && l.copy(n).sub(u), l.normalize();
439
- const d = Math.max(n.distanceTo(u), 0.2);
901
+ ).clone().sub(l);
902
+ u.lengthSq() < 1e-10 && u.copy(o).sub(l), u.normalize();
903
+ const f = Math.max(o.distanceTo(l), 0.2);
440
904
  return {
441
- position: u,
442
- target: u.clone().addScaledVector(l, d),
905
+ position: l,
906
+ target: l.clone().addScaledVector(u, f),
443
907
  ...e.camera.fov ? { fov: e.camera.fov } : {}
444
908
  };
445
909
  }
446
- const o = i.outward ?? !0, r = new h(n.x, 0, n.z);
447
- r.lengthSq() < 1e-8 && r.set(0, 0, 1), r.normalize();
448
- const s = o ? -(i.outwardDistance ?? ie) : i.inwardDistance ?? oe, c = n.clone().addScaledVector(r, s);
449
- return c.y = n.y, { position: c, target: n };
910
+ const r = n.outward ?? !0, i = new b(o.x, 0, o.z);
911
+ i.lengthSq() < 1e-8 && i.set(0, 0, 1), i.normalize();
912
+ const s = r ? -(n.outwardDistance ?? We) : n.inwardDistance ?? qe, c = o.clone().addScaledVector(i, s);
913
+ return c.y = o.y, { position: c, target: o };
450
914
  }
451
- const re = { cancel: () => {
915
+ const Ye = { cancel: () => {
452
916
  } };
453
- function Ee(e) {
454
- const { camera: t, controls: i, to: n, onFrame: o, onDone: r } = e, s = () => {
455
- o == null || o(), r == null || r();
917
+ function wt(e) {
918
+ const { camera: t, controls: n, to: o, onFrame: r, onDone: i } = e, s = () => {
919
+ r == null || r(), i == null || i();
456
920
  };
457
921
  if (e.reducedMotion)
458
- return t.position.copy(n.position), i.target.copy(n.target), i.update(), s(), re;
459
- const c = e.durationMs ?? 900, u = t.position.clone(), a = i.target.clone(), l = performance.now();
460
- let d = null;
461
- const f = (m) => {
462
- const p = Math.min((m - l) / c, 1), M = p * (2 - p);
463
- t.position.lerpVectors(u, n.position, M), i.target.lerpVectors(a, n.target, M), i.update(), o == null || o(), p < 1 ? d = requestAnimationFrame(f) : (d = null, r == null || r());
922
+ return t.position.copy(o.position), n.target.copy(o.target), n.update(), s(), Ye;
923
+ const c = e.durationMs ?? 900, l = t.position.clone(), a = n.target.clone(), u = performance.now();
924
+ let f = null;
925
+ const m = (p) => {
926
+ const y = Math.min((p - u) / c, 1), O = y * (2 - y);
927
+ t.position.lerpVectors(l, o.position, O), n.target.lerpVectors(a, o.target, O), n.update(), r == null || r(), y < 1 ? f = requestAnimationFrame(m) : (f = null, i == null || i());
464
928
  };
465
- return d = requestAnimationFrame(f), {
929
+ return f = requestAnimationFrame(m), {
466
930
  cancel() {
467
- d !== null && cancelAnimationFrame(d), d = null;
931
+ f !== null && cancelAnimationFrame(f), f = null;
468
932
  }
469
933
  };
470
934
  }
471
- function Be(e, t, i) {
472
- const n = t || i;
473
- e.fov !== n && (e.fov = n, e.updateProjectionMatrix());
935
+ function xt(e, t, n) {
936
+ const o = t || n;
937
+ e.fov !== o && (e.fov = o, e.updateProjectionMatrix());
474
938
  }
475
- const se = 500;
476
- function Re(e) {
477
- var o, r, s;
939
+ const He = 500;
940
+ function vt(e) {
941
+ var r, i, s;
478
942
  if (!e)
479
943
  return "Model loaded, but it carries no educational metadata.";
480
944
  const t = [];
481
- (o = e.model) != null && o.title && t.push(`${e.model.title} loaded`), (r = e.model) != null && r.altText && t.push(e.model.altText);
482
- const i = ((s = e.regions) == null ? void 0 : s.length) ?? 0, n = w(e).length;
483
- return i && t.push(`${i} labelled ${i === 1 ? "region" : "regions"}`), n && t.push(
484
- `${n} ${n === 1 ? "annotation" : "annotations"}`
945
+ (r = e.model) != null && r.title && t.push(`${e.model.title} loaded`), (i = e.model) != null && i.altText && t.push(e.model.altText);
946
+ const n = ((s = e.regions) == null ? void 0 : s.length) ?? 0, o = M(e).length;
947
+ return n && t.push(`${n} labeled ${n === 1 ? "region" : "regions"}`), o && t.push(
948
+ `${o} ${o === 1 ? "annotation" : "annotations"}`
485
949
  ), t.map((c) => c.replace(/\.$/, "")).join(". ") + ".";
486
950
  }
487
- function _e(e, t, i) {
488
- return `Annotation ${t + 1} of ${i}: ${e || "Untitled"}.`;
951
+ function At(e, t, n) {
952
+ return `Annotation ${t + 1} of ${n}: ${e || "Untitled"}.`;
489
953
  }
490
- function De(e, t = se, i = () => Date.now()) {
491
- let n = -1 / 0, o = null, r = null;
954
+ function St(e, t = He, n = () => Date.now()) {
955
+ let o = -1 / 0, r = null, i = null;
492
956
  const s = (a) => {
493
- n = i(), o = null, e(a);
957
+ o = n(), r = null, e(a);
494
958
  };
495
959
  return { announce: (a) => {
496
- const l = i() - n;
497
- if (l >= t) {
960
+ const u = n() - o;
961
+ if (u >= t) {
498
962
  s(a);
499
963
  return;
500
964
  }
501
- o = a, r || (r = setTimeout(() => {
502
- r = null, o !== null && s(o);
503
- }, t - l));
965
+ r = a, i || (i = setTimeout(() => {
966
+ i = null, r !== null && s(r);
967
+ }, t - u));
504
968
  }, flush: () => {
505
- r && (clearTimeout(r), r = null), o !== null && s(o);
969
+ i && (clearTimeout(i), i = null), r !== null && s(r);
506
970
  } };
507
971
  }
508
- function A(e, t) {
972
+ function R(e, t) {
509
973
  return `## ${e}
510
974
  ${t}
511
975
 
512
976
  `;
513
977
  }
514
- function Ce(e, t = {}) {
515
- const i = e.model ?? {}, n = k(e), o = w(e);
516
- let r = `# ${i.title || "Untitled model"}
978
+ function It(e, t = {}) {
979
+ const n = e.model ?? {}, o = z(e), r = M(e);
980
+ let i = `# ${n.title || "Untitled model"}
517
981
 
518
982
  `;
519
- if (i.altText && (r += A(t.summaryHeading ?? "Summary", i.altText)), i.longDescription && (r += A("Full description", i.longDescription)), n.length) {
520
- r += `## Regions (${n.length})
983
+ if (n.altText && (i += R(t.summaryHeading ?? "Summary", n.altText)), n.longDescription && (i += R("Full description", n.longDescription)), o.length) {
984
+ i += `## Regions (${o.length})
521
985
 
522
986
  `;
523
- for (const s of n)
524
- r += `### ${T(s)}
987
+ for (const s of o)
988
+ i += `### ${L(s)}
525
989
  ${s.description || "No description."}
526
990
 
527
991
  `;
528
992
  }
529
- return o.length && (r += `## Annotations (${o.length})
993
+ return r.length && (i += `## Annotations (${r.length})
530
994
 
531
- `, o.forEach((s, c) => {
532
- const u = s.regionId ? ` (${T(n.find((l) => l.id === s.regionId))})` : "", a = `${c + 1}. ${s.title || "Untitled"}${u}`;
533
- r += `### ${a}
995
+ `, r.forEach((s, c) => {
996
+ const l = s.regionId ? ` (${L(o.find((u) => u.id === s.regionId))})` : "", a = `${c + 1}. ${s.title || "Untitled"}${l}`;
997
+ i += `### ${a}
534
998
  ${s.body || "No description."}
535
999
 
536
1000
  `;
537
- })), r += `## Licensing
538
- `, r += `- **License:** ${i.license || "Not specified"}
539
- `, r += `- **Attribution:** ${i.attribution || "Not specified"}
540
- `, r += `- **Creator:** ${i.creator || "Not specified"}
541
- `, r += `- **Source:** ${i.source || "Not specified"}
542
- `, r;
1001
+ })), i += `## Licensing
1002
+ `, i += `- **License:** ${n.license || "Not specified"}
1003
+ `, i += `- **Attribution:** ${n.attribution || "Not specified"}
1004
+ `, i += `- **Creator:** ${n.creator || "Not specified"}
1005
+ `, i += `- **Source:** ${n.source || "Not specified"}
1006
+ `, i;
543
1007
  }
544
- function Le(e) {
545
- var i;
546
- return `${(((i = e.model) == null ? void 0 : i.title) || "model").trim().replace(/[^\w\-. ]+/g, "").replace(/\s+/g, "_") || "model"}_transcript.md`;
1008
+ function Mt(e) {
1009
+ var n;
1010
+ return `${(((n = e.model) == null ? void 0 : n.title) || "model").trim().replace(/[^\w\-. ]+/g, "").replace(/\s+/g, "_") || "model"}_transcript.md`;
547
1011
  }
548
- function Ue(e) {
1012
+ function Ot(e) {
549
1013
  e && e.traverse((t) => {
550
- var r, s;
551
- const i = t, n = i.geometry;
552
- n && (n.boundsTree && n.disposeBoundsTree && n.disposeBoundsTree(), (r = n.dispose) == null || r.call(n));
553
- const o = [].concat(
554
- i.material ?? []
1014
+ var i, s;
1015
+ const n = t, o = n.geometry;
1016
+ o && (o.boundsTree && o.disposeBoundsTree && o.disposeBoundsTree(), (i = o.dispose) == null || i.call(o));
1017
+ const r = [].concat(
1018
+ n.material ?? []
555
1019
  );
556
- for (const c of o)
1020
+ for (const c of r)
557
1021
  if (c) {
558
- for (const u of Object.values(c)) {
559
- const a = u;
1022
+ for (const l of Object.values(c)) {
1023
+ const a = l;
560
1024
  a && a.isTexture && a.dispose();
561
1025
  }
562
1026
  (s = c.dispose) == null || s.call(c);
@@ -564,62 +1028,64 @@ function Ue(e) {
564
1028
  });
565
1029
  }
566
1030
  export {
567
- b as BACKGROUND_OPTIONS,
568
- se as CAMERA_ANNOUNCE_INTERVAL,
569
- J as DEFAULT_BACKGROUND,
570
- Q as DEFAULT_LIGHTING,
571
- ze as GlbParseError,
572
- y as LIGHTING_PRESETS,
573
- K as MARKER_FILL,
574
- we as MARKER_FILL_ACTIVE,
575
- ne as NORMALIZED_SIZE,
576
- j as OCCLUSION_BIAS,
577
- oe as TOUR_DISTANCE_INWARD,
578
- ie as TOUR_DISTANCE_OUTWARD,
579
- _e as annotationSummary,
580
- w as annotationsInReadingOrder,
581
- Be as applyFov,
582
- Se as applyLighting,
583
- xe as applyVisibilityDefaults,
584
- he as buildRegionMeshMap,
585
- Ce as buildTranscript,
586
- ye as clearRegionHighlight,
587
- $ as computeDisplayBox,
588
- ke as computeTourPlacement,
589
- De as createAnnouncer,
590
- X as createMarkerSprite,
591
- Ie as createMarkerSprites,
592
- $e as createOcclusionIndex,
593
- Ue as disposeSceneGraph,
594
- Oe as distanceForFov,
595
- E as drawMarkerCanvas,
596
- W as errorsOf,
597
- P as fetchBytes,
598
- Ee as flyCamera,
599
- ve as frameModel,
600
- fe as fromViewerPosition,
601
- be as highlightRegion,
602
- v as isVec3,
603
- Ae as lightingPresetNames,
604
- ue as loadModel,
605
- de as logFindings,
606
- te as luminance,
607
- Re as modelSummary,
608
- O as needsConversion,
609
- V as normalizeAnnotationIds,
610
- ee as normalizeHexColor,
611
- pe as normalizeModel,
612
- me as parseBodySegments,
613
- Te as projectMarkers,
614
- G as readEmbedded,
615
- ge as regionBindingCounts,
616
- T as regionLabel,
617
- k as regionsInOrder,
618
- Ne as resolveBackground,
619
- le as resourcePathFor,
620
- Me as setMarkerSpriteColor,
621
- q as setRegionVisible,
622
- z as sidecarUrlFor,
623
- x as toViewerPosition,
624
- Le as transcriptFileName
1031
+ S as BACKGROUND_OPTIONS,
1032
+ He as CAMERA_ANNOUNCE_INTERVAL,
1033
+ Pe as DEFAULT_BACKGROUND,
1034
+ Fe as DEFAULT_LIGHTING,
1035
+ I as LIGHTING_PRESETS,
1036
+ Ee as MARKER_FILL,
1037
+ ut as MARKER_FILL_ACTIVE,
1038
+ Ve as NORMALIZED_SIZE,
1039
+ _e as OCCLUSION_BIAS,
1040
+ qe as TOUR_DISTANCE_INWARD,
1041
+ We as TOUR_DISTANCE_OUTWARD,
1042
+ At as annotationSummary,
1043
+ M as annotationsInReadingOrder,
1044
+ xt as applyFov,
1045
+ pt as applyLighting,
1046
+ st as applyVisibilityDefaults,
1047
+ rt as buildRegionMeshMap,
1048
+ It as buildTranscript,
1049
+ ct as clearRegionHighlight,
1050
+ D as computeDisplayBox,
1051
+ $t as computeTourPlacement,
1052
+ St as createAnnouncer,
1053
+ Ce as createMarkerSprite,
1054
+ dt as createMarkerSprites,
1055
+ mt as createOcclusionIndex,
1056
+ Ot as disposeSceneGraph,
1057
+ bt as distanceForFov,
1058
+ j as drawMarkerCanvas,
1059
+ Me as errorsOf,
1060
+ Te as fetchBytes,
1061
+ wt as flyCamera,
1062
+ yt as frameModel,
1063
+ et as fromViewerPosition,
1064
+ at as highlightRegion,
1065
+ Le as isAuthoredRegion,
1066
+ Je as isGlbParseError,
1067
+ G as isVec3,
1068
+ ht as lightingPresetNames,
1069
+ Ze as loadModel,
1070
+ Qe as logFindings,
1071
+ je as luminance,
1072
+ vt as modelSummary,
1073
+ P as needsConversion,
1074
+ ke as normalizeAnnotationIds,
1075
+ ze as normalizeHexColor,
1076
+ ot as normalizeModel,
1077
+ nt as parseBodySegments,
1078
+ ft as projectMarkers,
1079
+ Ne as readEmbedded,
1080
+ tt as readableRegions,
1081
+ it as regionBindingCounts,
1082
+ L as regionLabel,
1083
+ z as regionsInOrder,
1084
+ gt as resolveBackground,
1085
+ Ke as resourcePathFor,
1086
+ lt as setMarkerSpriteColor,
1087
+ Re as setRegionVisible,
1088
+ Oe as sidecarUrlFor,
1089
+ A as toViewerPosition,
1090
+ Mt as transcriptFileName
625
1091
  };