@liveroom-tech/react-immersive 2.0.0 → 2.1.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.
- package/README.md +37 -4
- package/dist/index.d.mts +24 -3
- package/dist/index.d.ts +24 -3
- package/dist/index.js +82 -42
- package/dist/index.mjs +78 -40
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,10 +12,12 @@ import {
|
|
|
12
12
|
material,
|
|
13
13
|
ModelViewer,
|
|
14
14
|
patchBindings,
|
|
15
|
+
patchSceneConfig,
|
|
15
16
|
SimpleModelViewer,
|
|
16
17
|
useObjectBinding,
|
|
17
18
|
useObjectBindingIds,
|
|
18
19
|
useObjectBindings,
|
|
20
|
+
useSceneConfig,
|
|
19
21
|
useViewerActions,
|
|
20
22
|
useViewerAnimations,
|
|
21
23
|
useViewerCamera,
|
|
@@ -27,7 +29,7 @@ import {
|
|
|
27
29
|
} from "@liveroom-tech/react-immersive";
|
|
28
30
|
```
|
|
29
31
|
|
|
30
|
-
It also exports types for `ObjectBinding`, `ObjectBindingMaterial`, `ObjectBindingsController`, `ObjectActionEvent`, `SceneConfig`, `AnimationControls`, `CinematicConfig` / `CinematicWaypoint`, and related shapes used throughout this document.
|
|
32
|
+
It also exports types for `ObjectBinding`, `ObjectBindingMaterial`, `ObjectBindingsController`, `ObjectActionEvent`, `SceneConfig`, `SceneConfigPatch`, `SceneConfigController`, `AnimationControls`, `CinematicConfig` / `CinematicWaypoint`, and related shapes used throughout this document.
|
|
31
33
|
|
|
32
34
|
`ModelViewer` provides:
|
|
33
35
|
|
|
@@ -334,7 +336,7 @@ If you want one state owner for binding patches, materials, and visibility, use
|
|
|
334
336
|
const {
|
|
335
337
|
objectBindings,
|
|
336
338
|
setObjectBindings,
|
|
337
|
-
|
|
339
|
+
updateObjectBindings,
|
|
338
340
|
setMaterial,
|
|
339
341
|
setBaseColor,
|
|
340
342
|
resetMaterial,
|
|
@@ -356,7 +358,7 @@ const {
|
|
|
356
358
|
/>;
|
|
357
359
|
```
|
|
358
360
|
|
|
359
|
-
`useObjectBindings` owns the state used by the viewer. Every setter uses a functional update, so consecutive material, visibility, and general
|
|
361
|
+
`useObjectBindings` owns the state used by the viewer. Every setter uses a functional update, so consecutive material, visibility, and general binding updates in the same tick compose instead of overwriting each other.
|
|
360
362
|
|
|
361
363
|
Object identifiers accepted by its methods can be:
|
|
362
364
|
|
|
@@ -367,7 +369,7 @@ Object identifiers accepted by its methods can be:
|
|
|
367
369
|
The hook returns:
|
|
368
370
|
|
|
369
371
|
- `objectBindings` and `setObjectBindings`
|
|
370
|
-
- `
|
|
372
|
+
- `updateObjectBindings` for any binding field or atomic edit batch
|
|
371
373
|
- `setMaterial`, `setBaseColor`, `resetMaterial`, and `getMaterial`
|
|
372
374
|
- `hiddenObjects`: a derived map of hidden binding keys
|
|
373
375
|
- `hiddenObjectIds`: the currently hidden binding IDs
|
|
@@ -375,6 +377,37 @@ The hook returns:
|
|
|
375
377
|
- `isObjectHidden`
|
|
376
378
|
- `clearHiddenObjects`
|
|
377
379
|
|
|
380
|
+
For scene-wide state, use `useSceneConfig`:
|
|
381
|
+
|
|
382
|
+
```tsx
|
|
383
|
+
const {
|
|
384
|
+
sceneConfig,
|
|
385
|
+
setSceneConfig,
|
|
386
|
+
updateSceneConfig,
|
|
387
|
+
resetSceneConfig,
|
|
388
|
+
} = useSceneConfig(initialSceneConfig);
|
|
389
|
+
|
|
390
|
+
const enableUvChecker = () =>
|
|
391
|
+
updateSceneConfig({
|
|
392
|
+
model: { renderer: "uv-checker" },
|
|
393
|
+
lighting: { ambient: { intensity: 0.5 } },
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
<ModelViewer
|
|
397
|
+
modelUrl="/model.glb"
|
|
398
|
+
licenseKey="your-license-key"
|
|
399
|
+
objectBindings={objectBindings}
|
|
400
|
+
sceneConfig={sceneConfig}
|
|
401
|
+
/>;
|
|
402
|
+
|
|
403
|
+
<button onClick={enableUvChecker}>Show UV checker</button>;
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Nested objects merge recursively, while arrays and tuples are replaced. Every
|
|
407
|
+
update uses a functional state updater, so consecutive calls compose. Use the
|
|
408
|
+
pure `patchSceneConfig(sceneConfig, patch)` utility when a store or parent owns
|
|
409
|
+
the scene state.
|
|
410
|
+
|
|
378
411
|
If you want to keep hover state in sync with the viewer, the library also exports:
|
|
379
412
|
|
|
380
413
|
```tsx
|
package/dist/index.d.mts
CHANGED
|
@@ -664,9 +664,10 @@ declare function useObjectBinding(objectBindings: Record<string, ObjectBinding>,
|
|
|
664
664
|
|
|
665
665
|
declare function useObjectBindingIds(objectBindings: Record<string, ObjectBinding>): string[];
|
|
666
666
|
|
|
667
|
-
type DeepPartial<T> = T extends
|
|
667
|
+
type DeepPartial<T> = T extends readonly unknown[] ? T : T extends object ? {
|
|
668
668
|
[K in keyof T]?: DeepPartial<T[K]>;
|
|
669
669
|
} : T;
|
|
670
|
+
|
|
670
671
|
type ObjectBindingPatch = DeepPartial<ObjectBinding>;
|
|
671
672
|
type BindingEdit = {
|
|
672
673
|
ids: string | string[];
|
|
@@ -689,7 +690,7 @@ type HiddenObjectsState = Record<string, boolean>;
|
|
|
689
690
|
type ObjectBindingsController = {
|
|
690
691
|
objectBindings: Record<string, ObjectBinding>;
|
|
691
692
|
setObjectBindings: React.Dispatch<React.SetStateAction<Record<string, ObjectBinding>>>;
|
|
692
|
-
|
|
693
|
+
updateObjectBindings: {
|
|
693
694
|
(objectId: string | string[], patch: ObjectBindingPatch): void;
|
|
694
695
|
(edits: BindingEdit[]): void;
|
|
695
696
|
};
|
|
@@ -714,6 +715,26 @@ type ObjectBindingsController = {
|
|
|
714
715
|
*/
|
|
715
716
|
declare function useObjectBindings(initialBindings: Record<string, ObjectBinding> | (() => Record<string, ObjectBinding>)): ObjectBindingsController;
|
|
716
717
|
|
|
718
|
+
type SceneConfigPatch = DeepPartial<SceneConfig>;
|
|
719
|
+
/**
|
|
720
|
+
* Applies a nested scene-config patch without mutating either input. Objects
|
|
721
|
+
* are merged recursively, while arrays and tuples are replaced wholesale.
|
|
722
|
+
*/
|
|
723
|
+
declare function patchSceneConfig(sceneConfig: SceneConfig, patch: SceneConfigPatch): SceneConfig;
|
|
724
|
+
|
|
725
|
+
type SceneConfigUpdate = SceneConfigPatch | ((current: SceneConfig) => SceneConfigPatch);
|
|
726
|
+
type SceneConfigController = {
|
|
727
|
+
sceneConfig: SceneConfig;
|
|
728
|
+
setSceneConfig: React.Dispatch<React.SetStateAction<SceneConfig>>;
|
|
729
|
+
updateSceneConfig: (update: SceneConfigUpdate) => void;
|
|
730
|
+
resetSceneConfig: () => void;
|
|
731
|
+
};
|
|
732
|
+
/**
|
|
733
|
+
* Owns scene-config state and applies nested patches through functional React
|
|
734
|
+
* updates, so consecutive calls in the same tick compose safely.
|
|
735
|
+
*/
|
|
736
|
+
declare function useSceneConfig(initialSceneConfig: SceneConfig | (() => SceneConfig)): SceneConfigController;
|
|
737
|
+
|
|
717
738
|
type ViewerHoverProps = {
|
|
718
739
|
hoveredObjectBinding: ObjectBinding | null;
|
|
719
740
|
handleHoveredObject: (binding: ObjectBinding | null) => void;
|
|
@@ -766,4 +787,4 @@ type ShareableViewerStateProps = {
|
|
|
766
787
|
};
|
|
767
788
|
declare function useShareableViewerState({ cameraState, setCameraState, objectBindings, onObjectBindingsChange, selectedObjectBinding, setSelectedObjectBinding, paramKey, debounceMs, autoSync, }: UseShareableViewerStateOptions): ShareableViewerStateProps;
|
|
768
789
|
|
|
769
|
-
export { type AnimationClipInfo, type AnimationControls, type AnimationLoopMode, type AnimationPlaybackState, BindingBuilder, type BindingEdit, type CaptureImageOptions, type CinematicConfig, type CinematicWaypoint, type CustomObjectBindingDataPanelProps, type CustomSceneObjectsPanelProps, type HiddenObjectsState, type HomeCameraState, MATERIAL_BLENDING_MODES, MATERIAL_SIDES, ModelViewer, type ModelViewerProps, type ObjectActionEvent, type ObjectBinding, type ObjectBindingAction, type ObjectBindingMaterial, type ObjectBindingMaterialBlendingMode, type ObjectBindingMaterialSide, type ObjectBindingPatch, type ObjectBindingTextureSlot, type ObjectBindingsController, type SceneAnimationClipConfig, type SceneAnimationConfig, type SceneCinematicConfig, type SceneCinematicWaypoint, type SceneConfig, type SceneModelRenderer, SimpleModelViewer, type SimpleModelViewerProps, type ViewerActionsOptions, type ViewerActionsProps, type ViewerAnimationsProps, type ViewerCameraProps, type ViewerCameraState, type ViewerModelBounds, type ViewerModelProps, type ViewerReadyState, type ViewerSelectionProps, type XRScaleMode, material, patchBindings, useObjectBinding, useObjectBindingIds, useObjectBindings, useShareableViewerState, useViewerActions, useViewerAnimations, useViewerCamera, useViewerHover, useViewerModel, useViewerSelection };
|
|
790
|
+
export { type AnimationClipInfo, type AnimationControls, type AnimationLoopMode, type AnimationPlaybackState, BindingBuilder, type BindingEdit, type CaptureImageOptions, type CinematicConfig, type CinematicWaypoint, type CustomObjectBindingDataPanelProps, type CustomSceneObjectsPanelProps, type HiddenObjectsState, type HomeCameraState, MATERIAL_BLENDING_MODES, MATERIAL_SIDES, ModelViewer, type ModelViewerProps, type ObjectActionEvent, type ObjectBinding, type ObjectBindingAction, type ObjectBindingMaterial, type ObjectBindingMaterialBlendingMode, type ObjectBindingMaterialSide, type ObjectBindingPatch, type ObjectBindingTextureSlot, type ObjectBindingsController, type SceneAnimationClipConfig, type SceneAnimationConfig, type SceneCinematicConfig, type SceneCinematicWaypoint, type SceneConfig, type SceneConfigController, type SceneConfigPatch, type SceneConfigUpdate, type SceneModelRenderer, SimpleModelViewer, type SimpleModelViewerProps, type ViewerActionsOptions, type ViewerActionsProps, type ViewerAnimationsProps, type ViewerCameraProps, type ViewerCameraState, type ViewerModelBounds, type ViewerModelProps, type ViewerReadyState, type ViewerSelectionProps, type XRScaleMode, material, patchBindings, patchSceneConfig, useObjectBinding, useObjectBindingIds, useObjectBindings, useSceneConfig, useShareableViewerState, useViewerActions, useViewerAnimations, useViewerCamera, useViewerHover, useViewerModel, useViewerSelection };
|
package/dist/index.d.ts
CHANGED
|
@@ -664,9 +664,10 @@ declare function useObjectBinding(objectBindings: Record<string, ObjectBinding>,
|
|
|
664
664
|
|
|
665
665
|
declare function useObjectBindingIds(objectBindings: Record<string, ObjectBinding>): string[];
|
|
666
666
|
|
|
667
|
-
type DeepPartial<T> = T extends
|
|
667
|
+
type DeepPartial<T> = T extends readonly unknown[] ? T : T extends object ? {
|
|
668
668
|
[K in keyof T]?: DeepPartial<T[K]>;
|
|
669
669
|
} : T;
|
|
670
|
+
|
|
670
671
|
type ObjectBindingPatch = DeepPartial<ObjectBinding>;
|
|
671
672
|
type BindingEdit = {
|
|
672
673
|
ids: string | string[];
|
|
@@ -689,7 +690,7 @@ type HiddenObjectsState = Record<string, boolean>;
|
|
|
689
690
|
type ObjectBindingsController = {
|
|
690
691
|
objectBindings: Record<string, ObjectBinding>;
|
|
691
692
|
setObjectBindings: React.Dispatch<React.SetStateAction<Record<string, ObjectBinding>>>;
|
|
692
|
-
|
|
693
|
+
updateObjectBindings: {
|
|
693
694
|
(objectId: string | string[], patch: ObjectBindingPatch): void;
|
|
694
695
|
(edits: BindingEdit[]): void;
|
|
695
696
|
};
|
|
@@ -714,6 +715,26 @@ type ObjectBindingsController = {
|
|
|
714
715
|
*/
|
|
715
716
|
declare function useObjectBindings(initialBindings: Record<string, ObjectBinding> | (() => Record<string, ObjectBinding>)): ObjectBindingsController;
|
|
716
717
|
|
|
718
|
+
type SceneConfigPatch = DeepPartial<SceneConfig>;
|
|
719
|
+
/**
|
|
720
|
+
* Applies a nested scene-config patch without mutating either input. Objects
|
|
721
|
+
* are merged recursively, while arrays and tuples are replaced wholesale.
|
|
722
|
+
*/
|
|
723
|
+
declare function patchSceneConfig(sceneConfig: SceneConfig, patch: SceneConfigPatch): SceneConfig;
|
|
724
|
+
|
|
725
|
+
type SceneConfigUpdate = SceneConfigPatch | ((current: SceneConfig) => SceneConfigPatch);
|
|
726
|
+
type SceneConfigController = {
|
|
727
|
+
sceneConfig: SceneConfig;
|
|
728
|
+
setSceneConfig: React.Dispatch<React.SetStateAction<SceneConfig>>;
|
|
729
|
+
updateSceneConfig: (update: SceneConfigUpdate) => void;
|
|
730
|
+
resetSceneConfig: () => void;
|
|
731
|
+
};
|
|
732
|
+
/**
|
|
733
|
+
* Owns scene-config state and applies nested patches through functional React
|
|
734
|
+
* updates, so consecutive calls in the same tick compose safely.
|
|
735
|
+
*/
|
|
736
|
+
declare function useSceneConfig(initialSceneConfig: SceneConfig | (() => SceneConfig)): SceneConfigController;
|
|
737
|
+
|
|
717
738
|
type ViewerHoverProps = {
|
|
718
739
|
hoveredObjectBinding: ObjectBinding | null;
|
|
719
740
|
handleHoveredObject: (binding: ObjectBinding | null) => void;
|
|
@@ -766,4 +787,4 @@ type ShareableViewerStateProps = {
|
|
|
766
787
|
};
|
|
767
788
|
declare function useShareableViewerState({ cameraState, setCameraState, objectBindings, onObjectBindingsChange, selectedObjectBinding, setSelectedObjectBinding, paramKey, debounceMs, autoSync, }: UseShareableViewerStateOptions): ShareableViewerStateProps;
|
|
768
789
|
|
|
769
|
-
export { type AnimationClipInfo, type AnimationControls, type AnimationLoopMode, type AnimationPlaybackState, BindingBuilder, type BindingEdit, type CaptureImageOptions, type CinematicConfig, type CinematicWaypoint, type CustomObjectBindingDataPanelProps, type CustomSceneObjectsPanelProps, type HiddenObjectsState, type HomeCameraState, MATERIAL_BLENDING_MODES, MATERIAL_SIDES, ModelViewer, type ModelViewerProps, type ObjectActionEvent, type ObjectBinding, type ObjectBindingAction, type ObjectBindingMaterial, type ObjectBindingMaterialBlendingMode, type ObjectBindingMaterialSide, type ObjectBindingPatch, type ObjectBindingTextureSlot, type ObjectBindingsController, type SceneAnimationClipConfig, type SceneAnimationConfig, type SceneCinematicConfig, type SceneCinematicWaypoint, type SceneConfig, type SceneModelRenderer, SimpleModelViewer, type SimpleModelViewerProps, type ViewerActionsOptions, type ViewerActionsProps, type ViewerAnimationsProps, type ViewerCameraProps, type ViewerCameraState, type ViewerModelBounds, type ViewerModelProps, type ViewerReadyState, type ViewerSelectionProps, type XRScaleMode, material, patchBindings, useObjectBinding, useObjectBindingIds, useObjectBindings, useShareableViewerState, useViewerActions, useViewerAnimations, useViewerCamera, useViewerHover, useViewerModel, useViewerSelection };
|
|
790
|
+
export { type AnimationClipInfo, type AnimationControls, type AnimationLoopMode, type AnimationPlaybackState, BindingBuilder, type BindingEdit, type CaptureImageOptions, type CinematicConfig, type CinematicWaypoint, type CustomObjectBindingDataPanelProps, type CustomSceneObjectsPanelProps, type HiddenObjectsState, type HomeCameraState, MATERIAL_BLENDING_MODES, MATERIAL_SIDES, ModelViewer, type ModelViewerProps, type ObjectActionEvent, type ObjectBinding, type ObjectBindingAction, type ObjectBindingMaterial, type ObjectBindingMaterialBlendingMode, type ObjectBindingMaterialSide, type ObjectBindingPatch, type ObjectBindingTextureSlot, type ObjectBindingsController, type SceneAnimationClipConfig, type SceneAnimationConfig, type SceneCinematicConfig, type SceneCinematicWaypoint, type SceneConfig, type SceneConfigController, type SceneConfigPatch, type SceneConfigUpdate, type SceneModelRenderer, SimpleModelViewer, type SimpleModelViewerProps, type ViewerActionsOptions, type ViewerActionsProps, type ViewerAnimationsProps, type ViewerCameraProps, type ViewerCameraState, type ViewerModelBounds, type ViewerModelProps, type ViewerReadyState, type ViewerSelectionProps, type XRScaleMode, material, patchBindings, patchSceneConfig, useObjectBinding, useObjectBindingIds, useObjectBindings, useSceneConfig, useShareableViewerState, useViewerActions, useViewerAnimations, useViewerCamera, useViewerHover, useViewerModel, useViewerSelection };
|
package/dist/index.js
CHANGED
|
@@ -54,9 +54,11 @@ __export(index_exports, {
|
|
|
54
54
|
SimpleModelViewer: () => SimpleModelViewer,
|
|
55
55
|
material: () => material,
|
|
56
56
|
patchBindings: () => patchBindings,
|
|
57
|
+
patchSceneConfig: () => patchSceneConfig,
|
|
57
58
|
useObjectBinding: () => useObjectBinding,
|
|
58
59
|
useObjectBindingIds: () => useObjectBindingIds,
|
|
59
60
|
useObjectBindings: () => useObjectBindings,
|
|
61
|
+
useSceneConfig: () => useSceneConfig,
|
|
60
62
|
useShareableViewerState: () => useShareableViewerState,
|
|
61
63
|
useViewerActions: () => useViewerActions,
|
|
62
64
|
useViewerAnimations: () => useViewerAnimations,
|
|
@@ -17596,15 +17598,12 @@ function useObjectBindingIds(objectBindings) {
|
|
|
17596
17598
|
// src/hooks/useObjectBindings.ts
|
|
17597
17599
|
var import_react44 = require("react");
|
|
17598
17600
|
|
|
17599
|
-
// src/utils/
|
|
17601
|
+
// src/utils/deepMerge.ts
|
|
17600
17602
|
function isPlainObject2(value) {
|
|
17601
17603
|
if (typeof value !== "object" || value === null) return false;
|
|
17602
17604
|
const prototype = Object.getPrototypeOf(value);
|
|
17603
17605
|
return prototype === Object.prototype || prototype === null;
|
|
17604
17606
|
}
|
|
17605
|
-
function isBindingEditArray(value) {
|
|
17606
|
-
return Array.isArray(value) && value.length > 0 && typeof value[0] !== "string";
|
|
17607
|
-
}
|
|
17608
17607
|
function deepMerge(base, patch) {
|
|
17609
17608
|
if (!isPlainObject2(patch)) return patch;
|
|
17610
17609
|
const target = isPlainObject2(base) ? { ...base } : {};
|
|
@@ -17614,6 +17613,11 @@ function deepMerge(base, patch) {
|
|
|
17614
17613
|
}
|
|
17615
17614
|
return target;
|
|
17616
17615
|
}
|
|
17616
|
+
|
|
17617
|
+
// src/utils/patchBindings.ts
|
|
17618
|
+
function isBindingEditArray(value) {
|
|
17619
|
+
return Array.isArray(value) && value.length > 0 && typeof value[0] !== "string";
|
|
17620
|
+
}
|
|
17617
17621
|
function patchBindings(bindings, objectIdOrEdits, patch) {
|
|
17618
17622
|
const edits = isBindingEditArray(objectIdOrEdits) ? objectIdOrEdits : [{ ids: objectIdOrEdits, patch: patch ?? {} }];
|
|
17619
17623
|
let next = bindings;
|
|
@@ -17643,7 +17647,7 @@ function getHiddenObjects(objectBindings) {
|
|
|
17643
17647
|
}
|
|
17644
17648
|
function useObjectBindings(initialBindings) {
|
|
17645
17649
|
const [objectBindings, setObjectBindings] = (0, import_react44.useState)(initialBindings);
|
|
17646
|
-
const
|
|
17650
|
+
const updateObjectBindings = (0, import_react44.useCallback)(
|
|
17647
17651
|
(objectIdOrEdits, patchValue) => {
|
|
17648
17652
|
setObjectBindings(
|
|
17649
17653
|
(current) => patchValue === void 0 ? patchBindings(current, objectIdOrEdits) : patchBindings(
|
|
@@ -17656,16 +17660,16 @@ function useObjectBindings(initialBindings) {
|
|
|
17656
17660
|
[]
|
|
17657
17661
|
);
|
|
17658
17662
|
const setMaterial = (0, import_react44.useCallback)(
|
|
17659
|
-
(objectId, value) =>
|
|
17660
|
-
[
|
|
17663
|
+
(objectId, value) => updateObjectBindings(objectId, material(value)),
|
|
17664
|
+
[updateObjectBindings]
|
|
17661
17665
|
);
|
|
17662
17666
|
const setBaseColor = (0, import_react44.useCallback)(
|
|
17663
17667
|
(objectId, color) => setMaterial(objectId, { baseColor: color }),
|
|
17664
17668
|
[setMaterial]
|
|
17665
17669
|
);
|
|
17666
17670
|
const resetMaterial = (0, import_react44.useCallback)(
|
|
17667
|
-
(objectId) =>
|
|
17668
|
-
[
|
|
17671
|
+
(objectId) => updateObjectBindings(objectId, { style: { material: void 0 } }),
|
|
17672
|
+
[updateObjectBindings]
|
|
17669
17673
|
);
|
|
17670
17674
|
const getMaterial = (0, import_react44.useCallback)(
|
|
17671
17675
|
(objectId) => {
|
|
@@ -17675,12 +17679,12 @@ function useObjectBindings(initialBindings) {
|
|
|
17675
17679
|
[objectBindings]
|
|
17676
17680
|
);
|
|
17677
17681
|
const hideObject = (0, import_react44.useCallback)(
|
|
17678
|
-
(objectId) =>
|
|
17679
|
-
[
|
|
17682
|
+
(objectId) => updateObjectBindings(objectId, { visible: false }),
|
|
17683
|
+
[updateObjectBindings]
|
|
17680
17684
|
);
|
|
17681
17685
|
const showObject = (0, import_react44.useCallback)(
|
|
17682
|
-
(objectId) =>
|
|
17683
|
-
[
|
|
17686
|
+
(objectId) => updateObjectBindings(objectId, { visible: true }),
|
|
17687
|
+
[updateObjectBindings]
|
|
17684
17688
|
);
|
|
17685
17689
|
const toggleObjectVisibility = (0, import_react44.useCallback)(
|
|
17686
17690
|
(objectId) => {
|
|
@@ -17726,7 +17730,7 @@ function useObjectBindings(initialBindings) {
|
|
|
17726
17730
|
return {
|
|
17727
17731
|
objectBindings,
|
|
17728
17732
|
setObjectBindings,
|
|
17729
|
-
|
|
17733
|
+
updateObjectBindings,
|
|
17730
17734
|
setMaterial,
|
|
17731
17735
|
setBaseColor,
|
|
17732
17736
|
resetMaterial,
|
|
@@ -17741,11 +17745,45 @@ function useObjectBindings(initialBindings) {
|
|
|
17741
17745
|
};
|
|
17742
17746
|
}
|
|
17743
17747
|
|
|
17744
|
-
// src/hooks/
|
|
17748
|
+
// src/hooks/useSceneConfig.ts
|
|
17745
17749
|
var import_react45 = require("react");
|
|
17750
|
+
|
|
17751
|
+
// src/utils/patchSceneConfig.ts
|
|
17752
|
+
function patchSceneConfig(sceneConfig, patch) {
|
|
17753
|
+
return deepMerge(sceneConfig, patch);
|
|
17754
|
+
}
|
|
17755
|
+
|
|
17756
|
+
// src/hooks/useSceneConfig.ts
|
|
17757
|
+
function useSceneConfig(initialSceneConfig) {
|
|
17758
|
+
const initialSceneConfigRef = (0, import_react45.useRef)(null);
|
|
17759
|
+
const [sceneConfig, setSceneConfig] = (0, import_react45.useState)(() => {
|
|
17760
|
+
const initial = typeof initialSceneConfig === "function" ? initialSceneConfig() : initialSceneConfig;
|
|
17761
|
+
initialSceneConfigRef.current = initial;
|
|
17762
|
+
return initial;
|
|
17763
|
+
});
|
|
17764
|
+
const updateSceneConfig = (0, import_react45.useCallback)((update) => {
|
|
17765
|
+
setSceneConfig((current) => {
|
|
17766
|
+
const patch = typeof update === "function" ? update(current) : update;
|
|
17767
|
+
return patchSceneConfig(current, patch);
|
|
17768
|
+
});
|
|
17769
|
+
}, []);
|
|
17770
|
+
const resetSceneConfig = (0, import_react45.useCallback)(() => {
|
|
17771
|
+
const initial = initialSceneConfigRef.current;
|
|
17772
|
+
if (initial) setSceneConfig(initial);
|
|
17773
|
+
}, []);
|
|
17774
|
+
return {
|
|
17775
|
+
sceneConfig,
|
|
17776
|
+
setSceneConfig,
|
|
17777
|
+
updateSceneConfig,
|
|
17778
|
+
resetSceneConfig
|
|
17779
|
+
};
|
|
17780
|
+
}
|
|
17781
|
+
|
|
17782
|
+
// src/hooks/useViewerHover.ts
|
|
17783
|
+
var import_react46 = require("react");
|
|
17746
17784
|
function useViewerHover() {
|
|
17747
|
-
const [hoveredObjectBinding, setHoveredObjectBinding] = (0,
|
|
17748
|
-
const handleHoveredObject = (0,
|
|
17785
|
+
const [hoveredObjectBinding, setHoveredObjectBinding] = (0, import_react46.useState)(null);
|
|
17786
|
+
const handleHoveredObject = (0, import_react46.useCallback)(
|
|
17749
17787
|
(binding) => {
|
|
17750
17788
|
setHoveredObjectBinding(binding);
|
|
17751
17789
|
},
|
|
@@ -17758,18 +17796,18 @@ function useViewerHover() {
|
|
|
17758
17796
|
}
|
|
17759
17797
|
|
|
17760
17798
|
// src/hooks/useViewerModel.ts
|
|
17761
|
-
var
|
|
17799
|
+
var import_react47 = require("react");
|
|
17762
17800
|
var import_three22 = require("three");
|
|
17763
17801
|
function toTuple2(vector) {
|
|
17764
17802
|
return [vector.x, vector.y, vector.z];
|
|
17765
17803
|
}
|
|
17766
17804
|
function useViewerModel() {
|
|
17767
|
-
const [isLoading, setIsLoading] = (0,
|
|
17768
|
-
const [isReady, setIsReady] = (0,
|
|
17769
|
-
const [error, setError] = (0,
|
|
17770
|
-
const [bounds, setBounds] = (0,
|
|
17771
|
-
const [objectCount, setObjectCount] = (0,
|
|
17772
|
-
const handleModelLoaded = (0,
|
|
17805
|
+
const [isLoading, setIsLoading] = (0, import_react47.useState)(true);
|
|
17806
|
+
const [isReady, setIsReady] = (0, import_react47.useState)(false);
|
|
17807
|
+
const [error, setError] = (0, import_react47.useState)(null);
|
|
17808
|
+
const [bounds, setBounds] = (0, import_react47.useState)(null);
|
|
17809
|
+
const [objectCount, setObjectCount] = (0, import_react47.useState)(0);
|
|
17810
|
+
const handleModelLoaded = (0, import_react47.useCallback)((scene) => {
|
|
17773
17811
|
const box = new import_three22.Box3().setFromObject(scene);
|
|
17774
17812
|
const min = box.min.clone();
|
|
17775
17813
|
const max = box.max.clone();
|
|
@@ -17794,14 +17832,14 @@ function useViewerModel() {
|
|
|
17794
17832
|
setIsLoading(false);
|
|
17795
17833
|
setIsReady(true);
|
|
17796
17834
|
}, []);
|
|
17797
|
-
const handleLoadError = (0,
|
|
17835
|
+
const handleLoadError = (0, import_react47.useCallback)((nextError) => {
|
|
17798
17836
|
setError(nextError);
|
|
17799
17837
|
setBounds(null);
|
|
17800
17838
|
setObjectCount(0);
|
|
17801
17839
|
setIsLoading(false);
|
|
17802
17840
|
setIsReady(false);
|
|
17803
17841
|
}, []);
|
|
17804
|
-
const resetModelState = (0,
|
|
17842
|
+
const resetModelState = (0, import_react47.useCallback)(() => {
|
|
17805
17843
|
setIsLoading(true);
|
|
17806
17844
|
setIsReady(false);
|
|
17807
17845
|
setError(null);
|
|
@@ -17821,10 +17859,10 @@ function useViewerModel() {
|
|
|
17821
17859
|
}
|
|
17822
17860
|
|
|
17823
17861
|
// src/hooks/useViewerActions.ts
|
|
17824
|
-
var
|
|
17862
|
+
var import_react48 = require("react");
|
|
17825
17863
|
function useViewerActions(objectBindings, options = {}) {
|
|
17826
17864
|
const { onAction, onObjectBindingsChange } = options;
|
|
17827
|
-
const getActionsForObject = (0,
|
|
17865
|
+
const getActionsForObject = (0, import_react48.useCallback)(
|
|
17828
17866
|
(objectId) => {
|
|
17829
17867
|
const bindingKey = resolveBindingKey(objectBindings, objectId);
|
|
17830
17868
|
if (!bindingKey) {
|
|
@@ -17834,7 +17872,7 @@ function useViewerActions(objectBindings, options = {}) {
|
|
|
17834
17872
|
},
|
|
17835
17873
|
[objectBindings]
|
|
17836
17874
|
);
|
|
17837
|
-
const runAction = (0,
|
|
17875
|
+
const runAction = (0, import_react48.useCallback)(
|
|
17838
17876
|
(objectId, actionId) => {
|
|
17839
17877
|
const bindingKey = resolveBindingKey(objectBindings, objectId);
|
|
17840
17878
|
if (!bindingKey) {
|
|
@@ -17876,7 +17914,7 @@ function useViewerActions(objectBindings, options = {}) {
|
|
|
17876
17914
|
}
|
|
17877
17915
|
|
|
17878
17916
|
// src/hooks/useShareableViewerState.ts
|
|
17879
|
-
var
|
|
17917
|
+
var import_react49 = require("react");
|
|
17880
17918
|
function serializeState(cameraState, objectBindings, selectedObjectBinding) {
|
|
17881
17919
|
const hidden = Object.values(objectBindings).filter((binding) => binding.visible === false).map((binding) => binding.id);
|
|
17882
17920
|
return {
|
|
@@ -17896,8 +17934,8 @@ function useShareableViewerState({
|
|
|
17896
17934
|
debounceMs = 400,
|
|
17897
17935
|
autoSync = true
|
|
17898
17936
|
}) {
|
|
17899
|
-
const lastWrittenRawRef = (0,
|
|
17900
|
-
const buildHash = (0,
|
|
17937
|
+
const lastWrittenRawRef = (0, import_react49.useRef)(null);
|
|
17938
|
+
const buildHash = (0, import_react49.useCallback)(() => {
|
|
17901
17939
|
const state = serializeState(
|
|
17902
17940
|
cameraState,
|
|
17903
17941
|
objectBindings,
|
|
@@ -17905,12 +17943,12 @@ function useShareableViewerState({
|
|
|
17905
17943
|
);
|
|
17906
17944
|
return `${paramKey}=${encodeURIComponent(JSON.stringify(state))}`;
|
|
17907
17945
|
}, [cameraState, objectBindings, selectedObjectBinding, paramKey]);
|
|
17908
|
-
const getShareUrl = (0,
|
|
17946
|
+
const getShareUrl = (0, import_react49.useCallback)(() => {
|
|
17909
17947
|
const url = new URL(window.location.href);
|
|
17910
17948
|
url.hash = buildHash();
|
|
17911
17949
|
return url.toString();
|
|
17912
17950
|
}, [buildHash]);
|
|
17913
|
-
const syncUrl = (0,
|
|
17951
|
+
const syncUrl = (0, import_react49.useCallback)(() => {
|
|
17914
17952
|
const url = new URL(window.location.href);
|
|
17915
17953
|
url.hash = buildHash();
|
|
17916
17954
|
window.history.replaceState(null, "", url.toString());
|
|
@@ -17918,7 +17956,7 @@ function useShareableViewerState({
|
|
|
17918
17956
|
paramKey
|
|
17919
17957
|
);
|
|
17920
17958
|
}, [buildHash, paramKey]);
|
|
17921
|
-
const latestStateRef = (0,
|
|
17959
|
+
const latestStateRef = (0, import_react49.useRef)({
|
|
17922
17960
|
cameraState,
|
|
17923
17961
|
objectBindings,
|
|
17924
17962
|
selectedObjectBinding
|
|
@@ -17928,9 +17966,9 @@ function useShareableViewerState({
|
|
|
17928
17966
|
objectBindings,
|
|
17929
17967
|
selectedObjectBinding
|
|
17930
17968
|
};
|
|
17931
|
-
const [restoreAttempted, setRestoreAttempted] = (0,
|
|
17932
|
-
const lastSyncedHashRef = (0,
|
|
17933
|
-
(0,
|
|
17969
|
+
const [restoreAttempted, setRestoreAttempted] = (0, import_react49.useState)(false);
|
|
17970
|
+
const lastSyncedHashRef = (0, import_react49.useRef)(null);
|
|
17971
|
+
(0, import_react49.useEffect)(() => {
|
|
17934
17972
|
if (!autoSync || !restoreAttempted) return;
|
|
17935
17973
|
const tick = () => {
|
|
17936
17974
|
const current = latestStateRef.current;
|
|
@@ -17952,9 +17990,9 @@ function useShareableViewerState({
|
|
|
17952
17990
|
const id = window.setInterval(tick, debounceMs);
|
|
17953
17991
|
return () => window.clearInterval(id);
|
|
17954
17992
|
}, [autoSync, restoreAttempted, debounceMs, paramKey]);
|
|
17955
|
-
const lastRestoredRawRef = (0,
|
|
17956
|
-
const restoringRawRef = (0,
|
|
17957
|
-
const restoreFromUrl = (0,
|
|
17993
|
+
const lastRestoredRawRef = (0, import_react49.useRef)(null);
|
|
17994
|
+
const restoringRawRef = (0, import_react49.useRef)(null);
|
|
17995
|
+
const restoreFromUrl = (0, import_react49.useCallback)(async () => {
|
|
17958
17996
|
setRestoreAttempted(true);
|
|
17959
17997
|
const rawHash = window.location.hash.startsWith("#") ? window.location.hash.slice(1) : window.location.hash;
|
|
17960
17998
|
const raw = new URLSearchParams(rawHash).get(paramKey);
|
|
@@ -18007,7 +18045,7 @@ function useShareableViewerState({
|
|
|
18007
18045
|
setCameraState,
|
|
18008
18046
|
setSelectedObjectBinding
|
|
18009
18047
|
]);
|
|
18010
|
-
(0,
|
|
18048
|
+
(0, import_react49.useEffect)(() => {
|
|
18011
18049
|
const handleHashChange = () => {
|
|
18012
18050
|
void restoreFromUrl();
|
|
18013
18051
|
};
|
|
@@ -18027,9 +18065,11 @@ function useShareableViewerState({
|
|
|
18027
18065
|
SimpleModelViewer,
|
|
18028
18066
|
material,
|
|
18029
18067
|
patchBindings,
|
|
18068
|
+
patchSceneConfig,
|
|
18030
18069
|
useObjectBinding,
|
|
18031
18070
|
useObjectBindingIds,
|
|
18032
18071
|
useObjectBindings,
|
|
18072
|
+
useSceneConfig,
|
|
18033
18073
|
useShareableViewerState,
|
|
18034
18074
|
useViewerActions,
|
|
18035
18075
|
useViewerAnimations,
|
package/dist/index.mjs
CHANGED
|
@@ -17697,15 +17697,12 @@ function useObjectBindingIds(objectBindings) {
|
|
|
17697
17697
|
// src/hooks/useObjectBindings.ts
|
|
17698
17698
|
import { useCallback as useCallback12, useMemo as useMemo20, useState as useState28 } from "react";
|
|
17699
17699
|
|
|
17700
|
-
// src/utils/
|
|
17700
|
+
// src/utils/deepMerge.ts
|
|
17701
17701
|
function isPlainObject2(value) {
|
|
17702
17702
|
if (typeof value !== "object" || value === null) return false;
|
|
17703
17703
|
const prototype = Object.getPrototypeOf(value);
|
|
17704
17704
|
return prototype === Object.prototype || prototype === null;
|
|
17705
17705
|
}
|
|
17706
|
-
function isBindingEditArray(value) {
|
|
17707
|
-
return Array.isArray(value) && value.length > 0 && typeof value[0] !== "string";
|
|
17708
|
-
}
|
|
17709
17706
|
function deepMerge(base, patch) {
|
|
17710
17707
|
if (!isPlainObject2(patch)) return patch;
|
|
17711
17708
|
const target = isPlainObject2(base) ? { ...base } : {};
|
|
@@ -17715,6 +17712,11 @@ function deepMerge(base, patch) {
|
|
|
17715
17712
|
}
|
|
17716
17713
|
return target;
|
|
17717
17714
|
}
|
|
17715
|
+
|
|
17716
|
+
// src/utils/patchBindings.ts
|
|
17717
|
+
function isBindingEditArray(value) {
|
|
17718
|
+
return Array.isArray(value) && value.length > 0 && typeof value[0] !== "string";
|
|
17719
|
+
}
|
|
17718
17720
|
function patchBindings(bindings, objectIdOrEdits, patch) {
|
|
17719
17721
|
const edits = isBindingEditArray(objectIdOrEdits) ? objectIdOrEdits : [{ ids: objectIdOrEdits, patch: patch ?? {} }];
|
|
17720
17722
|
let next = bindings;
|
|
@@ -17744,7 +17746,7 @@ function getHiddenObjects(objectBindings) {
|
|
|
17744
17746
|
}
|
|
17745
17747
|
function useObjectBindings(initialBindings) {
|
|
17746
17748
|
const [objectBindings, setObjectBindings] = useState28(initialBindings);
|
|
17747
|
-
const
|
|
17749
|
+
const updateObjectBindings = useCallback12(
|
|
17748
17750
|
(objectIdOrEdits, patchValue) => {
|
|
17749
17751
|
setObjectBindings(
|
|
17750
17752
|
(current) => patchValue === void 0 ? patchBindings(current, objectIdOrEdits) : patchBindings(
|
|
@@ -17757,16 +17759,16 @@ function useObjectBindings(initialBindings) {
|
|
|
17757
17759
|
[]
|
|
17758
17760
|
);
|
|
17759
17761
|
const setMaterial = useCallback12(
|
|
17760
|
-
(objectId, value) =>
|
|
17761
|
-
[
|
|
17762
|
+
(objectId, value) => updateObjectBindings(objectId, material(value)),
|
|
17763
|
+
[updateObjectBindings]
|
|
17762
17764
|
);
|
|
17763
17765
|
const setBaseColor = useCallback12(
|
|
17764
17766
|
(objectId, color) => setMaterial(objectId, { baseColor: color }),
|
|
17765
17767
|
[setMaterial]
|
|
17766
17768
|
);
|
|
17767
17769
|
const resetMaterial = useCallback12(
|
|
17768
|
-
(objectId) =>
|
|
17769
|
-
[
|
|
17770
|
+
(objectId) => updateObjectBindings(objectId, { style: { material: void 0 } }),
|
|
17771
|
+
[updateObjectBindings]
|
|
17770
17772
|
);
|
|
17771
17773
|
const getMaterial = useCallback12(
|
|
17772
17774
|
(objectId) => {
|
|
@@ -17776,12 +17778,12 @@ function useObjectBindings(initialBindings) {
|
|
|
17776
17778
|
[objectBindings]
|
|
17777
17779
|
);
|
|
17778
17780
|
const hideObject = useCallback12(
|
|
17779
|
-
(objectId) =>
|
|
17780
|
-
[
|
|
17781
|
+
(objectId) => updateObjectBindings(objectId, { visible: false }),
|
|
17782
|
+
[updateObjectBindings]
|
|
17781
17783
|
);
|
|
17782
17784
|
const showObject = useCallback12(
|
|
17783
|
-
(objectId) =>
|
|
17784
|
-
[
|
|
17785
|
+
(objectId) => updateObjectBindings(objectId, { visible: true }),
|
|
17786
|
+
[updateObjectBindings]
|
|
17785
17787
|
);
|
|
17786
17788
|
const toggleObjectVisibility = useCallback12(
|
|
17787
17789
|
(objectId) => {
|
|
@@ -17827,7 +17829,7 @@ function useObjectBindings(initialBindings) {
|
|
|
17827
17829
|
return {
|
|
17828
17830
|
objectBindings,
|
|
17829
17831
|
setObjectBindings,
|
|
17830
|
-
|
|
17832
|
+
updateObjectBindings,
|
|
17831
17833
|
setMaterial,
|
|
17832
17834
|
setBaseColor,
|
|
17833
17835
|
resetMaterial,
|
|
@@ -17842,11 +17844,45 @@ function useObjectBindings(initialBindings) {
|
|
|
17842
17844
|
};
|
|
17843
17845
|
}
|
|
17844
17846
|
|
|
17847
|
+
// src/hooks/useSceneConfig.ts
|
|
17848
|
+
import { useCallback as useCallback13, useRef as useRef20, useState as useState29 } from "react";
|
|
17849
|
+
|
|
17850
|
+
// src/utils/patchSceneConfig.ts
|
|
17851
|
+
function patchSceneConfig(sceneConfig, patch) {
|
|
17852
|
+
return deepMerge(sceneConfig, patch);
|
|
17853
|
+
}
|
|
17854
|
+
|
|
17855
|
+
// src/hooks/useSceneConfig.ts
|
|
17856
|
+
function useSceneConfig(initialSceneConfig) {
|
|
17857
|
+
const initialSceneConfigRef = useRef20(null);
|
|
17858
|
+
const [sceneConfig, setSceneConfig] = useState29(() => {
|
|
17859
|
+
const initial = typeof initialSceneConfig === "function" ? initialSceneConfig() : initialSceneConfig;
|
|
17860
|
+
initialSceneConfigRef.current = initial;
|
|
17861
|
+
return initial;
|
|
17862
|
+
});
|
|
17863
|
+
const updateSceneConfig = useCallback13((update) => {
|
|
17864
|
+
setSceneConfig((current) => {
|
|
17865
|
+
const patch = typeof update === "function" ? update(current) : update;
|
|
17866
|
+
return patchSceneConfig(current, patch);
|
|
17867
|
+
});
|
|
17868
|
+
}, []);
|
|
17869
|
+
const resetSceneConfig = useCallback13(() => {
|
|
17870
|
+
const initial = initialSceneConfigRef.current;
|
|
17871
|
+
if (initial) setSceneConfig(initial);
|
|
17872
|
+
}, []);
|
|
17873
|
+
return {
|
|
17874
|
+
sceneConfig,
|
|
17875
|
+
setSceneConfig,
|
|
17876
|
+
updateSceneConfig,
|
|
17877
|
+
resetSceneConfig
|
|
17878
|
+
};
|
|
17879
|
+
}
|
|
17880
|
+
|
|
17845
17881
|
// src/hooks/useViewerHover.ts
|
|
17846
|
-
import { useCallback as
|
|
17882
|
+
import { useCallback as useCallback14, useState as useState30 } from "react";
|
|
17847
17883
|
function useViewerHover() {
|
|
17848
|
-
const [hoveredObjectBinding, setHoveredObjectBinding] =
|
|
17849
|
-
const handleHoveredObject =
|
|
17884
|
+
const [hoveredObjectBinding, setHoveredObjectBinding] = useState30(null);
|
|
17885
|
+
const handleHoveredObject = useCallback14(
|
|
17850
17886
|
(binding) => {
|
|
17851
17887
|
setHoveredObjectBinding(binding);
|
|
17852
17888
|
},
|
|
@@ -17859,18 +17895,18 @@ function useViewerHover() {
|
|
|
17859
17895
|
}
|
|
17860
17896
|
|
|
17861
17897
|
// src/hooks/useViewerModel.ts
|
|
17862
|
-
import { useCallback as
|
|
17898
|
+
import { useCallback as useCallback15, useState as useState31 } from "react";
|
|
17863
17899
|
import { Box3 as Box36, Vector3 as Vector310 } from "three";
|
|
17864
17900
|
function toTuple2(vector) {
|
|
17865
17901
|
return [vector.x, vector.y, vector.z];
|
|
17866
17902
|
}
|
|
17867
17903
|
function useViewerModel() {
|
|
17868
|
-
const [isLoading, setIsLoading] =
|
|
17869
|
-
const [isReady, setIsReady] =
|
|
17870
|
-
const [error, setError] =
|
|
17871
|
-
const [bounds, setBounds] =
|
|
17872
|
-
const [objectCount, setObjectCount] =
|
|
17873
|
-
const handleModelLoaded =
|
|
17904
|
+
const [isLoading, setIsLoading] = useState31(true);
|
|
17905
|
+
const [isReady, setIsReady] = useState31(false);
|
|
17906
|
+
const [error, setError] = useState31(null);
|
|
17907
|
+
const [bounds, setBounds] = useState31(null);
|
|
17908
|
+
const [objectCount, setObjectCount] = useState31(0);
|
|
17909
|
+
const handleModelLoaded = useCallback15((scene) => {
|
|
17874
17910
|
const box = new Box36().setFromObject(scene);
|
|
17875
17911
|
const min = box.min.clone();
|
|
17876
17912
|
const max = box.max.clone();
|
|
@@ -17895,14 +17931,14 @@ function useViewerModel() {
|
|
|
17895
17931
|
setIsLoading(false);
|
|
17896
17932
|
setIsReady(true);
|
|
17897
17933
|
}, []);
|
|
17898
|
-
const handleLoadError =
|
|
17934
|
+
const handleLoadError = useCallback15((nextError) => {
|
|
17899
17935
|
setError(nextError);
|
|
17900
17936
|
setBounds(null);
|
|
17901
17937
|
setObjectCount(0);
|
|
17902
17938
|
setIsLoading(false);
|
|
17903
17939
|
setIsReady(false);
|
|
17904
17940
|
}, []);
|
|
17905
|
-
const resetModelState =
|
|
17941
|
+
const resetModelState = useCallback15(() => {
|
|
17906
17942
|
setIsLoading(true);
|
|
17907
17943
|
setIsReady(false);
|
|
17908
17944
|
setError(null);
|
|
@@ -17922,10 +17958,10 @@ function useViewerModel() {
|
|
|
17922
17958
|
}
|
|
17923
17959
|
|
|
17924
17960
|
// src/hooks/useViewerActions.ts
|
|
17925
|
-
import { useCallback as
|
|
17961
|
+
import { useCallback as useCallback16 } from "react";
|
|
17926
17962
|
function useViewerActions(objectBindings, options = {}) {
|
|
17927
17963
|
const { onAction, onObjectBindingsChange } = options;
|
|
17928
|
-
const getActionsForObject =
|
|
17964
|
+
const getActionsForObject = useCallback16(
|
|
17929
17965
|
(objectId) => {
|
|
17930
17966
|
const bindingKey = resolveBindingKey(objectBindings, objectId);
|
|
17931
17967
|
if (!bindingKey) {
|
|
@@ -17935,7 +17971,7 @@ function useViewerActions(objectBindings, options = {}) {
|
|
|
17935
17971
|
},
|
|
17936
17972
|
[objectBindings]
|
|
17937
17973
|
);
|
|
17938
|
-
const runAction =
|
|
17974
|
+
const runAction = useCallback16(
|
|
17939
17975
|
(objectId, actionId) => {
|
|
17940
17976
|
const bindingKey = resolveBindingKey(objectBindings, objectId);
|
|
17941
17977
|
if (!bindingKey) {
|
|
@@ -17977,7 +18013,7 @@ function useViewerActions(objectBindings, options = {}) {
|
|
|
17977
18013
|
}
|
|
17978
18014
|
|
|
17979
18015
|
// src/hooks/useShareableViewerState.ts
|
|
17980
|
-
import { useCallback as
|
|
18016
|
+
import { useCallback as useCallback17, useEffect as useEffect22, useRef as useRef21, useState as useState32 } from "react";
|
|
17981
18017
|
function serializeState(cameraState, objectBindings, selectedObjectBinding) {
|
|
17982
18018
|
const hidden = Object.values(objectBindings).filter((binding) => binding.visible === false).map((binding) => binding.id);
|
|
17983
18019
|
return {
|
|
@@ -17997,8 +18033,8 @@ function useShareableViewerState({
|
|
|
17997
18033
|
debounceMs = 400,
|
|
17998
18034
|
autoSync = true
|
|
17999
18035
|
}) {
|
|
18000
|
-
const lastWrittenRawRef =
|
|
18001
|
-
const buildHash =
|
|
18036
|
+
const lastWrittenRawRef = useRef21(null);
|
|
18037
|
+
const buildHash = useCallback17(() => {
|
|
18002
18038
|
const state = serializeState(
|
|
18003
18039
|
cameraState,
|
|
18004
18040
|
objectBindings,
|
|
@@ -18006,12 +18042,12 @@ function useShareableViewerState({
|
|
|
18006
18042
|
);
|
|
18007
18043
|
return `${paramKey}=${encodeURIComponent(JSON.stringify(state))}`;
|
|
18008
18044
|
}, [cameraState, objectBindings, selectedObjectBinding, paramKey]);
|
|
18009
|
-
const getShareUrl =
|
|
18045
|
+
const getShareUrl = useCallback17(() => {
|
|
18010
18046
|
const url = new URL(window.location.href);
|
|
18011
18047
|
url.hash = buildHash();
|
|
18012
18048
|
return url.toString();
|
|
18013
18049
|
}, [buildHash]);
|
|
18014
|
-
const syncUrl =
|
|
18050
|
+
const syncUrl = useCallback17(() => {
|
|
18015
18051
|
const url = new URL(window.location.href);
|
|
18016
18052
|
url.hash = buildHash();
|
|
18017
18053
|
window.history.replaceState(null, "", url.toString());
|
|
@@ -18019,7 +18055,7 @@ function useShareableViewerState({
|
|
|
18019
18055
|
paramKey
|
|
18020
18056
|
);
|
|
18021
18057
|
}, [buildHash, paramKey]);
|
|
18022
|
-
const latestStateRef =
|
|
18058
|
+
const latestStateRef = useRef21({
|
|
18023
18059
|
cameraState,
|
|
18024
18060
|
objectBindings,
|
|
18025
18061
|
selectedObjectBinding
|
|
@@ -18029,8 +18065,8 @@ function useShareableViewerState({
|
|
|
18029
18065
|
objectBindings,
|
|
18030
18066
|
selectedObjectBinding
|
|
18031
18067
|
};
|
|
18032
|
-
const [restoreAttempted, setRestoreAttempted] =
|
|
18033
|
-
const lastSyncedHashRef =
|
|
18068
|
+
const [restoreAttempted, setRestoreAttempted] = useState32(false);
|
|
18069
|
+
const lastSyncedHashRef = useRef21(null);
|
|
18034
18070
|
useEffect22(() => {
|
|
18035
18071
|
if (!autoSync || !restoreAttempted) return;
|
|
18036
18072
|
const tick = () => {
|
|
@@ -18053,9 +18089,9 @@ function useShareableViewerState({
|
|
|
18053
18089
|
const id = window.setInterval(tick, debounceMs);
|
|
18054
18090
|
return () => window.clearInterval(id);
|
|
18055
18091
|
}, [autoSync, restoreAttempted, debounceMs, paramKey]);
|
|
18056
|
-
const lastRestoredRawRef =
|
|
18057
|
-
const restoringRawRef =
|
|
18058
|
-
const restoreFromUrl =
|
|
18092
|
+
const lastRestoredRawRef = useRef21(null);
|
|
18093
|
+
const restoringRawRef = useRef21(null);
|
|
18094
|
+
const restoreFromUrl = useCallback17(async () => {
|
|
18059
18095
|
setRestoreAttempted(true);
|
|
18060
18096
|
const rawHash = window.location.hash.startsWith("#") ? window.location.hash.slice(1) : window.location.hash;
|
|
18061
18097
|
const raw = new URLSearchParams(rawHash).get(paramKey);
|
|
@@ -18127,9 +18163,11 @@ export {
|
|
|
18127
18163
|
SimpleModelViewer,
|
|
18128
18164
|
material,
|
|
18129
18165
|
patchBindings,
|
|
18166
|
+
patchSceneConfig,
|
|
18130
18167
|
useObjectBinding,
|
|
18131
18168
|
useObjectBindingIds,
|
|
18132
18169
|
useObjectBindings,
|
|
18170
|
+
useSceneConfig,
|
|
18133
18171
|
useShareableViewerState,
|
|
18134
18172
|
useViewerActions,
|
|
18135
18173
|
useViewerAnimations,
|