@react-three/fiber 8.9.2 → 8.10.1

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,102 @@ 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
595
-
561
+ const rootState = store.getState();
562
+ // If anything has been found, forward it to the event listeners
596
563
  if (intersections.length) {
597
564
  const localState = {
598
565
  stopped: false
599
566
  };
600
-
601
567
  for (const hit of intersections) {
602
568
  const state = getRootState(hit.object) || rootState;
603
569
  const {
@@ -607,19 +573,15 @@ function createEvents(store) {
607
573
  internal
608
574
  } = state;
609
575
  const unprojectedPoint = new THREE.Vector3(pointer.x, pointer.y, 0).unproject(camera);
610
-
611
576
  const hasPointerCapture = id => {
612
577
  var _internal$capturedMap, _internal$capturedMap2;
613
-
614
578
  return (_internal$capturedMap = (_internal$capturedMap2 = internal.capturedMap.get(id)) == null ? void 0 : _internal$capturedMap2.has(hit.eventObject)) != null ? _internal$capturedMap : false;
615
579
  };
616
-
617
580
  const setPointerCapture = id => {
618
581
  const captureData = {
619
582
  intersection: hit,
620
583
  target: event.target
621
584
  };
622
-
623
585
  if (internal.capturedMap.has(id)) {
624
586
  // if the pointerId was previously captured, we add the hit to the
625
587
  // event capturedMap.
@@ -629,29 +591,27 @@ function createEvents(store) {
629
591
  // containing the hitObject, and the hit. hitObject is used for
630
592
  // faster access.
631
593
  internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
632
- } // Call the original event now
594
+ }
633
595
  event.target.setPointerCapture(id);
634
596
  };
635
-
636
597
  const releasePointerCapture = id => {
637
598
  const captures = internal.capturedMap.get(id);
638
-
639
599
  if (captures) {
640
600
  releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
641
601
  }
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.
602
+ };
646
603
 
604
+ // Add native event props
605
+ let extractEventProps = {};
606
+ // 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
607
  for (let prop in event) {
648
- let property = event[prop]; // Only copy over atomics, leave functions alone as these should be
608
+ let property = event[prop];
609
+ // Only copy over atomics, leave functions alone as these should be
649
610
  // called as event.nativeEvent.fn()
650
-
651
611
  if (typeof property !== 'function') extractEventProps[prop] = property;
652
612
  }
653
-
654
- let raycastEvent = { ...hit,
613
+ let raycastEvent = {
614
+ ...hit,
655
615
  ...extractEventProps,
656
616
  pointer,
657
617
  intersections,
@@ -660,19 +620,21 @@ function createEvents(store) {
660
620
  unprojectedPoint,
661
621
  ray: raycaster.ray,
662
622
  camera: camera,
663
-
664
623
  // Hijack stopPropagation, which just sets a flag
665
624
  stopPropagation() {
666
625
  // https://github.com/pmndrs/react-three-fiber/issues/596
667
626
  // 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...
627
+ const capturesForPointer = 'pointerId' in event && internal.capturedMap.get(event.pointerId);
669
628
 
670
- if ( // ...if this pointer hasn't been captured
671
- !capturesForPointer || // ... or if the hit object is capturing the pointer
629
+ // We only authorize stopPropagation...
630
+ if (
631
+ // ...if this pointer hasn't been captured
632
+ !capturesForPointer ||
633
+ // ... or if the hit object is capturing the pointer
672
634
  capturesForPointer.has(hit.eventObject)) {
673
- raycastEvent.stopped = localState.stopped = true; // Propagation is stopped, remove all other hover records
635
+ raycastEvent.stopped = localState.stopped = true;
636
+ // Propagation is stopped, remove all other hover records
674
637
  // An event handler is only allowed to flush other handlers if it is hovered itself
675
-
676
638
  if (internal.hovered.size && Array.from(internal.hovered.values()).find(i => i.eventObject === hit.eventObject)) {
677
639
  // Objects cannot flush out higher up objects that have already caught the event
678
640
  const higher = intersections.slice(0, intersections.indexOf(hit));
@@ -680,7 +642,6 @@ function createEvents(store) {
680
642
  }
681
643
  }
682
644
  },
683
-
684
645
  // there should be a distinction between target and currentTarget
685
646
  target: {
686
647
  hasPointerCapture,
@@ -693,22 +654,20 @@ function createEvents(store) {
693
654
  releasePointerCapture
694
655
  },
695
656
  nativeEvent: event
696
- }; // Call subscribers
697
-
698
- callback(raycastEvent); // Event bubbling may be interrupted by stopPropagation
657
+ };
699
658
 
659
+ // Call subscribers
660
+ callback(raycastEvent);
661
+ // Event bubbling may be interrupted by stopPropagation
700
662
  if (localState.stopped === true) break;
701
663
  }
702
664
  }
703
-
704
665
  return intersections;
705
666
  }
706
-
707
667
  function cancelPointer(intersections) {
708
668
  const {
709
669
  internal
710
670
  } = store.getState();
711
-
712
671
  for (const hoveredObj of internal.hovered.values()) {
713
672
  // When no objects were hit or the the hovered object wasn't found underneath the cursor
714
673
  // we call onPointerOut and delete the object from the hovered-elements map
@@ -717,10 +676,10 @@ function createEvents(store) {
717
676
  const instance = eventObject.__r3f;
718
677
  const handlers = instance == null ? void 0 : instance.handlers;
719
678
  internal.hovered.delete(makeId(hoveredObj));
720
-
721
679
  if (instance != null && instance.eventCount) {
722
680
  // Clear out intersects, they are outdated by now
723
- const data = { ...hoveredObj,
681
+ const data = {
682
+ ...hoveredObj,
724
683
  intersections
725
684
  };
726
685
  handlers.onPointerOut == null ? void 0 : handlers.onPointerOut(data);
@@ -729,27 +688,23 @@ function createEvents(store) {
729
688
  }
730
689
  }
731
690
  }
732
-
733
691
  function pointerMissed(event, objects) {
734
692
  for (let i = 0; i < objects.length; i++) {
735
693
  const instance = objects[i].__r3f;
736
694
  instance == null ? void 0 : instance.handlers.onPointerMissed == null ? void 0 : instance.handlers.onPointerMissed(event);
737
695
  }
738
696
  }
739
-
740
697
  function handlePointer(name) {
741
698
  // Deal with cancelation
742
699
  switch (name) {
743
700
  case 'onPointerLeave':
744
701
  case 'onPointerCancel':
745
702
  return () => cancelPointer([]);
746
-
747
703
  case 'onLostPointerCapture':
748
704
  return event => {
749
705
  const {
750
706
  internal
751
707
  } = store.getState();
752
-
753
708
  if ('pointerId' in event && internal.capturedMap.has(event.pointerId)) {
754
709
  // If the object event interface had onLostPointerCapture, we'd call it here on every
755
710
  // object that's getting removed.
@@ -757,55 +712,54 @@ function createEvents(store) {
757
712
  cancelPointer([]);
758
713
  }
759
714
  };
760
- } // Any other pointer goes here ...
761
-
715
+ }
762
716
 
717
+ // Any other pointer goes here ...
763
718
  return function handleEvent(event) {
764
719
  const {
765
720
  onPointerMissed,
766
721
  internal
767
- } = store.getState(); // prepareRay(event)
722
+ } = store.getState();
768
723
 
769
- internal.lastEvent.current = event; // Get fresh intersects
724
+ // prepareRay(event)
725
+ internal.lastEvent.current = event;
770
726
 
727
+ // Get fresh intersects
771
728
  const isPointerMove = name === 'onPointerMove';
772
729
  const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
773
- const filter = isPointerMove ? filterPointerEvents : undefined; // const hits = patchIntersects(intersect(filter), event)
774
-
730
+ const filter = isPointerMove ? filterPointerEvents : undefined;
731
+ // const hits = patchIntersects(intersect(filter), event)
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
799
-
754
+ const handlers = instance == null ? void 0 : instance.handlers;
755
+ // Check presence of handlers
800
756
  if (!(instance != null && instance.eventCount)) return;
801
-
802
757
  if (isPointerMove) {
803
758
  // Move event ...
804
759
  if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
805
760
  // When enter or out is present take care of hover-state
806
761
  const id = makeId(data);
807
762
  const hoveredItem = internal.hovered.get(id);
808
-
809
763
  if (!hoveredItem) {
810
764
  // If the object wasn't previously hovered, book it and call its handler
811
765
  internal.hovered.set(id, data);
@@ -815,21 +769,19 @@ function createEvents(store) {
815
769
  // If the object was previously hovered and stopped, we shouldn't allow other items to proceed
816
770
  data.stopPropagation();
817
771
  }
818
- } // Call mouse move
819
-
820
-
772
+ }
773
+ // Call mouse move
821
774
  handlers.onPointerMove == null ? void 0 : handlers.onPointerMove(data);
822
775
  } else {
823
776
  // All other events ...
824
777
  const handler = handlers[name];
825
-
826
778
  if (handler) {
827
779
  // Forward all events back to their respective handlers with the exception of click events,
828
780
  // which must use the initial target
829
781
  if (!isClickEvent || internal.initialHits.includes(eventObject)) {
830
782
  // Missed events have to come first
831
- pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
832
-
783
+ pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
784
+ // Now call the handler
833
785
  handler(data);
834
786
  }
835
787
  } else {
@@ -840,22 +792,19 @@ function createEvents(store) {
840
792
  }
841
793
  }
842
794
  }
843
-
844
795
  handleIntersects(hits, event, delta, onIntersect);
845
796
  };
846
797
  }
847
-
848
798
  return {
849
799
  handlePointer
850
800
  };
851
801
  }
852
802
 
853
803
  let catalogue = {};
854
-
855
- let extend = objects => void (catalogue = { ...catalogue,
804
+ let extend = objects => void (catalogue = {
805
+ ...catalogue,
856
806
  ...objects
857
807
  });
858
-
859
808
  function createRenderer(_roots, _getEventPriority) {
860
809
  function createInstance(type, {
861
810
  args = [],
@@ -864,7 +813,6 @@ function createRenderer(_roots, _getEventPriority) {
864
813
  }, root) {
865
814
  let name = `${type[0].toUpperCase()}${type.slice(1)}`;
866
815
  let instance;
867
-
868
816
  if (type === 'primitive') {
869
817
  if (props.object === undefined) throw new Error("R3F: Primitives without 'object' are invalid!");
870
818
  const object = props.object;
@@ -876,15 +824,15 @@ function createRenderer(_roots, _getEventPriority) {
876
824
  });
877
825
  } else {
878
826
  const target = catalogue[name];
879
-
880
827
  if (!target) {
881
828
  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
829
+ }
883
830
 
831
+ // Throw if an object or literal was passed for args
832
+ if (!Array.isArray(args)) throw new Error('R3F: The args prop must be an array!');
884
833
 
885
- if (!Array.isArray(args)) throw new Error('R3F: The args prop must be an array!'); // Instanciate new object, link it to the root
834
+ // Instanciate new object, link it to the root
886
835
  // Append memoized props with args so it's not forgotten
887
-
888
836
  instance = prepare(new target(...args), {
889
837
  type,
890
838
  root,
@@ -894,27 +842,24 @@ function createRenderer(_roots, _getEventPriority) {
894
842
  args
895
843
  }
896
844
  });
897
- } // Auto-attach geometries and materials
898
-
845
+ }
899
846
 
847
+ // Auto-attach geometries and materials
900
848
  if (instance.__r3f.attach === undefined) {
901
849
  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
850
+ }
851
+
852
+ // It should NOT call onUpdate on object instanciation, because it hasn't been added to the
903
853
  // view yet. If the callback relies on references for instance, they won't be ready yet, this is
904
854
  // why it passes "true" here
905
855
  // There is no reason to apply props to injects
906
-
907
-
908
856
  if (name !== 'inject') applyProps$1(instance, props);
909
857
  return instance;
910
858
  }
911
-
912
859
  function appendChild(parentInstance, child) {
913
860
  let added = false;
914
-
915
861
  if (child) {
916
862
  var _child$__r3f, _parentInstance$__r3f;
917
-
918
863
  // The attach attribute implies that the object attaches itself on the parent
919
864
  if ((_child$__r3f = child.__r3f) != null && _child$__r3f.attach) {
920
865
  attach(parentInstance, child, child.__r3f.attach);
@@ -922,10 +867,9 @@ function createRenderer(_roots, _getEventPriority) {
922
867
  // add in the usual parent-child way
923
868
  parentInstance.add(child);
924
869
  added = true;
925
- } // This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
870
+ }
871
+ // This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
926
872
  // that is, anything that's a child in React but not a child in the scenegraph.
927
-
928
-
929
873
  if (!added) (_parentInstance$__r3f = parentInstance.__r3f) == null ? void 0 : _parentInstance$__r3f.objects.push(child);
930
874
  if (!child.__r3f) prepare(child, {});
931
875
  child.__r3f.parent = parentInstance;
@@ -933,13 +877,10 @@ function createRenderer(_roots, _getEventPriority) {
933
877
  invalidateInstance(child);
934
878
  }
935
879
  }
936
-
937
880
  function insertBefore(parentInstance, child, beforeChild) {
938
881
  let added = false;
939
-
940
882
  if (child) {
941
883
  var _child$__r3f2, _parentInstance$__r3f2;
942
-
943
884
  if ((_child$__r3f2 = child.__r3f) != null && _child$__r3f2.attach) {
944
885
  attach(parentInstance, child, child.__r3f.attach);
945
886
  } else if (child.isObject3D && parentInstance.isObject3D) {
@@ -952,7 +893,6 @@ function createRenderer(_roots, _getEventPriority) {
952
893
  parentInstance.children = [...restSiblings.slice(0, index), child, ...restSiblings.slice(index)];
953
894
  added = true;
954
895
  }
955
-
956
896
  if (!added) (_parentInstance$__r3f2 = parentInstance.__r3f) == null ? void 0 : _parentInstance$__r3f2.objects.push(child);
957
897
  if (!child.__r3f) prepare(child, {});
958
898
  child.__r3f.parent = parentInstance;
@@ -960,31 +900,29 @@ function createRenderer(_roots, _getEventPriority) {
960
900
  invalidateInstance(child);
961
901
  }
962
902
  }
963
-
964
903
  function removeRecursive(array, parent, dispose = false) {
965
904
  if (array) [...array].forEach(child => removeChild(parent, child, dispose));
966
905
  }
967
-
968
906
  function removeChild(parentInstance, child, dispose) {
969
907
  if (child) {
970
908
  var _parentInstance$__r3f3, _child$__r3f3, _child$__r3f5;
971
-
972
909
  // 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
-
910
+ if (child.__r3f) child.__r3f.parent = null;
911
+ // Remove child from the parents objects
912
+ if ((_parentInstance$__r3f3 = parentInstance.__r3f) != null && _parentInstance$__r3f3.objects) parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child);
913
+ // Remove attachment
977
914
  if ((_child$__r3f3 = child.__r3f) != null && _child$__r3f3.attach) {
978
915
  detach(parentInstance, child, child.__r3f.attach);
979
916
  } else if (child.isObject3D && parentInstance.isObject3D) {
980
917
  var _child$__r3f4;
981
-
982
- parentInstance.remove(child); // Remove interactivity
983
-
918
+ parentInstance.remove(child);
919
+ // Remove interactivity
984
920
  if ((_child$__r3f4 = child.__r3f) != null && _child$__r3f4.root) {
985
921
  removeInteractivity(child.__r3f.root, child);
986
922
  }
987
- } // Allow objects to bail out of recursive dispose altogether by passing dispose={null}
923
+ }
924
+
925
+ // Allow objects to bail out of recursive dispose altogether by passing dispose={null}
988
926
  // Never dispose of primitives because their state may be kept outside of React!
989
927
  // In order for an object to be able to dispose it has to have
990
928
  // - a dispose method,
@@ -993,29 +931,27 @@ function createRenderer(_roots, _getEventPriority) {
993
931
  //
994
932
  // Since disposal is recursive, we can check the optional dispose arg, which will be undefined
995
933
  // when the reconciler calls it, but then carry our own check recursively
996
-
997
-
998
934
  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 ...
935
+ const shouldDispose = dispose === undefined ? child.dispose !== null && !isPrimitive : dispose;
1001
936
 
937
+ // Remove nested child objects. Primitives should not have objects and children that are
938
+ // attached to them declaratively ...
1002
939
  if (!isPrimitive) {
1003
940
  var _child$__r3f6;
1004
-
1005
941
  removeRecursive((_child$__r3f6 = child.__r3f) == null ? void 0 : _child$__r3f6.objects, child, shouldDispose);
1006
942
  removeRecursive(child.children, child, shouldDispose);
1007
- } // Remove references
1008
-
943
+ }
1009
944
 
945
+ // Remove references
1010
946
  if (child.__r3f) {
1011
947
  delete child.__r3f.root;
1012
948
  delete child.__r3f.objects;
1013
949
  delete child.__r3f.handlers;
1014
950
  delete child.__r3f.memoizedProps;
1015
951
  if (!isPrimitive) delete child.__r3f;
1016
- } // Dispose item whenever the reconciler feels like it
1017
-
952
+ }
1018
953
 
954
+ // Dispose item whenever the reconciler feels like it
1019
955
  if (shouldDispose && child.dispose && child.type !== 'Scene') {
1020
956
  unstable_scheduleCallback(unstable_IdlePriority, () => {
1021
957
  try {
@@ -1025,61 +961,51 @@ function createRenderer(_roots, _getEventPriority) {
1025
961
  }
1026
962
  });
1027
963
  }
1028
-
1029
964
  invalidateInstance(parentInstance);
1030
965
  }
1031
966
  }
1032
-
1033
967
  function switchInstance(instance, type, newProps, fiber) {
1034
968
  var _instance$__r3f;
1035
-
1036
969
  const parent = (_instance$__r3f = instance.__r3f) == null ? void 0 : _instance$__r3f.parent;
1037
970
  if (!parent) return;
1038
- const newInstance = createInstance(type, newProps, instance.__r3f.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
971
+ const newInstance = createInstance(type, newProps, instance.__r3f.root);
972
+
973
+ // https://github.com/pmndrs/react-three-fiber/issues/1348
1039
974
  // When args change the instance has to be re-constructed, which then
1040
975
  // forces r3f to re-parent the children and non-scene objects
1041
-
1042
976
  if (instance.children) {
1043
977
  for (const child of instance.children) {
1044
978
  if (child.__r3f) appendChild(newInstance, child);
1045
979
  }
1046
-
1047
980
  instance.children = instance.children.filter(child => !child.__r3f);
1048
981
  }
1049
-
1050
982
  instance.__r3f.objects.forEach(child => appendChild(newInstance, child));
1051
-
1052
983
  instance.__r3f.objects = [];
1053
-
1054
984
  if (!instance.__r3f.autoRemovedBeforeAppend) {
1055
985
  removeChild(parent, instance);
1056
986
  }
1057
-
1058
987
  if (newInstance.parent) {
1059
988
  newInstance.__r3f.autoRemovedBeforeAppend = true;
1060
989
  }
990
+ appendChild(parent, newInstance);
1061
991
 
1062
- appendChild(parent, newInstance); // Re-bind event handlers
1063
-
992
+ // Re-bind event handlers
1064
993
  if (newInstance.raycast && newInstance.__r3f.eventCount) {
1065
994
  const rootState = newInstance.__r3f.root.getState();
1066
-
1067
995
  rootState.internal.interaction.push(newInstance);
1068
- } // This evil hack switches the react-internal fiber node
996
+ }
1069
997
  [fiber, fiber.alternate].forEach(fiber => {
1070
998
  if (fiber !== null) {
1071
999
  fiber.stateNode = newInstance;
1072
-
1073
1000
  if (fiber.ref) {
1074
1001
  if (typeof fiber.ref === 'function') fiber.ref(newInstance);else fiber.ref.current = newInstance;
1075
1002
  }
1076
1003
  }
1077
1004
  });
1078
- } // Don't handle text instances, warn on undefined behavior
1079
-
1005
+ }
1080
1006
 
1007
+ // Don't handle text instances, warn on undefined behavior
1081
1008
  const handleTextInstance = () => console.warn('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
1082
-
1083
1009
  const reconciler = Reconciler({
1084
1010
  createInstance,
1085
1011
  removeChild,
@@ -1092,11 +1018,13 @@ function createRenderer(_roots, _getEventPriority) {
1092
1018
  supportsHydration: false,
1093
1019
  noTimeout: -1,
1094
1020
  appendChildToContainer: (container, child) => {
1095
- if (!child) return; // Don't append to unmounted container
1021
+ if (!child) return;
1096
1022
 
1023
+ // Don't append to unmounted container
1097
1024
  const scene = container.getState().scene;
1098
- if (!scene.__r3f) return; // Link current root to the default scene
1025
+ if (!scene.__r3f) return;
1099
1026
 
1027
+ // Link current root to the default scene
1100
1028
  scene.__r3f.root = container;
1101
1029
  appendChild(scene, child);
1102
1030
  },
@@ -1105,24 +1033,22 @@ function createRenderer(_roots, _getEventPriority) {
1105
1033
  removeChild(container.getState().scene, child);
1106
1034
  },
1107
1035
  insertInContainerBefore: (container, child, beforeChild) => {
1108
- if (!child || !beforeChild) return; // Don't append to unmounted container
1036
+ if (!child || !beforeChild) return;
1109
1037
 
1038
+ // Don't append to unmounted container
1110
1039
  const scene = container.getState().scene;
1111
1040
  if (!scene.__r3f) return;
1112
1041
  insertBefore(scene, child, beforeChild);
1113
1042
  },
1114
1043
  getRootHostContext: () => null,
1115
1044
  getChildHostContext: parentHostContext => parentHostContext,
1116
-
1117
1045
  finalizeInitialChildren(instance) {
1118
1046
  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
1047
+ const localState = (_instance$__r3f2 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f2 : {};
1048
+ // https://github.com/facebook/react/issues/20271
1121
1049
  // Returning true will trigger commitMount
1122
-
1123
1050
  return Boolean(localState.handlers);
1124
1051
  },
1125
-
1126
1052
  prepareUpdate(instance, _type, oldProps, newProps) {
1127
1053
  // Create diff-sets
1128
1054
  if (instance.__r3f.primitive && newProps.object && newProps.object !== instance) {
@@ -1138,47 +1064,44 @@ function createRenderer(_roots, _getEventPriority) {
1138
1064
  args: argsOld = [],
1139
1065
  children: cO,
1140
1066
  ...restOld
1141
- } = oldProps; // Throw if an object or literal was passed for args
1067
+ } = oldProps;
1142
1068
 
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
1144
-
1145
- if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
1069
+ // Throw if an object or literal was passed for args
1070
+ if (!Array.isArray(argsNew)) throw new Error('R3F: the args prop must be an array!');
1146
1071
 
1072
+ // If it has new props or arguments, then it needs to be re-instantiated
1073
+ if (argsNew.some((value, index) => value !== argsOld[index])) return [true];
1074
+ // Create a diff-set, flag if there are any changes
1147
1075
  const diff = diffProps(instance, restNew, restOld, true);
1148
- if (diff.changes.length) return [false, diff]; // Otherwise do not touch the instance
1076
+ if (diff.changes.length) return [false, diff];
1149
1077
 
1078
+ // Otherwise do not touch the instance
1150
1079
  return null;
1151
1080
  }
1152
1081
  },
1153
-
1154
1082
  commitUpdate(instance, [reconstruct, diff], type, _oldProps, newProps, fiber) {
1155
1083
  // Reconstruct when args or <primitive object={...} have changes
1156
- if (reconstruct) switchInstance(instance, type, newProps, fiber); // Otherwise just overwrite props
1084
+ if (reconstruct) switchInstance(instance, type, newProps, fiber);
1085
+ // Otherwise just overwrite props
1157
1086
  else applyProps$1(instance, diff);
1158
1087
  },
1159
-
1160
1088
  commitMount(instance, _type, _props, _int) {
1161
1089
  var _instance$__r3f3;
1162
-
1163
1090
  // https://github.com/facebook/react/issues/20271
1164
1091
  // This will make sure events are only added once to the central container
1165
1092
  const localState = (_instance$__r3f3 = instance.__r3f) != null ? _instance$__r3f3 : {};
1166
-
1167
1093
  if (instance.raycast && localState.handlers && localState.eventCount) {
1168
1094
  instance.__r3f.root.getState().internal.interaction.push(instance);
1169
1095
  }
1170
1096
  },
1171
-
1172
1097
  getPublicInstance: instance => instance,
1173
1098
  prepareForCommit: () => null,
1174
1099
  preparePortalMount: container => prepare(container.getState().scene),
1175
1100
  resetAfterCommit: () => {},
1176
1101
  shouldSetTextContent: () => false,
1177
1102
  clearContainer: () => false,
1178
-
1179
1103
  hideInstance(instance) {
1180
1104
  var _instance$__r3f4;
1181
-
1182
1105
  // Detach while the instance is hidden
1183
1106
  const {
1184
1107
  attach: type,
@@ -1188,10 +1111,8 @@ function createRenderer(_roots, _getEventPriority) {
1188
1111
  if (instance.isObject3D) instance.visible = false;
1189
1112
  invalidateInstance(instance);
1190
1113
  },
1191
-
1192
1114
  unhideInstance(instance, props) {
1193
1115
  var _instance$__r3f5;
1194
-
1195
1116
  // Re-attach when the instance is unhidden
1196
1117
  const {
1197
1118
  attach: type,
@@ -1201,7 +1122,6 @@ function createRenderer(_roots, _getEventPriority) {
1201
1122
  if (instance.isObject3D && props.visible == null || props.visible) instance.visible = true;
1202
1123
  invalidateInstance(instance);
1203
1124
  },
1204
-
1205
1125
  createTextInstance: handleTextInstance,
1206
1126
  hideTextInstance: handleTextInstance,
1207
1127
  unhideTextInstance: handleTextInstance,
@@ -1222,16 +1142,15 @@ function createRenderer(_roots, _getEventPriority) {
1222
1142
  };
1223
1143
  }
1224
1144
 
1145
+ // Keys that shouldn't be copied between R3F stores
1225
1146
  const privateKeys = ['set', 'get', 'setSize', 'setFrameloop', 'setDpr', 'events', 'invalidate', 'advance', 'size', 'viewport'];
1226
1147
  const isRenderer = def => !!(def != null && def.render);
1227
1148
  const context = /*#__PURE__*/React.createContext(null);
1228
-
1229
1149
  const createStore = (invalidate, advance) => {
1230
1150
  const rootState = create((set, get) => {
1231
1151
  const position = new THREE.Vector3();
1232
1152
  const defaultTarget = new THREE.Vector3();
1233
1153
  const tempTarget = new THREE.Vector3();
1234
-
1235
1154
  function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
1236
1155
  const {
1237
1156
  width,
@@ -1242,7 +1161,6 @@ const createStore = (invalidate, advance) => {
1242
1161
  const aspect = width / height;
1243
1162
  if (target instanceof THREE.Vector3) tempTarget.copy(target);else tempTarget.set(...target);
1244
1163
  const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
1245
-
1246
1164
  if (isOrthographicCamera(camera)) {
1247
1165
  return {
1248
1166
  width: width / camera.zoom,
@@ -1255,9 +1173,7 @@ const createStore = (invalidate, advance) => {
1255
1173
  };
1256
1174
  } else {
1257
1175
  const fov = camera.fov * Math.PI / 180; // convert vertical fov to radians
1258
-
1259
1176
  const h = 2 * Math.tan(fov / 2) * distance; // visible height
1260
-
1261
1177
  const w = h * (width / height);
1262
1178
  return {
1263
1179
  width: w,
@@ -1270,15 +1186,13 @@ const createStore = (invalidate, advance) => {
1270
1186
  };
1271
1187
  }
1272
1188
  }
1273
-
1274
1189
  let performanceTimeout = undefined;
1275
-
1276
1190
  const setPerformanceCurrent = current => set(state => ({
1277
- performance: { ...state.performance,
1191
+ performance: {
1192
+ ...state.performance,
1278
1193
  current
1279
1194
  }
1280
1195
  }));
1281
-
1282
1196
  const pointer = new THREE.Vector2();
1283
1197
  const rootState = {
1284
1198
  set,
@@ -1311,12 +1225,12 @@ const createStore = (invalidate, advance) => {
1311
1225
  max: 1,
1312
1226
  debounce: 200,
1313
1227
  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
-
1228
+ const state = get();
1229
+ // Clear timeout
1230
+ if (performanceTimeout) clearTimeout(performanceTimeout);
1231
+ // Set lower bound performance
1232
+ if (state.performance.current !== state.performance.min) setPerformanceCurrent(state.performance.min);
1233
+ // Go back to upper bound performance after a while unless something regresses meanwhile
1320
1234
  performanceTimeout = setTimeout(() => setPerformanceCurrent(get().performance.max), state.performance.debounce);
1321
1235
  }
1322
1236
  },
@@ -1339,8 +1253,10 @@ const createStore = (invalidate, advance) => {
1339
1253
  factor: 0,
1340
1254
  getCurrentViewport
1341
1255
  },
1342
- setEvents: events => set(state => ({ ...state,
1343
- events: { ...state.events,
1256
+ setEvents: events => set(state => ({
1257
+ ...state,
1258
+ events: {
1259
+ ...state.events,
1344
1260
  ...events
1345
1261
  }
1346
1262
  })),
@@ -1355,7 +1271,8 @@ const createStore = (invalidate, advance) => {
1355
1271
  };
1356
1272
  set(state => ({
1357
1273
  size,
1358
- viewport: { ...state.viewport,
1274
+ viewport: {
1275
+ ...state.viewport,
1359
1276
  ...getCurrentViewport(camera, defaultTarget, size)
1360
1277
  }
1361
1278
  }));
@@ -1363,23 +1280,23 @@ const createStore = (invalidate, advance) => {
1363
1280
  setDpr: dpr => set(state => {
1364
1281
  const resolved = calculateDpr(dpr);
1365
1282
  return {
1366
- viewport: { ...state.viewport,
1283
+ viewport: {
1284
+ ...state.viewport,
1367
1285
  dpr: resolved,
1368
1286
  initialDpr: state.viewport.initialDpr || resolved
1369
1287
  }
1370
1288
  };
1371
1289
  }),
1372
1290
  setFrameloop: (frameloop = 'always') => {
1373
- const clock = get().clock; // if frameloop === "never" clock.elapsedTime is updated using advance(timestamp)
1291
+ const clock = get().clock;
1374
1292
 
1293
+ // if frameloop === "never" clock.elapsedTime is updated using advance(timestamp)
1375
1294
  clock.stop();
1376
1295
  clock.elapsedTime = 0;
1377
-
1378
1296
  if (frameloop !== 'never') {
1379
1297
  clock.start();
1380
1298
  clock.elapsedTime = 0;
1381
1299
  }
1382
-
1383
1300
  set(() => ({
1384
1301
  frameloop
1385
1302
  }));
@@ -1397,27 +1314,26 @@ const createStore = (invalidate, advance) => {
1397
1314
  initialHits: [],
1398
1315
  capturedMap: new Map(),
1399
1316
  subscribe: (ref, priority, store) => {
1400
- const internal = get().internal; // If this subscription was given a priority, it takes rendering into its own hands
1317
+ const internal = get().internal;
1318
+ // If this subscription was given a priority, it takes rendering into its own hands
1401
1319
  // For that reason we switch off automatic rendering and increase the manual flag
1402
1320
  // As long as this flag is positive there can be no internal rendering at all
1403
1321
  // because there could be multiple render subscriptions
1404
-
1405
1322
  internal.priority = internal.priority + (priority > 0 ? 1 : 0);
1406
1323
  internal.subscribers.push({
1407
1324
  ref,
1408
1325
  priority,
1409
1326
  store
1410
- }); // Register subscriber and sort layers from lowest to highest, meaning,
1327
+ });
1328
+ // Register subscriber and sort layers from lowest to highest, meaning,
1411
1329
  // highest priority renders last (on top of the other frames)
1412
-
1413
1330
  internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
1414
1331
  return () => {
1415
1332
  const internal = get().internal;
1416
-
1417
1333
  if (internal != null && internal.subscribers) {
1418
1334
  // Decrease manual flag if this subscription had a priority
1419
- internal.priority = internal.priority - (priority > 0 ? 1 : 0); // Remove subscriber from list
1420
-
1335
+ internal.priority = internal.priority - (priority > 0 ? 1 : 0);
1336
+ // Remove subscriber from list
1421
1337
  internal.subscribers = internal.subscribers.filter(s => s.ref !== ref);
1422
1338
  }
1423
1339
  };
@@ -1437,31 +1353,35 @@ const createStore = (invalidate, advance) => {
1437
1353
  viewport,
1438
1354
  gl,
1439
1355
  set
1440
- } = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
1356
+ } = rootState.getState();
1441
1357
 
1358
+ // Resize camera and renderer on changes to size and pixelratio
1442
1359
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1443
1360
  oldSize = size;
1444
- oldDpr = viewport.dpr; // Update camera & renderer
1445
-
1361
+ oldDpr = viewport.dpr;
1362
+ // Update camera & renderer
1446
1363
  updateCamera(camera, size);
1447
1364
  gl.setPixelRatio(viewport.dpr);
1448
1365
  gl.setSize(size.width, size.height, size.updateStyle);
1449
- } // Update viewport once the camera changes
1450
-
1366
+ }
1451
1367
 
1368
+ // Update viewport once the camera changes
1452
1369
  if (camera !== oldCamera) {
1453
- oldCamera = camera; // Update viewport
1454
-
1370
+ oldCamera = camera;
1371
+ // Update viewport
1455
1372
  set(state => ({
1456
- viewport: { ...state.viewport,
1373
+ viewport: {
1374
+ ...state.viewport,
1457
1375
  ...state.viewport.getCurrentViewport(camera)
1458
1376
  }
1459
1377
  }));
1460
1378
  }
1461
- }); // Invalidate on any change
1379
+ });
1462
1380
 
1463
- rootState.subscribe(state => invalidate(state)); // Return root state
1381
+ // Invalidate on any change
1382
+ rootState.subscribe(state => invalidate(state));
1464
1383
 
1384
+ // Return root state
1465
1385
  return rootState;
1466
1386
  };
1467
1387
 
@@ -1472,144 +1392,129 @@ function createSubs(callback, subs) {
1472
1392
  subs.add(sub);
1473
1393
  return () => void subs.delete(sub);
1474
1394
  }
1475
-
1476
1395
  let i;
1477
1396
  let globalEffects = new Set();
1478
1397
  let globalAfterEffects = new Set();
1479
1398
  let globalTailEffects = new Set();
1399
+
1480
1400
  /**
1481
1401
  * Adds a global render callback which is called each frame.
1482
1402
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
1483
1403
  */
1484
-
1485
1404
  const addEffect = callback => createSubs(callback, globalEffects);
1405
+
1486
1406
  /**
1487
1407
  * Adds a global after-render callback which is called each frame.
1488
1408
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
1489
1409
  */
1490
-
1491
1410
  const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
1411
+
1492
1412
  /**
1493
1413
  * Adds a global callback which is called when rendering stops.
1494
1414
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
1495
1415
  */
1496
-
1497
1416
  const addTail = callback => createSubs(callback, globalTailEffects);
1498
-
1499
1417
  function run(effects, timestamp) {
1500
1418
  if (!effects.size) return;
1501
-
1502
1419
  for (const {
1503
1420
  callback
1504
1421
  } of effects.values()) {
1505
1422
  callback(timestamp);
1506
1423
  }
1507
1424
  }
1508
-
1509
1425
  function flushGlobalEffects(type, timestamp) {
1510
1426
  switch (type) {
1511
1427
  case 'before':
1512
1428
  return run(globalEffects, timestamp);
1513
-
1514
1429
  case 'after':
1515
1430
  return run(globalAfterEffects, timestamp);
1516
-
1517
1431
  case 'tail':
1518
1432
  return run(globalTailEffects, timestamp);
1519
1433
  }
1520
1434
  }
1521
1435
  let subscribers;
1522
1436
  let subscription;
1523
-
1524
1437
  function render$1(timestamp, state, frame) {
1525
1438
  // Run local effects
1526
- let delta = state.clock.getDelta(); // In frameloop='never' mode, clock times are updated using the provided timestamp
1527
-
1439
+ let delta = state.clock.getDelta();
1440
+ // In frameloop='never' mode, clock times are updated using the provided timestamp
1528
1441
  if (state.frameloop === 'never' && typeof timestamp === 'number') {
1529
1442
  delta = timestamp - state.clock.elapsedTime;
1530
1443
  state.clock.oldTime = state.clock.elapsedTime;
1531
1444
  state.clock.elapsedTime = timestamp;
1532
- } // Call subscribers (useFrame)
1533
-
1534
-
1445
+ }
1446
+ // Call subscribers (useFrame)
1535
1447
  subscribers = state.internal.subscribers;
1536
-
1537
1448
  for (i = 0; i < subscribers.length; i++) {
1538
1449
  subscription = subscribers[i];
1539
1450
  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
-
1451
+ }
1452
+ // Render content
1453
+ if (!state.internal.priority && state.gl.render) state.gl.render(state.scene, state.camera);
1454
+ // Decrease frame count
1545
1455
  state.internal.frames = Math.max(0, state.internal.frames - 1);
1546
1456
  return state.frameloop === 'always' ? 1 : state.internal.frames;
1547
1457
  }
1548
-
1549
1458
  function createLoop(roots) {
1550
1459
  let running = false;
1551
1460
  let repeat;
1552
1461
  let frame;
1553
1462
  let state;
1554
-
1555
1463
  function loop(timestamp) {
1556
1464
  frame = requestAnimationFrame(loop);
1557
1465
  running = true;
1558
- repeat = 0; // Run effects
1466
+ repeat = 0;
1559
1467
 
1560
- flushGlobalEffects('before', timestamp); // Render all roots
1468
+ // Run effects
1469
+ flushGlobalEffects('before', timestamp);
1561
1470
 
1471
+ // Render all roots
1562
1472
  for (const root of roots.values()) {
1563
1473
  var _state$gl$xr;
1564
-
1565
- state = root.store.getState(); // If the frameloop is invalidated, do not run another frame
1566
-
1474
+ state = root.store.getState();
1475
+ // If the frameloop is invalidated, do not run another frame
1567
1476
  if (state.internal.active && (state.frameloop === 'always' || state.internal.frames > 0) && !((_state$gl$xr = state.gl.xr) != null && _state$gl$xr.isPresenting)) {
1568
1477
  repeat += render$1(timestamp, state);
1569
1478
  }
1570
- } // Run after-effects
1571
-
1479
+ }
1572
1480
 
1573
- flushGlobalEffects('after', timestamp); // Stop the loop if nothing invalidates it
1481
+ // Run after-effects
1482
+ flushGlobalEffects('after', timestamp);
1574
1483
 
1484
+ // Stop the loop if nothing invalidates it
1575
1485
  if (repeat === 0) {
1576
1486
  // Tail call effects, they are called when rendering stops
1577
- flushGlobalEffects('tail', timestamp); // Flag end of operation
1487
+ flushGlobalEffects('tail', timestamp);
1578
1488
 
1489
+ // Flag end of operation
1579
1490
  running = false;
1580
1491
  return cancelAnimationFrame(frame);
1581
1492
  }
1582
1493
  }
1583
-
1584
1494
  function invalidate(state, frames = 1) {
1585
1495
  var _state$gl$xr2;
1586
-
1587
1496
  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
-
1497
+ if ((_state$gl$xr2 = state.gl.xr) != null && _state$gl$xr2.isPresenting || !state.internal.active || state.frameloop === 'never') return;
1498
+ // Increase frames, do not go higher than 60
1499
+ state.internal.frames = Math.min(60, state.internal.frames + frames);
1500
+ // If the render-loop isn't active, start it
1592
1501
  if (!running) {
1593
1502
  running = true;
1594
1503
  requestAnimationFrame(loop);
1595
1504
  }
1596
1505
  }
1597
-
1598
1506
  function advance(timestamp, runGlobalEffects = true, state, frame) {
1599
1507
  if (runGlobalEffects) flushGlobalEffects('before', timestamp);
1600
1508
  if (!state) for (const root of roots.values()) render$1(timestamp, root.store.getState());else render$1(timestamp, state, frame);
1601
1509
  if (runGlobalEffects) flushGlobalEffects('after', timestamp);
1602
1510
  }
1603
-
1604
1511
  return {
1605
1512
  loop,
1606
-
1607
1513
  /**
1608
1514
  * Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
1609
1515
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
1610
1516
  */
1611
1517
  invalidate,
1612
-
1613
1518
  /**
1614
1519
  * Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
1615
1520
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
@@ -1634,80 +1539,77 @@ function useStore() {
1634
1539
  if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
1635
1540
  return store;
1636
1541
  }
1542
+
1637
1543
  /**
1638
1544
  * Accesses R3F's internal state, containing renderer, canvas, scene, etc.
1639
1545
  * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usethree
1640
1546
  */
1641
-
1642
1547
  function useThree(selector = state => state, equalityFn) {
1643
1548
  return useStore()(selector, equalityFn);
1644
1549
  }
1550
+
1645
1551
  /**
1646
1552
  * Executes a callback before render in a shared frame loop.
1647
1553
  * Can order effects with render priority or manually render with a positive priority.
1648
1554
  * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
1649
1555
  */
1650
-
1651
1556
  function useFrame(callback, renderPriority = 0) {
1652
1557
  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
-
1558
+ const subscribe = store.getState().internal.subscribe;
1559
+ // Memoize ref
1560
+ const ref = useMutableCallback(callback);
1561
+ // Subscribe on mount, unsubscribe on unmount
1657
1562
  useIsomorphicLayoutEffect(() => subscribe(ref, renderPriority, store), [renderPriority, subscribe, store]);
1658
1563
  return null;
1659
1564
  }
1565
+
1660
1566
  /**
1661
1567
  * Returns a node graph of an object with named nodes & materials.
1662
1568
  * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
1663
1569
  */
1664
-
1665
1570
  function useGraph(object) {
1666
1571
  return React.useMemo(() => buildGraph(object), [object]);
1667
1572
  }
1668
-
1669
1573
  function loadingFn(extensions, onProgress) {
1670
1574
  return function (Proto, ...input) {
1671
1575
  // Construct new loader and run extensions
1672
1576
  const loader = new Proto();
1673
- if (extensions) extensions(loader); // Go through the urls and load them
1674
-
1577
+ if (extensions) extensions(loader);
1578
+ // Go through the urls and load them
1675
1579
  return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => {
1676
1580
  if (data.scene) Object.assign(data, buildGraph(data.scene));
1677
1581
  res(data);
1678
1582
  }, onProgress, error => reject(new Error(`Could not load ${input}: ${error.message})`))))));
1679
1583
  };
1680
1584
  }
1585
+
1681
1586
  /**
1682
1587
  * Synchronously loads and caches assets with a three loader.
1683
1588
  *
1684
1589
  * Note: this hook's caller must be wrapped with `React.Suspense`
1685
1590
  * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useloader
1686
1591
  */
1687
-
1688
-
1689
1592
  function useLoader(Proto, input, extensions, onProgress) {
1690
1593
  // Use suspense to load async assets
1691
1594
  const keys = Array.isArray(input) ? input : [input];
1692
1595
  const results = suspend(loadingFn(extensions, onProgress), [Proto, ...keys], {
1693
1596
  equal: is.equ
1694
- }); // Return the object/s
1695
-
1597
+ });
1598
+ // Return the object/s
1696
1599
  return Array.isArray(input) ? results : results[0];
1697
1600
  }
1601
+
1698
1602
  /**
1699
1603
  * Preloads an asset into cache as a side-effect.
1700
1604
  */
1701
-
1702
1605
  useLoader.preload = function (Proto, input, extensions) {
1703
1606
  const keys = Array.isArray(input) ? input : [input];
1704
1607
  return preload(loadingFn(extensions), [Proto, ...keys]);
1705
1608
  };
1609
+
1706
1610
  /**
1707
1611
  * Removes a loaded asset from cache.
1708
1612
  */
1709
-
1710
-
1711
1613
  useLoader.clear = function (Proto, input) {
1712
1614
  const keys = Array.isArray(input) ? input : [input];
1713
1615
  return clear([Proto, ...keys]);
@@ -1726,7 +1628,6 @@ const shallowLoose = {
1726
1628
  objects: 'shallow',
1727
1629
  strict: false
1728
1630
  };
1729
-
1730
1631
  const createRendererInstance = (gl, canvas) => {
1731
1632
  const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
1732
1633
  if (isRenderer(customRenderer)) return customRenderer;else return new THREE.WebGLRenderer({
@@ -1737,16 +1638,13 @@ const createRendererInstance = (gl, canvas) => {
1737
1638
  ...gl
1738
1639
  });
1739
1640
  };
1740
-
1741
1641
  function isCanvas(maybeCanvas) {
1742
1642
  return maybeCanvas instanceof HTMLCanvasElement;
1743
1643
  }
1744
-
1745
1644
  function computeInitialSize(canvas, defaultSize) {
1746
1645
  if (defaultSize) {
1747
1646
  return defaultSize;
1748
1647
  }
1749
-
1750
1648
  if (isCanvas(canvas) && canvas.parentElement) {
1751
1649
  const {
1752
1650
  width,
@@ -1761,7 +1659,6 @@ function computeInitialSize(canvas, defaultSize) {
1761
1659
  left
1762
1660
  };
1763
1661
  }
1764
-
1765
1662
  return {
1766
1663
  width: 0,
1767
1664
  height: 0,
@@ -1769,29 +1666,33 @@ function computeInitialSize(canvas, defaultSize) {
1769
1666
  left: 0
1770
1667
  };
1771
1668
  }
1772
-
1773
1669
  function createRoot(canvas) {
1774
1670
  // Check against mistaken use of createRoot
1775
1671
  const prevRoot = roots.get(canvas);
1776
1672
  const prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
1777
1673
  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
1674
+ if (prevRoot) console.warn('R3F.createRoot should only be called once!');
1780
1675
 
1781
- const logRecoverableError = typeof reportError === 'function' ? // In modern browsers, reportError will dispatch an error event,
1676
+ // Report when an error was detected in a previous render
1677
+ // https://github.com/pmndrs/react-three-fiber/pull/2261
1678
+ const logRecoverableError = typeof reportError === 'function' ?
1679
+ // In modern browsers, reportError will dispatch an error event,
1782
1680
  // 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
-
1681
+ reportError :
1682
+ // In older browsers and test environments, fallback to console.error.
1683
+ console.error;
1684
+
1685
+ // Create store
1686
+ const store = prevStore || createStore(invalidate, advance);
1687
+ // Create renderer
1688
+ const fiber = prevFiber || reconciler.createContainer(store, ConcurrentRoot, null, false, null, '', logRecoverableError, null);
1689
+ // Map it
1790
1690
  if (!prevRoot) roots.set(canvas, {
1791
1691
  fiber,
1792
1692
  store
1793
- }); // Locals
1693
+ });
1794
1694
 
1695
+ // Locals
1795
1696
  let onCreated;
1796
1697
  let configured = false;
1797
1698
  return {
@@ -1813,108 +1714,121 @@ function createRoot(canvas) {
1813
1714
  camera: cameraOptions,
1814
1715
  onPointerMissed
1815
1716
  } = props;
1816
- let state = store.getState(); // Set up renderer (one time only!)
1717
+ let state = store.getState();
1817
1718
 
1719
+ // Set up renderer (one time only!)
1818
1720
  let gl = state.gl;
1819
1721
  if (!state.gl) state.set({
1820
1722
  gl: gl = createRendererInstance(glConfig, canvas)
1821
- }); // Set up raycaster (one time only!)
1723
+ });
1822
1724
 
1725
+ // Set up raycaster (one time only!)
1823
1726
  let raycaster = state.raycaster;
1824
1727
  if (!raycaster) state.set({
1825
1728
  raycaster: raycaster = new THREE.Raycaster()
1826
- }); // Set raycaster options
1729
+ });
1827
1730
 
1731
+ // Set raycaster options
1828
1732
  const {
1829
1733
  params,
1830
1734
  ...options
1831
1735
  } = raycastOptions || {};
1832
- if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, { ...options
1736
+ if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, {
1737
+ ...options
1833
1738
  });
1834
1739
  if (!is.equ(params, raycaster.params, shallowLoose)) applyProps(raycaster, {
1835
- params: { ...raycaster.params,
1740
+ params: {
1741
+ ...raycaster.params,
1836
1742
  ...params
1837
1743
  }
1838
- }); // Create default camera (one time only!)
1744
+ });
1839
1745
 
1746
+ // Create default camera (one time only!)
1840
1747
  if (!state.camera) {
1841
1748
  const isCamera = cameraOptions instanceof THREE.Camera;
1842
1749
  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
1750
  if (!isCamera) {
1845
1751
  camera.position.z = 5;
1846
- if (cameraOptions) applyProps(camera, cameraOptions); // Always look at center by default
1847
-
1752
+ if (cameraOptions) applyProps(camera, cameraOptions);
1753
+ // Always look at center by default
1848
1754
  if (!(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
1849
1755
  }
1850
-
1851
1756
  state.set({
1852
1757
  camera
1853
1758
  });
1854
- } // Set up XR (one time only!)
1855
-
1759
+ }
1856
1760
 
1761
+ // Set up XR (one time only!)
1857
1762
  if (!state.xr) {
1858
1763
  // Handle frame behavior in WebXR
1859
1764
  const handleXRFrame = (timestamp, frame) => {
1860
1765
  const state = store.getState();
1861
1766
  if (state.frameloop === 'never') return;
1862
1767
  advance(timestamp, true, state, frame);
1863
- }; // Toggle render switching on session
1864
-
1768
+ };
1865
1769
 
1770
+ // Toggle render switching on session
1866
1771
  const handleSessionChange = () => {
1867
1772
  const state = store.getState();
1868
1773
  state.gl.xr.enabled = state.gl.xr.isPresenting;
1869
1774
  state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
1870
1775
  if (!state.gl.xr.isPresenting) invalidate(state);
1871
- }; // WebXR session manager
1872
-
1776
+ };
1873
1777
 
1778
+ // WebXR session manager
1874
1779
  const xr = {
1875
1780
  connect() {
1876
1781
  const gl = store.getState().gl;
1877
1782
  gl.xr.addEventListener('sessionstart', handleSessionChange);
1878
1783
  gl.xr.addEventListener('sessionend', handleSessionChange);
1879
1784
  },
1880
-
1881
1785
  disconnect() {
1882
1786
  const gl = store.getState().gl;
1883
1787
  gl.xr.removeEventListener('sessionstart', handleSessionChange);
1884
1788
  gl.xr.removeEventListener('sessionend', handleSessionChange);
1885
1789
  }
1790
+ };
1886
1791
 
1887
- }; // Subscribe to WebXR session events
1888
-
1792
+ // Subscribe to WebXR session events
1889
1793
  if (gl.xr) xr.connect();
1890
1794
  state.set({
1891
1795
  xr
1892
1796
  });
1893
- } // Set shadowmap
1894
-
1797
+ }
1895
1798
 
1799
+ // Set shadowmap
1896
1800
  if (gl.shadowMap) {
1897
- const isBoolean = is.boo(shadows);
1898
-
1899
- if (isBoolean && gl.shadowMap.enabled !== shadows || !is.equ(shadows, gl.shadowMap, shallowLoose)) {
1900
- const old = gl.shadowMap.enabled;
1901
- gl.shadowMap.enabled = !!shadows;
1902
- if (!isBoolean) Object.assign(gl.shadowMap, shadows);else gl.shadowMap.type = THREE.PCFSoftShadowMap;
1903
- if (old !== gl.shadowMap.enabled) gl.shadowMap.needsUpdate = true;
1801
+ const oldEnabled = gl.shadowMap.enabled;
1802
+ const oldType = gl.shadowMap.type;
1803
+ gl.shadowMap.enabled = !!shadows;
1804
+ if (is.boo(shadows)) {
1805
+ gl.shadowMap.type = THREE.PCFSoftShadowMap;
1806
+ } else if (is.str(shadows)) {
1807
+ var _types$shadows;
1808
+ const types = {
1809
+ basic: THREE.BasicShadowMap,
1810
+ percentage: THREE.PCFShadowMap,
1811
+ soft: THREE.PCFSoftShadowMap,
1812
+ variance: THREE.VSMShadowMap
1813
+ };
1814
+ gl.shadowMap.type = (_types$shadows = types[shadows]) != null ? _types$shadows : THREE.PCFSoftShadowMap;
1815
+ } else if (is.obj(shadows)) {
1816
+ Object.assign(gl.shadowMap, shadows);
1904
1817
  }
1905
- } // Safely set color management if available.
1906
- // Avoid accessing THREE.ColorManagement to play nice with older versions
1907
-
1818
+ if (oldEnabled !== gl.shadowMap.enabled || oldType !== gl.shadowMap.type) gl.shadowMap.needsUpdate = true;
1819
+ }
1908
1820
 
1821
+ // Safely set color management if available.
1822
+ // Avoid accessing THREE.ColorManagement to play nice with older versions
1909
1823
  if ('ColorManagement' in THREE) {
1910
1824
  setDeep(THREE, legacy, ['ColorManagement', 'legacyMode']);
1911
1825
  }
1912
-
1913
1826
  const outputEncoding = linear ? THREE.LinearEncoding : THREE.sRGBEncoding;
1914
1827
  const toneMapping = flat ? THREE.NoToneMapping : THREE.ACESFilmicToneMapping;
1915
1828
  if (gl.outputEncoding !== outputEncoding) gl.outputEncoding = outputEncoding;
1916
- if (gl.toneMapping !== toneMapping) gl.toneMapping = toneMapping; // Update color management state
1829
+ if (gl.toneMapping !== toneMapping) gl.toneMapping = toneMapping;
1917
1830
 
1831
+ // Update color management state
1918
1832
  if (state.legacy !== legacy) state.set(() => ({
1919
1833
  legacy
1920
1834
  }));
@@ -1923,40 +1837,40 @@ function createRoot(canvas) {
1923
1837
  }));
1924
1838
  if (state.flat !== flat) state.set(() => ({
1925
1839
  flat
1926
- })); // Set gl props
1927
-
1928
- if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig); // Store events internally
1840
+ }));
1929
1841
 
1842
+ // Set gl props
1843
+ if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig);
1844
+ // Store events internally
1930
1845
  if (events && !state.events.handlers) state.set({
1931
1846
  events: events(store)
1932
- }); // Check pixelratio
1933
-
1934
- if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr); // Check size, allow it to take on container bounds initially
1935
-
1847
+ });
1848
+ // Check pixelratio
1849
+ if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
1850
+ // Check size, allow it to take on container bounds initially
1936
1851
  const size = computeInitialSize(canvas, propsSize);
1937
-
1938
1852
  if (!is.equ(size, state.size, shallowLoose)) {
1939
1853
  state.setSize(size.width, size.height, size.updateStyle, size.top, size.left);
1940
- } // Check frameloop
1941
-
1942
-
1943
- if (state.frameloop !== frameloop) state.setFrameloop(frameloop); // Check pointer missed
1944
-
1854
+ }
1855
+ // Check frameloop
1856
+ if (state.frameloop !== frameloop) state.setFrameloop(frameloop);
1857
+ // Check pointer missed
1945
1858
  if (!state.onPointerMissed) state.set({
1946
1859
  onPointerMissed
1947
- }); // Check performance
1948
-
1860
+ });
1861
+ // Check performance
1949
1862
  if (performance && !is.equ(performance, state.performance, shallowLoose)) state.set(state => ({
1950
- performance: { ...state.performance,
1863
+ performance: {
1864
+ ...state.performance,
1951
1865
  ...performance
1952
1866
  }
1953
- })); // Set locals
1867
+ }));
1954
1868
 
