@react-three/fiber 8.10.0 → 8.10.2

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.
@@ -13,6 +13,7 @@ var threeTypes = /*#__PURE__*/Object.freeze({
13
13
  var _window$document, _window$navigator;
14
14
  const isOrthographicCamera = def => def && def.isOrthographicCamera;
15
15
  const isRef = obj => obj && obj.hasOwnProperty('current');
16
+
16
17
  /**
17
18
  * An SSR-friendly useLayoutEffect.
18
19
  *
@@ -22,7 +23,6 @@ const isRef = obj => obj && obj.hasOwnProperty('current');
22
23
  *
23
24
  * @see https://github.com/facebook/react/issues/14927
24
25
  */
25
-
26
26
  const useIsomorphicLayoutEffect = typeof window !== 'undefined' && ((_window$document = window.document) != null && _window$document.createElement || ((_window$navigator = window.navigator) == null ? void 0 : _window$navigator.product) === 'ReactNative') ? React.useLayoutEffect : React.useEffect;
27
27
  function useMutableCallback(fn) {
28
28
  const ref = React.useRef(fn);
@@ -39,40 +39,31 @@ function Block({
39
39
  return null;
40
40
  }
41
41
  class ErrorBoundary extends React.Component {
42
- constructor(...args) {
43
- super(...args);
44
- this.state = {
45
- error: false
46
- };
47
- }
48
-
42
+ state = {
43
+ error: false
44
+ };
45
+ static getDerivedStateFromError = () => ({
46
+ error: true
47
+ });
49
48
  componentDidCatch(err) {
50
49
  this.props.set(err);
51
50
  }
52
-
53
51
  render() {
54
52
  return this.state.error ? null : this.props.children;
55
53
  }
56
-
57
54
  }
58
-
59
- ErrorBoundary.getDerivedStateFromError = () => ({
60
- error: true
61
- });
62
-
63
55
  const DEFAULT = '__default';
64
56
  const isDiffSet = def => def && !!def.memoized && !!def.changes;
65
57
  function calculateDpr(dpr) {
66
58
  const target = typeof window !== 'undefined' ? window.devicePixelRatio : 1;
67
59
  return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
68
60
  }
61
+
69
62
  /**
70
63
  * Returns instance root state
71
64
  */
72
-
73
65
  const getRootState = obj => {
74
66
  var _r3f;
75
-
76
67
  return (_r3f = obj.__r3f) == null ? void 0 : _r3f.root.getState();
77
68
  };
78
69
  // A collection of compare functions
@@ -84,68 +75,61 @@ const is = {
84
75
  boo: a => typeof a === 'boolean',
85
76
  und: a => a === void 0,
86
77
  arr: a => Array.isArray(a),
87
-
88
78
  equ(a, b, {
89
79
  arrays = 'shallow',
90
80
  objects = 'reference',
91
81
  strict = true
92
82
  } = {}) {
93
83
  // Wrong type or one of the two undefined, doesn't match
94
- if (typeof a !== typeof b || !!a !== !!b) return false; // Atomic, just compare a against b
95
-
84
+ if (typeof a !== typeof b || !!a !== !!b) return false;
85
+ // Atomic, just compare a against b
96
86
  if (is.str(a) || is.num(a)) return a === b;
97
87
  const isObj = is.obj(a);
98
88
  if (isObj && objects === 'reference') return a === b;
99
89
  const isArr = is.arr(a);
100
- if (isArr && arrays === 'reference') return a === b; // Array or Object, shallow compare first to see if it's a match
101
-
102
- if ((isArr || isObj) && a === b) return true; // Last resort, go through keys
103
-
90
+ if (isArr && arrays === 'reference') return a === b;
91
+ // Array or Object, shallow compare first to see if it's a match
92
+ if ((isArr || isObj) && a === b) return true;
93
+ // Last resort, go through keys
104
94
  let i;
105
-
106
95
  for (i in a) if (!(i in b)) return false;
107
-
108
96
  for (i in strict ? b : a) if (a[i] !== b[i]) return false;
109
-
110
97
  if (is.und(i)) {
111
98
  if (isArr && a.length === 0 && b.length === 0) return true;
112
99
  if (isObj && Object.keys(a).length === 0 && Object.keys(b).length === 0) return true;
113
100
  if (a !== b) return false;
114
101
  }
115
-
116
102
  return true;
117
103
  }
104
+ };
118
105
 
119
- }; // Collects nodes and materials from a THREE.Object3D
120
-
106
+ // Collects nodes and materials from a THREE.Object3D
121
107
  function buildGraph(object) {
122
108
  const data = {
123
109
  nodes: {},
124
110
  materials: {}
125
111
  };
126
-
127
112
  if (object) {
128
113
  object.traverse(obj => {
129
114
  if (obj.name) data.nodes[obj.name] = obj;
130
115
  if (obj.material && !data.materials[obj.material.name]) data.materials[obj.material.name] = obj.material;
131
116
  });
132
117
  }
133
-
134
118
  return data;
135
- } // Disposes an object and all its properties
119
+ }
136
120
 
121
+ // Disposes an object and all its properties
137
122
  function dispose(obj) {
138
123
  if (obj.dispose && obj.type !== 'Scene') obj.dispose();
139
-
140
124
  for (const p in obj) {
141
125
  p.dispose == null ? void 0 : p.dispose();
142
126
  delete obj[p];
143
127
  }
144
- } // Each object in the scene carries a small LocalState descriptor
128
+ }
145
129
 
130
+ // Each object in the scene carries a small LocalState descriptor
146
131
  function prepare(object, state) {
147
132
  const instance = object;
148
-
149
133
  if (state != null && state.primitive || !instance.__r3f) {
150
134
  instance.__r3f = {
151
135
  type: '',
@@ -159,13 +143,10 @@ function prepare(object, state) {
159
143
  ...state
160
144
  };
161
145
  }
162
-
163
146
  return object;
164
147
  }
165
-
166
148
  function resolve(instance, key) {
167
149
  let target = instance;
168
-
169
150
  if (key.includes('-')) {
170
151
  const entries = key.split('-');
171
152
  const last = entries.pop();
@@ -178,9 +159,9 @@ function resolve(instance, key) {
178
159
  target,
179
160
  key
180
161
  };
181
- } // Checks if a dash-cased string ends with an integer
182
-
162
+ }
183
163
 
164
+ // Checks if a dash-cased string ends with an integer
184
165
  const INDEX_REGEX = /-\d+$/;
185
166
  function attach(parent, child, type) {
186
167
  if (is.str(type)) {
@@ -193,7 +174,6 @@ function attach(parent, child, type) {
193
174
  } = resolve(parent, root);
194
175
  if (!Array.isArray(target[key])) target[key] = [];
195
176
  }
196
-
197
177
  const {
198
178
  target,
199
179
  key
@@ -204,21 +184,21 @@ function attach(parent, child, type) {
204
184
  }
205
185
  function detach(parent, child, type) {
206
186
  var _child$__r3f, _child$__r3f2;
207
-
208
187
  if (is.str(type)) {
209
188
  const {
210
189
  target,
211
190
  key
212
191
  } = resolve(parent, type);
213
- const previous = child.__r3f.previousAttach; // When the previous value was undefined, it means the value was never set to begin with
214
-
215
- if (previous === undefined) delete target[key]; // Otherwise set the previous value
192
+ const previous = child.__r3f.previousAttach;
193
+ // When the previous value was undefined, it means the value was never set to begin with
194
+ if (previous === undefined) delete target[key];
195
+ // Otherwise set the previous value
216
196
  else target[key] = previous;
217
197
  } else (_child$__r3f = child.__r3f) == null ? void 0 : _child$__r3f.previousAttach == null ? void 0 : _child$__r3f.previousAttach(parent, child);
218
-
219
198
  (_child$__r3f2 = child.__r3f) == null ? true : delete _child$__r3f2.previousAttach;
220
- } // This function prepares a set of changes to be applied to the instance
199
+ }
221
200
 
201
+ // This function prepares a set of changes to be applied to the instance
222
202
  function diffProps(instance, {
223
203
  children: cN,
224
204
  key: kN,
@@ -231,39 +211,38 @@ function diffProps(instance, {
231
211
  ...previous
232
212
  } = {}, remove = false) {
233
213
  var _instance$__r3f;
234
-
235
214
  const localState = (_instance$__r3f = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f : {};
236
215
  const entries = Object.entries(props);
237
- const changes = []; // Catch removed props, prepend them so they can be reset or removed
216
+ const changes = [];
238
217
 
218
+ // Catch removed props, prepend them so they can be reset or removed
239
219
  if (remove) {
240
220
  const previousKeys = Object.keys(previous);
241
-
242
221
  for (let i = 0; i < previousKeys.length; i++) {
243
222
  if (!props.hasOwnProperty(previousKeys[i])) entries.unshift([previousKeys[i], DEFAULT + 'remove']);
244
223
  }
245
224
  }
246
-
247
225
  entries.forEach(([key, value]) => {
248
226
  var _instance$__r3f2;
249
-
250
227
  // Bail out on primitive object
251
- if ((_instance$__r3f2 = instance.__r3f) != null && _instance$__r3f2.primitive && key === 'object') return; // When props match bail out
252
-
253
- if (is.equ(value, previous[key])) return; // Collect handlers and bail out
254
-
255
- if (/^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(key)) return changes.push([key, value, true, []]); // Split dashed props
256
-
228
+ if ((_instance$__r3f2 = instance.__r3f) != null && _instance$__r3f2.primitive && key === 'object') return;
229
+ // When props match bail out
230
+ if (is.equ(value, previous[key])) return;
231
+ // Collect handlers and bail out
232
+ if (/^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(key)) return changes.push([key, value, true, []]);
233
+ // Split dashed props
257
234
  let entries = [];
258
235
  if (key.includes('-')) entries = key.split('-');
259
- changes.push([key, value, false, entries]); // Reset pierced props
236
+ changes.push([key, value, false, entries]);
260
237
 
238
+ // Reset pierced props
261
239
  for (const prop in props) {
262
240
  const value = props[prop];
263
241
  if (prop.startsWith(`${key}-`)) changes.push([prop, value, false, prop.split('-')]);
264
242
  }
265
243
  });
266
- const memoized = { ...props
244
+ const memoized = {
245
+ ...props
267
246
  };
268
247
  if (localState.memoizedProps && localState.memoizedProps.args) memoized.args = localState.memoizedProps.args;
269
248
  if (localState.memoizedProps && localState.memoizedProps.attach) memoized.attach = localState.memoizedProps.attach;
@@ -271,11 +250,11 @@ function diffProps(instance, {
271
250
  memoized,
272
251
  changes
273
252
  };
274
- } // This function applies a set of changes to the instance
253
+ }
275
254
 
255
+ // This function applies a set of changes to the instance
276
256
  function applyProps$1(instance, data) {
277
257
  var _instance$__r3f3, _root$getState, _instance$__r3f4;
278
-
279
258
  // Filter equals, events and reserved props
280
259
  const localState = (_instance$__r3f3 = instance.__r3f) != null ? _instance$__r3f3 : {};
281
260
  const root = localState.root;
@@ -284,104 +263,102 @@ function applyProps$1(instance, data) {
284
263
  memoized,
285
264
  changes
286
265
  } = isDiffSet(data) ? data : diffProps(instance, data);
287
- const prevHandlers = localState.eventCount; // Prepare memoized props
266
+ const prevHandlers = localState.eventCount;
288
267
 
268
+ // Prepare memoized props
289
269
  if (instance.__r3f) instance.__r3f.memoizedProps = memoized;
290
-
291
270
  for (let i = 0; i < changes.length; i++) {
292
271
  let [key, value, isEvent, keys] = changes[i];
293
272
  let currentInstance = instance;
294
- let targetProp = currentInstance[key]; // Revolve dashed props
273
+ let targetProp = currentInstance[key];
295
274
 
275
+ // Revolve dashed props
296
276
  if (keys.length) {
297
- targetProp = keys.reduce((acc, key) => acc[key], instance); // If the target is atomic, it forces us to switch the root
298
-
277
+ targetProp = keys.reduce((acc, key) => acc[key], instance);
278
+ // If the target is atomic, it forces us to switch the root
299
279
  if (!(targetProp && targetProp.set)) {
300
280
  const [name, ...reverseEntries] = keys.reverse();
301
281
  currentInstance = reverseEntries.reverse().reduce((acc, key) => acc[key], instance);
302
282
  key = name;
303
283
  }
304
- } // https://github.com/mrdoob/three.js/issues/21209
284
+ }
285
+
286
+ // https://github.com/mrdoob/three.js/issues/21209
305
287
  // HMR/fast-refresh relies on the ability to cancel out props, but threejs
306
288
  // has no means to do this. Hence we curate a small collection of value-classes
307
289
  // with their respective constructor/set arguments
308
290
  // For removed props, try to set default values, if possible
309
-
310
-
311
291
  if (value === DEFAULT + 'remove') {
312
- if (targetProp && targetProp.constructor) {
313
- var _memoized$args;
314
-
315
- // use the prop constructor to find the default it should be
316
- value = new targetProp.constructor(...((_memoized$args = memoized.args) != null ? _memoized$args : []));
317
- } else if (currentInstance.constructor) {
292
+ if (currentInstance.constructor) {
318
293
  var _currentInstance$__r;
319
-
320
294
  // create a blank slate of the instance and copy the particular parameter.
321
295
  // @ts-ignore
322
296
  const defaultClassCall = new currentInstance.constructor(...((_currentInstance$__r = currentInstance.__r3f.memoizedProps.args) != null ? _currentInstance$__r : []));
323
- value = defaultClassCall[targetProp]; // destory the instance
324
-
325
- if (defaultClassCall.dispose) defaultClassCall.dispose(); // instance does not have constructor, just set it to 0
297
+ value = defaultClassCall[key];
298
+ // destroy the instance
299
+ if (defaultClassCall.dispose) defaultClassCall.dispose();
326
300
  } else {
301
+ // instance does not have constructor, just set it to 0
327
302
  value = 0;
328
303
  }
329
- } // Deal with pointer events ...
330
-
304
+ }
331
305
 
306
+ // Deal with pointer events ...
332
307
  if (isEvent) {
333
308
  if (value) localState.handlers[key] = value;else delete localState.handlers[key];
334
309
  localState.eventCount = Object.keys(localState.handlers).length;
335
- } // Special treatment for objects with support for set/copy, and layers
310
+ }
311
+ // Special treatment for objects with support for set/copy, and layers
336
312
  else if (targetProp && targetProp.set && (targetProp.copy || targetProp instanceof THREE.Layers)) {
337
313
  // If value is an array
338
314
  if (Array.isArray(value)) {
339
315
  if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
340
- } // Test again target.copy(class) next ...
316
+ }
317
+ // Test again target.copy(class) next ...
341
318
  else if (targetProp.copy && value && value.constructor && targetProp.constructor.name === value.constructor.name) {
342
319
  targetProp.copy(value);
343
- } // If nothing else fits, just set the single value, ignore undefined
320
+ }
321
+ // If nothing else fits, just set the single value, ignore undefined
344
322
  // https://github.com/pmndrs/react-three-fiber/issues/274
345
323
  else if (value !== undefined) {
346
- const isColor = targetProp instanceof THREE.Color; // Allow setting array scalars
347
-
348
- if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
349
- else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers) targetProp.mask = value.mask; // Otherwise just set ...
350
- else targetProp.set(value); // For versions of three which don't support THREE.ColorManagement,
324
+ const isColor = targetProp instanceof THREE.Color;
325
+ // Allow setting array scalars
326
+ if (!isColor && targetProp.setScalar) targetProp.setScalar(value);
327
+ // Layers have no copy function, we must therefore copy the mask property
328
+ else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers) targetProp.mask = value.mask;
329
+ // Otherwise just set ...
330
+ else targetProp.set(value);
331
+ // For versions of three which don't support THREE.ColorManagement,
351
332
  // Auto-convert sRGB colors
352
333
  // https://github.com/pmndrs/react-three-fiber/issues/344
353
-
354
334
  const supportsColorManagement = ('ColorManagement' in THREE);
355
335
  if (!supportsColorManagement && !rootState.linear && isColor) targetProp.convertSRGBToLinear();
356
- } // Else, just overwrite the value
357
-
336
+ }
337
+ // Else, just overwrite the value
358
338
  } else {
359
- currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
339
+ currentInstance[key] = value;
340
+ // Auto-convert sRGB textures, for now ...
360
341
  // https://github.com/pmndrs/react-three-fiber/issues/344
361
-
362
342
  if (!rootState.linear && currentInstance[key] instanceof THREE.Texture) {
363
343
  currentInstance[key].encoding = THREE.sRGBEncoding;
364
344
  }
365
345
  }
366
-
367
346
  invalidateInstance(instance);
368
347
  }
369
-
370
348
  if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
371
349
  // Pre-emptively remove the instance from the interaction manager
372
350
  const index = rootState.internal.interaction.indexOf(instance);
373
- if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
374
-
351
+ if (index > -1) rootState.internal.interaction.splice(index, 1);
352
+ // Add the instance to the interaction manager only when it has handlers
375
353
  if (localState.eventCount) rootState.internal.interaction.push(instance);
376
- } // Call the update lifecycle when it is being updated, but only when it is part of the scene
377
-
354
+ }
378
355
 
