@react-three/fiber 7.0.21 → 7.0.25

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.25
4
+
5
+ ### Patch Changes
6
+
7
+ - 8698734: Release latest patches
8
+
9
+ ## 7.0.24
10
+
11
+ ### Patch Changes
12
+
13
+ - 7f46ddf: cleanup captured pointers when released (#1914)
14
+
15
+ ## 7.0.23
16
+
17
+ ### Patch Changes
18
+
19
+ - 30d38b1: remove logs
20
+
21
+ ## 7.0.22
22
+
23
+ ### Patch Changes
24
+
25
+ - 259e1fa: add camera:manual
26
+
3
27
  ## 7.0.21
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,9 +47,9 @@ export declare type InternalState = {
47
47
  priority: number;
48
48
  frames: number;
49
49
  lastProps: StoreProps;
50
- lastEvent: React.MutableRefObject<DomEvent>;
50
+ lastEvent: React.MutableRefObject<DomEvent | null>;
51
51
  interaction: THREE.Object3D[];
52
- hovered: Map<string, DomEvent>;
52
+ hovered: Map<string, ThreeEvent<DomEvent>>;
53
53
  subscribers: Subscription[];
54
54
  capturedMap: Map<number, Map<THREE.Object3D, PointerCaptureTarget>>;
55
55
  initialClick: [x: number, y: number];
@@ -59,7 +59,9 @@ export declare type InternalState = {
59
59
  export declare type RootState = {
60
60
  gl: THREE.WebGLRenderer;
61
61
  scene: THREE.Scene;
62
- camera: Camera;
62
+ camera: Camera & {
63
+ manual?: boolean;
64
+ };
63
65
  controls: THREE.EventDispatcher | null;
64
66
  raycaster: Raycaster;
65
67
  mouse: THREE.Vector2;
@@ -79,7 +81,8 @@ export declare type RootState = {
79
81
  advance: (timestamp: number, runGlobalEffects?: boolean) => void;
80
82
  setSize: (width: number, height: number) => void;
81
83
  setDpr: (dpr: Dpr) => void;
82
- onPointerMissed?: (event: ThreeEvent<PointerEvent>) => void;
84
+ setFrameloop: (frameloop?: 'always' | 'demand' | 'never') => void;
85
+ onPointerMissed?: (event: MouseEvent) => void;
83
86
  events: EventManager<any>;
84
87
  internal: InternalState;
85
88
  };
@@ -101,8 +104,10 @@ export declare type StoreProps = {
101
104
  dpr?: Dpr;
102
105
  clock?: THREE.Clock;
103
106
  raycaster?: Partial<Raycaster>;
104
- camera?: Camera | Partial<ReactThreeFiber.Object3DNode<THREE.Camera, typeof THREE.Camera> & ReactThreeFiber.Object3DNode<THREE.PerspectiveCamera, typeof THREE.PerspectiveCamera> & ReactThreeFiber.Object3DNode<THREE.OrthographicCamera, typeof THREE.OrthographicCamera>>;
105
- 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;
106
111
  };
107
112
  export declare type ApplyProps = (instance: Instance, newProps: InstanceProps) => void;
108
113
  export declare function calculateDpr(dpr: Dpr): number;
@@ -23,11 +23,14 @@ 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
  }
30
- export declare type Node<T, P> = Overwrite<Partial<T>, NodeProps<T, P>>;
30
+ export declare type ExtendedColors<T> = {
31
+ [K in keyof T]: T[K] extends THREE.Color | undefined ? Color : T[K];
32
+ };
33
+ export declare type Node<T, P> = ExtendedColors<Overwrite<Partial<T>, NodeProps<T, P>>>;
31
34
  export declare type Object3DNode<T, P> = Overwrite<Node<T, P>, {
32
35
  position?: Vector3;
33
36
  up?: Vector3;
@@ -38,13 +41,9 @@ export declare type Object3DNode<T, P> = Overwrite<Node<T, P>, {
38
41
  layers?: Layers;
39
42
  dispose?: (() => void) | null;
40
43
  }> & EventHandlers;
41
- export declare type BufferGeometryNode<T extends THREE.BufferGeometry, P> = Overwrite<Node<T, P>, {}>;
42
- export declare type MaterialNode<T extends THREE.Material, P> = Overwrite<Node<T, P>, {
43
- color?: Color;
44
- }>;
45
- export declare type LightNode<T extends THREE.Light, P> = Overwrite<Object3DNode<T, P>, {
46
- color?: Color;
47
- }>;
44
+ export declare type BufferGeometryNode<T extends THREE.BufferGeometry, P> = Node<T, P>;
45
+ export declare type MaterialNode<T extends THREE.Material, P> = Node<T, P>;
46
+ export declare type LightNode<T extends THREE.Light, P> = Object3DNode<T, P>;
48
47
  export declare type AudioListenerProps = Object3DNode<THREE.AudioListener, typeof THREE.AudioListener>;
49
48
  export declare type PositionalAudioProps = Object3DNode<THREE.PositionalAudio, typeof THREE.PositionalAudio>;
50
49
  export declare type MeshProps = Object3DNode<THREE.Mesh, typeof THREE.Mesh>;
@@ -75,19 +74,16 @@ export declare type ExtrudeBufferGeometryProps = BufferGeometryNode<THREE.Extrud
75
74
  export declare type IcosahedronBufferGeometryProps = BufferGeometryNode<THREE.IcosahedronBufferGeometry, typeof THREE.IcosahedronBufferGeometry>;
76
75
  export declare type LatheBufferGeometryProps = BufferGeometryNode<THREE.LatheBufferGeometry, typeof THREE.LatheBufferGeometry>;
77
76
  export declare type OctahedronBufferGeometryProps = BufferGeometryNode<THREE.OctahedronBufferGeometry, typeof THREE.OctahedronBufferGeometry>;
78
- export declare type ParametricBufferGeometryProps = BufferGeometryNode<THREE.ParametricBufferGeometry, typeof THREE.ParametricBufferGeometry>;
79
77
  export declare type PlaneBufferGeometryProps = BufferGeometryNode<THREE.PlaneBufferGeometry, typeof THREE.PlaneBufferGeometry>;
80
78
  export declare type PolyhedronBufferGeometryProps = BufferGeometryNode<THREE.PolyhedronBufferGeometry, typeof THREE.PolyhedronBufferGeometry>;
81
79
  export declare type RingBufferGeometryProps = BufferGeometryNode<THREE.RingBufferGeometry, typeof THREE.RingBufferGeometry>;
82
80
  export declare type ShapeBufferGeometryProps = BufferGeometryNode<THREE.ShapeBufferGeometry, typeof THREE.ShapeBufferGeometry>;
83
81
  export declare type SphereBufferGeometryProps = BufferGeometryNode<THREE.SphereBufferGeometry, typeof THREE.SphereBufferGeometry>;
84
82
  export declare type TetrahedronBufferGeometryProps = BufferGeometryNode<THREE.TetrahedronBufferGeometry, typeof THREE.TetrahedronBufferGeometry>;
85
- export declare type TextBufferGeometryProps = BufferGeometryNode<THREE.TextBufferGeometry, typeof THREE.TextBufferGeometry>;
86
83
  export declare type TorusBufferGeometryProps = BufferGeometryNode<THREE.TorusBufferGeometry, typeof THREE.TorusBufferGeometry>;
87
84
  export declare type TorusKnotBufferGeometryProps = BufferGeometryNode<THREE.TorusKnotBufferGeometry, typeof THREE.TorusKnotBufferGeometry>;
88
85
  export declare type TubeBufferGeometryProps = BufferGeometryNode<THREE.TubeBufferGeometry, typeof THREE.TubeBufferGeometry>;
89
86
  export declare type WireframeGeometryProps = BufferGeometryNode<THREE.WireframeGeometry, typeof THREE.WireframeGeometry>;
90
- export declare type ParametricGeometryProps = BufferGeometryNode<THREE.ParametricGeometry, typeof THREE.ParametricGeometry>;
91
87
  export declare type TetrahedronGeometryProps = BufferGeometryNode<THREE.TetrahedronGeometry, typeof THREE.TetrahedronGeometry>;
92
88
  export declare type OctahedronGeometryProps = BufferGeometryNode<THREE.OctahedronGeometry, typeof THREE.OctahedronGeometry>;
93
89
  export declare type IcosahedronGeometryProps = BufferGeometryNode<THREE.IcosahedronGeometry, typeof THREE.IcosahedronGeometry>;
@@ -96,7 +92,6 @@ export declare type PolyhedronGeometryProps = BufferGeometryNode<THREE.Polyhedro
96
92
  export declare type TubeGeometryProps = BufferGeometryNode<THREE.TubeGeometry, typeof THREE.TubeGeometry>;
97
93
  export declare type TorusKnotGeometryProps = BufferGeometryNode<THREE.TorusKnotGeometry, typeof THREE.TorusKnotGeometry>;
98
94
  export declare type TorusGeometryProps = BufferGeometryNode<THREE.TorusGeometry, typeof THREE.TorusGeometry>;
99
- export declare type TextGeometryProps = BufferGeometryNode<THREE.TextGeometry, typeof THREE.TextGeometry>;
100
95
  export declare type SphereGeometryProps = BufferGeometryNode<THREE.SphereGeometry, typeof THREE.SphereGeometry>;
101
96
  export declare type RingGeometryProps = BufferGeometryNode<THREE.RingGeometry, typeof THREE.RingGeometry>;
102
97
  export declare type PlaneGeometryProps = BufferGeometryNode<THREE.PlaneGeometry, typeof THREE.PlaneGeometry>;
@@ -174,6 +169,7 @@ export declare type Matrix3Props = Node<THREE.Matrix3, typeof THREE.Matrix3>;
174
169
  export declare type Matrix4Props = Node<THREE.Matrix4, typeof THREE.Matrix4>;
175
170
  export declare type QuaternionProps = Node<THREE.Quaternion, typeof THREE.Quaternion>;
176
171
  export declare type BufferAttributeProps = Node<THREE.BufferAttribute, typeof THREE.BufferAttribute>;
172
+ export declare type Float32BufferAttributeProps = Node<THREE.Float32BufferAttribute, typeof THREE.Float32BufferAttribute>;
177
173
  export declare type InstancedBufferAttributeProps = Node<THREE.InstancedBufferAttribute, typeof THREE.InstancedBufferAttribute>;
178
174
  export declare type ColorProps = Node<THREE.Color, ColorArray>;
179
175
  export declare type FogProps = Node<THREE.Fog, typeof THREE.Fog>;
@@ -212,19 +208,16 @@ declare global {
212
208
  icosahedronBufferGeometry: IcosahedronBufferGeometryProps;
213
209
  latheBufferGeometry: LatheBufferGeometryProps;
214
210
  octahedronBufferGeometry: OctahedronBufferGeometryProps;
215
- parametricBufferGeometry: ParametricBufferGeometryProps;
216
211
  planeBufferGeometry: PlaneBufferGeometryProps;
217
212
  polyhedronBufferGeometry: PolyhedronBufferGeometryProps;
218
213
  ringBufferGeometry: RingBufferGeometryProps;
219
214
  shapeBufferGeometry: ShapeBufferGeometryProps;
220
215
  sphereBufferGeometry: SphereBufferGeometryProps;
221
216
  tetrahedronBufferGeometry: TetrahedronBufferGeometryProps;
222
- textBufferGeometry: TextBufferGeometryProps;
223
217
  torusBufferGeometry: TorusBufferGeometryProps;
224
218
  torusKnotBufferGeometry: TorusKnotBufferGeometryProps;
225
219
  tubeBufferGeometry: TubeBufferGeometryProps;
226
220
  wireframeGeometry: WireframeGeometryProps;
227
- parametricGeometry: ParametricGeometryProps;
228
221
  tetrahedronGeometry: TetrahedronGeometryProps;
229
222
  octahedronGeometry: OctahedronGeometryProps;
230
223
  icosahedronGeometry: IcosahedronGeometryProps;
@@ -233,7 +226,6 @@ declare global {
233
226
  tubeGeometry: TubeGeometryProps;
234
227
  torusKnotGeometry: TorusKnotGeometryProps;
235
228
  torusGeometry: TorusGeometryProps;
236
- textGeometry: TextGeometryProps;
237
229
  sphereGeometry: SphereGeometryProps;
238
230
  ringGeometry: RingGeometryProps;
239
231
  planeGeometry: PlaneGeometryProps;
@@ -307,6 +299,7 @@ declare global {
307
299
  matrix4: Matrix4Props;
308
300
  quaternion: QuaternionProps;
309
301
  bufferAttribute: BufferAttributeProps;
302
+ float32BufferAttribute: Float32BufferAttributeProps;
310
303
  instancedBufferAttribute: InstancedBufferAttributeProps;
311
304
  color: ColorProps;
312
305
  fog: FogProps;
@@ -74,7 +74,8 @@ const is = {
74
74
  function makeId(event) {
75
75
  return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
76
76
  }
77
- /** Release pointer captures.
77
+ /**
78
+ * Release pointer captures.
78
79
  * This is called by releasePointerCapture in the API, and when an object is removed.
79
80
  */
80
81
 
@@ -361,13 +362,16 @@ function createEvents(store) {
361
362
 
362
363
  case 'onLostPointerCapture':
363
364
  return event => {
364
- if ('pointerId' in event) {
365
+ const {
366
+ internal
367
+ } = store.getState();
368
+
369
+ if ('pointerId' in event && !internal.capturedMap.has(event.pointerId)) {
365
370
  // If the object event interface had onLostPointerCapture, we'd call it here on every
366
371
  // object that's getting removed.
367
- store.getState().internal.capturedMap.delete(event.pointerId);
372
+ internal.capturedMap.delete(event.pointerId);
373
+ cancelPointer([]);
368
374
  }
369
-
370
- cancelPointer([]);
371
375
  };
372
376
  } // Any other pointer goes here ...
373
377
 
@@ -436,12 +440,17 @@ function createEvents(store) {
436
440
  if (handler) {
437
441
  // Forward all events back to their respective handlers with the exception of click events,
438
442
  // which must use the initial target
439
- if (name !== 'onClick' && name !== 'onContextMenu' && name !== 'onDoubleClick' || internal.initialHits.includes(eventObject)) {
443
+ if (!isClickEvent || internal.initialHits.includes(eventObject)) {
440
444
  // Missed events have to come first
441
445
  pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
442
446
 
443
447
  handler(data);
444
448
  }
449
+ } else {
450
+ // Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit
451
+ if (isClickEvent && internal.initialHits.includes(eventObject)) {
452
+ pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
453
+ }
445
454
  }
446
455
  }
447
456
  });
@@ -579,6 +588,8 @@ function createRenderer(roots) {
579
588
 
580
589
  if (instance.__r3f) instance.__r3f.memoizedProps = memoized;
581
590
  changes.forEach(([key, value, isEvent, keys]) => {
591
+ var _rootState$gl;
592
+
582
593
  let currentInstance = instance;
583
594
  let targetProp = currentInstance[key]; // Revolve dashed props
584
595
 
@@ -609,8 +620,9 @@ function createRenderer(roots) {
609
620
 
610
621
  if (defaultClassCall.dispose) defaultClassCall.dispose(); // instance does not have constructor, just set it to 0
611
622
  } else value = 0;
612
- } // Deal with pointer events ...
623
+ }
613
624
 
625
+ const isLinear = (rootState == null ? void 0 : (_rootState$gl = rootState.gl) == null ? void 0 : _rootState$gl.outputEncoding) === THREE__namespace.LinearEncoding; // Deal with pointer events ...
614
626
 
615
627
  if (isEvent) {
616
628
  if (value) localState.handlers[key] = value;else delete localState.handlers[key];
@@ -631,20 +643,20 @@ function createRenderer(roots) {
631
643
  else targetProp.set(value); // Auto-convert sRGB colors, for now ...
632
644
  // https://github.com/pmndrs/react-three-fiber/issues/344
633
645
 
634
- if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
646
+ if (!isLinear && isColor) targetProp.convertSRGBToLinear();
635
647
  } // Else, just overwrite the value
636
648
 
637
649
  } else {
638
650
  currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
639
651
  // https://github.com/pmndrs/react-three-fiber/issues/344
640
652
 
641
- if (!rootState.linear && currentInstance[key] instanceof THREE__namespace.Texture) currentInstance[key].encoding = THREE__namespace.sRGBEncoding;
653
+ if (!isLinear && currentInstance[key] instanceof THREE__namespace.Texture) currentInstance[key].encoding = THREE__namespace.sRGBEncoding;
642
654
  }
643
655
 
644
656
  invalidateInstance(instance);
645
657
  });
646
658
 
647
- if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
659
+ if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
648
660
  // Pre-emptively remove the instance from the interaction manager
649
661
  const index = rootState.internal.interaction.indexOf(instance);
650
662
  if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
@@ -697,7 +709,9 @@ function createRenderer(roots) {
697
709
  });
698
710
  } else {
699
711
  const target = catalogue[name] || THREE__namespace[name];
700
- 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
712
+ 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
713
+
714
+ if (!Array.isArray(args)) throw 'The args prop must be an array!'; // Instanciate new object, link it to the root
701
715
  // Append memoized props with args so it's not forgotten
702
716
 
703
717
  instance = prepare(new target(...args), {
@@ -830,7 +844,7 @@ function createRenderer(roots) {
830
844
  parentInstance[child.attachArray] = parentInstance[child.attachArray].filter(x => x !== child);
831
845
  } else if (child.attachObject) {
832
846
  delete parentInstance[child.attachObject[0]][child.attachObject[1]];
833
- } else if (child.attach && !is.fun(child.attach)) {
847
+ } else if (child.attach && !is.fun(child.attach) && parentInstance[child.attach] === child) {
834
848
  parentInstance[child.attach] = null;
835
849
  } else if (is.arr(child.attachFns)) {
836
850
  const [, detachFn] = child.attachFns;
@@ -913,10 +927,13 @@ function createRenderer(roots) {
913
927
 
914
928
  instance.__r3f.objects = [];
915
929
  removeChild(parent, instance);
916
- appendChild(parent, newInstance) // This evil hack switches the react-internal fiber node
917
- // https://github.com/facebook/react/issues/14983
918
- // https://github.com/facebook/react/pull/15021
919
- ;
930
+ appendChild(parent, newInstance); // Re-bind event handlers
931
+
932
+ if (newInstance.raycast && newInstance.__r3f.eventCount) {
933
+ const rootState = newInstance.__r3f.root.getState();
934
+
935
+ rootState.internal.interaction.push(newInstance);
936
+ } // This evil hack switches the react-internal fiber node
920
937
  [fiber, fiber.alternate].forEach(fiber => {
921
938
  if (fiber !== null) {
922
939
  fiber.stateNode = newInstance;
@@ -971,12 +988,24 @@ function createRenderer(roots) {
971
988
  args: argsOld = [],
972
989
  children: cO,
973
990
  ...restOld
974
- } = oldProps; // If it has new props or arguments, then it needs to be re-instanciated
991
+ } = oldProps; // Throw if an object or literal was passed for args
992
+
993
+ 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
975
994
 
976
995
  if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
977
996
 
978
997
  const diff = diffProps(instance, restNew, restOld, true);
979
- if (diff.changes.length) return [false, diff]; // Otherwise do not touch the instance
998
+ if (diff.changes.length) return [false, diff]; // If instance was never attached, attach it
999
+
1000
+ if (instance.attach && typeof instance.attach !== 'function') {
1001
+ const localState = instance.__r3f;
1002
+ const parent = localState.parent;
1003
+
1004
+ if (parent && parent[instance.attach] !== instance) {
1005
+ appendChild(parent, instance);
1006
+ }
1007
+ } // Otherwise do not touch the instance
1008
+
980
1009
 
981
1010
  return null;
982
1011
  }
@@ -1021,11 +1050,24 @@ function createRenderer(roots) {
1021
1050
 
1022
1051
  createTextInstance() {},
1023
1052
 
1024
- finalizeInitialChildren() {
1025
- return false;
1053
+ finalizeInitialChildren(instance) {
1054
+ var _instance$__r3f7;
1055
+
1056
+ // https://github.com/facebook/react/issues/20271
1057
+ // Returning true will trigger commitMount
1058
+ const localState = (_instance$__r3f7 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f7 : {};
1059
+ return !!localState.handlers;
1026
1060
  },
1027
1061
 
1028
- commitMount() {// noop
1062
+ commitMount(instance)
1063
+ /*, type, props*/
1064
+ {
1065
+ var _instance$__r3f8;
1066
+
1067
+ // https://github.com/facebook/react/issues/20271
1068
+ // This will make sure events are only added once to the central container
1069
+ const localState = (_instance$__r3f8 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f8 : {};
1070
+ if (instance.raycast && localState.handlers && localState.eventCount) instance.__r3f.root.getState().internal.interaction.push(instance);
1029
1071
  },
1030
1072
 
1031
1073
  shouldDeprioritizeSubtree() {
@@ -1232,6 +1274,9 @@ const createStore = (applyProps, invalidate, advance, props) => {
1232
1274
  dpr: calculateDpr(dpr)
1233
1275
  }
1234
1276
  })),
1277
+ setFrameloop: (frameloop = 'always') => set(() => ({
1278
+ frameloop
1279
+ })),
1235
1280
  events: {
1236
1281
  connected: false
1237
1282
  },
@@ -1240,7 +1285,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1240
1285
  priority: 0,
1241
1286
  frames: 0,
1242
1287
  lastProps: props,
1243
- lastEvent: /*#__PURE__*/React__namespace.createRef(null),
1288
+ lastEvent: /*#__PURE__*/React__namespace.createRef(),
1244
1289
  interaction: [],
1245
1290
  hovered: new Map(),
1246
1291
  subscribers: [],
@@ -1296,7 +1341,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1296
1341
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1297
1342
  // https://github.com/pmndrs/react-three-fiber/issues/92
1298
1343
  // Do not mess with the camera if it belongs to the user
1299
- if (!(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
1344
+ if (!camera.manual && !(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
1300
1345
  if (isOrthographicCamera(camera)) {
1301
1346
  camera.left = size.width / -2;
1302
1347
  camera.right = size.width / 2;
@@ -1721,7 +1766,9 @@ function render(element, canvas, {
1721
1766
  // Check pixelratio
1722
1767
  if (props.dpr !== undefined && !is.equ(state.viewport.dpr, calculateDpr(props.dpr))) state.setDpr(props.dpr); // Check size
1723
1768
 
1724
- 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
1769
+ if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // Check frameloop
1770
+
1771
+ if (state.frameloop !== props.frameloop) state.setFrameloop(props.frameloop); // For some props we want to reset the entire root
1725
1772
  // Changes to the color-space
1726
1773
 
1727
1774
  const linearChanged = props.linear !== state.internal.lastProps.linear;
@@ -74,7 +74,8 @@ const is = {
74
74
  function makeId(event) {
75
75
  return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
76
76
  }
77
- /** Release pointer captures.
77
+ /**
78
+ * Release pointer captures.
78
79
  * This is called by releasePointerCapture in the API, and when an object is removed.
79
80
  */
80
81
 
@@ -361,13 +362,16 @@ function createEvents(store) {
361
362
 
362
363
  case 'onLostPointerCapture':
363
364
  return event => {
364
- if ('pointerId' in event) {
365
+ const {
366
+ internal
367
+ } = store.getState();
368
+
369
+ if ('pointerId' in event && !internal.capturedMap.has(event.pointerId)) {
365
370
  // If the object event interface had onLostPointerCapture, we'd call it here on every
366
371
  // object that's getting removed.
367
- store.getState().internal.capturedMap.delete(event.pointerId);
372
+ internal.capturedMap.delete(event.pointerId);
373
+ cancelPointer([]);
368
374
  }
369
-
370
- cancelPointer([]);
371
375
  };
372
376
  } // Any other pointer goes here ...
373
377
 
@@ -436,12 +440,17 @@ function createEvents(store) {
436
440
  if (handler) {
437
441
  // Forward all events back to their respective handlers with the exception of click events,
438
442
  // which must use the initial target
439
- if (name !== 'onClick' && name !== 'onContextMenu' && name !== 'onDoubleClick' || internal.initialHits.includes(eventObject)) {
443
+ if (!isClickEvent || internal.initialHits.includes(eventObject)) {
440
444
  // Missed events have to come first
441
445
  pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
442
446
 
443
447
  handler(data);
444
448
  }
449
+ } else {
450
+ // Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit
451
+ if (isClickEvent && internal.initialHits.includes(eventObject)) {
452
+ pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
453
+ }
445
454
  }
446
455
  }
447
456
  });
@@ -579,6 +588,8 @@ function createRenderer(roots) {
579
588
 
580
589
  if (instance.__r3f) instance.__r3f.memoizedProps = memoized;
581
590
  changes.forEach(([key, value, isEvent, keys]) => {
591
+ var _rootState$gl;
592
+
582
593
  let currentInstance = instance;
583
594
  let targetProp = currentInstance[key]; // Revolve dashed props
584
595
 
@@ -609,8 +620,9 @@ function createRenderer(roots) {
609
620
 
610
621
  if (defaultClassCall.dispose) defaultClassCall.dispose(); // instance does not have constructor, just set it to 0
611
622
  } else value = 0;
612
- } // Deal with pointer events ...
623
+ }
613
624
 
625
+ const isLinear = (rootState == null ? void 0 : (_rootState$gl = rootState.gl) == null ? void 0 : _rootState$gl.outputEncoding) === THREE__namespace.LinearEncoding; // Deal with pointer events ...
614
626
 
615
627
  if (isEvent) {
616
628
  if (value) localState.handlers[key] = value;else delete localState.handlers[key];
@@ -631,20 +643,20 @@ function createRenderer(roots) {
631
643
  else targetProp.set(value); // Auto-convert sRGB colors, for now ...
632
644
  // https://github.com/pmndrs/react-three-fiber/issues/344
633
645
 
634
- if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
646
+ if (!isLinear && isColor) targetProp.convertSRGBToLinear();
635
647
  } // Else, just overwrite the value
636
648
 
637
649
  } else {
638
650
  currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
639
651
  // https://github.com/pmndrs/react-three-fiber/issues/344
640
652
 
641
- if (!rootState.linear && currentInstance[key] instanceof THREE__namespace.Texture) currentInstance[key].encoding = THREE__namespace.sRGBEncoding;
653
+ if (!isLinear && currentInstance[key] instanceof THREE__namespace.Texture) currentInstance[key].encoding = THREE__namespace.sRGBEncoding;
642
654
  }
643
655
 
644
656
  invalidateInstance(instance);
645
657
  });
646
658
 
647
- if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
659
+ if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
648
660
  // Pre-emptively remove the instance from the interaction manager
649
661
  const index = rootState.internal.interaction.indexOf(instance);
650
662
  if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
@@ -697,7 +709,9 @@ function createRenderer(roots) {
697
709
  });
698
710
  } else {
699
711
  const target = catalogue[name] || THREE__namespace[name];
700
- 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
712
+ 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
713
+
714
+ if (!Array.isArray(args)) throw 'The args prop must be an array!'; // Instanciate new object, link it to the root
701
715
  // Append memoized props with args so it's not forgotten
702
716
 
703
717
  instance = prepare(new target(...args), {
@@ -830,7 +844,7 @@ function createRenderer(roots) {
830
844
  parentInstance[child.attachArray] = parentInstance[child.attachArray].filter(x => x !== child);
831
845
  } else if (child.attachObject) {
832
846
  delete parentInstance[child.attachObject[0]][child.attachObject[1]];
833
- } else if (child.attach && !is.fun(child.attach)) {
847
+ } else if (child.attach && !is.fun(child.attach) && parentInstance[child.attach] === child) {
834
848
  parentInstance[child.attach] = null;
835
849
  } else if (is.arr(child.attachFns)) {
836
850
  const [, detachFn] = child.attachFns;
@@ -913,10 +927,13 @@ function createRenderer(roots) {
913
927
 
914
928
  instance.__r3f.objects = [];
915
929
  removeChild(parent, instance);
916
- appendChild(parent, newInstance) // This evil hack switches the react-internal fiber node
917
- // https://github.com/facebook/react/issues/14983
918
- // https://github.com/facebook/react/pull/15021
919
- ;
930
+ appendChild(parent, newInstance); // Re-bind event handlers
931
+
932
+ if (newInstance.raycast && newInstance.__r3f.eventCount) {
933
+ const rootState = newInstance.__r3f.root.getState();
934
+
935
+ rootState.internal.interaction.push(newInstance);
936
+ } // This evil hack switches the react-internal fiber node
920
937
  [fiber, fiber.alternate].forEach(fiber => {
921
938
  if (fiber !== null) {
922
939
  fiber.stateNode = newInstance;
@@ -971,12 +988,24 @@ function createRenderer(roots) {
971
988
  args: argsOld = [],
972
989
  children: cO,
973
990
  ...restOld
974
- } = oldProps; // If it has new props or arguments, then it needs to be re-instanciated
991
+ } = oldProps; // Throw if an object or literal was passed for args
992
+
993
+ 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
975
994
 
976
995
  if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
977
996
 
978
997
  const diff = diffProps(instance, restNew, restOld, true);
979
- if (diff.changes.length) return [false, diff]; // Otherwise do not touch the instance
998
+ if (diff.changes.length) return [false, diff]; // If instance was never attached, attach it
999
+
1000
+ if (instance.attach && typeof instance.attach !== 'function') {
1001
+ const localState = instance.__r3f;
1002
+ const parent = localState.parent;
1003
+
1004
+ if (parent && parent[instance.attach] !== instance) {
1005
+ appendChild(parent, instance);
1006
+ }
1007
+ } // Otherwise do not touch the instance
1008
+
980
1009
 
981
1010
  return null;
982
1011
  }
@@ -1021,11 +1050,24 @@ function createRenderer(roots) {
1021
1050
 
1022
1051
  createTextInstance() {},
1023
1052
 
1024
- finalizeInitialChildren() {
1025
- return false;
1053
+ finalizeInitialChildren(instance) {
1054
+ var _instance$__r3f7;
1055
+
1056
+ // https://github.com/facebook/react/issues/20271
1057
+ // Returning true will trigger commitMount
1058
+ const localState = (_instance$__r3f7 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f7 : {};
1059
+ return !!localState.handlers;
1026
1060
  },
1027
1061
 
1028
- commitMount() {// noop
1062
+ commitMount(instance)
1063
+ /*, type, props*/
1064
+ {
1065
+ var _instance$__r3f8;
1066
+
1067
+ // https://github.com/facebook/react/issues/20271
1068
+ // This will make sure events are only added once to the central container
1069
+ const localState = (_instance$__r3f8 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f8 : {};
1070
+ if (instance.raycast && localState.handlers && localState.eventCount) instance.__r3f.root.getState().internal.interaction.push(instance);
1029
1071
  },
1030
1072
 
1031
1073
  shouldDeprioritizeSubtree() {
@@ -1232,6 +1274,9 @@ const createStore = (applyProps, invalidate, advance, props) => {
1232
1274
  dpr: calculateDpr(dpr)
1233
1275
  }
1234
1276
  })),
1277
+ setFrameloop: (frameloop = 'always') => set(() => ({
1278
+ frameloop
1279
+ })),
1235
1280
  events: {
1236
1281
  connected: false
1237
1282
  },
@@ -1240,7 +1285,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1240
1285
  priority: 0,
1241
1286
  frames: 0,
1242
1287
  lastProps: props,
1243
- lastEvent: /*#__PURE__*/React__namespace.createRef(null),
1288
+ lastEvent: /*#__PURE__*/React__namespace.createRef(),
1244
1289
  interaction: [],
1245
1290
  hovered: new Map(),
1246
1291
  subscribers: [],
@@ -1296,7 +1341,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1296
1341
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1297
1342
  // https://github.com/pmndrs/react-three-fiber/issues/92
1298
1343
  // Do not mess with the camera if it belongs to the user
1299
- if (!(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
1344
+ if (!camera.manual && !(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
1300
1345
  if (isOrthographicCamera(camera)) {
1301
1346
  camera.left = size.width / -2;
1302
1347
  camera.right = size.width / 2;
@@ -1721,7 +1766,9 @@ function render(element, canvas, {
1721
1766
  // Check pixelratio
1722
1767
  if (props.dpr !== undefined && !is.equ(state.viewport.dpr, calculateDpr(props.dpr))) state.setDpr(props.dpr); // Check size
1723
1768
 
1724
- 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
1769
+ if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // Check frameloop
1770
+
1771
+ if (state.frameloop !== props.frameloop) state.setFrameloop(props.frameloop); // For some props we want to reset the entire root
1725
1772
  // Changes to the color-space
1726
1773
 
1727
1774
  const linearChanged = props.linear !== state.internal.lastProps.linear;