@harpern/edu-modelhub-viewer-core 0.1.0-beta.4 → 0.1.0-beta.6

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