356
+ // Call the update lifecycle when it is being updated, but only when it is part of the scene
379
357
  if (changes.length && (_instance$__r3f4 = instance.__r3f) != null && _instance$__r3f4.parent) updateInstance(instance);
380
358
  return instance;
381
359
  }
382
360
  function invalidateInstance(instance) {
383
361
  var _instance$__r3f5, _instance$__r3f5$root;
384
-
385
362
  const state = (_instance$__r3f5 = instance.__r3f) == null ? void 0 : (_instance$__r3f5$root = _instance$__r3f5.root) == null ? void 0 : _instance$__r3f5$root.getState == null ? void 0 : _instance$__r3f5$root.getState();
386
363
  if (state && state.internal.frames === 0) state.invalidate();
387
364
  }
@@ -400,17 +377,16 @@ function updateCamera(camera, size) {
400
377
  } else {
401
378
  camera.aspect = size.width / size.height;
402
379
  }
403
-
404
- camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
380
+ camera.updateProjectionMatrix();
381
+ // https://github.com/pmndrs/react-three-fiber/issues/178
405
382
  // Update matrix world since the renderer is a frame late
406
-
407
383
  camera.updateMatrixWorld();
408
384
  }
409
385
  }
386
+
410
387
  /**
411
388
  * Safely sets a deeply-nested value on an object.
412
389
  */
413
-
414
390
  function setDeep(obj, value, keys) {
415
391
  const key = keys.pop();
416
392
  const target = keys.reduce((acc, key) => acc[key], obj);
@@ -419,19 +395,17 @@ function setDeep(obj, value, keys) {
419
395
 
420
396
  function makeId(event) {
421
397
  return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
422
- } // https://github.com/facebook/react/tree/main/packages/react-reconciler#getcurrenteventpriority
423
- // Gives React a clue as to how import the current interaction is
424
-
398
+ }
425
399
 
400
+ // https://github.com/facebook/react/tree/main/packages/react-reconciler#getcurrenteventpriority
401
+ // Gives React a clue as to how import the current interaction is
426
402
  function getEventPriority() {
427
403
  var _globalScope$event;
428
-
429
404
  // Get a handle to the current global scope in window and worker contexts if able
430
405
  // https://github.com/pmndrs/react-three-fiber/pull/2493
431
406
  const globalScope = typeof self !== 'undefined' && self || typeof window !== 'undefined' && window;
432
407
  if (!globalScope) return DefaultEventPriority;
433
408
  const name = (_globalScope$event = globalScope.event) == null ? void 0 : _globalScope$event.type;
434
-
435
409
  switch (name) {
436
410
  case 'click':
437
411
  case 'contextmenu':
@@ -440,7 +414,6 @@ function getEventPriority() {
440
414
  case 'pointerdown':
441
415
  case 'pointerup':
442
416
  return DiscreteEventPriority;
443
-
444
417
  case 'pointermove':
445
418
  case 'pointerout':
446
419
  case 'pointerover':
@@ -448,34 +421,31 @@ function getEventPriority() {
448
421
  case 'pointerleave':
449
422
  case 'wheel':
450
423
  return ContinuousEventPriority;
451
-
452
424
  default:
453
425
  return DefaultEventPriority;
454
426
  }
455
427
  }
428
+
456
429
  /**
457
430
  * Release pointer captures.
458
431
  * This is called by releasePointerCapture in the API, and when an object is removed.
459
432
  */
460
-
461
433
  function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
462
434
  const captureData = captures.get(obj);
463
-
464
435
  if (captureData) {
465
- captures.delete(obj); // If this was the last capturing object for this pointer
466
-
436
+ captures.delete(obj);
437
+ // If this was the last capturing object for this pointer
467
438
  if (captures.size === 0) {
468
439
  capturedMap.delete(pointerId);
469
440
  captureData.target.releasePointerCapture(pointerId);
470
441
  }
471
442
  }
472
443
  }
473
-
474
444
  function removeInteractivity(store, object) {
475
445
  const {
476
446
  internal
477
- } = store.getState(); // Removes every trace of an object from the data store
478
-
447
+ } = store.getState();
448
+ // Removes every trace of an object from the data store
479
449
  internal.interaction = internal.interaction.filter(o => o !== object);
480
450
  internal.initialHits = internal.initialHits.filter(o => o !== object);
481
451
  internal.hovered.forEach((value, key) => {
@@ -498,106 +468,103 @@ function createEvents(store) {
498
468
  const dy = event.offsetY - internal.initialClick[1];
499
469
  return Math.round(Math.sqrt(dx * dx + dy * dy));
500
470
  }
501
- /** Returns true if an instance has a valid pointer-event registered, this excludes scroll, clicks etc */
502
-
503
471
 
472
+ /** Returns true if an instance has a valid pointer-event registered, this excludes scroll, clicks etc */
504
473
  function filterPointerEvents(objects) {
505
474
  return objects.filter(obj => ['Move', 'Over', 'Enter', 'Out', 'Leave'].some(name => {
506
475
  var _r3f;
507
-
508
476
  return (_r3f = obj.__r3f) == null ? void 0 : _r3f.handlers['onPointer' + name];
509
477
  }));
510
478
  }
511
-
512
479
  function intersect(event, filter) {
513
480
  const state = store.getState();
514
481
  const duplicates = new Set();
515
- const intersections = []; // Allow callers to eliminate event objects
516
-
517
- const eventsObjects = filter ? filter(state.internal.interaction) : state.internal.interaction; // Reset all raycaster cameras to undefined
518
-
482
+ const intersections = [];
483
+ // Allow callers to eliminate event objects
484
+ const eventsObjects = filter ? filter(state.internal.interaction) : state.internal.interaction;
485
+ // Reset all raycaster cameras to undefined
519
486
  for (let i = 0; i < eventsObjects.length; i++) {
520
487
  const state = getRootState(eventsObjects[i]);
521
-
522
488
  if (state) {
523
489
  state.raycaster.camera = undefined;
524
490
  }
525
491
  }
526
-
527
492
  if (!state.previousRoot) {
528
493
  // Make sure root-level pointer and ray are set up
529
494
  state.events.compute == null ? void 0 : state.events.compute(event, state);
530
495
  }
531
-
532
496
  function handleRaycast(obj) {
533
- const state = getRootState(obj); // Skip event handling when noEvents is set, or when the raycasters camera is null
534
-
535
- if (!state || !state.events.enabled || state.raycaster.camera === null) return []; // When the camera is undefined we have to call the event layers update function
497
+ const state = getRootState(obj);
498
+ // Skip event handling when noEvents is set, or when the raycasters camera is null
499
+ if (!state || !state.events.enabled || state.raycaster.camera === null) return [];
536
500
 
501
+ // When the camera is undefined we have to call the event layers update function
537
502
  if (state.raycaster.camera === undefined) {
538
503
  var _state$previousRoot;
539
-
540
- state.events.compute == null ? void 0 : state.events.compute(event, state, (_state$previousRoot = state.previousRoot) == null ? void 0 : _state$previousRoot.getState()); // If the camera is still undefined we have to skip this layer entirely
541
-
504
+ state.events.compute == null ? void 0 : state.events.compute(event, state, (_state$previousRoot = state.previousRoot) == null ? void 0 : _state$previousRoot.getState());
505
+ // If the camera is still undefined we have to skip this layer entirely
542
506
  if (state.raycaster.camera === undefined) state.raycaster.camera = null;
543
- } // Intersect object by object
544
-
507
+ }
545
508
 
509
+ // Intersect object by object
546
510
  return state.raycaster.camera ? state.raycaster.intersectObject(obj, true) : [];
547
- } // Collect events
548
-
511
+ }
549
512
 
550
- let hits = eventsObjects // Intersect objects
551
- .flatMap(handleRaycast) // Sort by event priority and distance
513
+ // Collect events
514
+ let hits = eventsObjects
515
+ // Intersect objects
516
+ .flatMap(handleRaycast)
517
+ // Sort by event priority and distance
552
518
  .sort((a, b) => {
553
519
  const aState = getRootState(a.object);
554
520
  const bState = getRootState(b.object);
555
521
  if (!aState || !bState) return a.distance - b.distance;
556
522
  return bState.events.priority - aState.events.priority || a.distance - b.distance;
557
- }) // Filter out duplicates
523
+ })
524
+ // Filter out duplicates
558
525
  .filter(item => {
559
526
  const id = makeId(item);
560
527
  if (duplicates.has(id)) return false;
561
528
  duplicates.add(id);
562
529
  return true;
563
- }); // https://github.com/mrdoob/three.js/issues/16031
564
- // Allow custom userland intersect sort order, this likely only makes sense on the root filter
530
+ });
565
531
 
