@vctrl/hooks 0.16.2 → 0.17.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 (76) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/GLTFLoader-CygFefRr.cjs +1 -0
  3. package/GLTFLoader-NiJ7qzh1.js +1381 -0
  4. package/README.md +0 -20
  5. package/__vite-browser-external-Bn_csQuM.js +7 -0
  6. package/__vite-browser-external-CVmj8TrW.cjs +1 -0
  7. package/chunk-foFoljWS.js +23 -0
  8. package/chunk-gGpyby2o.cjs +1 -0
  9. package/index.cjs.js +1 -0
  10. package/index.d.ts +5 -0
  11. package/index.es.js +4 -0
  12. package/lib-DKn2MJ9X.js +4111 -0
  13. package/lib-DZ-MihdJ.cjs +2 -0
  14. package/model-exporter-SMSAY90N.cjs +1 -0
  15. package/model-exporter-cvguDGnn.js +6512 -0
  16. package/package.json +1 -1
  17. package/server-communication-Bj6ZxFw2.js +4659 -0
  18. package/server-communication-yXZR8eso.cjs +18 -0
  19. package/use-export-model/use-export-model.d.ts +14 -0
  20. package/use-export-model-CaijtW1c.cjs +1 -0
  21. package/use-export-model-DzVKdqnY.js +49 -0
  22. package/use-export-model.cjs.js +1 -0
  23. package/use-export-model.es.js +2 -0
  24. package/use-load-model/event-system.d.ts +7 -0
  25. package/use-load-model/index.d.ts +4 -0
  26. package/use-load-model/state.d.ts +19 -0
  27. package/use-load-model/types.d.ts +231 -0
  28. package/use-load-model/use-load-model.d.ts +30 -0
  29. package/use-load-model/utils/calculate-referenced-bytes.d.ts +8 -0
  30. package/use-load-model/utils/index.d.ts +4 -0
  31. package/use-load-model/utils/read-directory.d.ts +8 -0
  32. package/use-load-model/utils/reconstruct-files.d.ts +29 -0
  33. package/use-load-model/utils/resolve-scene-payload.d.ts +6 -0
  34. package/use-load-model-B6UXiFWh.js +517 -0
  35. package/use-load-model-CH-WPQ_s.cjs +1 -0
  36. package/use-load-model.cjs.js +1 -0
  37. package/use-load-model.es.js +18 -0
  38. package/{src/use-optimize-model/index.ts → use-optimize-model/index.d.ts} +2 -2
  39. package/use-optimize-model/state.d.ts +13 -0
  40. package/use-optimize-model/types.d.ts +39 -0
  41. package/use-optimize-model/use-calc-optimization-info.d.ts +6 -0
  42. package/use-optimize-model/use-optimize-model.d.ts +119 -0
  43. package/use-optimize-model/utils/index.d.ts +2 -0
  44. package/use-optimize-model/utils/texture-optimization.d.ts +17 -0
  45. package/use-optimize-model/utils/validation.d.ts +8 -0
  46. package/use-optimize-model-C-fzzKh6.cjs +1 -0
  47. package/use-optimize-model-Cb3WMvDZ.js +299 -0
  48. package/use-optimize-model.cjs.js +1 -0
  49. package/use-optimize-model.es.js +2 -0
  50. package/utils/server-communication.d.ts +122 -0
  51. package/project.json +0 -55
  52. package/src/index.ts +0 -38
  53. package/src/use-export-model/use-export-model.ts +0 -113
  54. package/src/use-load-model/event-system.ts +0 -46
  55. package/src/use-load-model/index.ts +0 -15
  56. package/src/use-load-model/model-context.tsx +0 -174
  57. package/src/use-load-model/state.ts +0 -75
  58. package/src/use-load-model/types.ts +0 -284
  59. package/src/use-load-model/use-load-model.ts +0 -682
  60. package/src/use-load-model/utils/calculate-referenced-bytes.ts +0 -123
  61. package/src/use-load-model/utils/index.ts +0 -7
  62. package/src/use-load-model/utils/read-directory.ts +0 -35
  63. package/src/use-load-model/utils/reconstruct-files.ts +0 -85
  64. package/src/use-load-model/utils/resolve-scene-payload.ts +0 -151
  65. package/src/use-optimize-model/state.ts +0 -40
  66. package/src/use-optimize-model/types.ts +0 -37
  67. package/src/use-optimize-model/use-calc-optimization-info.ts +0 -101
  68. package/src/use-optimize-model/use-optimize-model.ts +0 -467
  69. package/src/use-optimize-model/utils/index.ts +0 -29
  70. package/src/use-optimize-model/utils/texture-optimization.ts +0 -292
  71. package/src/use-optimize-model/utils/validation.ts +0 -62
  72. package/src/utils/server-communication.ts +0 -351
  73. package/tsconfig.json +0 -21
  74. package/tsconfig.lib.json +0 -16
  75. package/vite.config.ts +0 -77
  76. /package/{src/use-export-model/index.ts → use-export-model/index.d.ts} +0 -0
