@vctrl/hooks 0.25.0 → 0.25.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.25.1](https://github.com/Vectreal/vectreal-platform/compare/hooks-v0.25.0...hooks-v0.25.1) (2026-08-08)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **core:** keep the pristine baseline when syncing the worker's output ([a2e5654](https://github.com/Vectreal/vectreal-platform/commit/a2e5654f6a2acd8dc95cb2e9dace3c32436fc826))
9
+ * **publisher:** stale scene state across navigation and nonsensical optimization stats ([4152ab1](https://github.com/Vectreal/vectreal-platform/commit/4152ab146770f86930a53b892900978a163ae167))
10
+
11
+
12
+ ### Dependencies
13
+
14
+ * The following workspace dependencies were updated
15
+ * dependencies
16
+ * @vctrl/core bumped to 0.25.1
17
+
3
18
  ## [0.25.0](https://github.com/Vectreal/vectreal-platform/compare/hooks-v0.24.1...hooks-v0.25.0) (2026-08-04)
4
19
 
5
20
 
package/index.cjs.js CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./use-load-model-B8oqou4I.cjs"),t=require("./use-export-model-yQWV3O3H.cjs"),n=require("./use-optimize-model-CD5zqTLK.cjs");exports.reconstructGltfFiles=e.r,exports.useExportModel=t.t,exports.useLoadModel=e.t,exports.useOptimizeModel=n.t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./use-load-model-B8oqou4I.cjs"),t=require("./use-export-model-yQWV3O3H.cjs"),n=require("./use-optimize-model-YAGNlhUN.cjs");exports.reconstructGltfFiles=e.r,exports.useExportModel=t.t,exports.useLoadModel=e.t,exports.useOptimizeModel=n.t;
package/index.es.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import { r as e, t } from "./use-load-model-C88r8-HE.js";
2
2
  import { t as n } from "./use-export-model-efFsSWe-.js";
3
- import { t as r } from "./use-optimize-model-D16-4Zwm.js";
3
+ import { t as r } from "./use-optimize-model-BCyM6An0.js";
4
4
  export { e as reconstructGltfFiles, n as useExportModel, t as useLoadModel, r as useOptimizeModel };
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.25.0",
2
+ "version": "0.25.1",
3
3
  "name": "@vctrl/hooks",
4
4
  "description": "vctrl/hooks is a React hooks package designed to simplify 3D model loading and management within React applications. It's part of the vectreal-core ecosystem and is primarily used in the vctrl/viewer React component and the official website application.",
5
5
  "bugs": {
@@ -62,7 +62,7 @@
62
62
  "three": "^0.177.0"
63
63
  },
64
64
  "dependencies": {
65
- "@vctrl/core": "^0.25.0",
65
+ "@vctrl/core": "^0.25.1",
66
66
  "file-saver": "^2.0.5"
67
67
  }
68
68
  }
@@ -47,7 +47,9 @@ declare const useOptimizeModel: () => {
47
47
  */
48
48
  load: (model: Object3D) => Promise<void>;
49
49
  loadFromServerSceneData: (sceneData: ServerSceneData) => Promise<void>;
50
- loadFromGlbBuffer: (buffer: Uint8Array, meta?: WorkerResultMeta) => Promise<void>;
50
+ loadFromGlbBuffer: (buffer: Uint8Array, meta?: WorkerResultMeta, options?: {
51
+ preserveBaseline?: boolean;
52
+ }) => Promise<void>;
51
53
  loadFromGLTFWithAssets: (gltfBytes: Uint8Array, assets: Map<string, Uint8Array>) => Promise<void>;
52
54
  /**
53
55
  * Retrieves the current model as a binary Uint8Array in glTF (.glb) format.
@@ -191,10 +191,11 @@ var g = async (e, t) => {
191
191
  payload: e
192
192
  }), console.error("Error loading server scene into optimizer:", e), e;
193
193
  }
194
- }, []), S = r(async (e, t) => {
194
+ }, []), S = r(async (e, t, n) => {
195
195
  c({ type: "LOAD_START" });
196
196
  try {
197
- await y.current.loadFromBuffer(e), y.current.setAppliedOptimizations(t?.appliedOptimizations ?? []), y.current.setDracoReport(t?.dracoReport ?? null), c({
197
+ let r = n?.preserveBaseline ? y.current.getBaseline() : null;
198
+ await y.current.loadFromBuffer(e), r && y.current.setBaseline(r), y.current.setAppliedOptimizations(t?.appliedOptimizations ?? []), y.current.setDracoReport(t?.dracoReport ?? null), c({
198
199
  type: "LOAD_SUCCESS",
199
200
  payload: { report: await y.current.getReport() }
200
201
  });
@@ -1 +1 @@
1
- let e=require("@vctrl/core"),t=require("react"),n=require("@vctrl/core/model-optimizer");var r={info:null,error:null,loading:!1,report:null},i=(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{...r};default:return e}};function a(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 o=e=>{let[n,r]=(0,t.useState)(null),i=e.report;return(0,t.useEffect)(()=>{!n&&i&&r(i)},[n,i]),{info:(0,t.useMemo)(()=>{let e=a(n),t=a(i);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}}},[i,n]),reset:(0,t.useCallback)(()=>{r(null)},[])}};async function s(e,t){let n=new Blob([e]),r=await createImageBitmap(n),{width:i,height:a}=r;if(t.maxWidth||t.maxHeight){let e=t.maxWidth?t.maxWidth/i:1/0,n=t.maxHeight?t.maxHeight/a:1/0,r=Math.min(e,n,1);r<1&&(i=Math.round(i*r),a=Math.round(a*r))}let o=new OffscreenCanvas(i,a),s=o.getContext(`2d`);if(!s)throw r.close(),Error(`OffscreenCanvas 2D context unavailable`);s.drawImage(r,0,0,i,a),r.close();let c=t.format===`webp`?`image/webp`:t.format===`jpeg`?`image/jpeg`:`image/png`,l=await o.convertToBlob({type:c,quality:t.quality/100});return new Uint8Array(await l.arrayBuffer())}function c(){return function(e){let t=e instanceof Uint8Array?e:new Uint8Array(e),n=`webp`,r=80,i,a,o={resize(e,t,n){return i=e,a=t,o},webp(e){return n=`webp`,typeof e?.quality==`number`&&(r=e.quality),o},jpeg(e){return n=`jpeg`,typeof e?.quality==`number`&&(r=e.quality),o},png(e){return n=`png`,o},toFormat(e,t){return(e===`webp`||e===`jpeg`||e===`png`)&&(n=e),typeof t?.quality==`number`&&(r=t.quality),o},async toBuffer(){return s(t,{format:n,quality:r,maxWidth:i,maxHeight:a})},async metadata(){let e=new Blob([t]),n=await createImageBitmap(e),r={width:n.width,height:n.height,format:`unknown`};return n.close(),r}};return o}}var l=async(e,t)=>{e.hasModel()&&await e.compressTextures({...t,encoder:c()})},u=()=>{let[a,s]=(0,t.useReducer)(i,r),{report:c,error:u,loading:d}=a,{info:f,reset:p}=o(a),m=(0,t.useRef)(new n.ModelOptimizer);(0,t.useEffect)(()=>{let e=m.current;return()=>{e.reset()}},[]);let h=(0,t.useCallback)(async e=>{s({type:`LOAD_START`});try{let t=m.current;await t.loadFromThreeJS(e),s({type:`LOAD_SUCCESS`,payload:{report:await t.getReport()}})}catch(e){s({type:`LOAD_ERROR`,payload:e}),console.error(`Error loading model:`,e)}},[]),g=(0,t.useCallback)(async t=>{s({type:`LOAD_START`});try{let n=m.current,r=new Map;for(let n of Object.values(t.assetData??{}))for(let t of(0,e.buildAssetLookupKeys)(n.fileName))r.set(t,n);let i={},a=t.gltfJson,o=[...(a.images??[]).map(e=>e.uri).filter(e=>!!e&&!e.startsWith(`data:`)),...(a.buffers??[]).map(e=>e.uri).filter(e=>!!e&&!e.startsWith(`data:`))];for(let t of o){let n=(0,e.normalizeAssetUri)(t),a=n.split(`/`).pop()||n,o=r.get(t)??r.get(n)??r.get(a);o&&(i[t]=(0,e.toSerializedAssetBytes)(o))}let c={json:t.gltfJson,resources:i};await n.loadFromJSON(c),s({type:`LOAD_SUCCESS`,payload:{report:await n.getReport()}})}catch(e){throw s({type:`LOAD_ERROR`,payload:e}),console.error(`Error loading server scene into optimizer:`,e),e}},[]),_=(0,t.useCallback)(async(e,t)=>{s({type:`LOAD_START`});try{await m.current.loadFromBuffer(e),m.current.setAppliedOptimizations(t?.appliedOptimizations??[]),m.current.setDracoReport(t?.dracoReport??null),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){throw s({type:`LOAD_ERROR`,payload:e}),console.error(`Error loading GLB buffer into optimizer:`,e),e}},[]),v=(0,t.useCallback)(async(e,t)=>{s({type:`LOAD_START`});try{await m.current.loadFromGLTFWithAssets(e,t),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){throw s({type:`LOAD_ERROR`,payload:e}),console.error(`Error loading GLTF with assets into optimizer:`,e),e}},[]),y=(0,t.useCallback)(async e=>{if(m.current.hasModel())try{await m.current.simplify(e),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){console.error(`Simplification failed:`,e)}},[]),b=(0,t.useCallback)(async e=>{if(m.current.hasModel())try{await m.current.deduplicate(e),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){console.error(`Deduplication failed:`,e)}},[]),x=(0,t.useCallback)(async e=>{if(m.current.hasModel())try{await m.current.quantize(e),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){console.error(`Quantization failed:`,e)}},[]),S=(0,t.useCallback)(async e=>{if(m.current.hasModel())try{await m.current.optimizeNormals(e),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){console.error(`Normals optimization failed:`,e)}},[]),C=(0,t.useCallback)(async e=>{try{await l(m.current,e),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){throw console.error(`Texture optimization failed:`,e),e}},[]),w=(0,t.useCallback)(async()=>{if(!m.current.hasModel())return null;try{return await m.current.export()}catch(e){return console.error(`Error getting model binary:`,e),null}},[]),T=(0,t.useCallback)(()=>m.current.hasModel()?m.current.document:null,[]);return{load:h,loadFromServerSceneData:g,loadFromGlbBuffer:_,loadFromGLTFWithAssets:v,getModel:w,isReady:!!T()&&!d,_getDocument:T,reset:(0,t.useCallback)(()=>{m.current.reset(),s({type:`RESET`}),p()},[p]),error:u,loading:d,report:c,info:f,simplifyOptimization:y,dedupOptimization:b,quantizeOptimization:x,normalsOptimization:S,texturesOptimization:C}};Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return u}});
1
+ let e=require("@vctrl/core"),t=require("react"),n=require("@vctrl/core/model-optimizer");var r={info:null,error:null,loading:!1,report:null},i=(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{...r};default:return e}};function a(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 o=e=>{let[n,r]=(0,t.useState)(null),i=e.report;return(0,t.useEffect)(()=>{!n&&i&&r(i)},[n,i]),{info:(0,t.useMemo)(()=>{let e=a(n),t=a(i);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}}},[i,n]),reset:(0,t.useCallback)(()=>{r(null)},[])}};async function s(e,t){let n=new Blob([e]),r=await createImageBitmap(n),{width:i,height:a}=r;if(t.maxWidth||t.maxHeight){let e=t.maxWidth?t.maxWidth/i:1/0,n=t.maxHeight?t.maxHeight/a:1/0,r=Math.min(e,n,1);r<1&&(i=Math.round(i*r),a=Math.round(a*r))}let o=new OffscreenCanvas(i,a),s=o.getContext(`2d`);if(!s)throw r.close(),Error(`OffscreenCanvas 2D context unavailable`);s.drawImage(r,0,0,i,a),r.close();let c=t.format===`webp`?`image/webp`:t.format===`jpeg`?`image/jpeg`:`image/png`,l=await o.convertToBlob({type:c,quality:t.quality/100});return new Uint8Array(await l.arrayBuffer())}function c(){return function(e){let t=e instanceof Uint8Array?e:new Uint8Array(e),n=`webp`,r=80,i,a,o={resize(e,t,n){return i=e,a=t,o},webp(e){return n=`webp`,typeof e?.quality==`number`&&(r=e.quality),o},jpeg(e){return n=`jpeg`,typeof e?.quality==`number`&&(r=e.quality),o},png(e){return n=`png`,o},toFormat(e,t){return(e===`webp`||e===`jpeg`||e===`png`)&&(n=e),typeof t?.quality==`number`&&(r=t.quality),o},async toBuffer(){return s(t,{format:n,quality:r,maxWidth:i,maxHeight:a})},async metadata(){let e=new Blob([t]),n=await createImageBitmap(e),r={width:n.width,height:n.height,format:`unknown`};return n.close(),r}};return o}}var l=async(e,t)=>{e.hasModel()&&await e.compressTextures({...t,encoder:c()})},u=()=>{let[a,s]=(0,t.useReducer)(i,r),{report:c,error:u,loading:d}=a,{info:f,reset:p}=o(a),m=(0,t.useRef)(new n.ModelOptimizer);(0,t.useEffect)(()=>{let e=m.current;return()=>{e.reset()}},[]);let h=(0,t.useCallback)(async e=>{s({type:`LOAD_START`});try{let t=m.current;await t.loadFromThreeJS(e),s({type:`LOAD_SUCCESS`,payload:{report:await t.getReport()}})}catch(e){s({type:`LOAD_ERROR`,payload:e}),console.error(`Error loading model:`,e)}},[]),g=(0,t.useCallback)(async t=>{s({type:`LOAD_START`});try{let n=m.current,r=new Map;for(let n of Object.values(t.assetData??{}))for(let t of(0,e.buildAssetLookupKeys)(n.fileName))r.set(t,n);let i={},a=t.gltfJson,o=[...(a.images??[]).map(e=>e.uri).filter(e=>!!e&&!e.startsWith(`data:`)),...(a.buffers??[]).map(e=>e.uri).filter(e=>!!e&&!e.startsWith(`data:`))];for(let t of o){let n=(0,e.normalizeAssetUri)(t),a=n.split(`/`).pop()||n,o=r.get(t)??r.get(n)??r.get(a);o&&(i[t]=(0,e.toSerializedAssetBytes)(o))}let c={json:t.gltfJson,resources:i};await n.loadFromJSON(c),s({type:`LOAD_SUCCESS`,payload:{report:await n.getReport()}})}catch(e){throw s({type:`LOAD_ERROR`,payload:e}),console.error(`Error loading server scene into optimizer:`,e),e}},[]),_=(0,t.useCallback)(async(e,t,n)=>{s({type:`LOAD_START`});try{let r=n?.preserveBaseline?m.current.getBaseline():null;await m.current.loadFromBuffer(e),r&&m.current.setBaseline(r),m.current.setAppliedOptimizations(t?.appliedOptimizations??[]),m.current.setDracoReport(t?.dracoReport??null),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){throw s({type:`LOAD_ERROR`,payload:e}),console.error(`Error loading GLB buffer into optimizer:`,e),e}},[]),v=(0,t.useCallback)(async(e,t)=>{s({type:`LOAD_START`});try{await m.current.loadFromGLTFWithAssets(e,t),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){throw s({type:`LOAD_ERROR`,payload:e}),console.error(`Error loading GLTF with assets into optimizer:`,e),e}},[]),y=(0,t.useCallback)(async e=>{if(m.current.hasModel())try{await m.current.simplify(e),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){console.error(`Simplification failed:`,e)}},[]),b=(0,t.useCallback)(async e=>{if(m.current.hasModel())try{await m.current.deduplicate(e),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){console.error(`Deduplication failed:`,e)}},[]),x=(0,t.useCallback)(async e=>{if(m.current.hasModel())try{await m.current.quantize(e),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){console.error(`Quantization failed:`,e)}},[]),S=(0,t.useCallback)(async e=>{if(m.current.hasModel())try{await m.current.optimizeNormals(e),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){console.error(`Normals optimization failed:`,e)}},[]),C=(0,t.useCallback)(async e=>{try{await l(m.current,e),s({type:`LOAD_SUCCESS`,payload:{report:await m.current.getReport()}})}catch(e){throw console.error(`Texture optimization failed:`,e),e}},[]),w=(0,t.useCallback)(async()=>{if(!m.current.hasModel())return null;try{return await m.current.export()}catch(e){return console.error(`Error getting model binary:`,e),null}},[]),T=(0,t.useCallback)(()=>m.current.hasModel()?m.current.document:null,[]);return{load:h,loadFromServerSceneData:g,loadFromGlbBuffer:_,loadFromGLTFWithAssets:v,getModel:w,isReady:!!T()&&!d,_getDocument:T,reset:(0,t.useCallback)(()=>{m.current.reset(),s({type:`RESET`}),p()},[p]),error:u,loading:d,report:c,info:f,simplifyOptimization:y,dedupOptimization:b,quantizeOptimization:x,normalsOptimization:S,texturesOptimization:C}};Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return u}});
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./use-optimize-model-CD5zqTLK.cjs");exports.useOptimizeModel=e.t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./use-optimize-model-YAGNlhUN.cjs");exports.useOptimizeModel=e.t;
@@ -1,2 +1,2 @@
1
- import { t as e } from "./use-optimize-model-D16-4Zwm.js";
1
+ import { t as e } from "./use-optimize-model-BCyM6An0.js";
2
2
  export { e as useOptimizeModel };