566
- if (state.events.filter) hits = state.events.filter(hits, state); // Bubble up the events, find the event source (eventObject)
532
+ // https://github.com/mrdoob/three.js/issues/16031
533
+ // Allow custom userland intersect sort order, this likely only makes sense on the root filter
534
+ if (state.events.filter) hits = state.events.filter(hits, state);
567
535
 
536
+ // Bubble up the events, find the event source (eventObject)
568
537
  for (const hit of hits) {
569
- let eventObject = hit.object; // Bubble event up
570
-
538
+ let eventObject = hit.object;
539
+ // Bubble event up
571
540
  while (eventObject) {
572
541
  var _r3f2;
573
-
574
- if ((_r3f2 = eventObject.__r3f) != null && _r3f2.eventCount) intersections.push({ ...hit,
542
+ if ((_r3f2 = eventObject.__r3f) != null && _r3f2.eventCount) intersections.push({
543
+ ...hit,
575
544
  eventObject
576
545
  });
577
546
  eventObject = eventObject.parent;
578
547
  }
579
- } // If the interaction is captured, make all capturing targets part of the intersect.
580
-
548
+ }
581
549
 
550
+ // If the interaction is captured, make all capturing targets part of the intersect.
582
551
  if ('pointerId' in event && state.internal.capturedMap.has(event.pointerId)) {
583
552
  for (let captureData of state.internal.capturedMap.get(event.pointerId).values()) {
584
553
  if (!duplicates.has(makeId(captureData.intersection))) intersections.push(captureData.intersection);
585
554
  }
586
555
  }
587
-
588
556
  return intersections;
589
557
  }
590
- /** Handles intersections by forwarding them to handlers */
591
-
592
558
 
