@vctrl/hooks 0.17.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/README.md +9 -9
  3. package/chunk-CMqjfN_6.cjs +1 -0
  4. package/index.cjs.js +1 -1
  5. package/index.es.js +3 -3
  6. package/package.json +67 -67
  7. package/use-export-model-8JbUalyf.cjs +1 -0
  8. package/{use-export-model-DzVKdqnY.js → use-export-model-BXg6L_W5.js} +5 -5
  9. package/use-export-model.cjs.js +1 -1
  10. package/use-export-model.es.js +1 -1
  11. package/use-load-model/error-helpers.d.ts +5 -0
  12. package/use-load-model/file-loaders.d.ts +12 -0
  13. package/use-load-model/index.d.ts +1 -1
  14. package/use-load-model/optimizer-integration.d.ts +16 -0
  15. package/use-load-model/scene-data-builder.d.ts +3 -0
  16. package/use-load-model/types.d.ts +13 -4
  17. package/use-load-model/use-load-model.d.ts +5 -16
  18. package/use-load-model-B9M4cF4B.cjs +1 -0
  19. package/use-load-model-BDCy9n2U.js +504 -0
  20. package/use-load-model.cjs.js +1 -1
  21. package/use-load-model.es.js +1 -1
  22. package/use-optimize-model/use-optimize-model.d.ts +14 -12
  23. package/use-optimize-model/utils/browser-texture-encoder.d.ts +41 -0
  24. package/use-optimize-model/utils/index.d.ts +2 -2
  25. package/use-optimize-model/utils/texture-optimization.d.ts +3 -13
  26. package/use-optimize-model-CPGezwrM.cjs +1 -0
  27. package/use-optimize-model-KAGxtv_k.js +296 -0
  28. package/use-optimize-model.cjs.js +1 -1
  29. package/use-optimize-model.es.js +1 -1
  30. package/GLTFLoader-CygFefRr.cjs +0 -1
  31. package/GLTFLoader-NiJ7qzh1.js +0 -1381
  32. package/__vite-browser-external-Bn_csQuM.js +0 -7
  33. package/__vite-browser-external-CVmj8TrW.cjs +0 -1
  34. package/chunk-foFoljWS.js +0 -23
  35. package/chunk-gGpyby2o.cjs +0 -1
  36. package/lib-DKn2MJ9X.js +0 -4111
  37. package/lib-DZ-MihdJ.cjs +0 -2
  38. package/model-exporter-SMSAY90N.cjs +0 -1
  39. package/model-exporter-cvguDGnn.js +0 -6512
  40. package/server-communication-Bj6ZxFw2.js +0 -4659
  41. package/server-communication-yXZR8eso.cjs +0 -18
  42. package/use-export-model-CaijtW1c.cjs +0 -1
  43. package/use-load-model-B6UXiFWh.js +0 -517
  44. package/use-load-model-CH-WPQ_s.cjs +0 -1
  45. package/use-optimize-model/utils/validation.d.ts +0 -8
  46. package/use-optimize-model-C-fzzKh6.cjs +0 -1
  47. package/use-optimize-model-Cb3WMvDZ.js +0 -299