@@ -0,0 +1,517 @@
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 };
@@ -0,0 +1 @@
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}});
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./chunk-gGpyby2o.cjs`),t=require(`./use-load-model-CH-WPQ_s.cjs`);let n=require(`react`);n=e.a(n,1);let r=require(`react/jsx-runtime`);var i=(0,n.createContext)(void 0),a=(0,n.createContext)(void 0),o=({children:e,optimizer:n})=>{let o=t.t(n);return n?(0,r.jsx)(i.Provider,{value:o,children:e}):(0,r.jsx)(a.Provider,{value:o,children:e})};function s(e){let t=(0,n.useContext)(i),r=(0,n.useContext)(a),o=t??r;if(!o)throw Error(`useModelContext must be used within a ModelProvider`);return o}exports.ModelProvider=o,exports.reconstructGltfFiles=t.n,exports.useLoadModel=t.t,exports.useModelContext=s;
@@ -0,0 +1,18 @@
1
+ import { n as e, t } from "./use-load-model-B6UXiFWh.js";
2
+ import { createContext as n, useContext as r } from "react";
3
+ import { jsx as i } from "react/jsx-runtime";
4
+ //#region packages/hooks/src/use-load-model/model-context.tsx
5
+ var a = n(void 0), o = n(void 0), s = ({ children: e, optimizer: n }) => {
6
+ let r = t(n);
7
+ return i(n ? a.Provider : o.Provider, {
8
+ value: r,
9
+ children: e
10
+ });
11
+ };
12
+ function c(e) {
13
+ let t = r(a), n = r(o), i = t ?? n;
14
+ if (!i) throw Error("useModelContext must be used within a ModelProvider");
15
+ return i;
16
+ }
17
+ //#endregion
18
+ export { s as ModelProvider, e as reconstructGltfFiles, t as useLoadModel, c as useModelContext };
@@ -1,2 +1,2 @@
1
- export { default as useOptimizeModel } from './use-optimize-model'
2
- export * from './types'
1
+ export { default as useOptimizeModel } from './use-optimize-model';
2
+ export * from './types';
@@ -0,0 +1,13 @@
1
+ import { Action, OptimizationState } from './types';
2
+ /**
3
+ * Initial state for the reducer.
4
+ */
5
+ export declare const initialState: OptimizationState;
6
+ /**
7
+ * Reducer function to manage state transitions.
8
+ *
9
+ * @param state - Current state.
10
+ * @param action - Action to perform.
11
+ * @returns New state after applying the action.
12
+ */
13
+ export declare const reducer: (state: OptimizationState, action: Action) => OptimizationState;
@@ -0,0 +1,39 @@
1
+ import { OptimizationReport } from '../../../core/src/model-optimizer/index.ts';
2
+ interface ModelTotals {
3
+ verticesCount: number;
4
+ primitivesCount: number;
5
+ texturesCount: number;
6
+ meshesCount: number;
7
+ sceneBytes: number;
8
+ }
9
+ export interface OptimizationInfo {
10
+ initial: ModelTotals;
11
+ optimized: ModelTotals;
12
+ improvement: ModelTotals;
13
+ }
14
+ /**
15
+ * Interface representing the state of the model optimizer.
16
+ */
17
+ export interface OptimizationState {
18
+ report: OptimizationReport | null;
19
+ info: OptimizationInfo | null;
20
+ error: Error | null;
21
+ loading: boolean;
22
+ }
23
+ /**
24
+ * Types of actions for the reducer.
25
+ */
26
+ export type Action = {
27
+ type: 'LOAD_START';
28
+ } | {
29
+ type: 'LOAD_SUCCESS';
30
+ payload: {
31
+ report: OptimizationReport;
32
+ };
33
+ } | {
34
+ type: 'LOAD_ERROR';
35
+ payload: Error;
36
+ } | {
37
+ type: 'RESET';
38
+ };
39
+ export {};
@@ -0,0 +1,6 @@
1
+ import { OptimizationInfo, OptimizationState } from './types';
2
+ export interface OptimizationInfoData {
3
+ info: OptimizationInfo;
4
+ reset: () => void;
5
+ }
6
+ export declare const useCalcOptimizationInfo: (state: OptimizationState) => OptimizationInfoData;