559
+ /** Handles intersections by forwarding them to handlers */
593
560
  function handleIntersects(intersections, event, delta, callback) {
594
- const rootState = store.getState(); // If anything has been found, forward it to the event listeners
561
+ const rootState = store.getState();
595
562
 
563
+ // If anything has been found, forward it to the event listeners
596
564
  if (intersections.length) {
597
565
  const localState = {
598
566
  stopped: false
599
567
  };
600
-
601
568
  for (const hit of intersections) {
602
569
  const state = getRootState(hit.object) || rootState;
603
570
  const {
@@ -607,19 +574,15 @@ function createEvents(store) {
607
574
  internal
608
575
  } = state;
609
576
  const unprojectedPoint = new THREE.Vector3(pointer.x, pointer.y, 0).unproject(camera);
610
-
611
577
  const hasPointerCapture = id => {
612
578
  var _internal$capturedMap, _internal$capturedMap2;
613
-
614
579
  return (_internal$capturedMap = (_internal$capturedMap2 = internal.capturedMap.get(id)) == null ? void 0 : _internal$capturedMap2.has(hit.eventObject)) != null ? _internal$capturedMap : false;
615
580
  };
616
-
617
581
  const setPointerCapture = id => {
618
582
  const captureData = {
619
583
  intersection: hit,
620
584
  target: event.target
621
585
  };
622
-
623
586
  if (internal.capturedMap.has(id)) {
624
587
  // if the pointerId was previously captured, we add the hit to the
625
588
  // event capturedMap.
@@ -629,29 +592,27 @@ function createEvents(store) {
629
592
  // containing the hitObject, and the hit. hitObject is used for
630
593
  // faster access.
631
594
  internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
632
- } // Call the original event now
595
+ }
633
596
  event.target.setPointerCapture(id);
634
597
  };
635
-
636
598
  const releasePointerCapture = id => {
637
599
  const captures = internal.capturedMap.get(id);
638
-
639
600
  if (captures) {
640
601
  releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
641
602
  }
642
- }; // Add native event props
643
-
644
-
645
- let extractEventProps = {}; // This iterates over the event's properties including the inherited ones. Native PointerEvents have most of their props as getters which are inherited, but polyfilled PointerEvents have them all as their own properties (i.e. not inherited). We can't use Object.keys() or Object.entries() as they only return "own" properties; nor Object.getPrototypeOf(event) as that *doesn't* return "own" properties, only inherited ones.
603
+ };
646
604
 
605
+ // Add native event props
606
+ let extractEventProps = {};
607
+ // This iterates over the event's properties including the inherited ones. Native PointerEvents have most of their props as getters which are inherited, but polyfilled PointerEvents have them all as their own properties (i.e. not inherited). We can't use Object.keys() or Object.entries() as they only return "own" properties; nor Object.getPrototypeOf(event) as that *doesn't* return "own" properties, only inherited ones.
647
608
  for (let prop in event) {
648
- let property = event[prop]; // Only copy over atomics, leave functions alone as these should be
609
+ let property = event[prop];
610
+ // Only copy over atomics, leave functions alone as these should be
649
611
  // called as event.nativeEvent.fn()
650
-
651
612
  if (typeof property !== 'function') extractEventProps[prop] = property;
652
613
  }
653
-
654
- let raycastEvent = { ...hit,
614
+ let raycastEvent = {
615
+ ...hit,
655
616
  ...extractEventProps,
656
617
  pointer,
657
618
  intersections,
@@ -660,19 +621,21 @@ function createEvents(store) {
660
621
  unprojectedPoint,
661
622
  ray: raycaster.ray,
662
623
  camera: camera,
663
-
664
624
  // Hijack stopPropagation, which just sets a flag
665
625
  stopPropagation() {
666
626
  // https://github.com/pmndrs/react-three-fiber/issues/596
667
627
  // Events are not allowed to stop propagation if the pointer has been captured
668
- const capturesForPointer = 'pointerId' in event && internal.capturedMap.get(event.pointerId); // We only authorize stopPropagation...
628
+ const capturesForPointer = 'pointerId' in event && internal.capturedMap.get(event.pointerId);
669
629
 
670
- if ( // ...if this pointer hasn't been captured
671
- !capturesForPointer || // ... or if the hit object is capturing the pointer
630
+ // We only authorize stopPropagation...
631
+ if (
632
+ // ...if this pointer hasn't been captured
633
+ !capturesForPointer ||
634
+ // ... or if the hit object is capturing the pointer
672
635
  capturesForPointer.has(hit.eventObject)) {
673
- raycastEvent.stopped = localState.stopped = true; // Propagation is stopped, remove all other hover records
636
+ raycastEvent.stopped = localState.stopped = true;
637
+ // Propagation is stopped, remove all other hover records
674
638
  // An event handler is only allowed to flush other handlers if it is hovered itself
675
-
676
639
  if (internal.hovered.size && Array.from(internal.hovered.values()).find(i => i.eventObject === hit.eventObject)) {
677
640
  // Objects cannot flush out higher up objects that have already caught the event
678
641
  const higher = intersections.slice(0, intersections.indexOf(hit));
@@ -680,7 +643,6 @@ function createEvents(store) {
680
643
  }
681
644
  }
682
645
  },
683
-
684
646
  // there should be a distinction between target and currentTarget
685
647
  target: {
686
648
  hasPointerCapture,
@@ -693,22 +655,20 @@ function createEvents(store) {
693
655
  releasePointerCapture
694
656
  },
695
657
  nativeEvent: event
696
- }; // Call subscribers
697
-
698
- callback(raycastEvent); // Event bubbling may be interrupted by stopPropagation
658
+ };
699
659
 
660
+ // Call subscribers
661
+ callback(raycastEvent);
662
+ // Event bubbling may be interrupted by stopPropagation
700
663
  if (localState.stopped === true) break;
701
664
  }
702
665
  }
703
-
704
666
  return intersections;
705
667
  }
706
-
707
668
  function cancelPointer(intersections) {
708
669
  const {
709
670
  internal
710
671
  } = store.getState();
711
-
712
672
  for (const hoveredObj of internal.hovered.values()) {
713
673
  // When no objects were hit or the the hovered object wasn't found underneath the cursor
714
674
  // we call onPointerOut and delete the object from the hovered-elements map
@@ -717,10 +677,10 @@ function createEvents(store) {
717
677
  const instance = eventObject.__r3f;
718
678
  const handlers = instance == null ? void 0 : instance.handlers;
719
679
  internal.hovered.delete(makeId(hoveredObj));
720
-
721
680
  if (instance != null && instance.eventCount) {
722
681
  // Clear out intersects, they are outdated by now
723
- const data = { ...hoveredObj,
682
+ const data = {
683
+ ...hoveredObj,
724
684
  intersections
725
685
  };
726
686
  handlers.onPointerOut == null ? void 0 : handlers.onPointerOut(data);
@@ -729,27 +689,23 @@ function createEvents(store) {
729
689
  }
730
690
  }
731
691
  }
732
-
733
692
  function pointerMissed(event, objects) {
734
693
  for (let i = 0; i < objects.length; i++) {
735
694
  const instance = objects[i].__r3f;
736
695
  instance == null ? void 0 : instance.handlers.onPointerMissed == null ? void 0 : instance.handlers.onPointerMissed(event);
737
696
  }
738
697
  }
739
-
740
698
  function handlePointer(name) {
741
699
  // Deal with cancelation
742
700
  switch (name) {
743
701
  case 'onPointerLeave':
744
702
  case 'onPointerCancel':
745
703
  return () => cancelPointer([]);
746
-
747
704
  case 'onLostPointerCapture':
748
705
  return event => {
749
706
  const {
750
707
  internal
751
708
  } = store.getState();
752
-
753
709
  if ('pointerId' in event && internal.capturedMap.has(event.pointerId)) {
754
710
  // If the object event interface had onLostPointerCapture, we'd call it here on every
755
711
  // object that's getting removed.
@@ -757,55 +713,54 @@ function createEvents(store) {
757
713
  cancelPointer([]);
758
714
  }
759
715
  };
760
- } // Any other pointer goes here ...
761
-
716
+ }
762
717
 
718
+ // Any other pointer goes here ...
763
719
  return function handleEvent(event) {
764
720
  const {
765
721
  onPointerMissed,
766
722
  internal
767
- } = store.getState(); // prepareRay(event)
723
+ } = store.getState();
768
724
 
769
- internal.lastEvent.current = event; // Get fresh intersects
725
+ // prepareRay(event)
726
+ internal.lastEvent.current = event;
770
727
 
728
+ // Get fresh intersects
771
729
  const isPointerMove = name === 'onPointerMove';
772
730
  const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
773
- const filter = isPointerMove ? filterPointerEvents : undefined; // const hits = patchIntersects(intersect(filter), event)
774
-
731
+ const filter = isPointerMove ? filterPointerEvents : undefined;
775
732
  const hits = intersect(event, filter);
776
- const delta = isClickEvent ? calculateDistance(event) : 0; // Save initial coordinates on pointer-down
733
+ const delta = isClickEvent ? calculateDistance(event) : 0;
777
734
 
735
+ // Save initial coordinates on pointer-down
778
736
  if (name === 'onPointerDown') {
779
737
  internal.initialClick = [event.offsetX, event.offsetY];
780
738
  internal.initialHits = hits.map(hit => hit.eventObject);
781
- } // If a click yields no results, pass it back to the user as a miss
782
- // Missed events have to come first in order to establish user-land side-effect clean up
783
-
739
+ }
784
740
 
741
+ // If a click yields no results, pass it back to the user as a miss
742
+ // Missed events have to come first in order to establish user-land side-effect clean up
785
743
  if (isClickEvent && !hits.length) {
786
744
  if (delta <= 2) {
787
745
  pointerMissed(event, internal.interaction);
788
746
  if (onPointerMissed) onPointerMissed(event);
789
747
  }
790
- } // Take care of unhover
791
-
792
-
748
+ }
749
+ // Take care of unhover
793
750
  if (isPointerMove) cancelPointer(hits);
794
-
795
751
  function onIntersect(data) {
796
752
  const eventObject = data.eventObject;
797
753
  const instance = eventObject.__r3f;
798
- const handlers = instance == null ? void 0 : instance.handlers; // Check presence of handlers
754
+ const handlers = instance == null ? void 0 : instance.handlers;
799
755
 
756
+ // Check presence of handlers
800
757
  if (!(instance != null && instance.eventCount)) return;
801
-
802
758
  if (isPointerMove) {
803
759
  // Move event ...
804
760
  if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
805
761
  // When enter or out is present take care of hover-state
806
762
  const id = makeId(data);
807
763
  const hoveredItem = internal.hovered.get(id);
808
-
809
764
  if (!hoveredItem) {
810
765
  // If the object wasn't previously hovered, book it and call its handler
811
766
  internal.hovered.set(id, data);
@@ -815,21 +770,19 @@ function createEvents(store) {
815
770
  // If the object was previously hovered and stopped, we shouldn't allow other items to proceed
816
771
  data.stopPropagation();
817
772
  }
818
- } // Call mouse move
819
-
820
-
773
+ }
774
+ // Call mouse move
821
775
  handlers.onPointerMove == null ? void 0 : handlers.onPointerMove(data);
822
776
  } else {
823
777
  // All other events ...
824
778
  const handler = handlers[name];
825
-
826
779
  if (handler) {
827
780
  // Forward all events back to their respective handlers with the exception of click events,
828
781
  // which must use the initial target
829
782
  if (!isClickEvent || internal.initialHits.includes(eventObject)) {
830
783
  // Missed events have to come first
831
- pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
832
-
784
+ pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
785
+ // Now call the handler
833
786
  handler(data);
834
787
  }
835
788
  } else {
@@ -840,22 +793,19 @@ function createEvents(store) {
840
793
  }
841
794
  }
842
795
  }
843
-
844
796
  handleIntersects(hits, event, delta, onIntersect);
845
797
  };
846
798
  }
847
-
848
799
  return {
849
800
  handlePointer
850
801
  };
851
802
  }
852
803
 
853
804
  let catalogue = {};
854
-
855
- let extend = objects => void (catalogue = { ...catalogue,
805
+ let extend = objects => void (catalogue = {
806
+ ...catalogue,
856
807
  ...objects
857
808
  });
858
-
859
809
  function createRenderer(_roots, _getEventPriority) {
860
810
  function createInstance(type, {
861
811
  args = [],
@@ -864,7 +814,6 @@ function createRenderer(_roots, _getEventPriority) {
864
814
  }, root) {
865
815
  let name = `${type[0].toUpperCase()}${type.slice(1)}`;
866
816
  let instance;
867
-
868
817
  if (type === 'primitive') {
869
818
  if (props.object === undefined) throw new Error("R3F: Primitives without 'object' are invalid!");
870
819
  const object = props.object;
@@ -876,15 +825,15 @@ function createRenderer(_roots, _getEventPriority) {
876
825
  });
877
826
  } else {
878
827
  const target = catalogue[name];
879
-
880
828
  if (!target) {
881
829
  throw new Error(`R3F: ${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`);
882
- } // Throw if an object or literal was passed for args
830
+ }
883
831
 
832
+ // Throw if an object or literal was passed for args
833
+ if (!Array.isArray(args)) throw new Error('R3F: The args prop must be an array!');
884
834
 
885
- if (!Array.isArray(args)) throw new Error('R3F: The args prop must be an array!'); // Instanciate new object, link it to the root
835
+ // Instanciate new object, link it to the root
886
836
  // Append memoized props with args so it's not forgotten
887
-
888
837
  instance = prepare(new target(...args), {
889
838
  type,
890
839
  root,
@@ -894,27 +843,24 @@ function createRenderer(_roots, _getEventPriority) {
894
843
  args
895
844
  }
896
845
  });
897
- } // Auto-attach geometries and materials
898
-
846
+ }
899
847
 
848
+ // Auto-attach geometries and materials
900
849
  if (instance.__r3f.attach === undefined) {
901
850
  if (instance instanceof THREE.BufferGeometry) instance.__r3f.attach = 'geometry';else if (instance instanceof THREE.Material) instance.__r3f.attach = 'material';
902
- } // It should NOT call onUpdate on object instanciation, because it hasn't been added to the
851
+ }
852
+
853
+ // It should NOT call onUpdate on object instanciation, because it hasn't been added to the
903
854
  // view yet. If the callback relies on references for instance, they won't be ready yet, this is
904
855
  // why it passes "true" here
905
856
  // There is no reason to apply props to injects
906
-
907
-
908
857
  if (name !== 'inject') applyProps$1(instance, props);
909
858
  return instance;
910
859
  }
911
-
912
860
  function appendChild(parentInstance, child) {
913
861
  let added = false;
914
-
915
862
  if (child) {
916
863
  var _child$__r3f, _parentInstance$__r3f;
917
-
918
864
  // The attach attribute implies that the object attaches itself on the parent
919
865
  if ((_child$__r3f = child.__r3f) != null && _child$__r3f.attach) {
920
866
  attach(parentInstance, child, child.__r3f.attach);
@@ -922,10 +868,9 @@ function createRenderer(_roots, _getEventPriority) {
922
868
  // add in the usual parent-child way
923
869
  parentInstance.add(child);
924
870
  added = true;
925
- } // This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
871
+ }
872
+ // This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
926
873
  // that is, anything that's a child in React but not a child in the scenegraph.
927
-
928
-
929
874
  if (!added) (_parentInstance$__r3f = parentInstance.__r3f) == null ? void 0 : _parentInstance$__r3f.objects.push(child);
930
875
  if (!child.__r3f) prepare(child, {});
931
876
  child.__r3f.parent = parentInstance;
@@ -933,13 +878,10 @@ function createRenderer(_roots, _getEventPriority) {
933
878
  invalidateInstance(child);
934
879
  }
935
880
  }
936
-
937
881
  function insertBefore(parentInstance, child, beforeChild) {
938
882
  let added = false;
939
-
940
883
  if (child) {
941
884
  var _child$__r3f2, _parentInstance$__r3f2;
942
-
943
885
  if ((_child$__r3f2 = child.__r3f) != null && _child$__r3f2.attach) {
944
886
  attach(parentInstance, child, child.__r3f.attach);
945
887
  } else if (child.isObject3D && parentInstance.isObject3D) {
@@ -952,7 +894,6 @@ function createRenderer(_roots, _getEventPriority) {
952
894
  parentInstance.children = [...restSiblings.slice(0, index), child, ...restSiblings.slice(index)];
953
895
  added = true;
954
896
  }
955
-
956
897
  if (!added) (_parentInstance$__r3f2 = parentInstance.__r3f) == null ? void 0 : _parentInstance$__r3f2.objects.push(child);
957
898
  if (!child.__r3f) prepare(child, {});
958
899
  child.__r3f.parent = parentInstance;
@@ -960,31 +901,29 @@ function createRenderer(_roots, _getEventPriority) {
960
901
  invalidateInstance(child);
961
902
  }
962
903
  }
963
-
964
904
  function removeRecursive(array, parent, dispose = false) {
965
905
  if (array) [...array].forEach(child => removeChild(parent, child, dispose));
966
906
  }
967
-
968
907
  function removeChild(parentInstance, child, dispose) {
969
908
  if (child) {
970
909
  var _parentInstance$__r3f3, _child$__r3f3, _child$__r3f5;
971
-
972
910
  // Clear the parent reference
973
- if (child.__r3f) child.__r3f.parent = null; // Remove child from the parents objects
974
-
975
- if ((_parentInstance$__r3f3 = parentInstance.__r3f) != null && _parentInstance$__r3f3.objects) parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child); // Remove attachment
976
-
911
+ if (child.__r3f) child.__r3f.parent = null;
912
+ // Remove child from the parents objects
913
+ if ((_parentInstance$__r3f3 = parentInstance.__r3f) != null && _parentInstance$__r3f3.objects) parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child);
914
+ // Remove attachment
977
915
  if ((_child$__r3f3 = child.__r3f) != null && _child$__r3f3.attach) {
978
916
  detach(parentInstance, child, child.__r3f.attach);
979
917
  } else if (child.isObject3D && parentInstance.isObject3D) {
980
918
  var _child$__r3f4;
981
-
982
- parentInstance.remove(child); // Remove interactivity
983
-
919
+ parentInstance.remove(child);
920
+ // Remove interactivity
984
921
  if ((_child$__r3f4 = child.__r3f) != null && _child$__r3f4.root) {
985
922
  removeInteractivity(child.__r3f.root, child);
986
923
  }
987
- } // Allow objects to bail out of recursive dispose altogether by passing dispose={null}
924
+ }
925
+
926
+ // Allow objects to bail out of recursive dispose altogether by passing dispose={null}
988
927
  // Never dispose of primitives because their state may be kept outside of React!
989
928
  // In order for an object to be able to dispose it has to have
990
929
  // - a dispose method,
@@ -993,29 +932,27 @@ function createRenderer(_roots, _getEventPriority) {
993
932
  //
994
933
  // Since disposal is recursive, we can check the optional dispose arg, which will be undefined
995
934
  // when the reconciler calls it, but then carry our own check recursively
996
-
997
-
998
935
  const isPrimitive = (_child$__r3f5 = child.__r3f) == null ? void 0 : _child$__r3f5.primitive;
999
- const shouldDispose = dispose === undefined ? child.dispose !== null && !isPrimitive : dispose; // Remove nested child objects. Primitives should not have objects and children that are
1000
- // attached to them declaratively ...
936
+ const shouldDispose = dispose === undefined ? child.dispose !== null && !isPrimitive : dispose;
1001
937
 
938
+ // Remove nested child objects. Primitives should not have objects and children that are
939
+ // attached to them declaratively ...
1002
940
  if (!isPrimitive) {
1003
941
  var _child$__r3f6;
1004
-
1005
942
  removeRecursive((_child$__r3f6 = child.__r3f) == null ? void 0 : _child$__r3f6.objects, child, shouldDispose);
1006
943
  removeRecursive(child.children, child, shouldDispose);
1007
- } // Remove references
1008
-
944
+ }
1009
945
 
946
+ // Remove references
1010
947
  if (child.__r3f) {
1011
948
  delete child.__r3f.root;
1012
949
  delete child.__r3f.objects;
1013
950
  delete child.__r3f.handlers;
1014
951
  delete child.__r3f.memoizedProps;
1015
952
  if (!isPrimitive) delete child.__r3f;
1016
- } // Dispose item whenever the reconciler feels like it
1017
-
953
+ }
1018
954
 
955
+ // Dispose item whenever the reconciler feels like it
1019
956
  if (shouldDispose && child.dispose && child.type !== 'Scene') {
1020
957
  unstable_scheduleCallback(unstable_IdlePriority, () => {
1021
958
  try {
@@ -1025,61 +962,51 @@ function createRenderer(_roots, _getEventPriority) {
1025
962
  }
1026
963
  });
1027
964
  }
1028
-
1029
965
  invalidateInstance(parentInstance);
1030
966
  }
1031
967
  }
1032
-
1033
968
  function switchInstance(instance, type, newProps, fiber) {
1034
969
  var _instance$__r3f;
1035
-
1036
970
  const parent = (_instance$__r3f = instance.__r3f) == null ? void 0 : _instance$__r3f.parent;
1037
971
  if (!parent) return;
1038
- const newInstance = createInstance(type, newProps, instance.__r3f.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
972
+ const newInstance = createInstance(type, newProps, instance.__r3f.root);
973
+
974
+ // https://github.com/pmndrs/react-three-fiber/issues/1348
1039
975
  // When args change the instance has to be re-constructed, which then
1040
976
  // forces r3f to re-parent the children and non-scene objects
1041
-
1042
977
  if (instance.children) {
1043
978
  for (const child of instance.children) {
1044
979
  if (child.__r3f) appendChild(newInstance, child);
1045
980
  }
1046
-
1047
981
  instance.children = instance.children.filter(child => !child.__r3f);
1048
982
  }
1049
-
1050
983
  instance.__r3f.objects.forEach(child => appendChild(newInstance, child));
1051
-
1052
984
  instance.__r3f.objects = [];
1053
-
1054
985
  if (!instance.__r3f.autoRemovedBeforeAppend) {
1055
986
  removeChild(parent, instance);
1056
987
  }
1057
-
1058
988
  if (newInstance.parent) {
1059
989
  newInstance.__r3f.autoRemovedBeforeAppend = true;
1060
990
  }
991
+ appendChild(parent, newInstance);
1061
992
 
1062
- appendChild(parent, newInstance); // Re-bind event handlers
1063
-
993
+ // Re-bind event handlers
1064
994
  if (newInstance.raycast && newInstance.__r3f.eventCount) {
1065
995
  const rootState = newInstance.__r3f.root.getState();
1066
-
1067
996
  rootState.internal.interaction.push(newInstance);
1068
- } // This evil hack switches the react-internal fiber node
997
+ }
1069
998
  [fiber, fiber.alternate].forEach(fiber => {
1070
999
  if (fiber !== null) {
1071
1000
  fiber.stateNode = newInstance;
1072
-
1073
1001
  if (fiber.ref) {
1074
1002
  if (typeof fiber.ref === 'function') fiber.ref(newInstance);else fiber.ref.current = newInstance;
1075
1003
  }
1076
1004
  }
1077
1005
  });
1078
- } // Don't handle text instances, warn on undefined behavior
1079
-
1006
+ }
1080
1007
 
1008
+ // Don't handle text instances, warn on undefined behavior
1081
1009
  const handleTextInstance = () => console.warn('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
1082
-
1083
1010
  const reconciler = Reconciler({
1084
1011
  createInstance,
1085
1012
  removeChild,
@@ -1092,11 +1019,13 @@ function createRenderer(_roots, _getEventPriority) {
1092
1019
  supportsHydration: false,
1093
1020
  noTimeout: -1,
1094
1021
  appendChildToContainer: (container, child) => {
1095
- if (!child) return; // Don't append to unmounted container
1022
+ if (!child) return;
1096
1023
 
1024
+ // Don't append to unmounted container
1097
1025
  const scene = container.getState().scene;
1098
- if (!scene.__r3f) return; // Link current root to the default scene
1026
+ if (!scene.__r3f) return;
1099
1027
 
1028
+ // Link current root to the default scene
1100
1029
  scene.__r3f.root = container;
1101
1030
  appendChild(scene, child);
1102
1031
  },
@@ -1105,24 +1034,22 @@ function createRenderer(_roots, _getEventPriority) {
1105
1034
  removeChild(container.getState().scene, child);
1106
1035
  },
1107
1036
  insertInContainerBefore: (container, child, beforeChild) => {
1108
- if (!child || !beforeChild) return; // Don't append to unmounted container
1037
+ if (!child || !beforeChild) return;
1109
1038
 
1039
+ // Don't append to unmounted container
1110
1040
  const scene = container.getState().scene;
1111
1041
  if (!scene.__r3f) return;
1112
1042
  insertBefore(scene, child, beforeChild);
1113
1043
  },
1114
1044
  getRootHostContext: () => null,
1115
1045
  getChildHostContext: parentHostContext => parentHostContext,
1116
-
1117
1046
  finalizeInitialChildren(instance) {
1118
1047
  var _instance$__r3f2;
1119
-
1120
- const localState = (_instance$__r3f2 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f2 : {}; // https://github.com/facebook/react/issues/20271
1048
+ const localState = (_instance$__r3f2 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f2 : {};
1049
+ // https://github.com/facebook/react/issues/20271
1121
1050
  // Returning true will trigger commitMount
1122
-
1123
1051
  return Boolean(localState.handlers);
1124
1052
  },
1125
-
1126
1053
  prepareUpdate(instance, _type, oldProps, newProps) {
1127
1054
  // Create diff-sets
1128
1055
  if (instance.__r3f.primitive && newProps.object && newProps.object !== instance) {
@@ -1138,47 +1065,44 @@ function createRenderer(_roots, _getEventPriority) {
1138
1065
  args: argsOld = [],
1139
1066
  children: cO,
1140
1067
  ...restOld
1141
- } = oldProps; // Throw if an object or literal was passed for args
1142
-
1143
- if (!Array.isArray(argsNew)) throw new Error('R3F: the args prop must be an array!'); // If it has new props or arguments, then it needs to be re-instantiated
1068
+ } = oldProps;
1144
1069
 
1145
- if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
1070
+ // Throw if an object or literal was passed for args
1071
+ if (!Array.isArray(argsNew)) throw new Error('R3F: the args prop must be an array!');
1146
1072
 
1073
+ // If it has new props or arguments, then it needs to be re-instantiated
1074
+ if (argsNew.some((value, index) => value !== argsOld[index])) return [true];
1075
+ // Create a diff-set, flag if there are any changes
1147
1076
  const diff = diffProps(instance, restNew, restOld, true);
1148
- if (diff.changes.length) return [false, diff]; // Otherwise do not touch the instance
1077
+ if (diff.changes.length) return [false, diff];
1149
1078
 
1079
+ // Otherwise do not touch the instance
1150
1080
  return null;
1151
1081
  }
1152
1082
  },
1153
-
1154
1083
  commitUpdate(instance, [reconstruct, diff], type, _oldProps, newProps, fiber) {
1155
1084
  // Reconstruct when args or <primitive object={...} have changes
1156
- if (reconstruct) switchInstance(instance, type, newProps, fiber); // Otherwise just overwrite props
1085
+ if (reconstruct) switchInstance(instance, type, newProps, fiber);
1086
+ // Otherwise just overwrite props
1157
1087
  else applyProps$1(instance, diff);
1158
1088
  },
1159
-
1160
1089
  commitMount(instance, _type, _props, _int) {
1161
1090
  var _instance$__r3f3;
1162
-
1163
1091
  // https://github.com/facebook/react/issues/20271
1164
1092
  // This will make sure events are only added once to the central container
1165
1093
  const localState = (_instance$__r3f3 = instance.__r3f) != null ? _instance$__r3f3 : {};
1166
-
1167
1094
  if (instance.raycast && localState.handlers && localState.eventCount) {
1168
1095
  instance.__r3f.root.getState().internal.interaction.push(instance);
1169
1096
  }
1170
1097
  },
1171
-
1172
1098
  getPublicInstance: instance => instance,
1173
1099
  prepareForCommit: () => null,
1174
1100
  preparePortalMount: container => prepare(container.getState().scene),
1175
1101
  resetAfterCommit: () => {},
1176
1102
  shouldSetTextContent: () => false,
1177
1103
  clearContainer: () => false,
1178
-
1179
1104
  hideInstance(instance) {
1180
1105
  var _instance$__r3f4;
1181
-
1182
1106
  // Detach while the instance is hidden
1183
1107
  const {
1184
1108
  attach: type,
@@ -1188,10 +1112,8 @@ function createRenderer(_roots, _getEventPriority) {
1188
1112
  if (instance.isObject3D) instance.visible = false;
1189
1113
  invalidateInstance(instance);
1190
1114
  },
1191
-
1192
1115
  unhideInstance(instance, props) {
1193
1116
  var _instance$__r3f5;
1194
-
1195
1117
  // Re-attach when the instance is unhidden
1196
1118
  const {
1197
1119
  attach: type,
@@ -1201,7 +1123,6 @@ function createRenderer(_roots, _getEventPriority) {
1201
1123
  if (instance.isObject3D && props.visible == null || props.visible) instance.visible = true;
1202
1124
  invalidateInstance(instance);
1203
1125
  },
1204
-
1205
1126
  createTextInstance: handleTextInstance,
1206
1127
  hideTextInstance: handleTextInstance,
1207
1128
  unhideTextInstance: handleTextInstance,
@@ -1222,16 +1143,15 @@ function createRenderer(_roots, _getEventPriority) {
1222
1143
  };
1223
1144
  }
1224
1145
 
1146
+ // Keys that shouldn't be copied between R3F stores
1225
1147
  const privateKeys = ['set', 'get', 'setSize', 'setFrameloop', 'setDpr', 'events', 'invalidate', 'advance', 'size', 'viewport'];
1226
1148
  const isRenderer = def => !!(def != null && def.render);
1227
1149
  const context = /*#__PURE__*/React.createContext(null);
1228
-
1229
1150
  const createStore = (invalidate, advance) => {
1230
1151
  const rootState = create((set, get) => {
1231
1152
  const position = new THREE.Vector3();
1232
1153
  const defaultTarget = new THREE.Vector3();
1233
1154
  const tempTarget = new THREE.Vector3();
1234
-
1235
1155
  function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
1236
1156
  const {
1237
1157
  width,
@@ -1242,7 +1162,6 @@ const createStore = (invalidate, advance) => {
1242
1162
  const aspect = width / height;
1243
1163
  if (target instanceof THREE.Vector3) tempTarget.copy(target);else tempTarget.set(...target);
1244
1164
  const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
1245
-
1246
1165
  if (isOrthographicCamera(camera)) {
1247
1166
  return {
1248
1167
  width: width / camera.zoom,
@@ -1255,9 +1174,7 @@ const createStore = (invalidate, advance) => {
1255
1174
  };
1256
1175
  } else {
1257
1176
  const fov = camera.fov * Math.PI / 180; // convert vertical fov to radians
1258
-
1259
1177
  const h = 2 * Math.tan(fov / 2) * distance; // visible height
1260
-
1261
1178
  const w = h * (width / height);
1262
1179
  return {
1263
1180
  width: w,
@@ -1270,15 +1187,13 @@ const createStore = (invalidate, advance) => {
1270
1187
  };
1271
1188
  }
1272
1189
  }
1273
-
1274
1190
  let performanceTimeout = undefined;
1275
-
1276
1191
  const setPerformanceCurrent = current => set(state => ({
1277
- performance: { ...state.performance,
1192
+ performance: {
1193
+ ...state.performance,
1278
1194
  current
1279
1195
  }
1280
1196
  }));
1281
-
1282
1197
  const pointer = new THREE.Vector2();
1283
1198
  const rootState = {
1284
1199
  set,
@@ -1311,12 +1226,12 @@ const createStore = (invalidate, advance) => {
1311
1226
  max: 1,
1312
1227
  debounce: 200,
1313
1228
  regress: () => {
1314
- const state = get(); // Clear timeout
1315
-
1316
- if (performanceTimeout) clearTimeout(performanceTimeout); // Set lower bound performance
1317
-
1318
- if (state.performance.current !== state.performance.min) setPerformanceCurrent(state.performance.min); // Go back to upper bound performance after a while unless something regresses meanwhile
1319
-
1229
+ const state = get();
1230
+ // Clear timeout
1231
+ if (performanceTimeout) clearTimeout(performanceTimeout);
1232
+ // Set lower bound performance
1233
+ if (state.performance.current !== state.performance.min) setPerformanceCurrent(state.performance.min);
1234
+ // Go back to upper bound performance after a while unless something regresses meanwhile
1320
1235
  performanceTimeout = setTimeout(() => setPerformanceCurrent(get().performance.max), state.performance.debounce);
1321
1236
  }
1322
1237
  },
@@ -1339,8 +1254,10 @@ const createStore = (invalidate, advance) => {
1339
1254
  factor: 0,
1340
1255
  getCurrentViewport
1341
1256
  },
1342
- setEvents: events => set(state => ({ ...state,
1343
- events: { ...state.events,
1257
+ setEvents: events => set(state => ({
1258
+ ...state,
1259
+ events: {
1260
+ ...state.events,
1344
1261
  ...events
1345
1262
  }
1346
1263
  })),
@@ -1355,7 +1272,8 @@ const createStore = (invalidate, advance) => {
1355
1272
  };
1356
1273
  set(state => ({
1357
1274
  size,
1358
- viewport: { ...state.viewport,
1275
+ viewport: {
1276
+ ...state.viewport,
1359
1277
  ...getCurrentViewport(camera, defaultTarget, size)
1360
1278
  }
1361
1279
  }));
@@ -1363,23 +1281,23 @@ const createStore = (invalidate, advance) => {
1363
1281
  setDpr: dpr => set(state => {
1364
1282
  const resolved = calculateDpr(dpr);
1365
1283
  return {
1366
- viewport: { ...state.viewport,
1284
+ viewport: {
1285
+ ...state.viewport,
1367
1286
  dpr: resolved,
1368
1287
  initialDpr: state.viewport.initialDpr || resolved
1369
1288
  }
1370
1289
  };
1371
1290
  }),
1372
1291
  setFrameloop: (frameloop = 'always') => {
1373
- const clock = get().clock; // if frameloop === "never" clock.elapsedTime is updated using advance(timestamp)
1292
+ const clock = get().clock;
1374
1293
 
1294
+ // if frameloop === "never" clock.elapsedTime is updated using advance(timestamp)
1375
1295
  clock.stop();
1376
1296
  clock.elapsedTime = 0;
1377
-
1378
1297
  if (frameloop !== 'never') {
1379
1298
  clock.start();
1380
1299
  clock.elapsedTime = 0;
1381
1300
  }
1382
-
1383
1301
  set(() => ({
1384
1302
  frameloop
1385
1303
  }));
@@ -1397,27 +1315,26 @@ const createStore = (invalidate, advance) => {
1397
1315
  initialHits: [],
1398
1316
  capturedMap: new Map(),
1399
1317
  subscribe: (ref, priority, store) => {
1400
- const internal = get().internal; // If this subscription was given a priority, it takes rendering into its own hands
1318
+ const internal = get().internal;
1319
+ // If this subscription was given a priority, it takes rendering into its own hands
1401
1320
  // For that reason we switch off automatic rendering and increase the manual flag
1402
1321
  // As long as this flag is positive there can be no internal rendering at all
1403
1322
  // because there could be multiple render subscriptions
1404
-
1405
1323
  internal.priority = internal.priority + (priority > 0 ? 1 : 0);
1406
1324
  internal.subscribers.push({
1407
1325
  ref,
1408
1326
  priority,
1409
1327
  store
1410
- }); // Register subscriber and sort layers from lowest to highest, meaning,
1328
+ });
1329
+ // Register subscriber and sort layers from lowest to highest, meaning,
1411
1330
  // highest priority renders last (on top of the other frames)
1412
-
1413
1331
  internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
1414
1332
  return () => {
1415
1333
  const internal = get().internal;
1416
-
1417
1334
  if (internal != null && internal.subscribers) {
1418
1335
  // Decrease manual flag if this subscription had a priority
1419
- internal.priority = internal.priority - (priority > 0 ? 1 : 0); // Remove subscriber from list
1420
-
1336
+ internal.priority = internal.priority - (priority > 0 ? 1 : 0);
1337
+ // Remove subscriber from list
1421
1338
  internal.subscribers = internal.subscribers.filter(s => s.ref !== ref);
1422
1339
  }
1423
1340
  };
@@ -1437,31 +1354,35 @@ const createStore = (invalidate, advance) => {
1437
1354
  viewport,
1438
1355
  gl,
1439
1356
  set
1440
- } = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
1357
+ } = rootState.getState();
1441
1358
 
1359
+ // Resize camera and renderer on changes to size and pixelratio
1442
1360
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1443
1361
  oldSize = size;
1444
- oldDpr = viewport.dpr; // Update camera & renderer
1445
-
1362
+ oldDpr = viewport.dpr;
1363
+ // Update camera & renderer
1446
1364
  updateCamera(camera, size);
1447
1365
  gl.setPixelRatio(viewport.dpr);
1448
1366
  gl.setSize(size.width, size.height, size.updateStyle);
1449
- } // Update viewport once the camera changes
1450
-
1367
+ }
1451
1368
 
1369
+ // Update viewport once the camera changes
1452
1370
  if (camera !== oldCamera) {
1453
- oldCamera = camera; // Update viewport
1454
-
1371
+ oldCamera = camera;
1372
+ // Update viewport
1455
1373
  set(state => ({
1456
- viewport: { ...state.viewport,
1374
+ viewport: {
1375
+ ...state.viewport,
1457
1376
  ...state.viewport.getCurrentViewport(camera)
1458
1377
  }
1459
1378
  }));
1460
1379
  }
1461
- }); // Invalidate on any change
1380
+ });
1462
1381
 
1463
- rootState.subscribe(state => invalidate(state)); // Return root state
1382
+ // Invalidate on any change
1383
+ rootState.subscribe(state => invalidate(state));
1464
1384
 
1385
+ // Return root state
1465
1386
  return rootState;
1466
1387
  };
1467
1388
 
@@ -1472,144 +1393,129 @@ function createSubs(callback, subs) {
1472
1393
  subs.add(sub);
1473
1394
  return () => void subs.delete(sub);
1474
1395
  }
1475
-
1476
1396
  let i;
1477
1397
  let globalEffects = new Set();
1478
1398
  let globalAfterEffects = new Set();
1479
1399
  let globalTailEffects = new Set();
1400
+
1480
1401
  /**
1481
1402
  * Adds a global render callback which is called each frame.
1482
1403
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
1483
1404
  */
1484
-
1485
1405
  const addEffect = callback => createSubs(callback, globalEffects);
1406
+
1486
1407
  /**
1487
1408
  * Adds a global after-render callback which is called each frame.
1488
1409
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
1489
1410
  */
1490
-
1491
1411
  const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
1412
+
1492
1413
  /**
1493
1414
  * Adds a global callback which is called when rendering stops.
1494
1415
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
1495
1416
  */
1496
-
1497
1417
  const addTail = callback => createSubs(callback, globalTailEffects);
1498
-
1499
1418
  function run(effects, timestamp) {
1500
1419
  if (!effects.size) return;
1501
-
1502
1420
  for (const {
1503
1421
  callback
1504
1422
  } of effects.values()) {
1505
1423
  callback(timestamp);
1506
1424
  }
1507
1425
  }
1508
-
1509
1426
  function flushGlobalEffects(type, timestamp) {
1510
1427
  switch (type) {
1511
1428
  case 'before':
1512
1429
  return run(globalEffects, timestamp);
1513
-
1514
1430
  case 'after':
1515
1431
  return run(globalAfterEffects, timestamp);
1516
-
1517
1432
  case 'tail':
1518
1433
  return run(globalTailEffects, timestamp);
1519
1434
  }
1520
1435
  }
1521
1436
  let subscribers;
1522
1437
  let subscription;
1523
-
1524
1438
  function render$1(timestamp, state, frame) {
1525
1439
  // Run local effects
1526
- let delta = state.clock.getDelta(); // In frameloop='never' mode, clock times are updated using the provided timestamp
1527
-
1440
+ let delta = state.clock.getDelta();
1441
+ // In frameloop='never' mode, clock times are updated using the provided timestamp
1528
1442
  if (state.frameloop === 'never' && typeof timestamp === 'number') {
1529
1443
  delta = timestamp - state.clock.elapsedTime;
1530
1444
  state.clock.oldTime = state.clock.elapsedTime;
1531
1445
  state.clock.elapsedTime = timestamp;
1532
- } // Call subscribers (useFrame)
1533
-
1534
-
1446
+ }
1447
+ // Call subscribers (useFrame)
1535
1448
  subscribers = state.internal.subscribers;
1536
-
1537
1449
  for (i = 0; i < subscribers.length; i++) {
1538
1450
  subscription = subscribers[i];
1539
1451
  subscription.ref.current(subscription.store.getState(), delta, frame);
1540
- } // Render content
1541
-
1542
-
1543
- if (!state.internal.priority && state.gl.render) state.gl.render(state.scene, state.camera); // Decrease frame count
1544
-
1452
+ }
1453
+ // Render content
1454
+ if (!state.internal.priority && state.gl.render) state.gl.render(state.scene, state.camera);
1455
+ // Decrease frame count
1545
1456
  state.internal.frames = Math.max(0, state.internal.frames - 1);
1546
1457
  return state.frameloop === 'always' ? 1 : state.internal.frames;
1547
1458
  }
1548
-
1549
1459
  function createLoop(roots) {
1550
1460
  let running = false;
1551
1461
  let repeat;
1552
1462
  let frame;
1553
1463
  let state;
1554
-
1555
1464
  function loop(timestamp) {
1556
1465
  frame = requestAnimationFrame(loop);
1557
1466
  running = true;
1558
- repeat = 0; // Run effects
1467
+ repeat = 0;
1559
1468
 
1560
- flushGlobalEffects('before', timestamp); // Render all roots
1469
+ // Run effects
1470
+ flushGlobalEffects('before', timestamp);
1561
1471
 
1472
+ // Render all roots
1562
1473
  for (const root of roots.values()) {
1563
1474
  var _state$gl$xr;
1564
-
1565
- state = root.store.getState(); // If the frameloop is invalidated, do not run another frame
1566
-
1475
+ state = root.store.getState();
1476
+ // If the frameloop is invalidated, do not run another frame
1567
1477
  if (state.internal.active && (state.frameloop === 'always' || state.internal.frames > 0) && !((_state$gl$xr = state.gl.xr) != null && _state$gl$xr.isPresenting)) {
1568
1478
  repeat += render$1(timestamp, state);
1569
1479
  }
1570
- } // Run after-effects
1571
-
1480
+ }
1572
1481
 
1573
- flushGlobalEffects('after', timestamp); // Stop the loop if nothing invalidates it
1482
+ // Run after-effects
1483
+ flushGlobalEffects('after', timestamp);
1574
1484
 
1485
+ // Stop the loop if nothing invalidates it
1575
1486
  if (repeat === 0) {
1576
1487
  // Tail call effects, they are called when rendering stops
1577
- flushGlobalEffects('tail', timestamp); // Flag end of operation
1488
+ flushGlobalEffects('tail', timestamp);
1578
1489
 
1490
+ // Flag end of operation
1579
1491
  running = false;
1580
1492
  return cancelAnimationFrame(frame);
1581
1493
  }
1582
1494
  }
1583
-
1584
1495
  function invalidate(state, frames = 1) {
1585
1496
  var _state$gl$xr2;
1586
-
1587
1497
  if (!state) return roots.forEach(root => invalidate(root.store.getState()), frames);
1588
- if ((_state$gl$xr2 = state.gl.xr) != null && _state$gl$xr2.isPresenting || !state.internal.active || state.frameloop === 'never') return; // Increase frames, do not go higher than 60
1589
-
1590
- state.internal.frames = Math.min(60, state.internal.frames + frames); // If the render-loop isn't active, start it
1591
-
1498
+ if ((_state$gl$xr2 = state.gl.xr) != null && _state$gl$xr2.isPresenting || !state.internal.active || state.frameloop === 'never') return;
1499
+ // Increase frames, do not go higher than 60
1500
+ state.internal.frames = Math.min(60, state.internal.frames + frames);
1501
+ // If the render-loop isn't active, start it
1592
1502
  if (!running) {
1593
1503
  running = true;
1594
1504
  requestAnimationFrame(loop);
1595
1505
  }
1596
1506
  }
1597
-
1598
1507
  function advance(timestamp, runGlobalEffects = true, state, frame) {
1599
1508
  if (runGlobalEffects) flushGlobalEffects('before', timestamp);
1600
1509
  if (!state) for (const root of roots.values()) render$1(timestamp, root.store.getState());else render$1(timestamp, state, frame);
1601
1510
  if (runGlobalEffects) flushGlobalEffects('after', timestamp);
1602
1511
  }
1603
-
1604
1512
  return {
1605
1513
  loop,
1606
-
1607
1514
  /**
1608
1515
  * Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
1609
1516
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
1610
1517
  */
1611
1518
  invalidate,
1612
-
1613
1519
  /**
1614
1520
  * Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
1615
1521
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
@@ -1634,80 +1540,77 @@ function useStore() {
1634
1540
  if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
1635
1541
  return store;
1636
1542
  }
1543
+
1637
1544
  /**
1638
1545
  * Accesses R3F's internal state, containing renderer, canvas, scene, etc.
1639
1546
  * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usethree
1640
1547
  */
1641
-
1642
1548
  function useThree(selector = state => state, equalityFn) {
1643
1549
  return useStore()(selector, equalityFn);
1644
1550
  }
1551
+
1645
1552
  /**
1646
1553
  * Executes a callback before render in a shared frame loop.
1647
1554
  * Can order effects with render priority or manually render with a positive priority.
1648
1555
  * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
1649
1556
  */
1650
-
1651
1557
  function useFrame(callback, renderPriority = 0) {
1652
1558
  const store = useStore();
1653
- const subscribe = store.getState().internal.subscribe; // Memoize ref
1654
-
1655
- const ref = useMutableCallback(callback); // Subscribe on mount, unsubscribe on unmount
1656
-
1559
+ const subscribe = store.getState().internal.subscribe;
1560
+ // Memoize ref
1561
+ const ref = useMutableCallback(callback);
1562
+ // Subscribe on mount, unsubscribe on unmount
1657
1563
  useIsomorphicLayoutEffect(() => subscribe(ref, renderPriority, store), [renderPriority, subscribe, store]);
1658
1564
  return null;
1659
1565
  }
1566
+
1660
1567
  /**
1661
1568
  * Returns a node graph of an object with named nodes & materials.
1662
1569
  * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
1663
1570
  */
1664
-
1665
1571
  function useGraph(object) {
1666
1572
  return React.useMemo(() => buildGraph(object), [object]);
1667
1573
  }
1668
-
1669
1574
  function loadingFn(extensions, onProgress) {
1670
1575
  return function (Proto, ...input) {
1671
1576
  // Construct new loader and run extensions
1672
1577
  const loader = new Proto();
1673
- if (extensions) extensions(loader); // Go through the urls and load them
1674
-
1578
+ if (extensions) extensions(loader);
1579
+ // Go through the urls and load them
1675
1580
  return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => {
1676
1581
  if (data.scene) Object.assign(data, buildGraph(data.scene));
1677
1582
  res(data);
1678
1583
  }, onProgress, error => reject(new Error(`Could not load ${input}: ${error.message})`))))));
1679
1584
  };
1680
1585
  }
1586
+
1681
1587
  /**
1682
1588
  * Synchronously loads and caches assets with a three loader.
1683
1589
  *
1684
1590
  * Note: this hook's caller must be wrapped with `React.Suspense`
1685
1591
  * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useloader
1686
1592
  */
1687
-
1688
-
1689
1593
  function useLoader(Proto, input, extensions, onProgress) {
1690
1594
  // Use suspense to load async assets
1691
1595
  const keys = Array.isArray(input) ? input : [input];
1692
1596
  const results = suspend(loadingFn(extensions, onProgress), [Proto, ...keys], {
1693
1597
  equal: is.equ
1694
- }); // Return the object/s
1695
-
1598
+ });
1599
+ // Return the object/s
1696
1600
  return Array.isArray(input) ? results : results[0];
1697
1601
  }
1602
+
1698
1603
  /**
1699
1604
  * Preloads an asset into cache as a side-effect.
1700
1605
  */
1701
-
1702
1606
  useLoader.preload = function (Proto, input, extensions) {
1703
1607
  const keys = Array.isArray(input) ? input : [input];
1704
1608
  return preload(loadingFn(extensions), [Proto, ...keys]);
1705
1609
  };
1610
+
1706
1611
  /**
1707
1612
  * Removes a loaded asset from cache.
1708
1613
  */
1709
-
1710
-
1711
1614
  useLoader.clear = function (Proto, input) {
1712
1615
  const keys = Array.isArray(input) ? input : [input];
1713
1616
  return clear([Proto, ...keys]);
@@ -1726,7 +1629,6 @@ const shallowLoose = {
1726
1629
  objects: 'shallow',
1727
1630
  strict: false
1728
1631
  };
1729
-
1730
1632
  const createRendererInstance = (gl, canvas) => {
1731
1633
  const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
1732
1634
  if (isRenderer(customRenderer)) return customRenderer;else return new THREE.WebGLRenderer({
@@ -1737,16 +1639,13 @@ const createRendererInstance = (gl, canvas) => {
1737
1639
  ...gl
1738
1640
  });
1739
1641
  };
1740
-
1741
1642
  function isCanvas(maybeCanvas) {
1742
1643
  return maybeCanvas instanceof HTMLCanvasElement;
1743
1644
  }
1744
-
1745
1645
  function computeInitialSize(canvas, defaultSize) {
1746
1646
  if (defaultSize) {
1747
1647
  return defaultSize;
1748
1648
  }
1749
-
1750
1649
  if (isCanvas(canvas) && canvas.parentElement) {
1751
1650
  const {
1752
1651
  width,
@@ -1761,7 +1660,6 @@ function computeInitialSize(canvas, defaultSize) {
1761
1660
  left
1762
1661
  };
1763
1662
  }
1764
-
1765
1663
  return {
1766
1664
  width: 0,
1767
1665
  height: 0,
@@ -1769,29 +1667,33 @@ function computeInitialSize(canvas, defaultSize) {
1769
1667
  left: 0
1770
1668
  };
1771
1669
  }
1772
-
1773
1670
  function createRoot(canvas) {
1774
1671
  // Check against mistaken use of createRoot
1775
1672
  const prevRoot = roots.get(canvas);
1776
1673
  const prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
1777
1674
  const prevStore = prevRoot == null ? void 0 : prevRoot.store;
1778
- if (prevRoot) console.warn('R3F.createRoot should only be called once!'); // Report when an error was detected in a previous render
1779
- // https://github.com/pmndrs/react-three-fiber/pull/2261
1675
+ if (prevRoot) console.warn('R3F.createRoot should only be called once!');
1780
1676
 
1781
- const logRecoverableError = typeof reportError === 'function' ? // In modern browsers, reportError will dispatch an error event,
1677
+ // Report when an error was detected in a previous render
1678
+ // https://github.com/pmndrs/react-three-fiber/pull/2261
1679
+ const logRecoverableError = typeof reportError === 'function' ?
1680
+ // In modern browsers, reportError will dispatch an error event,
1782
1681
  // emulating an uncaught JavaScript error.
1783
- reportError : // In older browsers and test environments, fallback to console.error.
1784
- console.error; // Create store
1785
-
1786
- const store = prevStore || createStore(invalidate, advance); // Create renderer
1787
-
1788
- const fiber = prevFiber || reconciler.createContainer(store, ConcurrentRoot, null, false, null, '', logRecoverableError, null); // Map it
1789
-
1682
+ reportError :
1683
+ // In older browsers and test environments, fallback to console.error.
1684
+ console.error;
1685
+
1686
+ // Create store
1687
+ const store = prevStore || createStore(invalidate, advance);
1688
+ // Create renderer
1689
+ const fiber = prevFiber || reconciler.createContainer(store, ConcurrentRoot, null, false, null, '', logRecoverableError, null);
1690
+ // Map it
1790
1691
  if (!prevRoot) roots.set(canvas, {
1791
1692
  fiber,
1792
1693
  store
1793
- }); // Locals
1694
+ });
1794
1695
 
1696
+ // Locals
1795
1697
  let onCreated;
1796
1698
  let configured = false;
1797
1699
  return {
@@ -1813,96 +1715,97 @@ function createRoot(canvas) {
1813
1715
  camera: cameraOptions,
1814
1716
  onPointerMissed
1815
1717
  } = props;
1816
- let state = store.getState(); // Set up renderer (one time only!)
1718
+ let state = store.getState();
1817
1719
 
1720
+ // Set up renderer (one time only!)
1818
1721
  let gl = state.gl;
1819
1722
  if (!state.gl) state.set({
1820
1723
  gl: gl = createRendererInstance(glConfig, canvas)
1821
- }); // Set up raycaster (one time only!)
1724
+ });
1822
1725
 
1726
+ // Set up raycaster (one time only!)
1823
1727
  let raycaster = state.raycaster;
1824
1728
  if (!raycaster) state.set({
1825
1729
  raycaster: raycaster = new THREE.Raycaster()
1826
- }); // Set raycaster options
1730
+ });
1827
1731
 
1732
+ // Set raycaster options
1828
1733
  const {
1829
1734
  params,
1830
1735
  ...options
1831
1736
  } = raycastOptions || {};
1832
- if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, { ...options
1737
+ if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, {
1738
+ ...options
1833
1739
  });
1834
1740
  if (!is.equ(params, raycaster.params, shallowLoose)) applyProps(raycaster, {
1835
- params: { ...raycaster.params,
1741
+ params: {
1742
+ ...raycaster.params,
1836
1743
  ...params
1837
1744
  }
1838
- }); // Create default camera (one time only!)
1745
+ });
1839
1746
 
1747
+ // Create default camera (one time only!)
1840
1748
  if (!state.camera) {
1841
1749
  const isCamera = cameraOptions instanceof THREE.Camera;
1842
1750
  const camera = isCamera ? cameraOptions : orthographic ? new THREE.OrthographicCamera(0, 0, 0, 0, 0.1, 1000) : new THREE.PerspectiveCamera(75, 0, 0.1, 1000);
1843
-
1844
1751
  if (!isCamera) {
1845
1752
  camera.position.z = 5;
1846
- if (cameraOptions) applyProps(camera, cameraOptions); // Always look at center by default
1847
-
1753
+ if (cameraOptions) applyProps(camera, cameraOptions);
1754
+ // Always look at center by default
1848
1755
  if (!(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
1849
1756
  }
1850
-
1851
1757
  state.set({
1852
1758
  camera
1853
1759
  });
1854
- } // Set up XR (one time only!)
1855
-
1760
+ }
1856
1761
 
1762
+ // Set up XR (one time only!)
1857
1763
  if (!state.xr) {
1858
1764
  // Handle frame behavior in WebXR
1859
1765
  const handleXRFrame = (timestamp, frame) => {
1860
1766
  const state = store.getState();
1861
1767
  if (state.frameloop === 'never') return;
1862
1768
  advance(timestamp, true, state, frame);
1863
- }; // Toggle render switching on session
1864
-
1769
+ };
1865
1770
 
1771
+ // Toggle render switching on session
1866
1772
  const handleSessionChange = () => {
1867
1773
  const state = store.getState();
1868
1774
  state.gl.xr.enabled = state.gl.xr.isPresenting;
1869
1775
  state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
1870
1776
  if (!state.gl.xr.isPresenting) invalidate(state);
1871
- }; // WebXR session manager
1872
-
1777
+ };
1873
1778
 
1779
+ // WebXR session manager
1874
1780
  const xr = {
1875
1781
  connect() {
1876
1782
  const gl = store.getState().gl;
1877
1783
  gl.xr.addEventListener('sessionstart', handleSessionChange);
1878
1784
  gl.xr.addEventListener('sessionend', handleSessionChange);
1879
1785
  },
1880
-
1881
1786
  disconnect() {
1882
1787
  const gl = store.getState().gl;
1883
1788
  gl.xr.removeEventListener('sessionstart', handleSessionChange);
1884
1789
  gl.xr.removeEventListener('sessionend', handleSessionChange);
1885
1790
  }
1791
+ };
1886
1792
 
1887
- }; // Subscribe to WebXR session events
1888
-
1793
+ // Subscribe to WebXR session events
1889
1794
  if (gl.xr) xr.connect();
1890
1795
  state.set({
1891
1796
  xr
1892
1797
  });
1893
- } // Set shadowmap
1894
-
1798
+ }
1895
1799
 
1800
+ // Set shadowmap
1896
1801
  if (gl.shadowMap) {
1897
1802
  const oldEnabled = gl.shadowMap.enabled;
1898
1803
  const oldType = gl.shadowMap.type;
1899
1804
  gl.shadowMap.enabled = !!shadows;
1900
-
1901
1805
  if (is.boo(shadows)) {
1902
1806
  gl.shadowMap.type = THREE.PCFSoftShadowMap;
1903
1807
  } else if (is.str(shadows)) {
1904
1808
  var _types$shadows;
1905
-
1906
1809
  const types = {
1907
1810
  basic: THREE.BasicShadowMap,
1908
1811
  percentage: THREE.PCFShadowMap,
@@ -1913,21 +1816,20 @@ function createRoot(canvas) {
1913
1816
  } else if (is.obj(shadows)) {
1914
1817
  Object.assign(gl.shadowMap, shadows);
1915
1818
  }
1916
-
1917
1819
  if (oldEnabled !== gl.shadowMap.enabled || oldType !== gl.shadowMap.type) gl.shadowMap.needsUpdate = true;
1918
- } // Safely set color management if available.
1919
- // Avoid accessing THREE.ColorManagement to play nice with older versions
1920
-
1820
+ }
1921
1821
 
1822
+ // Safely set color management if available.
1823
+ // Avoid accessing THREE.ColorManagement to play nice with older versions
1922
1824
  if ('ColorManagement' in THREE) {
1923
1825
  setDeep(THREE, legacy, ['ColorManagement', 'legacyMode']);
1924
1826
  }
1925
-
1926
1827
  const outputEncoding = linear ? THREE.LinearEncoding : THREE.sRGBEncoding;
1927
1828
  const toneMapping = flat ? THREE.NoToneMapping : THREE.ACESFilmicToneMapping;
1928
1829
  if (gl.outputEncoding !== outputEncoding) gl.outputEncoding = outputEncoding;
1929
- if (gl.toneMapping !== toneMapping) gl.toneMapping = toneMapping; // Update color management state
1830
+ if (gl.toneMapping !== toneMapping) gl.toneMapping = toneMapping;
1930
1831
 
1832
+ // Update color management state
1931
1833
  if (state.legacy !== legacy) state.set(() => ({
1932
1834
  legacy
1933
1835
  }));
@@ -1936,40 +1838,40 @@ function createRoot(canvas) {
1936
1838
  }));
1937
1839
  if (state.flat !== flat) state.set(() => ({
1938
1840
  flat
1939
- })); // Set gl props
1940
-
1941
- if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig); // Store events internally
1841
+ }));
1942
1842
 
1843
+ // Set gl props
1844
+ if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig);
1845
+ // Store events internally
1943
1846
  if (events && !state.events.handlers) state.set({
1944
1847
  events: events(store)
1945
- }); // Check pixelratio
1946
-
1947
- if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr); // Check size, allow it to take on container bounds initially
1948
-
1848
+ });
1849
+ // Check pixelratio
1850
+ if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
1851
+ // Check size, allow it to take on container bounds initially
1949
1852
  const size = computeInitialSize(canvas, propsSize);