1869
+ // Set locals
1955
1870
  onCreated = onCreatedCallback;
1956
1871
  configured = true;
1957
1872
  return this;
1958
1873
  },
1959
-
1960
1874
  render(children) {
1961
1875
  // The root has to be configured before it can be rendered
1962
1876
  if (!configured) this.configure();
@@ -1968,21 +1882,17 @@ function createRoot(canvas) {
1968
1882
  }), fiber, null, () => undefined);
1969
1883
  return store;
1970
1884
  },
1971
-
1972
1885
  unmount() {
1973
1886
  unmountComponentAtNode(canvas);
1974
1887
  }
1975
-
1976
1888
  };
1977
1889
  }
1978
-
1979
1890
  function render(children, canvas, config) {
1980
1891
  console.warn('R3F.render is no longer supported in React 18. Use createRoot instead!');
1981
1892
  const root = createRoot(canvas);
1982
1893
  root.configure(config);
1983
1894
  return root.render(children);
1984
1895
  }
1985
-
1986
1896
  function Provider({
1987
1897
  store,
1988
1898
  children,
@@ -1990,28 +1900,28 @@ function Provider({
1990
1900
  rootElement
1991
1901
  }) {
1992
1902
  useIsomorphicLayoutEffect(() => {
1993
- const state = store.getState(); // Flag the canvas active, rendering will now begin
1994
-
1903
+ const state = store.getState();
1904
+ // Flag the canvas active, rendering will now begin
1995
1905
  state.set(state => ({
1996
- internal: { ...state.internal,
1906
+ internal: {
1907
+ ...state.internal,
1997
1908
  active: true
1998
1909
  }
1999
- })); // Notifiy that init is completed, the scene graph exists, but nothing has yet rendered
2000
-
2001
- if (onCreated) onCreated(state); // Connect events to the targets parent, this is done to ensure events are registered on
1910
+ }));
1911
+ // Notifiy that init is completed, the scene graph exists, but nothing has yet rendered
1912
+ if (onCreated) onCreated(state);
1913
+ // Connect events to the targets parent, this is done to ensure events are registered on
2002
1914
  // a shared target, and not on the canvas itself
2003
-
2004
- if (!store.getState().events.connected) state.events.connect == null ? void 0 : state.events.connect(rootElement); // eslint-disable-next-line react-hooks/exhaustive-deps
1915
+ if (!store.getState().events.connected) state.events.connect == null ? void 0 : state.events.connect(rootElement);
1916
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2005
1917
  }, []);
2006
1918
  return /*#__PURE__*/React.createElement(context.Provider, {
2007
1919
  value: store
2008
1920
  }, children);
2009
1921
  }
