@liveroom-tech/react-immersive 2.2.0 → 3.0.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/dist/index.d.mts CHANGED
@@ -8,13 +8,25 @@ import { PresetsType } from '@react-three/drei/helpers/environment-assets';
8
8
 
9
9
  declare const LIGHT_TYPES: readonly ["none", "directional", "point", "hemisphere"];
10
10
  type SceneLightType = (typeof LIGHT_TYPES)[number];
11
+ type SceneLightAttachment = {
12
+ /** Binding key, binding id, modelObjectId, or raw model node name. */
13
+ objectId: string;
14
+ /** Local-space offset from the attached model object. */
15
+ offset: [number, number, number];
16
+ };
11
17
  type SceneLight = {
12
18
  id: string;
13
19
  type: SceneLightType;
14
20
  color: string;
15
21
  intensity: number;
16
22
  position: [number, number, number];
23
+ /** Point-light range. Zero means no distance limit. */
24
+ distance?: number;
25
+ /** Point-light physically correct decay. */
26
+ decay?: number;
17
27
  attachedToCamera: boolean;
28
+ /** Follow a model object instead of using the world-space position. */
29
+ attachment?: SceneLightAttachment;
18
30
  castShadow: boolean;
19
31
  shadowBias: number;
20
32
  visible: boolean;
@@ -322,6 +334,7 @@ type SceneConfig = {
322
334
  annotations: SceneAnnotationMarker[];
323
335
  cinematic?: SceneCinematicConfig;
324
336
  };
337
+ declare const DEFAULT_SCENE_CONFIG: SceneConfig;
325
338
 
326
339
  type CanvasCamera = ComponentProps<typeof Canvas>["camera"];
327
340
 
@@ -368,16 +381,183 @@ type CinematicConfig = {
368
381
 
369
382
  type MouseControllerPosition = 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' | 'center' | 'center-bottom' | 'center-top';
370
383
 
384
+ type CaptureImageOptions = {
385
+ width?: number;
386
+ height?: number;
387
+ transparent?: boolean;
388
+ };
389
+
390
+ type ViewerCameraState = {
391
+ position: [number, number, number];
392
+ target: [number, number, number];
393
+ fov: number | null;
394
+ zoom: number;
395
+ azimuthAngle?: number;
396
+ polarAngle?: number;
397
+ };
398
+ type ViewerCameraPreset = {
399
+ position: [number, number, number];
400
+ target: [number, number, number];
401
+ fov?: number | null;
402
+ zoom?: number;
403
+ azimuthAngle?: number;
404
+ polarAngle?: number;
405
+ };
406
+ type UseViewerCameraOptions = {
407
+ /** Camera position applied once when each model becomes ready. */
408
+ initialPosition?: [number, number, number];
409
+ /** Orbit target applied once when each model becomes ready. */
410
+ initialTarget?: [number, number, number];
411
+ /** Whether the initial position/target should animate. Defaults to false. */
412
+ initialTransition?: boolean;
413
+ /** Named views that can be opened with goToPreset. */
414
+ presets?: Record<string, ViewerCameraPreset>;
415
+ };
416
+ type HomeCameraState = {
417
+ position: [number, number, number];
418
+ target: [number, number, number];
419
+ };
420
+ type ViewerReadyState = {
421
+ controls: CameraControls;
422
+ scene: Object3D | null;
423
+ objectBindings: Record<string, ObjectBinding>;
424
+ nodeRefs: Record<string, Object3D>;
425
+ homeCameraState: HomeCameraState | null;
426
+ captureImage: (options?: CaptureImageOptions) => Promise<string>;
427
+ invalidate: () => void;
428
+ };
429
+ type ViewerCameraProps = {
430
+ cameraState: ViewerCameraState | null;
431
+ cameraPresets: Record<string, ViewerCameraPreset>;
432
+ resetView: () => Promise<boolean>;
433
+ focusObject: (objectId: string) => Promise<boolean>;
434
+ fitScene: () => Promise<boolean>;
435
+ setCameraTarget: (target: [number, number, number], enableTransition?: boolean) => Promise<boolean>;
436
+ setCameraState: (state: ViewerCameraState, enableTransition?: boolean) => Promise<boolean>;
437
+ lookAt: (position: [number, number, number], target: [number, number, number], enableTransition?: boolean) => Promise<boolean>;
438
+ orbitTo: (azimuthAngle: number, polarAngle: number, enableTransition?: boolean) => Promise<boolean>;
439
+ dollyTo: (distance: number, enableTransition?: boolean) => Promise<boolean>;
440
+ savePreset: (name: string) => ViewerCameraState | null;
441
+ goToPreset: (name: string, enableTransition?: boolean) => Promise<boolean>;
442
+ handleCameraChange: (camera: Camera, controls: CameraControls) => void;
443
+ handleViewerReady: (viewer: ViewerReadyState) => void;
444
+ };
445
+ declare function useViewerCamera(options?: UseViewerCameraOptions): ViewerCameraProps;
446
+
447
+ type DeepPartial<T> = T extends readonly unknown[] ? T : T extends object ? {
448
+ [K in keyof T]?: DeepPartial<T[K]>;
449
+ } : T;
450
+
451
+ type ObjectBindingSelector = {
452
+ group: string;
453
+ } | {
454
+ tag: string;
455
+ } | {
456
+ type: ObjectBindingType;
457
+ };
458
+ type ObjectBindingTarget = string | readonly string[] | ObjectBindingSelector;
459
+ /**
460
+ * Resolves IDs and selectors to binding-map keys in stable record order.
461
+ * Explicit ID arrays keep their supplied order. Duplicate matches are removed.
462
+ */
463
+ declare function selectBindingKeys(bindings: Record<string, ObjectBinding>, target: ObjectBindingTarget): string[];
464
+ /** Selects bindings by ID, group, tag, or binding type. */
465
+ declare function selectBindings(bindings: Record<string, ObjectBinding>, target: ObjectBindingTarget): ObjectBinding[];
466
+
467
+ type ObjectBindingPatch = DeepPartial<ObjectBinding>;
468
+ type BindingEdit = {
469
+ ids: ObjectBindingTarget;
470
+ patch: ObjectBindingPatch;
471
+ };
472
+ /**
473
+ * Applies field-level patches to object bindings and returns the updated
474
+ * record. Pure — nothing is mutated, and the original reference comes back
475
+ * untouched when no id matched, so React can skip the re-render.
476
+ *
477
+ * Ids resolve the same way everywhere else in the library: binding key first,
478
+ * then `binding.id`, then `binding.modelObjectId`.
479
+ */
480
+ declare function patchBindings(bindings: Record<string, ObjectBinding>, target: ObjectBindingTarget, patch: ObjectBindingPatch): Record<string, ObjectBinding>;
481
+ declare function patchBindings(bindings: Record<string, ObjectBinding>, edits: BindingEdit[]): Record<string, ObjectBinding>;
482
+ /** Shorthand for the common `{ style: { material: … } }` nesting. */
483
+ declare function material(value: ObjectBindingMaterial): ObjectBindingPatch;
484
+
485
+ type SceneConfigPatch = DeepPartial<SceneConfig>;
486
+ /**
487
+ * Applies a nested scene-config patch without mutating either input. Objects
488
+ * are merged recursively, while arrays and tuples are replaced wholesale.
489
+ */
490
+ declare function patchSceneConfig(sceneConfig: SceneConfig, patch: SceneConfigPatch): SceneConfig;
491
+
492
+ type ObjectBindingsActionEffect = {
493
+ target: ObjectBindingTarget;
494
+ objectBindings: ObjectBindingPatch;
495
+ };
496
+ type SceneConfigActionEffect = {
497
+ sceneConfig: SceneConfigPatch;
498
+ };
499
+ type VisibilityActionEffect = {
500
+ target: ObjectBindingTarget;
501
+ visibility: "show" | "hide" | "toggle";
502
+ };
503
+ type CameraAction = {
504
+ type: "focus-object";
505
+ objectId?: string;
506
+ } | {
507
+ type: "fit-scene";
508
+ } | {
509
+ type: "reset";
510
+ } | {
511
+ type: "set-target";
512
+ target: [number, number, number];
513
+ transition?: boolean;
514
+ } | {
515
+ type: "set-state";
516
+ state: ViewerCameraState;
517
+ transition?: boolean;
518
+ };
519
+ type CameraActionEffect = {
520
+ camera: CameraAction;
521
+ };
522
+ type AnimationAction = {
523
+ type: "play";
524
+ clip: string;
525
+ } | {
526
+ type: "pause";
527
+ } | {
528
+ type: "stop";
529
+ } | {
530
+ type: "set-speed";
531
+ speed: number;
532
+ } | {
533
+ type: "seek";
534
+ time: number;
535
+ };
536
+ type AnimationActionEffect = {
537
+ animation: AnimationAction;
538
+ };
539
+ type ObjectActionEffect = ObjectBindingsActionEffect | SceneConfigActionEffect | VisibilityActionEffect | CameraActionEffect | AnimationActionEffect;
540
+
371
541
  type ObjectBindingAction = {
372
542
  id: "change-color" | "apply-texture" | "toggle-visibility" | string;
373
543
  label: string;
374
544
  type: "command";
545
+ effects?: ObjectActionEffect[];
375
546
  };
376
547
  type ObjectBindingType = "body" | "other" | "glass" | "windshield" | "rear-windshield" | "window" | "sunroof" | "wheel" | "rim" | "tire" | "brake-caliper" | "brake-disc" | "suspension" | "spring" | "shock-absorber" | "axle" | "control-arm" | "interior" | "seat" | "headrest" | "seatbelt" | "dashboard" | "steering-wheel" | "gear-shift" | "center-console" | "armrest" | "door-panel" | "carpet" | "headliner" | "sun-visor" | "pedal" | "instrument-cluster" | "infotainment" | "glove-box" | "engine" | "gearbox" | "radiator" | "battery" | "fuel-tank" | "air-filter" | "intercooler" | "alternator" | "turbo" | "light" | "headlight" | "taillight" | "fog-light" | "indicator" | "daytime-running-light" | "interior-light" | "ambient-light" | "floor" | "floor-tile" | "floor-board" | "floor-mat" | "ceiling" | "ceiling-tile" | "wall" | "wall-tile" | "wall-panel" | "wall-trim" | "baseboard" | "crown-molding" | "column" | "pillar" | "beam" | "arch" | "stairs" | "step" | "railing" | "balustrade" | "window-frame" | "window-sill" | "blind" | "curtain" | "shutter" | "door" | "door-frame" | "door-knob" | "furniture" | "sofa" | "armchair" | "ottoman" | "bed" | "headboard" | "mattress" | "nightstand" | "dresser" | "wardrobe" | "closet" | "shelf" | "bookcase" | "desk" | "office-chair" | "dining-table" | "dining-chair" | "bar-stool" | "bench" | "cabinet" | "sideboard" | "coffee-table" | "side-table" | "tv-stand" | "kitchen-island" | "countertop" | "sink" | "bathtub" | "shower" | "toilet" | "vanity" | "decor" | "rug" | "cushion" | "throw" | "curtain-rod" | "artwork" | "mirror" | "vase" | "plant" | "pot" | "candle" | "frame" | "sculpture" | "clock" | "lamp" | "floor-lamp" | "table-lamp" | "pendant-light" | "chandelier" | "sconce" | "ceiling-fan" | "electronics" | "tv" | "monitor" | "speaker" | "soundbar" | "projector" | "remote" | "console" | "router" | "smart-hub" | "thermostat" | "appliance" | "refrigerator" | "oven" | "microwave" | "dishwasher" | "washing-machine" | "dryer" | "air-conditioner" | "heater" | "ventilation" | "root" | "bone" | "joint" | "socket" | "pivot" | "head" | "face" | "eye" | "eyelid" | "eyebrow" | "mouth" | "teeth" | "tongue" | "ear" | "nose" | "hair" | "beard" | "neck" | "torso" | "chest" | "abdomen" | "back" | "shoulder" | "upper-arm" | "forearm" | "hand" | "finger" | "thumb" | "hip" | "thigh" | "shin" | "foot" | "toe" | "tail" | "wing" | "tentacle" | "clothing" | "hat" | "helmet" | "visor" | "mask" | "goggles" | "glasses" | "jacket" | "shirt" | "pants" | "skirt" | "shoes" | "boots" | "gloves" | "belt" | "watch" | "bag" | "backpack" | "jewelry" | "necklace" | "ring" | "armor" | "chest-plate" | "pauldron" | "gauntlet" | "greave" | "shield" | "weapon" | "blade" | "edge" | "tip" | "guard" | "grip" | "pommel" | "barrel" | "stock" | "scope" | "trigger" | "magazine" | "muzzle" | "gear" | "piston" | "lever" | "valve" | "pump" | "motor" | "rotor" | "blade-prop" | "nozzle" | "pipe" | "tube" | "cable" | "wire" | "connector" | "panel" | "hatch" | "vent" | "antenna" | "sensor" | "camera" | "screen" | "dial" | "button" | "knob" | "switch" | "gauge" | "terrain" | "ground" | "rock" | "cliff" | "water" | "ocean" | "river" | "lake" | "wave" | "foam" | "sky" | "cloud" | "sun" | "moon" | "star" | "fog" | "foliage" | "tree" | "branch" | "leaf" | "grass" | "bush" | "flower" | "soil" | "sand" | "snow" | "ice" | "facade" | "foundation" | "roof-structure" | "chimney" | "balcony" | "porch" | "pathway" | "fence" | "gate" | "wall-exterior";
377
548
  type ObjectBindingStatus = "normal" | "hidden" | "selected" | "disabled";
378
549
  type ObjectBindingTextureSlot = {
379
550
  path: string;
380
551
  };
552
+ type ObjectBindingTextureChannel = "baseColor" | "metalness" | "roughness" | "emissive" | "alpha" | "normal" | "bump" | "ao" | "displacement" | "clearcoat" | "clearcoatRoughness" | "clearcoatNormal" | "anisotropy" | "transmission" | "thickness" | "sheenColor" | "sheenRoughness" | "specularIntensity" | "specularColor";
553
+ type ObjectBindingTransform = {
554
+ /** Local-space position in model units. */
555
+ position?: [number, number, number];
556
+ /** Local-space Euler rotation in radians. */
557
+ rotation?: [number, number, number];
558
+ /** Local-space scale. */
559
+ scale?: [number, number, number];
560
+ };
381
561
  declare const MATERIAL_SIDES: readonly ["front", "back", "double"];
382
562
  type ObjectBindingMaterialSide = (typeof MATERIAL_SIDES)[number];
383
563
  declare const MATERIAL_BLENDING_MODES: readonly ["normal", "additive"];
@@ -450,10 +630,13 @@ type ObjectBinding = {
450
630
  type: ObjectBindingType;
451
631
  modelObjectId: string;
452
632
  label?: string;
633
+ group?: string;
634
+ tags?: string[];
453
635
  status?: ObjectBindingStatus;
454
636
  visible?: boolean;
455
637
  selectable?: boolean;
456
638
  hoverable?: boolean;
639
+ transform?: ObjectBindingTransform;
457
640
  style?: ObjectBindingStyle;
458
641
  actions?: ObjectBindingAction[];
459
642
  metrics?: Record<string, number>;
@@ -468,44 +651,6 @@ type ObjectActionEvent = {
468
651
  screenY?: number;
469
652
  };
470
653
 
471
- type CaptureImageOptions = {
472
- width?: number;
473
- height?: number;
474
- transparent?: boolean;
475
- };
476
-
477
- type ViewerCameraState = {
478
- position: [number, number, number];
479
- target: [number, number, number];
480
- fov: number | null;
481
- zoom: number;
482
- azimuthAngle?: number;
483
- polarAngle?: number;
484
- };
485
- type HomeCameraState = {
486
- position: [number, number, number];
487
- target: [number, number, number];
488
- };
489
- type ViewerReadyState = {
490
- controls: CameraControls;
491
- scene: Object3D | null;
492
- objectBindings: Record<string, ObjectBinding>;
493
- nodeRefs: Record<string, Object3D>;
494
- homeCameraState: HomeCameraState | null;
495
- captureImage: (options?: CaptureImageOptions) => Promise<string>;
496
- };
497
- type ViewerCameraProps = {
498
- cameraState: ViewerCameraState | null;
499
- resetView: () => Promise<boolean>;
500
- focusObject: (objectId: string) => Promise<boolean>;
501
- fitScene: () => Promise<boolean>;
502
- setCameraTarget: (target: [number, number, number], enableTransition?: boolean) => Promise<boolean>;
503
- setCameraState: (state: ViewerCameraState, enableTransition?: boolean) => Promise<boolean>;
504
- handleCameraChange: (camera: Camera, controls: CameraControls) => void;
505
- handleViewerReady: (viewer: ViewerReadyState) => void;
506
- };
507
- declare function useViewerCamera(): ViewerCameraProps;
508
-
509
654
  type AnimationClipInfo = {
510
655
  sourceName: string;
511
656
  duration: number;
@@ -665,45 +810,31 @@ declare function useObjectBinding(objectBindings: Record<string, ObjectBinding>,
665
810
 
666
811
  declare function useObjectBindingIds(objectBindings: Record<string, ObjectBinding>): string[];
667
812
 
668
- type DeepPartial<T> = T extends readonly unknown[] ? T : T extends object ? {
669
- [K in keyof T]?: DeepPartial<T[K]>;
670
- } : T;
671
-
672
- type ObjectBindingPatch = DeepPartial<ObjectBinding>;
673
- type BindingEdit = {
674
- ids: string | string[];
675
- patch: ObjectBindingPatch;
676
- };
677
- /**
678
- * Applies field-level patches to object bindings and returns the updated
679
- * record. Pure — nothing is mutated, and the original reference comes back
680
- * untouched when no id matched, so React can skip the re-render.
681
- *
682
- * Ids resolve the same way everywhere else in the library: binding key first,
683
- * then `binding.id`, then `binding.modelObjectId`.
684
- */
685
- declare function patchBindings(bindings: Record<string, ObjectBinding>, objectId: string | string[], patch: ObjectBindingPatch): Record<string, ObjectBinding>;
686
- declare function patchBindings(bindings: Record<string, ObjectBinding>, edits: BindingEdit[]): Record<string, ObjectBinding>;
687
- /** Shorthand for the common `{ style: { material: … } }` nesting. */
688
- declare function material(value: ObjectBindingMaterial): ObjectBindingPatch;
689
-
690
813
  type HiddenObjectsState = Record<string, boolean>;
691
814
  type ObjectBindingsController = {
692
815
  objectBindings: Record<string, ObjectBinding>;
693
816
  setObjectBindings: React.Dispatch<React.SetStateAction<Record<string, ObjectBinding>>>;
694
817
  updateObjectBindings: {
695
- (objectId: string | string[], patch: ObjectBindingPatch): void;
818
+ (target: ObjectBindingTarget, patch: ObjectBindingPatch): void;
696
819
  (edits: BindingEdit[]): void;
697
820
  };
698
- setMaterial: (objectId: string | string[], material: ObjectBindingMaterial) => void;
699
- setBaseColor: (objectId: string | string[], color: string) => void;
700
- resetMaterial: (objectId: string | string[]) => void;
821
+ setMaterial: (target: ObjectBindingTarget, material: ObjectBindingMaterial) => void;
822
+ setBaseColor: (target: ObjectBindingTarget, color: string) => void;
823
+ setTexture: (target: ObjectBindingTarget, texture: string | ObjectBindingTextureSlot, channel?: ObjectBindingTextureChannel) => void;
824
+ clearTexture: (target: ObjectBindingTarget, channel?: ObjectBindingTextureChannel) => void;
825
+ copyMaterial: (source: string, target: ObjectBindingTarget) => void;
826
+ resetMaterial: (target: ObjectBindingTarget) => void;
701
827
  getMaterial: (objectId: string) => ObjectBindingMaterial | null;
828
+ setTransform: (target: ObjectBindingTarget, transform: ObjectBindingTransform) => void;
829
+ resetTransform: (target: ObjectBindingTarget) => void;
830
+ updateMetadata: (target: ObjectBindingTarget, metadata: Record<string, unknown>) => void;
831
+ selectObjectBindings: (target: ObjectBindingTarget) => ObjectBinding[];
832
+ selectObjectBindingIds: (target: ObjectBindingTarget) => string[];
702
833
  hiddenObjects: HiddenObjectsState;
703
834
  hiddenObjectIds: string[];
704
- hideObject: (objectId: string | string[]) => void;
705
- showObject: (objectId: string | string[]) => void;
706
- toggleObjectVisibility: (objectId: string | string[]) => void;
835
+ hideObject: (target: ObjectBindingTarget) => void;
836
+ showObject: (target: ObjectBindingTarget) => void;
837
+ toggleObjectVisibility: (target: ObjectBindingTarget) => void;
707
838
  isObjectHidden: (objectId: string) => boolean;
708
839
  clearHiddenObjects: () => void;
709
840
  };
@@ -716,12 +847,19 @@ type ObjectBindingsController = {
716
847
  */
717
848
  declare function useObjectBindings(initialBindings: Record<string, ObjectBinding> | (() => Record<string, ObjectBinding>)): ObjectBindingsController;
718
849
 
719
- type SceneConfigPatch = DeepPartial<SceneConfig>;
720
850
  /**
721
- * Applies a nested scene-config patch without mutating either input. Objects
722
- * are merged recursively, while arrays and tuples are replaced wholesale.
851
+ * Validates an object-bindings literal while preserving its exact keys and
852
+ * literal values for TypeScript autocomplete and derived union types.
853
+ *
854
+ * This is an identity function at runtime.
723
855
  */
724
- declare function patchSceneConfig(sceneConfig: SceneConfig, patch: SceneConfigPatch): SceneConfig;
856
+ declare function defineObjectBindings<const TBindings extends Record<string, ObjectBinding>>(bindings: TBindings): TBindings;
857
+ /** Binding-map keys preserved by defineObjectBindings. */
858
+ type ObjectBindingKey<TBindings extends Record<string, ObjectBinding>> = Extract<keyof TBindings, string>;
859
+ /** Action ids declared on one binding in a defined bindings map. */
860
+ type ObjectBindingActionId<TBindings extends Record<string, ObjectBinding>, TKey extends ObjectBindingKey<TBindings>> = TBindings[TKey]["actions"] extends readonly (infer TAction)[] ? TAction extends {
861
+ id: infer TId extends string;
862
+ } ? TId : never : never;
725
863
 
726
864
  type SceneConfigUpdate = SceneConfigPatch | ((current: SceneConfig) => SceneConfigPatch);
727
865
  type SceneConfigController = {
@@ -729,6 +867,23 @@ type SceneConfigController = {
729
867
  setSceneConfig: React.Dispatch<React.SetStateAction<SceneConfig>>;
730
868
  updateSceneConfig: (update: SceneConfigUpdate) => void;
731
869
  resetSceneConfig: () => void;
870
+ lights: SceneLightsController;
871
+ };
872
+ type SceneLightInput = Pick<SceneLight, "id"> & Partial<Omit<SceneLight, "id">>;
873
+ type SceneLightPatch = Partial<Omit<SceneLight, "id">>;
874
+ type SceneLightsController = {
875
+ items: SceneLight[];
876
+ get: (id: string) => SceneLight | undefined;
877
+ add: (light: SceneLightInput) => void;
878
+ update: (id: string, patch: SceneLightPatch) => void;
879
+ remove: (id: string) => void;
880
+ setIntensity: (id: string, intensity: number) => void;
881
+ setColor: (id: string, color: string) => void;
882
+ show: (id: string) => void;
883
+ hide: (id: string) => void;
884
+ toggle: (id: string) => void;
885
+ attach: (id: string, attachment: SceneLightAttachment) => void;
886
+ detach: (id: string) => void;
732
887
  };
733
888
  /**
734
889
  * Owns scene-config state and applies nested patches through functional React
@@ -760,15 +915,170 @@ type ViewerModelProps = {
760
915
  };
761
916
  declare function useViewerModel(): ViewerModelProps;
762
917
 
918
+ type ViewerActionBindingsController = Pick<ObjectBindingsController, "objectBindings" | "updateObjectBindings" | "showObject" | "hideObject" | "toggleObjectVisibility">;
919
+ type ViewerActionSceneController = Pick<SceneConfigController, "updateSceneConfig">;
920
+ type ViewerActionCameraController = Pick<ViewerCameraProps, "focusObject" | "fitScene" | "resetView" | "setCameraTarget" | "setCameraState">;
921
+ type ViewerActionAnimationController = Pick<ViewerAnimationsProps, "play" | "pause" | "stop" | "setSpeed" | "seek">;
763
922
  type ViewerActionsOptions = {
764
- onAction?: (event: ObjectActionEvent) => void;
765
- onObjectBindingsChange?: (next: Record<string, ObjectBinding>) => void;
923
+ bindings: ViewerActionBindingsController;
924
+ scene?: ViewerActionSceneController;
925
+ camera?: ViewerActionCameraController;
926
+ animations?: ViewerActionAnimationController;
927
+ onAction?: (event: ObjectActionEvent) => void | Promise<void>;
766
928
  };
767
929
  type ViewerActionsProps = {
768
930
  getActionsForObject: (objectId: string) => ObjectBindingAction[];
769
- runAction: (objectId: string, actionId: string) => ObjectActionEvent | null;
931
+ handleAction: (event: ObjectActionEvent) => Promise<void>;
932
+ runAction: (objectId: string, actionId: string) => Promise<ObjectActionEvent | null>;
933
+ };
934
+ /**
935
+ * Resolves object actions and executes their declarative binding, scene,
936
+ * visibility, camera, and animation effects in declaration order.
937
+ */
938
+ declare function useViewerActions({ bindings, scene, camera, animations, onAction, }: ViewerActionsOptions): ViewerActionsProps;
939
+
940
+ type ViewerReadyHandler = (viewer: ViewerReadyState) => void;
941
+ type ViewerReadyConsumer = ViewerReadyHandler | {
942
+ handleViewerReady: ViewerReadyHandler;
943
+ } | null | undefined;
944
+ type ViewerConnectionController = {
945
+ /** The single callback to pass to ModelViewer's onViewerReady prop. */
946
+ handleViewerReady: ViewerReadyHandler;
947
+ /** Returns the latest live viewer without causing camera-change rerenders. */
948
+ getViewer: () => ViewerReadyState | null;
949
+ /** Captures the connected viewer, or rejects when it is not ready yet. */
950
+ captureImage: (options?: CaptureImageOptions) => Promise<string>;
951
+ /** Requests a frame from the connected viewer. */
952
+ invalidate: () => boolean;
953
+ };
954
+ /**
955
+ * Composes camera, effects, and custom viewer-ready consumers into one typed
956
+ * ModelViewer connection. Pass the returned handleViewerReady to ModelViewer.
957
+ */
958
+ declare function useViewerConnection(...consumers: readonly ViewerReadyConsumer[]): ViewerConnectionController;
959
+
960
+ type ViewerEffectTarget = ObjectBindingTarget;
961
+ type ViewerVector3 = readonly [number, number, number];
962
+ type ViewerEffectRange = readonly [number, number];
963
+ type RuntimeMaterialPatch = {
964
+ baseColor?: string;
965
+ emissive?: string;
966
+ emissiveIntensity?: number;
967
+ opacity?: number;
968
+ metalness?: number;
969
+ roughness?: number;
970
+ transmission?: number;
971
+ clearcoat?: number;
972
+ clearcoatRoughness?: number;
973
+ ior?: number;
974
+ thickness?: number;
975
+ transparent?: boolean;
976
+ };
977
+ type RuntimeTransformPatch = {
978
+ position?: ViewerVector3;
979
+ rotation?: ViewerVector3;
980
+ scale?: ViewerVector3 | number;
981
+ visible?: boolean;
982
+ };
983
+ type RuntimeMaterialRanges = Partial<Record<"emissiveIntensity" | "opacity" | "metalness" | "roughness" | "transmission" | "clearcoat" | "clearcoatRoughness" | "ior" | "thickness", ViewerEffectRange>>;
984
+ type RuntimeTransformRanges = {
985
+ position?: readonly [ViewerVector3, ViewerVector3];
986
+ rotation?: readonly [ViewerVector3, ViewerVector3];
987
+ scale?: readonly [ViewerVector3, ViewerVector3];
988
+ };
989
+ type ViewerMaterialEffectChannel = {
990
+ targets: ViewerEffectTarget;
991
+ values: RuntimeMaterialRanges;
992
+ };
993
+ type ViewerTransformEffectChannel = {
994
+ targets: ViewerEffectTarget;
995
+ values: RuntimeTransformRanges;
996
+ };
997
+ type ViewerLightEffectChannel = {
998
+ lights: string | readonly string[];
999
+ intensity: ViewerEffectRange;
1000
+ };
1001
+ type ViewerEffectChannels = {
1002
+ materials?: ViewerMaterialEffectChannel[];
1003
+ transforms?: ViewerTransformEffectChannel[];
1004
+ lights?: ViewerLightEffectChannel[];
1005
+ };
1006
+ type ViewerEffectEasing = "linear" | "ease-in" | "ease-out" | "ease-in-out";
1007
+ type ViewerTransitionOptions = {
1008
+ id?: string;
1009
+ duration?: number;
1010
+ easing?: ViewerEffectEasing;
1011
+ onComplete?: () => void;
1012
+ };
1013
+ type ViewerTimelineStep = {
1014
+ channels: ViewerEffectChannels;
1015
+ duration: number;
1016
+ hold?: number;
1017
+ easing?: ViewerEffectEasing;
1018
+ };
1019
+ type ViewerTimelineOptions = {
1020
+ id?: string;
1021
+ repeat?: number;
1022
+ onComplete?: () => void;
770
1023
  };
771
- declare function useViewerActions(objectBindings: Record<string, ObjectBinding>, options?: ViewerActionsOptions): ViewerActionsProps;
1024
+ type ViewerPulseOptions = {
1025
+ id?: string;
1026
+ duration?: number;
1027
+ minLevel?: number;
1028
+ maxLevel?: number;
1029
+ repeat?: number;
1030
+ synchronized?: boolean;
1031
+ onComplete?: () => void;
1032
+ };
1033
+ type ViewerFlickerOptions = {
1034
+ id?: string;
1035
+ minLevel?: number;
1036
+ maxLevel?: number;
1037
+ interval?: number | ViewerEffectRange;
1038
+ response?: number;
1039
+ blackoutChance?: number;
1040
+ flashChance?: number;
1041
+ flashLevel?: number;
1042
+ synchronized?: boolean;
1043
+ duration?: number;
1044
+ onComplete?: () => void;
1045
+ };
1046
+ type RuntimePointLightOptions = {
1047
+ id: string;
1048
+ target: string;
1049
+ color?: string;
1050
+ intensity?: number;
1051
+ distance?: number;
1052
+ decay?: number;
1053
+ offset?: ViewerVector3;
1054
+ castShadow?: boolean;
1055
+ };
1056
+ type RuntimePointLightPatch = Partial<Omit<RuntimePointLightOptions, "id">>;
1057
+ type UseViewerEffectsOptions = {
1058
+ onViewerReady?: (viewer: ViewerReadyState) => void;
1059
+ };
1060
+ type ViewerEffectsController = {
1061
+ handleViewerReady: (viewer: ViewerReadyState) => void;
1062
+ setMaterial: (target: ViewerEffectTarget, patch: RuntimeMaterialPatch) => boolean;
1063
+ setTransform: (target: ViewerEffectTarget, patch: RuntimeTransformPatch) => boolean;
1064
+ getWorldPosition: (target: string) => ViewerVector3 | null;
1065
+ addPointLight: (options: RuntimePointLightOptions) => boolean;
1066
+ updatePointLight: (id: string, patch: RuntimePointLightPatch) => boolean;
1067
+ removePointLight: (id: string) => boolean;
1068
+ transition: (channels: ViewerEffectChannels, options?: ViewerTransitionOptions) => string;
1069
+ timeline: (steps: readonly ViewerTimelineStep[], options?: ViewerTimelineOptions) => string;
1070
+ pulse: (channels: ViewerEffectChannels, options?: ViewerPulseOptions) => string;
1071
+ flicker: (channels: ViewerEffectChannels, options?: ViewerFlickerOptions) => string;
1072
+ overrideEffect: (id: string, level: number, duration: number) => boolean;
1073
+ stopEffect: (id: string) => boolean;
1074
+ stopAllEffects: () => void;
1075
+ resetRuntime: () => void;
1076
+ };
1077
+ /**
1078
+ * Applies live material, transform, and point-light effects without putting
1079
+ * frame-by-frame values in React state or exposing Three.js objects to the app.
1080
+ */
1081
+ declare function useViewerEffects(options?: UseViewerEffectsOptions): ViewerEffectsController;
772
1082
 
773
1083
  type UseShareableViewerStateOptions = {
774
1084
  cameraState: ViewerCameraState | null;
@@ -788,4 +1098,4 @@ type ShareableViewerStateProps = {
788
1098
  };
789
1099
  declare function useShareableViewerState({ cameraState, setCameraState, objectBindings, onObjectBindingsChange, selectedObjectBinding, setSelectedObjectBinding, paramKey, debounceMs, autoSync, }: UseShareableViewerStateOptions): ShareableViewerStateProps;
790
1100
 
791
- 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 };
1101
+ export { type AnimationAction, type AnimationActionEffect, type AnimationClipInfo, type AnimationControls, type AnimationLoopMode, type AnimationPlaybackState, BindingBuilder, type BindingEdit, type CameraAction, type CameraActionEffect, type CaptureImageOptions, type CinematicConfig, type CinematicWaypoint, type CustomObjectBindingDataPanelProps, type CustomSceneObjectsPanelProps, DEFAULT_SCENE_CONFIG, type HiddenObjectsState, type HomeCameraState, MATERIAL_BLENDING_MODES, MATERIAL_SIDES, ModelViewer, type ModelViewerProps, type ObjectActionEffect, type ObjectActionEvent, type ObjectBinding, type ObjectBindingAction, type ObjectBindingActionId, type ObjectBindingKey, type ObjectBindingMaterial, type ObjectBindingMaterialBlendingMode, type ObjectBindingMaterialSide, type ObjectBindingPatch, type ObjectBindingSelector, type ObjectBindingTarget, type ObjectBindingTextureChannel, type ObjectBindingTextureSlot, type ObjectBindingTransform, type ObjectBindingsActionEffect, type ObjectBindingsController, type RuntimeMaterialPatch, type RuntimeMaterialRanges, type RuntimePointLightOptions, type RuntimePointLightPatch, type RuntimeTransformPatch, type RuntimeTransformRanges, type SceneAnimationClipConfig, type SceneAnimationConfig, type SceneCinematicConfig, type SceneCinematicWaypoint, type SceneConfig, type SceneConfigActionEffect, type SceneConfigController, type SceneConfigPatch, type SceneConfigUpdate, type SceneLight, type SceneLightAttachment, type SceneLightInput, type SceneLightPatch, type SceneLightType, type SceneLightsController, type SceneModelRenderer, SimpleModelViewer, type SimpleModelViewerProps, type UseViewerCameraOptions, type UseViewerEffectsOptions, type ViewerActionAnimationController, type ViewerActionBindingsController, type ViewerActionCameraController, type ViewerActionSceneController, type ViewerActionsOptions, type ViewerActionsProps, type ViewerAnimationsProps, type ViewerCameraPreset, type ViewerCameraProps, type ViewerCameraState, type ViewerConnectionController, type ViewerEffectChannels, type ViewerEffectEasing, type ViewerEffectRange, type ViewerEffectTarget, type ViewerEffectsController, type ViewerFlickerOptions, type ViewerLightEffectChannel, type ViewerMaterialEffectChannel, type ViewerModelBounds, type ViewerModelProps, type ViewerPulseOptions, type ViewerReadyConsumer, type ViewerReadyHandler, type ViewerReadyState, type ViewerSelectionProps, type ViewerTimelineOptions, type ViewerTimelineStep, type ViewerTransformEffectChannel, type ViewerTransitionOptions, type ViewerVector3, type VisibilityActionEffect, type XRScaleMode, defineObjectBindings, material, patchBindings, patchSceneConfig, selectBindingKeys, selectBindings, useObjectBinding, useObjectBindingIds, useObjectBindings, useSceneConfig, useShareableViewerState, useViewerActions, useViewerAnimations, useViewerCamera, useViewerConnection, useViewerEffects, useViewerHover, useViewerModel, useViewerSelection };