1950
-
1951
1853
  if (!is.equ(size, state.size, shallowLoose)) {
1952
1854
  state.setSize(size.width, size.height, size.updateStyle, size.top, size.left);
1953
- } // Check frameloop
1954
-
1955
-
1956
- if (state.frameloop !== frameloop) state.setFrameloop(frameloop); // Check pointer missed
1957
-
1855
+ }
1856
+ // Check frameloop
1857
+ if (state.frameloop !== frameloop) state.setFrameloop(frameloop);
1858
+ // Check pointer missed
1958
1859
  if (!state.onPointerMissed) state.set({
1959
1860
  onPointerMissed
1960
- }); // Check performance
1961
-
1861
+ });
1862
+ // Check performance
1962
1863
  if (performance && !is.equ(performance, state.performance, shallowLoose)) state.set(state => ({
1963
- performance: { ...state.performance,
1864
+ performance: {
1865
+ ...state.performance,
1964
1866
  ...performance
1965
1867
  }
1966
- })); // Set locals
1868
+ }));
1967
1869
 
1870
+ // Set locals
1968
1871
  onCreated = onCreatedCallback;
1969
1872
  configured = true;
1970
1873
  return this;
1971
1874
  },
1972
-
1973
1875
  render(children) {
1974
1876
  // The root has to be configured before it can be rendered
1975
1877
  if (!configured) this.configure();
@@ -1981,21 +1883,17 @@ function createRoot(canvas) {
1981
1883
  }), fiber, null, () => undefined);
