@react-three/fiber 7.0.19 → 7.0.23

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,29 @@
1
1
  # @react-three/fiber
2
2
 
3
+ ## 7.0.23
4
+
5
+ ### Patch Changes
6
+
7
+ - 30d38b1: remove logs
8
+
9
+ ## 7.0.22
10
+
11
+ ### Patch Changes
12
+
13
+ - 259e1fa: add camera:manual
14
+
15
+ ## 7.0.21
16
+
17
+ ### Patch Changes
18
+
19
+ - 65e4147: up usemeasure, add last event to internals"
20
+
21
+ ## 7.0.20
22
+
23
+ ### Patch Changes
24
+
25
+ - 54cb0fd: update react-use-measure, allow it to use the offsetSize
26
+
3
27
  ## 7.0.19
4
28
 
5
29
  ### Patch Changes
@@ -4,7 +4,7 @@ import type { RootState } from './store';
4
4
  export interface Intersection extends THREE.Intersection {
5
5
  eventObject: THREE.Object3D;
6
6
  }
7
- export interface IntesectionEvent<TSourceEvent> extends Intersection {
7
+ export interface IntersectionEvent<TSourceEvent> extends Intersection {
8
8
  intersections: Intersection[];
9
9
  stopped: boolean;
10
10
  unprojectedPoint: THREE.Vector3;
@@ -18,8 +18,8 @@ export interface IntesectionEvent<TSourceEvent> extends Intersection {
18
18
  spaceY: number;
19
19
  }
20
20
  export declare type Camera = THREE.OrthographicCamera | THREE.PerspectiveCamera;
21
- export declare type ThreeEvent<TEvent> = TEvent & IntesectionEvent<TEvent>;
22
- export declare type DomEvent = ThreeEvent<PointerEvent | MouseEvent | WheelEvent>;
21
+ export declare type ThreeEvent<TEvent> = IntersectionEvent<TEvent>;
22
+ export declare type DomEvent = PointerEvent | MouseEvent | WheelEvent;
23
23
  export declare type Events = {
24
24
  onClick: EventListener;
25
25
  onContextMenu: EventListener;
@@ -43,7 +43,7 @@ export declare type EventHandlers = {
43
43
  onPointerEnter?: (event: ThreeEvent<PointerEvent>) => void;
44
44
  onPointerLeave?: (event: ThreeEvent<PointerEvent>) => void;
45
45
  onPointerMove?: (event: ThreeEvent<PointerEvent>) => void;
46
- onPointerMissed?: (event: ThreeEvent<PointerEvent>) => void;
46
+ onPointerMissed?: (event: MouseEvent) => void;
47
47
  onPointerCancel?: (event: ThreeEvent<PointerEvent>) => void;
48
48
  onWheel?: (event: ThreeEvent<WheelEvent>) => void;
49
49
  };
@@ -47,8 +47,9 @@ export declare type InternalState = {
47
47
  priority: number;
48
48
  frames: number;
49
49
  lastProps: StoreProps;
50
+ lastEvent: React.MutableRefObject<DomEvent | null>;
50
51
  interaction: THREE.Object3D[];
51
- hovered: Map<string, DomEvent>;
52
+ hovered: Map<string, ThreeEvent<DomEvent>>;
52
53
  subscribers: Subscription[];
53
54
  capturedMap: Map<number, Map<THREE.Object3D, PointerCaptureTarget>>;
54
55
  initialClick: [x: number, y: number];
@@ -58,7 +59,9 @@ export declare type InternalState = {
58
59
  export declare type RootState = {
59
60
  gl: THREE.WebGLRenderer;
60
61
  scene: THREE.Scene;
61
- camera: Camera;
62
+ camera: Camera & {
63
+ manual?: boolean;
64
+ };
62
65
  controls: THREE.EventDispatcher | null;
63
66
  raycaster: Raycaster;
64
67
  mouse: THREE.Vector2;
@@ -78,7 +81,8 @@ export declare type RootState = {
78
81
  advance: (timestamp: number, runGlobalEffects?: boolean) => void;
79
82
  setSize: (width: number, height: number) => void;
80
83
  setDpr: (dpr: Dpr) => void;
81
- onPointerMissed?: (event: ThreeEvent<PointerEvent>) => void;
84
+ setFrameloop: (frameloop?: 'always' | 'demand' | 'never') => void;
85
+ onPointerMissed?: (event: MouseEvent) => void;
82
86
  events: EventManager<any>;
83
87
  internal: InternalState;
84
88
  };
@@ -100,8 +104,10 @@ export declare type StoreProps = {
100
104
  dpr?: Dpr;
101
105
  clock?: THREE.Clock;
102
106
  raycaster?: Partial<Raycaster>;
103
- camera?: Camera | Partial<ReactThreeFiber.Object3DNode<THREE.Camera, typeof THREE.Camera> & ReactThreeFiber.Object3DNode<THREE.PerspectiveCamera, typeof THREE.PerspectiveCamera> & ReactThreeFiber.Object3DNode<THREE.OrthographicCamera, typeof THREE.OrthographicCamera>>;
104
- onPointerMissed?: (event: ThreeEvent<PointerEvent>) => void;
107
+ camera?: (Camera | Partial<ReactThreeFiber.Object3DNode<THREE.Camera, typeof THREE.Camera> & ReactThreeFiber.Object3DNode<THREE.PerspectiveCamera, typeof THREE.PerspectiveCamera> & ReactThreeFiber.Object3DNode<THREE.OrthographicCamera, typeof THREE.OrthographicCamera>>) & {
108
+ manual?: boolean;
109
+ };
110
+ onPointerMissed?: (event: MouseEvent) => void;
105
111
  };
106
112
  export declare type ApplyProps = (instance: Instance, newProps: InstanceProps) => void;
107
113
  export declare function calculateDpr(dpr: Dpr): number;
@@ -23,7 +23,7 @@ export interface NodeProps<T, P> {
23
23
  attachFns?: [AttachCallback, AttachCallback];
24
24
  args?: Args<P>;
25
25
  children?: React.ReactNode;
26
- ref?: React.Ref<React.ReactNode>;
26
+ ref?: React.RefCallback<T> | React.RefObject<React.ReactNode> | null;
27
27
  key?: React.Key;
28
28
  onUpdate?: (self: T) => void;
29
29
  }
@@ -59,7 +59,6 @@ export declare type LineSegmentsProps = Object3DNode<THREE.LineSegments, typeof
59
59
  export declare type LineLoopProps = Object3DNode<THREE.LineLoop, typeof THREE.LineLoop>;
60
60
  export declare type PointsProps = Object3DNode<THREE.Points, typeof THREE.Points>;
61
61
  export declare type GroupProps = Object3DNode<THREE.Group, typeof THREE.Group>;
62
- export declare type ImmediateRenderObjectProps = Object3DNode<THREE.ImmediateRenderObject, typeof THREE.ImmediateRenderObject>;
63
62
  export declare type CameraProps = Object3DNode<THREE.Camera, typeof THREE.Camera>;
64
63
  export declare type PerspectiveCameraProps = Object3DNode<THREE.PerspectiveCamera, typeof THREE.PerspectiveCamera>;
65
64
  export declare type OrthographicCameraProps = Object3DNode<THREE.OrthographicCamera, typeof THREE.OrthographicCamera>;
@@ -175,6 +174,7 @@ export declare type Matrix3Props = Node<THREE.Matrix3, typeof THREE.Matrix3>;
175
174
  export declare type Matrix4Props = Node<THREE.Matrix4, typeof THREE.Matrix4>;
176
175
  export declare type QuaternionProps = Node<THREE.Quaternion, typeof THREE.Quaternion>;
177
176
  export declare type BufferAttributeProps = Node<THREE.BufferAttribute, typeof THREE.BufferAttribute>;
177
+ export declare type Float32BufferAttributeProps = Node<THREE.Float32BufferAttribute, typeof THREE.Float32BufferAttribute>;
178
178
  export declare type InstancedBufferAttributeProps = Node<THREE.InstancedBufferAttribute, typeof THREE.InstancedBufferAttribute>;
179
179
  export declare type ColorProps = Node<THREE.Color, ColorArray>;
180
180
  export declare type FogProps = Node<THREE.Fog, typeof THREE.Fog>;
@@ -197,7 +197,6 @@ declare global {
197
197
  lineLoop: LineLoopProps;
198
198
  points: PointsProps;
199
199
  group: GroupProps;
200
- immediateRenderObject: ImmediateRenderObjectProps;
201
200
  camera: CameraProps;
202
201
  perspectiveCamera: PerspectiveCameraProps;
203
202
  orthographicCamera: OrthographicCameraProps;
@@ -309,6 +308,7 @@ declare global {
309
308
  matrix4: Matrix4Props;
310
309
  quaternion: QuaternionProps;
311
310
  bufferAttribute: BufferAttributeProps;
311
+ float32BufferAttribute: Float32BufferAttributeProps;
312
312
  instancedBufferAttribute: InstancedBufferAttributeProps;
313
313
  color: ColorProps;
314
314
  fog: FogProps;
@@ -377,7 +377,8 @@ function createEvents(store) {
377
377
  onPointerMissed,
378
378
  internal
379
379
  } = store.getState();
380
- prepareRay(event); // Get fresh intersects
380
+ prepareRay(event);
381
+ internal.lastEvent.current = event; // Get fresh intersects
381
382
 
382
383
  const isPointerMove = name === 'onPointerMove';
383
384
  const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
@@ -435,12 +436,17 @@ function createEvents(store) {
435
436
  if (handler) {
436
437
  // Forward all events back to their respective handlers with the exception of click events,
437
438
  // which must use the initial target
438
- if (name !== 'onClick' && name !== 'onContextMenu' && name !== 'onDoubleClick' || internal.initialHits.includes(eventObject)) {
439
+ if (!isClickEvent || internal.initialHits.includes(eventObject)) {
439
440
  // Missed events have to come first
440
441
  pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
441
442
 
442
443
  handler(data);
443
444
  }
445
+ } else {
446
+ // Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit
447
+ if (isClickEvent && internal.initialHits.includes(eventObject)) {
448
+ pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
449
+ }
444
450
  }
445
451
  }
446
452
  });
@@ -621,21 +627,21 @@ function createRenderer(roots) {
621
627
  if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
622
628
  } // Test again target.copy(class) next ...
623
629
  else if (targetProp.copy && value && value.constructor && targetProp.constructor.name === value.constructor.name) targetProp.copy(value); // If nothing else fits, just set the single value, ignore undefined
624
- // https://github.com/react-spring/react-three-fiber/issues/274
630
+ // https://github.com/pmndrs/react-three-fiber/issues/274
625
631
  else if (value !== undefined) {
626
632
  const isColor = targetProp instanceof THREE__namespace.Color; // Allow setting array scalars
627
633
 
628
634
  if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
629
635
  else if (targetProp instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) targetProp.mask = value.mask; // Otherwise just set ...
630
636
  else targetProp.set(value); // Auto-convert sRGB colors, for now ...
631
- // https://github.com/react-spring/react-three-fiber/issues/344
637
+ // https://github.com/pmndrs/react-three-fiber/issues/344
632
638
 
633
639
  if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
634
640
  } // Else, just overwrite the value
635
641
 
636
642
  } else {
637
643
  currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
638
- // https://github.com/react-spring/react-three-fiber/issues/344
644
+ // https://github.com/pmndrs/react-three-fiber/issues/344
639
645
 
640
646
  if (!rootState.linear && currentInstance[key] instanceof THREE__namespace.Texture) currentInstance[key].encoding = THREE__namespace.sRGBEncoding;
641
647
  }
@@ -643,7 +649,7 @@ function createRenderer(roots) {
643
649
  invalidateInstance(instance);
644
650
  });
645
651
 
646
- if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
652
+ if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
647
653
  // Pre-emptively remove the instance from the interaction manager
648
654
  const index = rootState.internal.interaction.indexOf(instance);
649
655
  if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
@@ -696,7 +702,9 @@ function createRenderer(roots) {
696
702
  });
697
703
  } else {
698
704
  const target = catalogue[name] || THREE__namespace[name];
699
- if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; // Instanciate new object, link it to the root
705
+ if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; // Throw if an object or literal was passed for args
706
+
707
+ if (!Array.isArray(args)) throw 'The args prop must be an array!'; // Instanciate new object, link it to the root
700
708
  // Append memoized props with args so it's not forgotten
701
709
 
702
710
  instance = prepare(new target(...args), {
@@ -970,7 +978,9 @@ function createRenderer(roots) {
970
978
  args: argsOld = [],
971
979
  children: cO,
972
980
  ...restOld
973
- } = oldProps; // If it has new props or arguments, then it needs to be re-instanciated
981
+ } = oldProps; // Throw if an object or literal was passed for args
982
+
983
+ if (!Array.isArray(argsNew)) throw 'The args prop must be an array!'; // If it has new props or arguments, then it needs to be re-instanciated
974
984
 
975
985
  if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
976
986
 
@@ -1020,11 +1030,24 @@ function createRenderer(roots) {
1020
1030
 
1021
1031
  createTextInstance() {},
1022
1032
 
1023
- finalizeInitialChildren() {
1024
- return false;
1033
+ finalizeInitialChildren(instance) {
1034
+ var _instance$__r3f7;
1035
+
1036
+ // https://github.com/facebook/react/issues/20271
1037
+ // Returning true will trigger commitMount
1038
+ const localState = (_instance$__r3f7 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f7 : {};
1039
+ return !!localState.handlers;
1025
1040
  },
1026
1041
 
1027
- commitMount() {// noop
1042
+ commitMount(instance)
1043
+ /*, type, props*/
1044
+ {
1045
+ var _instance$__r3f8;
1046
+
1047
+ // https://github.com/facebook/react/issues/20271
1048
+ // This will make sure events are only added once to the central container
1049
+ const localState = (_instance$__r3f8 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f8 : {};
1050
+ if (instance.raycast && localState.handlers && localState.eventCount) instance.__r3f.root.getState().internal.interaction.push(instance);
1028
1051
  },
1029
1052
 
1030
1053
  shouldDeprioritizeSubtree() {
@@ -1231,6 +1254,9 @@ const createStore = (applyProps, invalidate, advance, props) => {
1231
1254
  dpr: calculateDpr(dpr)
1232
1255
  }
1233
1256
  })),
1257
+ setFrameloop: (frameloop = 'always') => set(() => ({
1258
+ frameloop
1259
+ })),
1234
1260
  events: {
1235
1261
  connected: false
1236
1262
  },
@@ -1239,6 +1265,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1239
1265
  priority: 0,
1240
1266
  frames: 0,
1241
1267
  lastProps: props,
1268
+ lastEvent: /*#__PURE__*/React__namespace.createRef(),
1242
1269
  interaction: [],
1243
1270
  hovered: new Map(),
1244
1271
  subscribers: [],
@@ -1294,7 +1321,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1294
1321
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1295
1322
  // https://github.com/pmndrs/react-three-fiber/issues/92
1296
1323
  // Do not mess with the camera if it belongs to the user
1297
- if (!(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
1324
+ if (!camera.manual && !(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
1298
1325
  if (isOrthographicCamera(camera)) {
1299
1326
  camera.left = size.width / -2;
1300
1327
  camera.right = size.width / 2;
@@ -1719,7 +1746,9 @@ function render(element, canvas, {
1719
1746
  // Check pixelratio
1720
1747
  if (props.dpr !== undefined && !is.equ(state.viewport.dpr, calculateDpr(props.dpr))) state.setDpr(props.dpr); // Check size
1721
1748
 
1722
- if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // For some props we want to reset the entire root
1749
+ if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // Check frameloop
1750
+
1751
+ if (state.frameloop !== props.frameloop) state.setFrameloop(props.frameloop); // For some props we want to reset the entire root
1723
1752
  // Changes to the color-space
1724
1753
 
1725
1754
  const linearChanged = props.linear !== state.internal.lastProps.linear;
@@ -377,7 +377,8 @@ function createEvents(store) {
377
377
  onPointerMissed,
378
378
  internal
379
379
  } = store.getState();
380
- prepareRay(event); // Get fresh intersects
380
+ prepareRay(event);
381
+ internal.lastEvent.current = event; // Get fresh intersects
381
382
 
382
383
  const isPointerMove = name === 'onPointerMove';
383
384
  const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
@@ -435,12 +436,17 @@ function createEvents(store) {
435
436
  if (handler) {
436
437
  // Forward all events back to their respective handlers with the exception of click events,
437
438
  // which must use the initial target
438
- if (name !== 'onClick' && name !== 'onContextMenu' && name !== 'onDoubleClick' || internal.initialHits.includes(eventObject)) {
439
+ if (!isClickEvent || internal.initialHits.includes(eventObject)) {
439
440
  // Missed events have to come first
440
441
  pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
441
442
 
442
443
  handler(data);
443
444
  }
445
+ } else {
446
+ // Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit
447
+ if (isClickEvent && internal.initialHits.includes(eventObject)) {
448
+ pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
449
+ }
444
450
  }
445
451
  }
446
452
  });
@@ -621,21 +627,21 @@ function createRenderer(roots) {
621
627
  if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
622
628
  } // Test again target.copy(class) next ...
623
629
  else if (targetProp.copy && value && value.constructor && targetProp.constructor.name === value.constructor.name) targetProp.copy(value); // If nothing else fits, just set the single value, ignore undefined
624
- // https://github.com/react-spring/react-three-fiber/issues/274
630
+ // https://github.com/pmndrs/react-three-fiber/issues/274
625
631
  else if (value !== undefined) {
626
632
  const isColor = targetProp instanceof THREE__namespace.Color; // Allow setting array scalars
627
633
 
628
634
  if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
629
635
  else if (targetProp instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) targetProp.mask = value.mask; // Otherwise just set ...
630
636
  else targetProp.set(value); // Auto-convert sRGB colors, for now ...
631
- // https://github.com/react-spring/react-three-fiber/issues/344
637
+ // https://github.com/pmndrs/react-three-fiber/issues/344
632
638
 
633
639
  if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
634
640
  } // Else, just overwrite the value
635
641
 
636
642
  } else {
637
643
  currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
638
- // https://github.com/react-spring/react-three-fiber/issues/344
644
+ // https://github.com/pmndrs/react-three-fiber/issues/344
639
645
 
640
646
  if (!rootState.linear && currentInstance[key] instanceof THREE__namespace.Texture) currentInstance[key].encoding = THREE__namespace.sRGBEncoding;
641
647
  }
@@ -643,7 +649,7 @@ function createRenderer(roots) {
643
649
  invalidateInstance(instance);
644
650
  });
645
651
 
646
- if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
652
+ if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
647
653
  // Pre-emptively remove the instance from the interaction manager
648
654
  const index = rootState.internal.interaction.indexOf(instance);
649
655
  if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
@@ -696,7 +702,9 @@ function createRenderer(roots) {
696
702
  });
697
703
  } else {
698
704
  const target = catalogue[name] || THREE__namespace[name];
699
- if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; // Instanciate new object, link it to the root
705
+ if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; // Throw if an object or literal was passed for args
706
+
707
+ if (!Array.isArray(args)) throw 'The args prop must be an array!'; // Instanciate new object, link it to the root
700
708
  // Append memoized props with args so it's not forgotten
701
709
 
702
710
  instance = prepare(new target(...args), {
@@ -970,7 +978,9 @@ function createRenderer(roots) {
970
978
  args: argsOld = [],
971
979
  children: cO,
972
980
  ...restOld
973
- } = oldProps; // If it has new props or arguments, then it needs to be re-instanciated
981
+ } = oldProps; // Throw if an object or literal was passed for args
982
+
983
+ if (!Array.isArray(argsNew)) throw 'The args prop must be an array!'; // If it has new props or arguments, then it needs to be re-instanciated
974
984
 
975
985
  if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
976
986
 
@@ -1020,11 +1030,24 @@ function createRenderer(roots) {
1020
1030
 
1021
1031
  createTextInstance() {},
1022
1032
 
1023
- finalizeInitialChildren() {
1024
- return false;
1033
+ finalizeInitialChildren(instance) {
1034
+ var _instance$__r3f7;
1035
+
1036
+ // https://github.com/facebook/react/issues/20271
1037
+ // Returning true will trigger commitMount
1038
+ const localState = (_instance$__r3f7 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f7 : {};
1039
+ return !!localState.handlers;
1025
1040
  },
1026
1041
 
1027
- commitMount() {// noop
1042
+ commitMount(instance)
1043
+ /*, type, props*/
1044
+ {
1045
+ var _instance$__r3f8;
1046
+
1047
+ // https://github.com/facebook/react/issues/20271
1048
+ // This will make sure events are only added once to the central container
1049
+ const localState = (_instance$__r3f8 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f8 : {};
1050
+ if (instance.raycast && localState.handlers && localState.eventCount) instance.__r3f.root.getState().internal.interaction.push(instance);
1028
1051
  },
1029
1052
 
1030
1053
  shouldDeprioritizeSubtree() {
@@ -1231,6 +1254,9 @@ const createStore = (applyProps, invalidate, advance, props) => {
1231
1254
  dpr: calculateDpr(dpr)
1232
1255
  }
1233
1256
  })),
1257
+ setFrameloop: (frameloop = 'always') => set(() => ({
1258
+ frameloop
1259
+ })),
1234
1260
  events: {
1235
1261
  connected: false
1236
1262
  },
@@ -1239,6 +1265,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1239
1265
  priority: 0,
1240
1266
  frames: 0,
1241
1267
  lastProps: props,
1268
+ lastEvent: /*#__PURE__*/React__namespace.createRef(),
1242
1269
  interaction: [],
1243
1270
  hovered: new Map(),
1244
1271
  subscribers: [],
@@ -1294,7 +1321,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1294
1321
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1295
1322
  // https://github.com/pmndrs/react-three-fiber/issues/92
1296
1323
  // Do not mess with the camera if it belongs to the user
1297
- if (!(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
1324
+ if (!camera.manual && !(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
1298
1325
  if (isOrthographicCamera(camera)) {
1299
1326
  camera.left = size.width / -2;
1300
1327
  camera.right = size.width / 2;
@@ -1719,7 +1746,9 @@ function render(element, canvas, {
1719
1746
  // Check pixelratio
1720
1747
  if (props.dpr !== undefined && !is.equ(state.viewport.dpr, calculateDpr(props.dpr))) state.setDpr(props.dpr); // Check size
1721
1748
 
1722
- if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // For some props we want to reset the entire root
1749
+ if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // Check frameloop
1750
+
1751
+ if (state.frameloop !== props.frameloop) state.setFrameloop(props.frameloop); // For some props we want to reset the entire root
1723
1752
  // Changes to the color-space
1724
1753
 
1725
1754
  const linearChanged = props.linear !== state.internal.lastProps.linear;
@@ -344,7 +344,8 @@ function createEvents(store) {
344
344
  onPointerMissed,
345
345
  internal
346
346
  } = store.getState();
347
- prepareRay(event); // Get fresh intersects
347
+ prepareRay(event);
348
+ internal.lastEvent.current = event; // Get fresh intersects
348
349
 
349
350
  const isPointerMove = name === 'onPointerMove';
350
351
  const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
@@ -402,12 +403,17 @@ function createEvents(store) {
402
403
  if (handler) {
403
404
  // Forward all events back to their respective handlers with the exception of click events,
404
405
  // which must use the initial target
405
- if (name !== 'onClick' && name !== 'onContextMenu' && name !== 'onDoubleClick' || internal.initialHits.includes(eventObject)) {
406
+ if (!isClickEvent || internal.initialHits.includes(eventObject)) {
406
407
  // Missed events have to come first
407
408
  pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
408
409
 
409
410
  handler(data);
410
411
  }
412
+ } else {
413
+ // Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit
414
+ if (isClickEvent && internal.initialHits.includes(eventObject)) {
415
+ pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
416
+ }
411
417
  }
412
418
  }
413
419
  });
@@ -588,21 +594,21 @@ function createRenderer(roots) {
588
594
  if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
589
595
  } // Test again target.copy(class) next ...
590
596
  else if (targetProp.copy && value && value.constructor && targetProp.constructor.name === value.constructor.name) targetProp.copy(value); // If nothing else fits, just set the single value, ignore undefined
591
- // https://github.com/react-spring/react-three-fiber/issues/274
597
+ // https://github.com/pmndrs/react-three-fiber/issues/274
592
598
  else if (value !== undefined) {
593
599
  const isColor = targetProp instanceof THREE.Color; // Allow setting array scalars
594
600
 
595
601
  if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
596
602
  else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers) targetProp.mask = value.mask; // Otherwise just set ...
597
603
  else targetProp.set(value); // Auto-convert sRGB colors, for now ...
598
- // https://github.com/react-spring/react-three-fiber/issues/344
604
+ // https://github.com/pmndrs/react-three-fiber/issues/344
599
605
 
600
606
  if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
601
607
  } // Else, just overwrite the value
602
608
 
603
609
  } else {
604
610
  currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
605
- // https://github.com/react-spring/react-three-fiber/issues/344
611
+ // https://github.com/pmndrs/react-three-fiber/issues/344
606
612
 
607
613
  if (!rootState.linear && currentInstance[key] instanceof THREE.Texture) currentInstance[key].encoding = THREE.sRGBEncoding;
608
614
  }
@@ -610,7 +616,7 @@ function createRenderer(roots) {
610
616
  invalidateInstance(instance);
611
617
  });
612
618
 
613
- if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
619
+ if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
614
620
  // Pre-emptively remove the instance from the interaction manager
615
621
  const index = rootState.internal.interaction.indexOf(instance);
616
622
  if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
@@ -663,7 +669,9 @@ function createRenderer(roots) {
663
669
  });
664
670
  } else {
665
671
  const target = catalogue[name] || THREE[name];
666
- if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; // Instanciate new object, link it to the root
672
+ if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; // Throw if an object or literal was passed for args
673
+
674
+ if (!Array.isArray(args)) throw 'The args prop must be an array!'; // Instanciate new object, link it to the root
667
675
  // Append memoized props with args so it's not forgotten
668
676
 
669
677
  instance = prepare(new target(...args), {
@@ -937,7 +945,9 @@ function createRenderer(roots) {
937
945
  args: argsOld = [],
938
946
  children: cO,
939
947
  ...restOld
940
- } = oldProps; // If it has new props or arguments, then it needs to be re-instanciated
948
+ } = oldProps; // Throw if an object or literal was passed for args
949
+
950
+ if (!Array.isArray(argsNew)) throw 'The args prop must be an array!'; // If it has new props or arguments, then it needs to be re-instanciated
941
951
 
942
952
  if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
943
953
 
@@ -987,11 +997,24 @@ function createRenderer(roots) {
987
997
 
988
998
  createTextInstance() {},
989
999
 
990
- finalizeInitialChildren() {
991
- return false;
1000
+ finalizeInitialChildren(instance) {
1001
+ var _instance$__r3f7;
1002
+
1003
+ // https://github.com/facebook/react/issues/20271
1004
+ // Returning true will trigger commitMount
1005
+ const localState = (_instance$__r3f7 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f7 : {};
1006
+ return !!localState.handlers;
992
1007
  },
993
1008
 
994
- commitMount() {// noop
1009
+ commitMount(instance)
1010
+ /*, type, props*/
1011
+ {
1012
+ var _instance$__r3f8;
1013
+
1014
+ // https://github.com/facebook/react/issues/20271
1015
+ // This will make sure events are only added once to the central container
1016
+ const localState = (_instance$__r3f8 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f8 : {};
1017
+ if (instance.raycast && localState.handlers && localState.eventCount) instance.__r3f.root.getState().internal.interaction.push(instance);
995
1018
  },
996
1019
 
997
1020
  shouldDeprioritizeSubtree() {
@@ -1198,6 +1221,9 @@ const createStore = (applyProps, invalidate, advance, props) => {
1198
1221
  dpr: calculateDpr(dpr)
1199
1222
  }
1200
1223
  })),
1224
+ setFrameloop: (frameloop = 'always') => set(() => ({
1225
+ frameloop
1226
+ })),
1201
1227
  events: {
1202
1228
  connected: false
1203
1229
  },
@@ -1206,6 +1232,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1206
1232
  priority: 0,
1207
1233
  frames: 0,
1208
1234
  lastProps: props,
1235
+ lastEvent: /*#__PURE__*/React.createRef(),
1209
1236
  interaction: [],
1210
1237
  hovered: new Map(),
1211
1238
  subscribers: [],
@@ -1261,7 +1288,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1261
1288
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1262
1289
  // https://github.com/pmndrs/react-three-fiber/issues/92
1263
1290
  // Do not mess with the camera if it belongs to the user
1264
- if (!(internal.lastProps.camera instanceof THREE.Camera)) {
1291
+ if (!camera.manual && !(internal.lastProps.camera instanceof THREE.Camera)) {
1265
1292
  if (isOrthographicCamera(camera)) {
1266
1293
  camera.left = size.width / -2;
1267
1294
  camera.right = size.width / 2;
@@ -1686,7 +1713,9 @@ function render(element, canvas, {
1686
1713
  // Check pixelratio
1687
1714
  if (props.dpr !== undefined && !is.equ(state.viewport.dpr, calculateDpr(props.dpr))) state.setDpr(props.dpr); // Check size
1688
1715
 
1689
- if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // For some props we want to reset the entire root
1716
+ if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // Check frameloop
1717
+
1718
+ if (state.frameloop !== props.frameloop) state.setFrameloop(props.frameloop); // For some props we want to reset the entire root
1690
1719
  // Changes to the color-space
1691
1720
 
1692
1721
  const linearChanged = props.linear !== state.internal.lastProps.linear;
@@ -1,11 +1 @@
1
- // are you seeing an error that a default export doesn't exist but your source file has a default export?
2
- // you should run `yarn` or `yarn preconstruct dev` if preconstruct dev isn't in your postinstall hook
3
-
4
- // curious why you need to?
5
- // this file exists so that you can import from the entrypoint normally
6
- // except that it points to your source file and you don't need to run build constantly
7
- // which means we need to re-export all of the modules from your source file
8
- // and since export * doesn't include default exports, we need to read your source file
9
- // to check for a default export and re-export it if it exists
10
- // it's not ideal, but it works pretty well ¯\_(ツ)_/¯
11
- export * from "../../src/native";
1
+ export * from "../../dist/declarations/src/native";