@@ -1,517 +0,0 @@
1
- import { a as e, i as t, l as n, n as r, o as i, r as a, s as o, t as s, u as c } from "./server-communication-Bj6ZxFw2.js";
2
- import { useCallback as l, useMemo as u, useReducer as d, useRef as f } from "react";
3
- //#region packages/core/src/scene-interaction/normalize-scene-interactions.ts
4
- function p(e) {
5
- return typeof e == "object" && !!e && !Array.isArray(e);
6
- }
7
- function m(e, t) {
8
- if (typeof e != "number" || !Number.isFinite(e)) throw Error(`${t} must be a finite number`);
9
- return e;
10
- }
11
- function h(e, t) {
12
- switch (e.type) {
13
- case "viewer_ready": return {
14
- source: "viewer",
15
- type: "viewer_ready"
16
- };
17
- case "host_scroll_progress": {
18
- let n = m(e.start, `${t}.start`), r = m(e.end, `${t}.end`);
19
- if (n > r) throw Error(`${t}.start must be less than or equal to ${t}.end`);
20
- return {
21
- source: "host",
22
- type: "host_scroll_progress",
23
- start: n,
24
- end: r
25
- };
26
- }
27
- case "host_message":
28
- if (typeof e.message != "string" || !e.message.trim()) throw Error(`${t}.message must be a non-empty string`);
29
- return {
30
- source: "host",
31
- type: "host_message",
32
- message: e.message.trim()
33
- };
34
- default: throw Error(`${t}.type must be one of viewer_ready, host_scroll_progress, host_message`);
35
- }
36
- }
37
- function g(e, t, n) {
38
- switch (e.type) {
39
- case "activate_camera": {
40
- if (typeof e.cameraId != "string" || !e.cameraId.trim()) throw Error(`${t}.cameraId must be a non-empty string`);
41
- let r = e.cameraId.trim();
42
- if (n.size > 0 && !n.has(r)) throw Error(`${t}.cameraId references an unknown camera: ${r}`);
43
- return {
44
- type: "activate_camera",
45
- cameraId: r
46
- };
47
- }
48
- case "set_controls_enabled":
49
- if (typeof e.enabled != "boolean") throw Error(`${t}.enabled must be a boolean`);
50
- return {
51
- type: "set_controls_enabled",
52
- enabled: e.enabled
53
- };
54
- case "emit_custom_event":
55
- if (typeof e.eventName != "string" || !e.eventName.trim()) throw Error(`${t}.eventName must be a non-empty string`);
56
- if (e.payload !== void 0 && !p(e.payload)) throw Error(`${t}.payload must be an object when provided`);
57
- return {
58
- type: "emit_custom_event",
59
- eventName: e.eventName.trim(),
60
- payload: e.payload
61
- };
62
- default: throw Error(`${t}.type must be one of activate_camera, set_controls_enabled, emit_custom_event`);
63
- }
64
- }
65
- function _(e, t = {}) {
66
- if (e === void 0) return;
67
- if (!Array.isArray(e)) throw Error("interactions must be an array");
68
- let n = new Set(t.camera?.cameras?.map((e) => e.cameraId?.trim()).filter((e) => !!e) ?? []), r = /* @__PURE__ */ new Set();
69
- return e.map((e, t) => {
70
- if (!p(e)) throw Error(`interactions[${t}] must be an object`);
71
- let i = typeof e.id == "string" && e.id.trim() ? e.id.trim() : `interaction-${t + 1}`;
72
- if (r.has(i)) throw Error(`Duplicate interaction id found: ${i}`);
73
- r.add(i);
74
- let a = typeof e.order == "number" && Number.isFinite(e.order) ? e.order : t + 1, o = e.trigger;
75
- if (!p(o)) throw Error(`interactions[${t}].trigger must be an object`);
76
- if (!Array.isArray(e.actions) || e.actions.length === 0) throw Error(`interactions[${t}].actions must be a non-empty array`);
77
- let s = e.actions;
78
- return {
79
- id: i,
80
- order: a,
81
- enabled: e.enabled !== !1,
82
- trigger: h(o, `interactions[${t}].trigger`),
83
- actions: s.map((e, r) => {
84
- if (!p(e)) throw Error(`interactions[${t}].actions[${r}] must be an object`);
85
- return g(e, `interactions[${t}].actions[${r}]`, n);
86
- })
87
- };
88
- });
89
- }
90
- //#endregion
91
- //#region packages/hooks/src/use-load-model/event-system.ts
92
- var v = {}, y = {
93
- emit(e, t) {
94
- let n = v[e];
95
- console.debug(`Event emitted: ${e}`, t), n && n.forEach((e) => e(t));
96
- },
97
- on(e, t) {
98
- v[e] || (v[e] = []), v[e].push(t);
99
- },
100
- off(e, t) {
101
- let n = v[e];
102
- n && (v[e] = n.filter((e) => e !== t));
103
- }
104
- }, b = {
105
- file: null,
106
- isFileLoading: !1,
107
- progress: 0,
108
- supportedFileTypes: [
109
- c.gltf,
110
- c.glb,
111
- c.usdz
112
- ]
113
- };
114
- function x(e, t) {
115
- switch (t.type) {
116
- case "set-file": return {
117
- ...e,
118
- file: t.payload
119
- };
120
- case "set-file-loading": return {
121
- ...e,
122
- isFileLoading: t.payload
123
- };
124
- case "set-progress": return {
125
- ...e,
126
- progress: t.payload
127
- };
128
- case "reset-state": return { ...b };
129
- default: return e;
130
- }
131
- }
132
- //#endregion
133
- //#region packages/hooks/src/use-load-model/utils/read-directory.ts
134
- async function S(e) {
135
- let t = [];
136
- async function* n(e) {
137
- let t = e;
138
- for await (let [, e] of t) e.kind === "file" ? yield await e.getFile() : e.kind === "directory" && (yield* n(e));
139
- }
140
- for await (let r of n(e)) t.push(r);
141
- return t;
142
- }
143
- //#endregion
144
- //#region packages/hooks/src/use-load-model/utils/reconstruct-files.ts
145
- function C(e) {
146
- let t = [];
147
- if (e.assetData && typeof e.assetData == "object") for (let [, n] of Object.entries(e.assetData)) {
148
- let { fileName: e, mimeType: r } = n, a = i(n), o = new Uint8Array(a.byteLength);
149
- o.set(a);
150
- let s = new Blob([o], { type: r }), c = new File([s], e, { type: r });
151
- t.push(c);
152
- }
153
- let n = JSON.stringify(e.gltfJson), r = new Blob([n], { type: "model/gltf+json" }), a = e.meta?.name, o = a ? `${a}.gltf` : "scene.gltf";
154
- return [new File([r], o, { type: "model/gltf+json" }), ...t];
155
- }
156
- //#endregion
157
- //#region packages/hooks/src/use-load-model/utils/calculate-referenced-bytes.ts
158
- var w = (t, n) => {
159
- let i = e(t), a = i.split("/").pop() || i;
160
- for (let e of n) {
161
- let t = r(e.fileName);
162
- if (t.has(i) || t.has(a)) return e.size;
163
- }
164
- return 0;
165
- }, T = (e) => {
166
- let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), r = e, i = Array.isArray(r.images) ? r.images : [];
167
- for (let e of i) typeof e.uri == "string" && !e.uri.startsWith("data:") && n.add(e.uri);
168
- let a = Array.isArray(r.buffers) ? r.buffers : [];
169
- for (let e of a) typeof e.uri == "string" && !e.uri.startsWith("data:") && t.add(e.uri);
170
- return {
171
- bufferUris: t,
172
- imageUris: n
173
- };
174
- };
175
- async function E(e, t) {
176
- let n = await e.text(), r;
177
- try {
178
- r = JSON.parse(n);
179
- } catch {
180
- return {
181
- sourcePackageBytes: e.size,
182
- textureBytes: 0
183
- };
184
- }
185
- let i = t.map((e) => ({
186
- fileName: e.name,
187
- size: e.size
188
- })), { bufferUris: a, imageUris: o } = T(r), s = Array.from(a).reduce((e, t) => e + w(t, i), 0), c = Array.from(o).reduce((e, t) => e + w(t, i), 0);
189
- return {
190
- sourcePackageBytes: e.size + s + c,
191
- textureBytes: c
192
- };
193
- }
194
- function D(e) {
195
- let t = e.gltfJson, n = Object.values(e.assetData || {}).map((e) => ({
196
- fileName: e.fileName,
197
- size: a(e.data)
198
- })), r = new TextEncoder().encode(JSON.stringify(t)).byteLength, { bufferUris: i, imageUris: o } = T(t), s = Array.from(i).reduce((e, t) => e + w(t, n), 0), c = Array.from(o).reduce((e, t) => e + w(t, n), 0);
199
- return {
200
- sourcePackageBytes: r + s + c,
201
- textureBytes: c
202
- };
203
- }
204
- //#endregion
205
- //#region packages/hooks/src/use-load-model/utils/resolve-scene-payload.ts
206
- function O(e) {
207
- return typeof e == "object" && !!e && !Array.isArray(e);
208
- }
209
- function k(e) {
210
- let t = O(e.settings) ? e.settings : {}, n = o(e.camera ?? t.camera);
211
- return {
212
- ...t,
213
- bounds: e.bounds ?? t.bounds,
214
- camera: n,
215
- interactions: _(t.interactions, { camera: n }),
216
- controls: e.controls ?? t.controls,
217
- environment: e.environment ?? t.environment,
218
- shadows: e.shadows ?? t.shadows
219
- };
220
- }
221
- function A(e) {
222
- let t = /* @__PURE__ */ new Set(), n = e, r = Array.isArray(n.images) ? n.images : [];
223
- for (let e of r) typeof e.uri == "string" && !e.uri.startsWith("data:") && t.add(e.uri);
224
- let i = Array.isArray(n.buffers) ? n.buffers : [];
225
- for (let e of i) typeof e.uri == "string" && !e.uri.startsWith("data:") && t.add(e.uri);
226
- return t;
227
- }
228
- function j(e) {
229
- for (let [n, r] of Object.entries(e)) {
230
- if (!r || typeof r != "object") throw Error(`Scene payload contains invalid asset entry for ${n}`);
231
- if (typeof r.fileName != "string" || r.fileName.trim().length === 0) throw Error(`Scene payload asset ${n} is missing a valid fileName`);
232
- if (typeof r.mimeType != "string" || r.mimeType.trim().length === 0) throw Error(`Scene payload asset ${n} is missing a valid mimeType`);
233
- if (typeof r.data == "string" && r.encoding === "base64" && !t(r.data)) throw Error(`Scene payload asset ${r.fileName} has invalid base64 data`);
234
- }
235
- }
236
- function M(t, n) {
237
- let i = A(t);
238
- if (i.size === 0) return;
239
- let a = /* @__PURE__ */ new Set();
240
- for (let e of Object.values(n)) for (let t of r(e.fileName)) a.add(t);
241
- let o = [];
242
- for (let t of i) {
243
- let n = e(t), r = n.split("/").pop() || n;
244
- !a.has(t) && !a.has(n) && !a.has(r) && o.push(t);
245
- }
246
- if (o.length > 0) throw Error(`Scene payload is missing required referenced assets: ${o.slice(0, 5).join(", ")}`);
247
- }
248
- function N(e) {
249
- if (!O(e.gltfJson)) throw Error("Scene payload is missing a valid glTF document");
250
- let t = e.assetData ?? {};
251
- return j(t), M(e.gltfJson, t), {
252
- meta: e.meta,
253
- gltfJson: e.gltfJson,
254
- assetData: t,
255
- ...k(e)
256
- };
257
- }
258
- //#endregion
259
- //#region packages/hooks/src/use-load-model/use-load-model.ts
260
- var P = (t) => {
261
- try {
262
- return e(t);
263
- } catch {
264
- return t;
265
- }
266
- }, F = (e) => {
267
- let t = /* @__PURE__ */ new Set(), n = e, r = Array.isArray(n.images) ? n.images : [];
268
- for (let e of r) typeof e.uri == "string" && !e.uri.startsWith("data:") && t.add(e.uri);
269
- let i = Array.isArray(n.buffers) ? n.buffers : [];
270
- for (let e of i) typeof e.uri == "string" && !e.uri.startsWith("data:") && t.add(e.uri);
271
- return t;
272
- }, I = async (e, t) => {
273
- let n = JSON.parse(await e.text()), i = F(n), a = {}, o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set(), l = async (e) => {
274
- let t = s.get(e);
275
- if (t) return t;
276
- let n = new Uint8Array(await e.arrayBuffer());
277
- return s.set(e, n), n;
278
- };
279
- for (let e of t) {
280
- for (let t of r(e.name)) o.set(t, e);
281
- if (e.webkitRelativePath) for (let t of r(e.webkitRelativePath)) o.set(t, e);
282
- }
283
- let u = [];
284
- for (let e of i) {
285
- let t = P(e), n = t.split("/").pop() || t, r = o.get(e) || o.get(t) || o.get(n);
286
- if (!r) {
287
- u.push(e);
288
- continue;
289
- }
290
- c.add(r);
291
- let i = await l(r);
292
- a[t] = {
293
- data: Array.from(i),
294
- fileName: t,
295
- mimeType: r.type || "application/octet-stream"
296
- };
297
- }
298
- if (u.length > 0) throw Error(`Scene payload is missing required referenced assets: ${u.slice(0, 5).join(", ")}`);
299
- for (let [e, n] of t.entries()) {
300
- if (c.has(n)) continue;
301
- let t = P(n.name), r = t.split("/").pop() || t, i = await l(n);
302
- a[`extra-${e}-${r}`] = {
303
- data: Array.from(i),
304
- fileName: r,
305
- mimeType: n.type || "application/octet-stream"
306
- };
307
- }
308
- return {
309
- gltfJson: n,
310
- assetData: a
311
- };
312
- };
313
- function L(e) {
314
- let t = f(!1), r = f(null), [i, a] = d(x, b), o = u(() => {
315
- let e = new n();
316
- return e.onProgress((e) => {
317
- a({
318
- type: "set-progress",
319
- payload: e.progress
320
- }), e.progress !== 100 && y.emit("load-progress", e.progress);
321
- }), e;
322
- }, []), p = l((e, t) => e.find((e) => e.name.endsWith("." + t)), []), m = l((e) => {
323
- a({
324
- type: "set-progress",
325
- payload: e
326
- }), y.emit("load-progress", e);
327
- }, []), h = l(() => {
328
- a({ type: "reset-state" }), y.emit("load-reset");
329
- }, []), g = l(async (t, n) => {
330
- try {
331
- let i = await o.loadToThreeJS(t), s = {
332
- model: i.scene,
333
- type: n,
334
- name: t.name
335
- };
336
- a({
337
- type: "set-file",
338
- payload: s
339
- }), r.current = s, a({
340
- type: "set-file-loading",
341
- payload: !1
342
- }), e && await e.load(i.scene);
343
- } catch (e) {
344
- console.error("Error loading binary model:", e), a({
345
- type: "set-file-loading",
346
- payload: !1
347
- }), y.emit("load-error", e);
348
- }
349
- }, [o, e]), _ = l(async (t, n) => {
350
- try {
351
- let { sourcePackageBytes: i, textureBytes: s } = await E(t, n), l = await o.loadGLTFWithAssetsToThreeJS(t, n), u = {
352
- model: l.scene,
353
- type: c.gltf,
354
- name: t.name,
355
- sourcePackageBytes: i,
356
- sourceTextureBytes: s
357
- };
358
- if (a({
359
- type: "set-file",
360
- payload: u
361
- }), a({
362
- type: "set-file-loading",
363
- payload: !1
364
- }), r.current = u, e) try {
365
- let r = await I(t, n);
366
- await e.loadFromServerSceneData(r);
367
- } catch (t) {
368
- console.warn("Failed to initialize optimizer from source GLTF payload; falling back to scene import.", t), await e.load(l.scene);
369
- }
370
- } catch (e) {
371
- console.error("Error loading GLTF model:", e), console.error("GLTF file:", t.name), console.error("Asset files:", n.map((e) => e.name)), a({
372
- type: "set-file-loading",
373
- payload: !1
374
- }), y.emit("load-error", e);
375
- }
376
- }, [o, e]), v = l(async (e) => {
377
- if (e.length === 0) return;
378
- let n = p(e, c.gltf), i = p(e, c.glb), o = p(e, c.usdz), s = [
379
- n,
380
- i,
381
- o
382
- ].filter(Boolean);
383
- if (s.length > 1) {
384
- y.emit("multiple-models", s);
385
- return;
386
- }
387
- let l = e.filter((e) => e !== n && e !== i && e !== o), u = () => {
388
- t.current = !0, r.current && (y.emit("load-complete", r.current), t.current = !1);
389
- };
390
- if (n) await _(n, l), u();
391
- else if (i) await g(i, c.glb), u();
392
- else if (o) await g(o, c.usdz), u();
393
- else {
394
- y.emit("not-loaded-files", e), a({
395
- type: "set-file-loading",
396
- payload: !1
397
- });
398
- return;
399
- }
400
- }, [
401
- p,
402
- _,
403
- g
404
- ]), w = l(async (e) => {
405
- let n = [];
406
- y.emit("load-start"), a({ type: "reset-state" }), a({
407
- type: "set-file-loading",
408
- payload: !0
409
- }), m(0), t.current = !1;
410
- for (let t of e) if (t instanceof File) n.push(t);
411
- else if ("kind" in t && t.kind === "directory") {
412
- let e = await S(t);
413
- n.push(...e);
414
- }
415
- await v(n);
416
- }, [v, m]), T = l(async (t) => {
417
- let { sceneData: n, sceneId: i } = t;
418
- m(40);
419
- let s = C(n), { sourcePackageBytes: l, textureBytes: u } = D(n);
420
- m(60);
421
- let d = s[0], f = s.slice(1), p = {
422
- model: (await o.loadGLTFWithAssetsToThreeJS(d, f)).scene,
423
- type: c.gltf,
424
- name: d.name,
425
- sourcePackageBytes: l,
426
- sourceTextureBytes: u
427
- };
428
- return a({
429
- type: "set-file",
430
- payload: p
431
- }), a({
432
- type: "set-file-loading",
433
- payload: !1
434
- }), r.current = p, e && await e.loadFromServerSceneData(n), m(100), {
435
- file: p,
436
- sceneId: i,
437
- ...n
438
- };
439
- }, [
440
- o,
441
- e,
442
- m
443
- ]), O = l(async (e) => {
444
- let { sceneId: t, serverOptions: n } = e;
445
- try {
446
- y.emit("server-load-start", t), a({ type: "reset-state" }), a({
447
- type: "set-file-loading",
448
- payload: !0
449
- }), m(0);
450
- let e = await T({
451
- sceneId: t,
452
- sceneData: N(await s.loadScene(t, n))
453
- });
454
- return y.emit("server-load-complete", e), e;
455
- } catch (e) {
456
- throw console.error("Server scene loading failed:", e), a({
457
- type: "set-file-loading",
458
- payload: !1
459
- }), y.emit("server-load-error", e), e;
460
- }
461
- }, [T, m]), k = R(e, a, i.file, o);
462
- return {
463
- ...i,
464
- on: y.on,
465
- off: y.off,
466
- load: w,
467
- loadFromData: T,
468
- loadFromServer: O,
469
- reset: h,
470
- optimizer: k
471
- };
472
- }
473
- function R(e, t, n, r) {
474
- let i = l(async (i, a) => {
475
- if (!e) {
476
- console.warn("Optimizer is not available");
477
- return;
478
- }
479
- try {
480
- i && await i(a);
481
- let o = await e.getModel();
482
- if (!o) {
483
- console.warn("No optimized model available after optimization");
484
- return;
485
- }
486
- let s = o instanceof Uint8Array ? o.slice() : new Uint8Array(o).slice(), l = new File([s], n?.name || "optimized_model.glb", { type: "model/gltf-binary" });
487
- t({
488
- type: "set-file",
489
- payload: {
490
- model: (await r.loadToThreeJS(l)).scene,
491
- type: c.glb,
492
- name: l.name
493
- }
494
- });
495
- } catch (e) {
496
- console.error("Optimization failed:", e);
497
- }
498
- }, [
499
- e,
500
- r,
501
- n,
502
- t
503
- ]);
504
- if (!e) return null;
505
- let a = e.isReady, o = !!n?.model && !a;
506
- return {
507
- ...e,
508
- isReady: a,
509
- isPreparing: o,
510
- applyOptimization: i,
511
- reset: e?.reset,
512
- error: e?.error,
513
- loading: e?.loading
514
- };
515
- }
516
- //#endregion
517
- export { C as n, L as t };
@@ -1 +0,0 @@
1
- require(`./chunk-gGpyby2o.cjs`);const e=require(`./server-communication-yXZR8eso.cjs`);let t=require(`react`);function n(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function r(e,t){if(typeof e!=`number`||!Number.isFinite(e))throw Error(`${t} must be a finite number`);return e}function i(e,t){switch(e.type){case`viewer_ready`:return{source:`viewer`,type:`viewer_ready`};case`host_scroll_progress`:{let n=r(e.start,`${t}.start`),i=r(e.end,`${t}.end`);if(n>i)throw Error(`${t}.start must be less than or equal to ${t}.end`);return{source:`host`,type:`host_scroll_progress`,start:n,end:i}}case`host_message`:if(typeof e.message!=`string`||!e.message.trim())throw Error(`${t}.message must be a non-empty string`);return{source:`host`,type:`host_message`,message:e.message.trim()};default:throw Error(`${t}.type must be one of viewer_ready, host_scroll_progress, host_message`)}}function a(e,t,r){switch(e.type){case`activate_camera`:{if(typeof e.cameraId!=`string`||!e.cameraId.trim())throw Error(`${t}.cameraId must be a non-empty string`);let n=e.cameraId.trim();if(r.size>0&&!r.has(n))throw Error(`${t}.cameraId references an unknown camera: ${n}`);return{type:`activate_camera`,cameraId:n}}case`set_controls_enabled`:if(typeof e.enabled!=`boolean`)throw Error(`${t}.enabled must be a boolean`);return{type:`set_controls_enabled`,enabled:e.enabled};case`emit_custom_event`:if(typeof e.eventName!=`string`||!e.eventName.trim())throw Error(`${t}.eventName must be a non-empty string`);if(e.payload!==void 0&&!n(e.payload))throw Error(`${t}.payload must be an object when provided`);return{type:`emit_custom_event`,eventName:e.eventName.trim(),payload:e.payload};default:throw Error(`${t}.type must be one of activate_camera, set_controls_enabled, emit_custom_event`)}}function o(e,t={}){if(e===void 0)return;if(!Array.isArray(e))throw Error(`interactions must be an array`);let r=new Set(t.camera?.cameras?.map(e=>e.cameraId?.trim()).filter(e=>!!e)??[]),o=new Set;return e.map((e,t)=>{if(!n(e))throw Error(`interactions[${t}] must be an object`);let s=typeof e.id==`string`&&e.id.trim()?e.id.trim():`interaction-${t+1}`;if(o.has(s))throw Error(`Duplicate interaction id found: ${s}`);o.add(s);let c=typeof e.order==`number`&&Number.isFinite(e.order)?e.order:t+1,l=e.trigger;if(!n(l))throw Error(`interactions[${t}].trigger must be an object`);if(!Array.isArray(e.actions)||e.actions.length===0)throw Error(`interactions[${t}].actions must be a non-empty array`);let u=e.actions;return{id:s,order:c,enabled:e.enabled!==!1,trigger:i(l,`interactions[${t}].trigger`),actions:u.map((e,i)=>{if(!n(e))throw Error(`interactions[${t}].actions[${i}] must be an object`);return a(e,`interactions[${t}].actions[${i}]`,r)})}})}var s={},c={emit(e,t){let n=s[e];console.debug(`Event emitted: ${e}`,t),n&&n.forEach(e=>e(t))},on(e,t){s[e]||(s[e]=[]),s[e].push(t)},off(e,t){let n=s[e];n&&(s[e]=n.filter(e=>e!==t))}},l={file:null,isFileLoading:!1,progress:0,supportedFileTypes:[e.u.gltf,e.u.glb,e.u.usdz]};function u(e,t){switch(t.type){case`set-file`:return{...e,file:t.payload};case`set-file-loading`:return{...e,isFileLoading:t.payload};case`set-progress`:return{...e,progress:t.payload};case`reset-state`:return{...l};default:return e}}async function d(e){let t=[];async function*n(e){let t=e;for await(let[,e]of t)e.kind===`file`?yield await e.getFile():e.kind===`directory`&&(yield*n(e))}for await(let r of n(e))t.push(r);return t}function f(t){let n=[];if(t.assetData&&typeof t.assetData==`object`)for(let[,r]of Object.entries(t.assetData)){let{fileName:t,mimeType:i}=r,a=e.o(r),o=new Uint8Array(a.byteLength);o.set(a);let s=new Blob([o],{type:i}),c=new File([s],t,{type:i});n.push(c)}let r=JSON.stringify(t.gltfJson),i=new Blob([r],{type:`model/gltf+json`}),a=t.meta?.name,o=a?`${a}.gltf`:`scene.gltf`;return[new File([i],o,{type:`model/gltf+json`}),...n]}var p=(t,n)=>{let r=e.a(t),i=r.split(`/`).pop()||r;for(let t of n){let n=e.n(t.fileName);if(n.has(r)||n.has(i))return t.size}return 0},m=e=>{let t=new Set,n=new Set,r=e,i=Array.isArray(r.images)?r.images:[];for(let e of i)typeof e.uri==`string`&&!e.uri.startsWith(`data:`)&&n.add(e.uri);let a=Array.isArray(r.buffers)?r.buffers:[];for(let e of a)typeof e.uri==`string`&&!e.uri.startsWith(`data:`)&&t.add(e.uri);return{bufferUris:t,imageUris:n}};async function h(e,t){let n=await e.text(),r;try{r=JSON.parse(n)}catch{return{sourcePackageBytes:e.size,textureBytes:0}}let i=t.map(e=>({fileName:e.name,size:e.size})),{bufferUris:a,imageUris:o}=m(r),s=Array.from(a).reduce((e,t)=>e+p(t,i),0),c=Array.from(o).reduce((e,t)=>e+p(t,i),0);return{sourcePackageBytes:e.size+s+c,textureBytes:c}}function g(t){let n=t.gltfJson,r=Object.values(t.assetData||{}).map(t=>({fileName:t.fileName,size:e.r(t.data)})),i=new TextEncoder().encode(JSON.stringify(n)).byteLength,{bufferUris:a,imageUris:o}=m(n),s=Array.from(a).reduce((e,t)=>e+p(t,r),0),c=Array.from(o).reduce((e,t)=>e+p(t,r),0);return{sourcePackageBytes:i+s+c,textureBytes:c}}function _(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function v(t){let n=_(t.settings)?t.settings:{},r=e.s(t.camera??n.camera);return{...n,bounds:t.bounds??n.bounds,camera:r,interactions:o(n.interactions,{camera:r}),controls:t.controls??n.controls,environment:t.environment??n.environment,shadows:t.shadows??n.shadows}}function y(e){let t=new Set,n=e,r=Array.isArray(n.images)?n.images:[];for(let e of r)typeof e.uri==`string`&&!e.uri.startsWith(`data:`)&&t.add(e.uri);let i=Array.isArray(n.buffers)?n.buffers:[];for(let e of i)typeof e.uri==`string`&&!e.uri.startsWith(`data:`)&&t.add(e.uri);return t}function b(t){for(let[n,r]of Object.entries(t)){if(!r||typeof r!=`object`)throw Error(`Scene payload contains invalid asset entry for ${n}`);if(typeof r.fileName!=`string`||r.fileName.trim().length===0)throw Error(`Scene payload asset ${n} is missing a valid fileName`);if(typeof r.mimeType!=`string`||r.mimeType.trim().length===0)throw Error(`Scene payload asset ${n} is missing a valid mimeType`);if(typeof r.data==`string`&&r.encoding===`base64`&&!e.i(r.data))throw Error(`Scene payload asset ${r.fileName} has invalid base64 data`)}}function x(t,n){let r=y(t);if(r.size===0)return;let i=new Set;for(let t of Object.values(n))for(let n of e.n(t.fileName))i.add(n);let a=[];for(let t of r){let n=e.a(t),r=n.split(`/`).pop()||n;!i.has(t)&&!i.has(n)&&!i.has(r)&&a.push(t)}if(a.length>0)throw Error(`Scene payload is missing required referenced assets: ${a.slice(0,5).join(`, `)}`)}function S(e){if(!_(e.gltfJson))throw Error(`Scene payload is missing a valid glTF document`);let t=e.assetData??{};return b(t),x(e.gltfJson,t),{meta:e.meta,gltfJson:e.gltfJson,assetData:t,...v(e)}}var C=t=>{try{return e.a(t)}catch{return t}},w=e=>{let t=new Set,n=e,r=Array.isArray(n.images)?n.images:[];for(let e of r)typeof e.uri==`string`&&!e.uri.startsWith(`data:`)&&t.add(e.uri);let i=Array.isArray(n.buffers)?n.buffers:[];for(let e of i)typeof e.uri==`string`&&!e.uri.startsWith(`data:`)&&t.add(e.uri);return t},T=async(t,n)=>{let r=JSON.parse(await t.text()),i=w(r),a={},o=new Map,s=new Map,c=new Set,l=async e=>{let t=s.get(e);if(t)return t;let n=new Uint8Array(await e.arrayBuffer());return s.set(e,n),n};for(let t of n){for(let n of e.n(t.name))o.set(n,t);if(t.webkitRelativePath)for(let n of e.n(t.webkitRelativePath))o.set(n,t)}let u=[];for(let e of i){let t=C(e),n=t.split(`/`).pop()||t,r=o.get(e)||o.get(t)||o.get(n);if(!r){u.push(e);continue}c.add(r);let i=await l(r);a[t]={data:Array.from(i),fileName:t,mimeType:r.type||`application/octet-stream`}}if(u.length>0)throw Error(`Scene payload is missing required referenced assets: ${u.slice(0,5).join(`, `)}`);for(let[e,t]of n.entries()){if(c.has(t))continue;let n=C(t.name),r=n.split(`/`).pop()||n,i=await l(t);a[`extra-${e}-${r}`]={data:Array.from(i),fileName:r,mimeType:t.type||`application/octet-stream`}}return{gltfJson:r,assetData:a}};function E(n){let r=(0,t.useRef)(!1),i=(0,t.useRef)(null),[a,o]=(0,t.useReducer)(u,l),s=(0,t.useMemo)(()=>{let t=new e.l;return t.onProgress(e=>{o({type:`set-progress`,payload:e.progress}),e.progress!==100&&c.emit(`load-progress`,e.progress)}),t},[]),p=(0,t.useCallback)((e,t)=>e.find(e=>e.name.endsWith(`.`+t)),[]),m=(0,t.useCallback)(e=>{o({type:`set-progress`,payload:e}),c.emit(`load-progress`,e)},[]),_=(0,t.useCallback)(()=>{o({type:`reset-state`}),c.emit(`load-reset`)},[]),v=(0,t.useCallback)(async(e,t)=>{try{let r=await s.loadToThreeJS(e),a={model:r.scene,type:t,name:e.name};o({type:`set-file`,payload:a}),i.current=a,o({type:`set-file-loading`,payload:!1}),n&&await n.load(r.scene)}catch(e){console.error(`Error loading binary model:`,e),o({type:`set-file-loading`,payload:!1}),c.emit(`load-error`,e)}},[s,n]),y=(0,t.useCallback)(async(t,r)=>{try{let{sourcePackageBytes:a,textureBytes:c}=await h(t,r),l=await s.loadGLTFWithAssetsToThreeJS(t,r),u={model:l.scene,type:e.u.gltf,name:t.name,sourcePackageBytes:a,sourceTextureBytes:c};if(o({type:`set-file`,payload:u}),o({type:`set-file-loading`,payload:!1}),i.current=u,n)try{let e=await T(t,r);await n.loadFromServerSceneData(e)}catch(e){console.warn(`Failed to initialize optimizer from source GLTF payload; falling back to scene import.`,e),await n.load(l.scene)}}catch(e){console.error(`Error loading GLTF model:`,e),console.error(`GLTF file:`,t.name),console.error(`Asset files:`,r.map(e=>e.name)),o({type:`set-file-loading`,payload:!1}),c.emit(`load-error`,e)}},[s,n]),b=(0,t.useCallback)(async t=>{if(t.length===0)return;let n=p(t,e.u.gltf),a=p(t,e.u.glb),s=p(t,e.u.usdz),l=[n,a,s].filter(Boolean);if(l.length>1){c.emit(`multiple-models`,l);return}let u=t.filter(e=>e!==n&&e!==a&&e!==s),d=()=>{r.current=!0,i.current&&(c.emit(`load-complete`,i.current),r.current=!1)};if(n)await y(n,u),d();else if(a)await v(a,e.u.glb),d();else if(s)await v(s,e.u.usdz),d();else{c.emit(`not-loaded-files`,t),o({type:`set-file-loading`,payload:!1});return}},[p,y,v]),x=(0,t.useCallback)(async e=>{let t=[];c.emit(`load-start`),o({type:`reset-state`}),o({type:`set-file-loading`,payload:!0}),m(0),r.current=!1;for(let n of e)if(n instanceof File)t.push(n);else if(`kind`in n&&n.kind===`directory`){let e=await d(n);t.push(...e)}await b(t)},[b,m]),C=(0,t.useCallback)(async t=>{let{sceneData:r,sceneId:a}=t;m(40);let c=f(r),{sourcePackageBytes:l,textureBytes:u}=g(r);m(60);let d=c[0],p=c.slice(1),h={model:(await s.loadGLTFWithAssetsToThreeJS(d,p)).scene,type:e.u.gltf,name:d.name,sourcePackageBytes:l,sourceTextureBytes:u};return o({type:`set-file`,payload:h}),o({type:`set-file-loading`,payload:!1}),i.current=h,n&&await n.loadFromServerSceneData(r),m(100),{file:h,sceneId:a,...r}},[s,n,m]),w=(0,t.useCallback)(async t=>{let{sceneId:n,serverOptions:r}=t;try{c.emit(`server-load-start`,n),o({type:`reset-state`}),o({type:`set-file-loading`,payload:!0}),m(0);let t=await C({sceneId:n,sceneData:S(await e.t.loadScene(n,r))});return c.emit(`server-load-complete`,t),t}catch(e){throw console.error(`Server scene loading failed:`,e),o({type:`set-file-loading`,payload:!1}),c.emit(`server-load-error`,e),e}},[C,m]),E=D(n,o,a.file,s);return{...a,on:c.on,off:c.off,load:x,loadFromData:C,loadFromServer:w,reset:_,optimizer:E}}function D(n,r,i,a){let o=(0,t.useCallback)(async(t,o)=>{if(!n){console.warn(`Optimizer is not available`);return}try{t&&await t(o);let s=await n.getModel();if(!s){console.warn(`No optimized model available after optimization`);return}let c=s instanceof Uint8Array?s.slice():new Uint8Array(s).slice(),l=new File([c],i?.name||`optimized_model.glb`,{type:`model/gltf-binary`});r({type:`set-file`,payload:{model:(await a.loadToThreeJS(l)).scene,type:e.u.glb,name:l.name}})}catch(e){console.error(`Optimization failed:`,e)}},[n,a,i,r]);if(!n)return null;let s=n.isReady,c=!!i?.model&&!s;return{...n,isReady:s,isPreparing:c,applyOptimization:o,reset:n?.reset,error:n?.error,loading:n?.loading}}Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return E}});
@@ -1,8 +0,0 @@
1
- /**
2
- * Validates that the response contains the expected content type.
3
- */
4
- export declare const validateResponseContentType: (response: Response) => void;
5
- /**
6
- * Validates a server response and throws appropriate errors.
7
- */
8
- export declare const validateServerResponse: (response: Response) => Promise<void>;
@@ -1 +0,0 @@
1
- require(`./chunk-gGpyby2o.cjs`);const e=require(`./server-communication-yXZR8eso.cjs`);let t=require(`react`);var n={info:null,error:null,loading:!1,report:null},r=(e,t)=>{switch(t.type){case`LOAD_START`:return{...e,loading:!0,error:null};case`LOAD_SUCCESS`:return{...e,loading:!1,report:t.payload.report};case`LOAD_ERROR`:return{...e,loading:!1,error:t.payload};case`RESET`:return{...n};default:return e}};function i(e){return e?{verticesCount:e.stats.vertices.after??0,primitivesCount:e.stats.triangles.after??0,meshesCount:e.stats.meshes.after??0,textureAssetCount:e.stats.texturesCount.after??0,materialsCount:e.stats.materials.after??0,sceneBytes:e.optimizedSize??0}:{verticesCount:0,primitivesCount:0,meshesCount:0,textureAssetCount:0,materialsCount:0,sceneBytes:0}}var a=e=>{let n=(0,t.useRef)(null),[r,a]=(0,t.useState)(!1),o=e.report;return(0,t.useEffect)(()=>{!r&&o&&(n.current=o,a(!0))},[r,o]),{info:(0,t.useMemo)(()=>{let e=i(n.current),t=i(o);return{initial:{verticesCount:e.verticesCount,primitivesCount:e.primitivesCount,meshesCount:e.meshesCount,texturesCount:e.textureAssetCount,sceneBytes:e.sceneBytes},optimized:{verticesCount:t.verticesCount,primitivesCount:t.primitivesCount,meshesCount:t.meshesCount,texturesCount:t.textureAssetCount,sceneBytes:t.sceneBytes},improvement:{verticesCount:e.verticesCount-t.verticesCount,primitivesCount:e.primitivesCount-t.primitivesCount,meshesCount:e.meshesCount-t.meshesCount,texturesCount:e.textureAssetCount-t.textureAssetCount,sceneBytes:e.sceneBytes-t.sceneBytes}}},[o]),reset:(0,t.useCallback)(()=>{n.current=null,a(!1)},[])}},o=e=>{let t=e.headers.get(`content-type`);if(!t)throw Error(`Missing content type from server response`);if(t.includes(`application/json`))throw Error(`Unexpected JSON success response from texture optimizer`);if(!t.startsWith(`image/`)&&!t.includes(`application/octet-stream`))throw Error(`Unexpected content type from server: ${t}`)},s=async e=>{if(e.ok){if(e.headers.get(`content-type`)?.includes(`application/json`)){let t=await e.json();throw Error(t.error||t.details||`Server returned error`)}o(e)}},c=2e4,l=2,u=50*1024*1024,d=4,f=new Set([408,425,429,500,502,503,504]),p=async e=>{await new Promise(t=>setTimeout(t,e))},m=e=>{let t=e.headers.get(`content-type`);return t&&t.split(`;`)[0]?.trim()||`application/octet-stream`},h=e=>{let t=e.headers.get(`X-Texture-File-Name`)||e.headers.get(`X-Texture-Name`);if(!t||t.trim().length===0)throw Error(`Optimized texture response is missing a canonical file name`);return t.trim()},g=async(e,t,n,r,i)=>{let a=0;for(;;){let o=new AbortController,s=setTimeout(()=>o.abort(),r);try{let r=await fetch(e,{method:`POST`,headers:t,body:n,signal:o.signal});if(!r.ok&&f.has(r.status)&&a<i){a+=1,await p(200*a+Math.floor(Math.random()*120));continue}return r}catch(e){if(a>=i)throw e;a+=1,await p(200*a+Math.floor(Math.random()*120))}finally{clearTimeout(s)}}},_=async(t,n,r,i)=>{let a=t.getTexturePayload(n.index),o=r.maxTextureUploadBytes??u;if(a.image.byteLength>o)throw Error(`Texture ${n.index} payload (${a.image.byteLength} bytes) exceeds maxTextureUploadBytes (${o} bytes). Increase maxTextureUploadBytes to allow optimizing larger source textures.`);let d=new Uint8Array(a.image.byteLength);d.set(a.image);let f=d.buffer,{serverOptions:p,..._}=r,v=e.t.createRequestHeaders(i,{"Content-Type":`application/octet-stream`,"X-Texture-Index":String(n.index),"X-Texture-Name":a.fileName,"X-Texture-File-Name":a.fileName,"X-Texture-Mime-Type":a.mimeType,"X-Optimize-Options":JSON.stringify(_)}),y=await g(i.endpoint,v,f,r.requestTimeoutMs??c,r.maxRetries??l);y.ok||await e.t.handleServerResponseError(y),await s(y);let b=Number.parseInt(y.headers.get(`X-Texture-Index`)||``,10);if(!Number.isFinite(b)||b!==n.index)throw Error(`Texture identity mismatch. Expected ${n.index}, received ${y.headers.get(`X-Texture-Index`)}`);let x=new Uint8Array(await y.arrayBuffer());if(x.byteLength===0)throw Error(`Empty optimized payload for texture ${n.index}`);let S=h(y);t.replaceTexturePayload(n.index,x,m(y),S)},v=async(t,n)=>{let r=e.t.createDefaultServerOptions(n.serverOptions),i=t.listTextureDescriptors(),a=[],o=0,s=n.maxConcurrentRequests??d;try{for(let e=0;e<i.length;e+=s){let c=i.slice(e,e+s),l=await Promise.allSettled(c.map(async e=>(await _(t,e,n,r),e.index)));for(let[e,t]of l.entries()){if(t.status===`fulfilled`){o+=1;continue}a.push({index:c[e].index,reason:t.reason instanceof Error?t.reason.message:String(t.reason)})}}if(o>0&&t.addAppliedOptimization(`texture compression`),a.length>0){let e=a.map(e=>`#${e.index}: ${e.reason}`).join(`; `),t=o===0?`Texture optimization failed for all textures.`:`Texture optimization failed for ${a.length} of ${i.length} textures.`;throw Error(`${t} ${e}`)}}catch(e){throw console.error(`Server-side texture compression failed:`,e),Error(`Server-side texture compression failed: ${e}. Client-side texture compression is not supported in browser environments.`,{cause:e})}},y=()=>{throw console.warn(`Client-side texture compression is not supported in browser environments. Please enable server-side compression by setting serverOptions.enabled = true.`),Error(`Texture compression requires server-side processing. Enable serverOptions.enabled = true in your options.`)},b=e=>e?.serverOptions?.enabled??!1,x=async(e,t)=>{e.hasModel()&&(b(t)&&t?await v(e,t):y())},S=()=>{let[i,o]=(0,t.useReducer)(r,n),{report:s,error:c,loading:l}=i,{info:u,reset:d}=a(i),f=(0,t.useRef)(new e.c);(0,t.useEffect)(()=>{let e=f.current;return()=>{e.reset()}},[]);let p=(0,t.useCallback)(async e=>{o({type:`LOAD_START`});try{let t=f.current;await t.loadFromThreeJS(e),o({type:`LOAD_SUCCESS`,payload:{report:await t.getReport()}})}catch(e){o({type:`LOAD_ERROR`,payload:e}),console.error(`Error loading model:`,e)}},[]),m=(0,t.useCallback)(async t=>{o({type:`LOAD_START`});try{let n=f.current,r={};for(let n of Object.values(t.assetData??{}))r[n.fileName]=e.o(n);let i={json:t.gltfJson,resources:r};await n.loadFromJSON(i),o({type:`LOAD_SUCCESS`,payload:{report:await n.getReport()}})}catch(e){throw o({type:`LOAD_ERROR`,payload:e}),console.error(`Error loading server scene into optimizer:`,e),e}},[]),h=(0,t.useCallback)(async e=>{if(f.current.hasModel())try{await f.current.simplify(e),o({type:`LOAD_SUCCESS`,payload:{report:await f.current.getReport()}})}catch(e){console.error(`Simplification failed:`,e)}},[]),g=(0,t.useCallback)(async e=>{if(f.current.hasModel())try{await f.current.deduplicate(e),o({type:`LOAD_SUCCESS`,payload:{report:await f.current.getReport()}})}catch(e){console.error(`Deduplication failed:`,e)}},[]),_=(0,t.useCallback)(async e=>{if(f.current.hasModel())try{await f.current.quantize(e),o({type:`LOAD_SUCCESS`,payload:{report:await f.current.getReport()}})}catch(e){console.error(`Quantization failed:`,e)}},[]),v=(0,t.useCallback)(async e=>{if(f.current.hasModel())try{await f.current.optimizeNormals(e),o({type:`LOAD_SUCCESS`,payload:{report:await f.current.getReport()}})}catch(e){console.error(`Normals optimization failed:`,e)}},[]),y=(0,t.useCallback)(async e=>{try{await x(f.current,e),o({type:`LOAD_SUCCESS`,payload:{report:await f.current.getReport()}})}catch(e){throw console.error(`Texture optimization failed:`,e),e}},[]),b=(0,t.useCallback)(async()=>{if(!f.current.hasModel())return null;try{return await f.current.export()}catch(e){return console.error(`Error getting model binary:`,e),null}},[]),S=(0,t.useCallback)(()=>f.current.hasModel()?f.current.document:null,[]);return{load:p,loadFromServerSceneData:m,getModel:b,isReady:!!S()&&!l,_getDocument:S,reset:(0,t.useCallback)(()=>{f.current.reset(),o({type:`RESET`}),d()},[d]),error:c,loading:l,report:s,info:u,simplifyOptimization:h,dedupOptimization:g,quantizeOptimization:_,normalsOptimization:v,texturesOptimization:y}};Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return S}});