1982
1884
  return store;
1983
1885
  },
1984
-
1985
1886
  unmount() {
1986
1887
  unmountComponentAtNode(canvas);
1987
1888
  }
1988
-
1989
1889
  };
1990
1890
  }
1991
-
1992
1891
  function render(children, canvas, config) {
1993
1892
  console.warn('R3F.render is no longer supported in React 18. Use createRoot instead!');
1994
1893
  const root = createRoot(canvas);
1995
1894
  root.configure(config);
1996
1895
  return root.render(children);
1997
1896
  }
1998
-
1999
1897
  function Provider({
2000
1898
  store,
2001
1899
  children,
@@ -2003,28 +1901,28 @@ function Provider({
2003
1901
  rootElement
2004
1902
  }) {
2005
1903
  useIsomorphicLayoutEffect(() => {
2006
- const state = store.getState(); // Flag the canvas active, rendering will now begin
2007
-
1904
+ const state = store.getState();
1905
+ // Flag the canvas active, rendering will now begin
2008
1906
  state.set(state => ({
2009
- internal: { ...state.internal,
1907
+ internal: {
1908
+ ...state.internal,
2010
1909
  active: true
2011
1910
  }
2012
- })); // Notifiy that init is completed, the scene graph exists, but nothing has yet rendered
2013
-
2014
- if (onCreated) onCreated(state); // Connect events to the targets parent, this is done to ensure events are registered on
1911
+ }));
1912
+ // Notifiy that init is completed, the scene graph exists, but nothing has yet rendered
1913
+ if (onCreated) onCreated(state);
1914
+ // Connect events to the targets parent, this is done to ensure events are registered on
2015
1915
  // a shared target, and not on the canvas itself
2016
-
2017
- if (!store.getState().events.connected) state.events.connect == null ? void 0 : state.events.connect(rootElement); // eslint-disable-next-line react-hooks/exhaustive-deps
1916
+ if (!store.getState().events.connected) state.events.connect == null ? void 0 : state.events.connect(rootElement);
1917
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2018
1918
  }, []);
2019
1919
  return /*#__PURE__*/React.createElement(context.Provider, {
2020
1920
  value: store
2021
1921
  }, children);
2022
1922
  }