2010
-
2011
1922
  function unmountComponentAtNode(canvas, callback) {
2012
1923
  const root = roots.get(canvas);
2013
1924
  const fiber = root == null ? void 0 : root.fiber;
2014
-
2015
1925
  if (fiber) {
2016
1926
  const state = root == null ? void 0 : root.store.getState();
2017
1927
  if (state) state.internal.active = false;
@@ -2020,7 +1930,6 @@ function unmountComponentAtNode(canvas, callback) {
2020
1930
  setTimeout(() => {
2021
1931
  try {
2022
1932
  var _state$gl, _state$gl$renderLists, _state$gl2, _state$gl3;
2023
-
2024
1933
  state.events.disconnect == null ? void 0 : state.events.disconnect();
2025
1934
  (_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();
2026
1935
  (_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
@@ -2036,7 +1945,6 @@ function unmountComponentAtNode(canvas, callback) {
2036
1945
  });
2037
1946
  }
2038
1947
  }
2039
-
2040
1948
  function createPortal(children, container, state) {
2041
1949
  return /*#__PURE__*/React.createElement(Portal, {
2042
1950
  key: container.uuid,
@@ -2045,7 +1953,6 @@ function createPortal(children, container, state) {
2045
1953
  state: state
2046
1954
  });
2047
1955
  }
2048
-
2049
1956
  function Portal({
2050
1957
  state = {},
2051
1958
  children,
@@ -2056,6 +1963,7 @@ function Portal({
2056
1963
  * the "R3F hooks can only be used within the Canvas component!" warning:
2057
1964
  * <Canvas>
2058
1965
  * {createPortal(...)} */
1966
+
2059
1967
  const {
2060
1968
  events,
2061
1969
  size,
@@ -2065,30 +1973,32 @@ function Portal({
2065
1973
  const [raycaster] = React.useState(() => new THREE.Raycaster());
2066
1974
  const [pointer] = React.useState(() => new THREE.Vector2());
2067
1975
  const inject = React.useCallback((rootState, injectState) => {
2068
- const intersect = { ...rootState
1976
+ const intersect = {
1977
+ ...rootState
2069
1978
  }; // all prev state props
1979
+
2070
1980
  // Only the fields of "rootState" that do not differ from injectState
2071
1981
  // Some props should be off-limits
2072
1982
  // Otherwise filter out the props that are different and let the inject layer take precedence
2073
-
2074
1983
  Object.keys(rootState).forEach(key => {
2075
- if ( // Some props should be off-limits
2076
- privateKeys.includes(key) || // Otherwise filter out the props that are different and let the inject layer take precedence
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
2077
1988
  rootState[key] !== injectState[key]) {
2078
1989
  delete intersect[key];
2079
1990
  }
2080
1991
  });
2081
1992
  let viewport = undefined;
2082
-
2083
1993
  if (injectState && size) {
2084
- const camera = injectState.camera; // Calculate the override viewport, if present
2085
-
2086
- viewport = rootState.viewport.getCurrentViewport(camera, new THREE.Vector3(), size); // Update the portal camera, if it differs from the previous layer
2087
-
1994
+ const camera = injectState.camera;
1995
+ // Calculate the override viewport, if present
1996
+ viewport = rootState.viewport.getCurrentViewport(camera, new THREE.Vector3(), size);
1997
+ // Update the portal camera, if it differs from the previous layer
2088
1998
  if (camera !== rootState.camera) updateCamera(camera, size);
2089
1999
  }
2090
-
2091
- return { // The intersect consists of the previous root state
2000
+ return {
2001
+ // The intersect consists of the previous root state
2092
2002
  ...intersect,
2093
2003
  // Portals have their own scene, which forms the root, a raycaster and a pointer
2094
2004
  scene: container,
@@ -2098,14 +2008,17 @@ function Portal({
2098
2008
  // Their previous root is the layer before it
2099
2009
  previousRoot,
2100
2010
  // Events, size and viewport can be overridden by the inject layer
2101
- events: { ...rootState.events,
2011
+ events: {
2012
+ ...rootState.events,
2102
2013
  ...(injectState == null ? void 0 : injectState.events),
2103
2014
  ...events
2104
2015
  },
2105
- size: { ...rootState.size,
2016
+ size: {
2017
+ ...rootState.size,
2106
2018
  ...size
2107
2019
  },
2108
- viewport: { ...rootState.viewport,
2020
+ viewport: {
2021
+ ...rootState.viewport,
2109
2022
  ...viewport
2110
2023
  },
2111
2024
  ...rest
@@ -2114,16 +2027,19 @@ function Portal({
2114
2027
  const [usePortalStore] = React.useState(() => {
2115
2028
  // Create a mirrored store, based on the previous root with a few overrides ...
2116
2029
  const previousState = previousRoot.getState();
2117
- const store = create((set, get) => ({ ...previousState,
2030
+ const store = create((set, get) => ({
2031
+ ...previousState,
2118
2032
  scene: container,
2119
2033
  raycaster,
2120
2034
  pointer,
2121
2035
  mouse: pointer,
2122
2036
  previousRoot,
2123
- events: { ...previousState.events,
2037
+ events: {
2038
+ ...previousState.events,
2124
2039
  ...events
2125
2040
  },
2126
- size: { ...previousState.size,
2041
+ size: {
2042
+ ...previousState.size,
2127
2043
  ...size
2128
2044
  },
2129
2045
  ...rest,
@@ -2131,8 +2047,10 @@ function Portal({
2131
2047
  set,
2132
2048
  get,
2133
2049
  // Layers are allowed to override events
2134
- setEvents: events => set(state => ({ ...state,
2135
- events: { ...state.events,
2050
+ setEvents: events => set(state => ({
2051
+ ...state,
2052
+ events: {
2053
+ ...state.events,
2136
2054
  ...events
2137
2055
  }
2138
2056
  }))
@@ -2154,7 +2072,6 @@ function Portal({
2154
2072
  value: usePortalStore
2155
2073
  }, children), usePortalStore, null));
2156
2074
  }
2157
-
2158
2075
  reconciler.injectIntoDevTools({
2159
2076
  bundleType: process.env.NODE_ENV === 'production' ? 0 : 1,
2160
2077
  rendererPackageName: '@react-three/fiber',