2023
-
2024
1923
  function unmountComponentAtNode(canvas, callback) {
2025
1924
  const root = roots.get(canvas);
2026
1925
  const fiber = root == null ? void 0 : root.fiber;
2027
-
2028
1926
  if (fiber) {
2029
1927
  const state = root == null ? void 0 : root.store.getState();
2030
1928
  if (state) state.internal.active = false;
@@ -2033,7 +1931,6 @@ function unmountComponentAtNode(canvas, callback) {
2033
1931
  setTimeout(() => {
2034
1932
  try {
2035
1933
  var _state$gl, _state$gl$renderLists, _state$gl2, _state$gl3;
2036
-
2037
1934
  state.events.disconnect == null ? void 0 : state.events.disconnect();
2038
1935
  (_state$gl = state.gl) == null ? void 0 : (_state$gl$renderLists = _state$gl.renderLists) == null ? void 0 : _state$gl$renderLists.dispose == null ? void 0 : _state$gl$renderLists.dispose();
2039
1936
  (_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
@@ -2049,7 +1946,6 @@ function unmountComponentAtNode(canvas, callback) {
2049
1946
  });
2050
1947
  }
2051
1948
  }
2052
-
2053
1949
  function createPortal(children, container, state) {
2054
1950
  return /*#__PURE__*/React.createElement(Portal, {
2055
1951
  key: container.uuid,
@@ -2058,7 +1954,6 @@ function createPortal(children, container, state) {
2058
1954
  state: state
2059
1955
  });
2060
1956
  }
2061
-
2062
1957
  function Portal({
2063
1958
  state = {},
2064
1959
  children,
@@ -2078,30 +1973,33 @@ function Portal({
2078
1973
  const [raycaster] = React.useState(() => new THREE.Raycaster());
2079
1974
  const [pointer] = React.useState(() => new THREE.Vector2());
2080
1975
  const inject = React.useCallback((rootState, injectState) => {
2081
- const intersect = { ...rootState
1976
+ const intersect = {
1977
+ ...rootState
2082
1978
  }; // all prev state props
1979
+
2083
1980
  // Only the fields of "rootState" that do not differ from injectState
2084
1981
  // Some props should be off-limits
2085
1982
  // Otherwise filter out the props that are different and let the inject layer take precedence
2086
-
2087
1983
  Object.keys(rootState).forEach(key => {
2088
- if ( // Some props should be off-limits
2089
- privateKeys.includes(key) || // Otherwise filter out the props that are different and let the inject layer take precedence
2090
- rootState[key] !== injectState[key]) {
1984
+ if (
1985
+ // Some props should be off-limits
1986
+ privateKeys.includes(key) ||
1987
+ // Otherwise filter out the props that are different and let the inject layer take precedence
1988
+ // Unless the inject layer props is undefined, then we keep the root layer
1989
+ rootState[key] !== injectState[key] && injectState[key]) {
2091
1990
  delete intersect[key];
2092
1991
  }
2093
1992
  });
2094
1993
  let viewport = undefined;
2095
-
2096
1994
  if (injectState && size) {
2097
- const camera = injectState.camera; // Calculate the override viewport, if present
2098
-
2099
- viewport = rootState.viewport.getCurrentViewport(camera, new THREE.Vector3(), size); // Update the portal camera, if it differs from the previous layer
2100
-
1995
+ const camera = injectState.camera;
1996
+ // Calculate the override viewport, if present
1997
+ viewport = rootState.viewport.getCurrentViewport(camera, new THREE.Vector3(), size);
1998
+ // Update the portal camera, if it differs from the previous layer
2101
1999
  if (camera !== rootState.camera) updateCamera(camera, size);
2102
2000
  }
2103
-
2104
- return { // The intersect consists of the previous root state
2001
+ return {
2002
+ // The intersect consists of the previous root state
2105
2003
  ...intersect,
2106
2004
  // Portals have their own scene, which forms the root, a raycaster and a pointer
2107
2005
  scene: container,
@@ -2111,14 +2009,17 @@ function Portal({
2111
2009
  // Their previous root is the layer before it
2112
2010
  previousRoot,
2113
2011
  // Events, size and viewport can be overridden by the inject layer
2114
- events: { ...rootState.events,
2012
+ events: {
2013
+ ...rootState.events,
2115
2014
  ...(injectState == null ? void 0 : injectState.events),
2116
2015
  ...events
2117
2016
  },
2118
- size: { ...rootState.size,
2017
+ size: {
2018
+ ...rootState.size,
2119
2019
  ...size
2120
2020
  },
2121
- viewport: { ...rootState.viewport,
2021
+ viewport: {
2022
+ ...rootState.viewport,
2122
2023
  ...viewport
2123
2024
  },
2124
2025
  ...rest
@@ -2127,16 +2028,19 @@ function Portal({
2127
2028
  const [usePortalStore] = React.useState(() => {
2128
2029
  // Create a mirrored store, based on the previous root with a few overrides ...
2129
2030
  const previousState = previousRoot.getState();
2130
- const store = create((set, get) => ({ ...previousState,
2031
+ const store = create((set, get) => ({
2032
+ ...previousState,
2131
2033
  scene: container,
2132
2034
  raycaster,
2133
2035
  pointer,
2134
2036
  mouse: pointer,
2135
2037
  previousRoot,
2136
- events: { ...previousState.events,
2038
+ events: {
2039
+ ...previousState.events,
2137
2040
  ...events
2138
2041
  },
2139
- size: { ...previousState.size,
2042
+ size: {
2043
+ ...previousState.size,
2140
2044
  ...size
2141
2045
  },
2142
2046
  ...rest,
@@ -2144,8 +2048,10 @@ function Portal({
2144
2048
  set,
2145
2049
  get,
2146
2050
  // Layers are allowed to override events
2147
- setEvents: events => set(state => ({ ...state,
2148
- events: { ...state.events,
2051
+ setEvents: events => set(state => ({
2052
+ ...state,
2053
+ events: {
2054
+ ...state.events,
2149
2055
  ...events
2150
2056
  }
2151
2057
  }))
@@ -2167,7 +2073,6 @@ function Portal({
2167
2073
  value: usePortalStore
2168
2074
  }, children), usePortalStore, null));
2169
2075
  }
2170
-
2171
2076
  reconciler.injectIntoDevTools({
2172
2077
  bundleType: process.env.NODE_ENV === 'production' ? 0 : 1,
2173
2078
  rendererPackageName: '@react-three/fiber',