@react-three/fiber 8.0.0-beta.3 → 8.0.0-beta.6

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.
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var React = require('react');
4
- var suspendReact = require('suspend-react');
5
3
  var THREE = require('three');
4
+ var React = require('react');
6
5
  var constants = require('react-reconciler/constants');
7
6
  var create = require('zustand');
8
7
  var Reconciler = require('react-reconciler');
9
8
  var scheduler = require('scheduler');
9
+ var suspendReact = require('suspend-react');
10
10
 
11
11
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
12
12
 
@@ -30,8 +30,8 @@ function _interopNamespace(e) {
30
30
  return Object.freeze(n);
31
31
  }
32
32
 
33
- var React__namespace = /*#__PURE__*/_interopNamespace(React);
34
33
  var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
34
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
35
35
  var create__default = /*#__PURE__*/_interopDefault(create);
36
36
  var Reconciler__default = /*#__PURE__*/_interopDefault(Reconciler);
37
37
 
@@ -44,6 +44,15 @@ const isDiffSet = def => def && !!def.memoized && !!def.changes;
44
44
  function calculateDpr(dpr) {
45
45
  return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
46
46
  }
47
+ /**
48
+ * Returns instance root state
49
+ */
50
+
51
+ const getRootState = obj => {
52
+ var _r3f;
53
+
54
+ return (_r3f = obj.__r3f) == null ? void 0 : _r3f.root.getState();
55
+ };
47
56
  /**
48
57
  * Picks or omits keys from an object
49
58
  * `omit` will filter out keys, and otherwise cherry-pick them.
@@ -53,11 +62,7 @@ function filterKeys(obj, omit, ...keys) {
53
62
  const keysToSelect = new Set(keys);
54
63
  return Object.entries(obj).reduce((acc, [key, value]) => {
55
64
  const shouldInclude = !omit;
56
-
57
- if (keysToSelect.has(key) === shouldInclude) {
58
- acc[key] = value;
59
- }
60
-
65
+ if (keysToSelect.has(key) === shouldInclude) acc[key] = value;
61
66
  return acc;
62
67
  }, {});
63
68
  }
@@ -95,7 +100,7 @@ const is = {
95
100
  const isArr = is.arr(a);
96
101
  if (isArr && arrays === 'reference') return a === b; // Array or Object, shallow compare first to see if it's a match
97
102
 
98
- if ((isArr || isObj) && a == b) return true; // Last resort, go through keys
103
+ if ((isArr || isObj) && a === b) return true; // Last resort, go through keys
99
104
 
100
105
  let i;
101
106
 
@@ -103,7 +108,13 @@ const is = {
103
108
 
104
109
  for (i in strict ? b : a) if (a[i] !== b[i]) return false;
105
110
 
106
- return is.und(i) ? a === b : true;
111
+ if (is.und(i)) {
112
+ if (isArr && a.length === 0 && b.length === 0) return true;
113
+ if (isObj && Object.keys(a).length === 0 && Object.keys(b).length === 0) return true;
114
+ if (a !== b) return false;
115
+ }
116
+
117
+ return true;
107
118
  }
108
119
 
109
120
  }; // Collects nodes and materials from a THREE.Object3D
@@ -138,7 +149,9 @@ function prepare(object, state) {
138
149
 
139
150
  if (state != null && state.primitive || !instance.__r3f) {
140
151
  instance.__r3f = {
152
+ type: '',
141
153
  root: null,
154
+ previousAttach: null,
142
155
  memoizedProps: {},
143
156
  eventCount: 0,
144
157
  handlers: {},
@@ -166,32 +179,42 @@ function resolve(instance, key) {
166
179
  target,
167
180
  key
168
181
  };
169
- }
182
+ } // Checks if a dash-cased string ends with an integer
183
+
170
184
 
185
+ const INDEX_REGEX = /-\d+$/;
171
186
  function attach(parent, child, type) {
172
187
  if (is.str(type)) {
188
+ // If attaching into an array (foo-0), create one
189
+ if (INDEX_REGEX.test(type)) {
190
+ const root = type.replace(INDEX_REGEX, '');
191
+ const {
192
+ target,
193
+ key
194
+ } = resolve(parent, root);
195
+ if (!Array.isArray(target[key])) target[key] = [];
196
+ }
197
+
173
198
  const {
174
199
  target,
175
200
  key
176
201
  } = resolve(parent, type);
177
- parent.__r3f.previousAttach = target[key];
202
+ child.__r3f.previousAttach = target[key];
178
203
  target[key] = child;
179
- } else if (is.arr(type)) {
180
- const [attach] = type;
181
- if (is.str(attach)) parent[attach](child);else if (is.fun(attach)) attach(parent, child);
182
- }
204
+ } else child.__r3f.previousAttach = type(parent, child);
183
205
  }
184
206
  function detach(parent, child, type) {
207
+ var _child$__r3f, _child$__r3f2;
208
+
185
209
  if (is.str(type)) {
186
210
  const {
187
211
  target,
188
212
  key
189
213
  } = resolve(parent, type);
190
- target[key] = parent.__r3f.previousAttach;
191
- } else if (is.arr(type)) {
192
- const [, detach] = type;
193
- if (is.str(detach)) parent[detach](child);else if (is.fun(detach)) detach(parent, child);
194
- }
214
+ target[key] = child.__r3f.previousAttach;
215
+ } else (_child$__r3f = child.__r3f) == null ? void 0 : _child$__r3f.previousAttach == null ? void 0 : _child$__r3f.previousAttach(parent, child);
216
+
217
+ (_child$__r3f2 = child.__r3f) == null ? true : delete _child$__r3f2.previousAttach;
195
218
  } // This function prepares a set of changes to be applied to the instance
196
219
 
197
220
  function diffProps(instance, {
@@ -279,11 +302,11 @@ function applyProps$1(instance, data) {
279
302
  if (value === DEFAULT + 'remove') {
280
303
  if (targetProp && targetProp.constructor) {
281
304
  // use the prop constructor to find the default it should be
282
- value = new targetProp.constructor(memoized.args);
305
+ value = new targetProp.constructor(...memoized.args);
283
306
  } else if (currentInstance.constructor) {
284
307
  // create a blank slate of the instance and copy the particular parameter.
285
308
  // @ts-ignore
286
- const defaultClassCall = new currentInstance.constructor(currentInstance.__r3f.memoizedProps.args);
309
+ const defaultClassCall = new currentInstance.constructor(...currentInstance.__r3f.memoizedProps.args);
287
310
  value = defaultClassCall[targetProp]; // destory the instance
288
311
 
289
312
  if (defaultClassCall.dispose) defaultClassCall.dispose(); // instance does not have constructor, just set it to 0
@@ -311,20 +334,10 @@ function applyProps$1(instance, data) {
311
334
 
312
335
  if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
313
336
  else if (targetProp instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) targetProp.mask = value.mask; // Otherwise just set ...
314
- else targetProp.set(value); // Auto-convert sRGB colors, for now ...
315
- // https://github.com/pmndrs/react-three-fiber/issues/344
316
-
317
- if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
337
+ else targetProp.set(value);
318
338
  } // Else, just overwrite the value
319
339
 
320
- } else {
321
- currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
322
- // https://github.com/pmndrs/react-three-fiber/issues/344
323
-
324
- if (!rootState.linear && currentInstance[key] instanceof THREE__namespace.Texture) {
325
- currentInstance[key].encoding = THREE__namespace.sRGBEncoding;
326
- }
327
- }
340
+ } else currentInstance[key] = value;
328
341
 
329
342
  invalidateInstance(instance);
330
343
  return instance;
@@ -403,6 +416,7 @@ function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
403
416
 
404
417
  function removeInteractivity(store, object) {
405
418
  const {
419
+ events,
406
420
  internal
407
421
  } = store.getState(); // Removes every trace of an object from the data store
408
422
 
@@ -410,6 +424,7 @@ function removeInteractivity(store, object) {
410
424
  internal.initialHits = internal.initialHits.filter(o => o !== object);
411
425
  internal.hovered.forEach((value, key) => {
412
426
  if (value.eventObject === object || value.object === object) {
427
+ // Clear out intersects, they are outdated by now
413
428
  internal.hovered.delete(key);
414
429
  }
415
430
  });
@@ -419,31 +434,8 @@ function removeInteractivity(store, object) {
419
434
  }
420
435
  function createEvents(store) {
421
436
  const temp = new THREE__namespace.Vector3();
422
- /** Sets up defaultRaycaster */
423
-
424
- function prepareRay(event) {
425
- var _customOffsets$offset, _customOffsets$offset2, _customOffsets$width, _customOffsets$height;
426
-
427
- const state = store.getState();
428
- const {
429
- raycaster,
430
- mouse,
431
- camera,
432
- size
433
- } = state; // https://github.com/pmndrs/react-three-fiber/pull/782
434
- // Events trigger outside of canvas when moved
435
-
436
- const customOffsets = raycaster.computeOffsets == null ? void 0 : raycaster.computeOffsets(event, state);
437
- const offsetX = (_customOffsets$offset = customOffsets == null ? void 0 : customOffsets.offsetX) != null ? _customOffsets$offset : event.offsetX;
438
- const offsetY = (_customOffsets$offset2 = customOffsets == null ? void 0 : customOffsets.offsetY) != null ? _customOffsets$offset2 : event.offsetY;
439
- const width = (_customOffsets$width = customOffsets == null ? void 0 : customOffsets.width) != null ? _customOffsets$width : size.width;
440
- const height = (_customOffsets$height = customOffsets == null ? void 0 : customOffsets.height) != null ? _customOffsets$height : size.height;
441
- mouse.set(offsetX / width * 2 - 1, -(offsetY / height) * 2 + 1);
442
- raycaster.setFromCamera(mouse, camera);
443
- }
444
437
  /** Calculates delta */
445
438
 
446
-
447
439
  function calculateDistance(event) {
448
440
  const {
449
441
  internal
@@ -463,55 +455,70 @@ function createEvents(store) {
463
455
  }));
464
456
  }
465
457
 
466
- function intersect(filter) {
458
+ function intersect(event, filter) {
467
459
  const state = store.getState();
468
- const {
469
- raycaster,
470
- internal
471
- } = state; // Skip event handling when noEvents is set
472
-
473
- if (!raycaster.enabled) return [];
474
- const seen = new Set();
460
+ const duplicates = new Set();
475
461
  const intersections = []; // Allow callers to eliminate event objects
476
462
 
477
- const eventsObjects = filter ? filter(internal.interaction) : internal.interaction; // Intersect known handler objects and filter against duplicates
463
+ const eventsObjects = filter ? filter(state.internal.interaction) : state.internal.interaction; // Reset all raycaster cameras to undefined
464
+
465
+ eventsObjects.forEach(obj => {
466
+ const state = getRootState(obj);
467
+
468
+ if (state) {
469
+ state.raycaster.camera = undefined;
470
+ }
471
+ }); // Collect events
472
+
473
+ let hits = eventsObjects // Intersect objects
474
+ .flatMap(obj => {
475
+ const state = getRootState(obj); // Skip event handling when noEvents is set, or when the raycasters camera is null
478
476
 
479
- let intersects = raycaster.intersectObjects(eventsObjects, true).filter(item => {
477
+ if (!state || !state.events.enabled || state.raycaster.camera === null) return []; // When the camera is undefined we have to call the event layers update function
478
+
479
+ if (state.raycaster.camera === undefined) {
480
+ var _state$previousRoot;
481
+
482
+ 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
483
+
484
+ if (state.raycaster.camera === undefined) state.raycaster.camera = null;
485
+ } // Intersect object by object
486
+
487
+
488
+ return state.raycaster.camera ? state.raycaster.intersectObject(obj, true) : [];
489
+ }) // Sort by event priority and distance
490
+ .sort((a, b) => {
491
+ const aState = getRootState(a.object);
492
+ const bState = getRootState(b.object);
493
+ if (!aState || !bState) return 0;
494
+ return bState.events.priority - aState.events.priority || a.distance - b.distance;
495
+ }) // Filter out duplicates
496
+ .filter(item => {
480
497
  const id = makeId(item);
481
- if (seen.has(id)) return false;
482
- seen.add(id);
498
+ if (duplicates.has(id)) return false;
499
+ duplicates.add(id);
483
500
  return true;
484
501
  }); // https://github.com/mrdoob/three.js/issues/16031
485
- // Allow custom userland intersect sort order
502
+ // Allow custom userland intersect sort order, this likely only makes sense on the root filter
486
503
 
487
- if (raycaster.filter) intersects = raycaster.filter(intersects, state);
504
+ if (state.events.filter) hits = state.events.filter(hits, state); // Bubble up the events, find the event source (eventObject)
488
505
 
489
- for (const intersect of intersects) {
490
- let eventObject = intersect.object; // Bubble event up
506
+ for (const hit of hits) {
507
+ let eventObject = hit.object; // Bubble event up
491
508
 
492
509
  while (eventObject) {
493
510
  var _r3f2;
494
511
 
495
- if ((_r3f2 = eventObject.__r3f) != null && _r3f2.eventCount) intersections.push({ ...intersect,
512
+ if ((_r3f2 = eventObject.__r3f) != null && _r3f2.eventCount) intersections.push({ ...hit,
496
513
  eventObject
497
514
  });
498
515
  eventObject = eventObject.parent;
499
516
  }
500
- }
517
+ } // If the interaction is captured, make all capturing targets part of the intersect.
501
518
 
502
- return intersections;
503
- }
504
- /** Creates filtered intersects and returns an array of positive hits */
505
-
506
-
507
- function patchIntersects(intersections, event) {
508
- const {
509
- internal
510
- } = store.getState(); // If the interaction is captured, make all capturing targets part of the
511
- // intersect.
512
519
 
513
- if ('pointerId' in event && internal.capturedMap.has(event.pointerId)) {
514
- for (let captureData of internal.capturedMap.get(event.pointerId).values()) {
520
+ if ('pointerId' in event && state.internal.capturedMap.has(event.pointerId)) {
521
+ for (let captureData of state.internal.capturedMap.get(event.pointerId).values()) {
515
522
  intersections.push(captureData.intersection);
516
523
  }
517
524
  }
@@ -524,13 +531,13 @@ function createEvents(store) {
524
531
  function handleIntersects(intersections, event, delta, callback) {
525
532
  const {
526
533
  raycaster,
527
- mouse,
534
+ pointer,
528
535
  camera,
529
536
  internal
530
537
  } = store.getState(); // If anything has been found, forward it to the event listeners
531
538
 
532
539
  if (intersections.length) {
533
- const unprojectedPoint = temp.set(mouse.x, mouse.y, 0).unproject(camera);
540
+ const unprojectedPoint = temp.set(pointer.x, pointer.y, 0).unproject(camera);
534
541
  const localState = {
535
542
  stopped: false
536
543
  };
@@ -581,8 +588,7 @@ function createEvents(store) {
581
588
 
582
589
  let raycastEvent = { ...hit,
583
590
  ...extractEventProps,
584
- spaceX: mouse.x,
585
- spaceY: mouse.y,
591
+ pointer,
586
592
  intersections,
587
593
  stopped: localState.stopped,
588
594
  delta,
@@ -619,8 +625,6 @@ function createEvents(store) {
619
625
  setPointerCapture,
620
626
  releasePointerCapture
621
627
  },
622
- sourceEvent: event,
623
- // deprecated
624
628
  nativeEvent: event
625
629
  }; // Call subscribers
626
630
 
@@ -685,14 +689,15 @@ function createEvents(store) {
685
689
  const {
686
690
  onPointerMissed,
687
691
  internal
688
- } = store.getState();
689
- prepareRay(event);
692
+ } = store.getState(); //prepareRay(event)
693
+
690
694
  internal.lastEvent.current = event; // Get fresh intersects
691
695
 
692
696
  const isPointerMove = name === 'onPointerMove';
693
697
  const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
694
- const filter = isPointerMove ? filterPointerEvents : undefined;
695
- const hits = patchIntersects(intersect(filter), event);
698
+ const filter = isPointerMove ? filterPointerEvents : undefined; //const hits = patchIntersects(intersect(filter), event)
699
+
700
+ const hits = intersect(event, filter);
696
701
  const delta = isClickEvent ? calculateDistance(event) : 0; // Save initial coordinates on pointer-down
697
702
 
698
703
  if (name === 'onPointerDown') {
@@ -775,23 +780,6 @@ function createEvents(store) {
775
780
  };
776
781
  }
777
782
 
778
- // Type guard to tell a store from a portal
779
- const isStore = def => def && !!def.getState;
780
-
781
- const getContainer = (container, child) => {
782
- var _container$__r3f$root, _container$__r3f;
783
-
784
- return {
785
- // If the container is not a root-store then it must be a THREE.Object3D into which part of the
786
- // scene is portalled into. Now there can be two variants of this, either that object is part of
787
- // the regular jsx tree, in which case it already has __r3f with a valid root attached, or it lies
788
- // outside react, in which case we must take the root of the child that is about to be attached to it.
789
- root: isStore(container) ? container : (_container$__r3f$root = (_container$__r3f = container.__r3f) == null ? void 0 : _container$__r3f.root) != null ? _container$__r3f$root : child.__r3f.root,
790
- // The container is the eventual target into which objects are mounted, it has to be a THREE.Object3D
791
- container: isStore(container) ? container.getState().scene : container
792
- };
793
- };
794
-
795
783
  let catalogue = {};
796
784
 
797
785
  let extend = objects => void (catalogue = { ...catalogue,
@@ -803,22 +791,9 @@ function createRenderer(roots, getEventPriority) {
803
791
  args = [],
804
792
  attach,
805
793
  ...props
806
- }, root, hostContext, internalInstanceHandle) {
794
+ }, root) {
807
795
  let name = `${type[0].toUpperCase()}${type.slice(1)}`;
808
- let instance; // https://github.com/facebook/react/issues/17147
809
- // Portals do not give us a root, they are themselves treated as a root by the reconciler
810
- // In order to figure out the actual root we have to climb through fiber internals :(
811
-
812
- if (!isStore(root) && internalInstanceHandle) {
813
- const fn = node => {
814
- if (!node.return) return node.stateNode && node.stateNode.containerInfo;else return fn(node.return);
815
- };
816
-
817
- root = fn(internalInstanceHandle);
818
- } // Assert that by now we have a valid root
819
-
820
-
821
- if (!root || !isStore(root)) throw `No valid root for ${name}!`; // Auto-attach geometries and materials
796
+ let instance; // Auto-attach geometries and materials
822
797
 
823
798
  if (attach === undefined) {
824
799
  if (name.endsWith('Geometry')) attach = 'geometry';else if (name.endsWith('Material')) attach = 'material';
@@ -828,6 +803,7 @@ function createRenderer(roots, getEventPriority) {
828
803
  if (props.object === undefined) throw `Primitives without 'object' are invalid!`;
829
804
  const object = props.object;
830
805
  instance = prepare(object, {
806
+ type,
831
807
  root,
832
808
  attach,
833
809
  primitive: true
@@ -844,19 +820,21 @@ function createRenderer(roots, getEventPriority) {
844
820
  // Append memoized props with args so it's not forgotten
845
821
 
846
822
  instance = prepare(new target(...args), {
823
+ type,
847
824
  root,
848
825
  attach,
849
826
  // TODO: Figure out what this is for
850
827
  memoizedProps: {
851
- args: args.length === 0 ? null : args
828
+ args
852
829
  }
853
830
  });
854
831
  } // It should NOT call onUpdate on object instanciation, because it hasn't been added to the
855
832
  // view yet. If the callback relies on references for instance, they won't be ready yet, this is
856
833
  // why it passes "true" here
834
+ // There is no reason to apply props to injects
857
835
 
858
836
 
859
- applyProps$1(instance, props);
837
+ if (name !== 'inject') applyProps$1(instance, props);
860
838
  return instance;
861
839
  }
862
840
 
@@ -978,11 +956,11 @@ function createRenderer(roots, getEventPriority) {
978
956
  }
979
957
 
980
958
  function switchInstance(instance, type, newProps, fiber) {
981
- var _instance$__r3f;
959
+ var _instance$__r3f, _instance$__r3f2;
982
960
 
983
961
  const parent = (_instance$__r3f = instance.__r3f) == null ? void 0 : _instance$__r3f.parent;
984
962
  if (!parent) return;
985
- const newInstance = createInstance(type, newProps, instance.__r3f.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
963
+ const newInstance = createInstance(type, newProps, (_instance$__r3f2 = instance.__r3f) == null ? void 0 : _instance$__r3f2.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
986
964
  // When args change the instance has to be re-constructed, which then
987
965
  // forces r3f to re-parent the children and non-scene objects
988
966
  // This can not include primitives, which should not have declarative children
@@ -1015,19 +993,38 @@ function createRenderer(roots, getEventPriority) {
1015
993
  }
1016
994
 
1017
995
  const reconciler = Reconciler__default['default']({
1018
- appendChildToContainer: (parentInstance, child) => {
1019
- const {
1020
- container,
1021
- root
1022
- } = getContainer(parentInstance, child); // Link current root to the default scene
996
+ createInstance,
997
+ removeChild,
998
+ appendChild,
999
+ appendInitialChild: appendChild,
1000
+ insertBefore,
1001
+ supportsMicrotask: true,
1002
+ warnsIfNotActing: true,
1003
+ supportsMutation: true,
1004
+ isPrimaryRenderer: false,
1005
+ noTimeout: -1,
1006
+ appendChildToContainer: (container, child) => {
1007
+ const scene = container.getState().scene; // Link current root to the default scene
1023
1008
 
1024
- container.__r3f.root = root;
1025
- appendChild(container, child);
1009
+ scene.__r3f.root = container;
1010
+ appendChild(scene, child);
1011
+ },
1012
+ removeChildFromContainer: (container, child) => removeChild(container.getState().scene, child),
1013
+ insertInContainerBefore: (container, child, beforeChild) => insertBefore(container.getState().scene, child, beforeChild),
1014
+ getRootHostContext: () => null,
1015
+ getChildHostContext: parentHostContext => parentHostContext,
1016
+
1017
+ finalizeInitialChildren(instance) {
1018
+ var _instance$__r3f3;
1019
+
1020
+ const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {}; // https://github.com/facebook/react/issues/20271
1021
+ // Returning true will trigger commitMount
1022
+
1023
+ return !!localState.handlers;
1026
1024
  },
1027
- removeChildFromContainer: (parentInstance, child) => removeChild(getContainer(parentInstance, child).container, child),
1028
- insertInContainerBefore: (parentInstance, child, beforeChild) => insertBefore(getContainer(parentInstance, child).container, child, beforeChild),
1029
1025
 
1030
1026
  prepareUpdate(instance, type, oldProps, newProps) {
1027
+ // Create diff-sets
1031
1028
  if (instance.__r3f.primitive && newProps.object && newProps.object !== instance) {
1032
1029
  return [true];
1033
1030
  } else {
@@ -1060,40 +1057,58 @@ function createRenderer(roots, getEventPriority) {
1060
1057
  else applyProps$1(instance, diff);
1061
1058
  },
1062
1059
 
1060
+ commitMount(instance, type, props, int) {
1061
+ var _instance$__r3f4;
1062
+
1063
+ // https://github.com/facebook/react/issues/20271
1064
+ // This will make sure events are only added once to the central container
1065
+ const localState = (_instance$__r3f4 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f4 : {};
1066
+
1067
+ if (instance.raycast && localState.handlers && localState.eventCount) {
1068
+ instance.__r3f.root.getState().internal.interaction.push(instance);
1069
+ }
1070
+ },
1071
+
1072
+ getPublicInstance: instance => instance,
1073
+ shouldDeprioritizeSubtree: () => false,
1074
+ prepareForCommit: () => null,
1075
+ preparePortalMount: container => prepare(container.getState().scene),
1076
+ resetAfterCommit: () => {},
1077
+ shouldSetTextContent: () => false,
1078
+ clearContainer: () => false,
1079
+ detachDeletedInstance: () => {},
1080
+ createTextInstance: () => {},
1081
+
1063
1082
  hideInstance(instance) {
1064
- var _instance$__r3f2;
1083
+ var _instance$__r3f5;
1065
1084
 
1066
1085
  // Deatch while the instance is hidden
1067
1086
  const {
1068
1087
  attach: type,
1069
1088
  parent
1070
- } = (_instance$__r3f2 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f2 : {};
1089
+ } = (_instance$__r3f5 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f5 : {};
1071
1090
  if (type && parent) detach(parent, instance, type);
1072
1091
  if (instance.isObject3D) instance.visible = false;
1073
1092
  invalidateInstance(instance);
1074
1093
  },
1075
1094
 
1076
1095
  unhideInstance(instance, props) {
1077
- var _instance$__r3f3;
1096
+ var _instance$__r3f6;
1078
1097
 
1079
1098
  // Re-attach when the instance is unhidden
1080
1099
  const {
1081
1100
  attach: type,
1082
1101
  parent
1083
- } = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
1102
+ } = (_instance$__r3f6 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f6 : {};
1084
1103
  if (type && parent) attach(parent, instance, type);
1085
1104
  if (instance.isObject3D && props.visible == null || props.visible) instance.visible = true;
1086
1105
  invalidateInstance(instance);
1087
1106
  },
1088
1107
 
1089
- createInstance,
1090
- removeChild,
1091
- appendChild,
1092
- appendInitialChild: appendChild,
1093
- insertBefore,
1094
- warnsIfNotActing: true,
1095
- supportsMutation: true,
1096
- isPrimaryRenderer: false,
1108
+ hideTextInstance: () => {
1109
+ throw new Error('Text is not allowed in the R3F tree.');
1110
+ },
1111
+ // prettier-ignore
1097
1112
  getCurrentEventPriority: () => getEventPriority ? getEventPriority() : constants.DefaultEventPriority,
1098
1113
  // @ts-ignore
1099
1114
  now: typeof performance !== 'undefined' && is.fun(performance.now) ? performance.now : is.fun(Date.now) ? Date.now : undefined,
@@ -1102,47 +1117,7 @@ function createRenderer(roots, getEventPriority) {
1102
1117
  // @ts-ignore
1103
1118
  cancelTimeout: is.fun(clearTimeout) ? clearTimeout : undefined,
1104
1119
  setTimeout: is.fun(setTimeout) ? setTimeout : undefined,
1105
- clearTimeout: is.fun(clearTimeout) ? clearTimeout : undefined,
1106
- noTimeout: -1,
1107
- hideTextInstance: () => {
1108
- throw new Error('Text is not allowed in the R3F tree.');
1109
- },
1110
- // prettier-ignore
1111
- getPublicInstance: instance => instance,
1112
- getRootHostContext: () => null,
1113
- getChildHostContext: parentHostContext => parentHostContext,
1114
- createTextInstance: () => {},
1115
-
1116
- finalizeInitialChildren(instance) {
1117
- var _instance$__r3f4;
1118
-
1119
- // https://github.com/facebook/react/issues/20271
1120
- // Returning true will trigger commitMount
1121
- const localState = (_instance$__r3f4 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f4 : {};
1122
- return !!localState.handlers;
1123
- },
1124
-
1125
- commitMount(instance)
1126
- /*, type, props*/
1127
- {
1128
- var _instance$__r3f5;
1129
-
1130
- // https://github.com/facebook/react/issues/20271
1131
- // This will make sure events are only added once to the central container
1132
- const localState = (_instance$__r3f5 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f5 : {};
1133
-
1134
- if (instance.raycast && localState.handlers && localState.eventCount) {
1135
- instance.__r3f.root.getState().internal.interaction.push(instance);
1136
- }
1137
- },
1138
-
1139
- shouldDeprioritizeSubtree: () => false,
1140
- prepareForCommit: () => null,
1141
- preparePortalMount: containerInfo => prepare(containerInfo),
1142
- resetAfterCommit: () => {},
1143
- shouldSetTextContent: () => false,
1144
- clearContainer: () => false,
1145
- detachDeletedInstance: () => {}
1120
+ clearTimeout: is.fun(clearTimeout) ? clearTimeout : undefined
1146
1121
  });
1147
1122
  return {
1148
1123
  reconciler,
@@ -1202,16 +1177,18 @@ const createStore = (invalidate, advance) => {
1202
1177
  }));
1203
1178
 
1204
1179
  return {
1180
+ set,
1181
+ get,
1205
1182
  // Mock objects that have to be configured
1206
1183
  gl: null,
1207
1184
  camera: null,
1208
1185
  raycaster: null,
1209
1186
  events: {
1187
+ priority: 1,
1188
+ enabled: true,
1210
1189
  connected: false
1211
1190
  },
1212
1191
  xr: null,
1213
- set,
1214
- get,
1215
1192
  invalidate: () => invalidate(get()),
1216
1193
  advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
1217
1194
  linear: false,
@@ -1219,7 +1196,7 @@ const createStore = (invalidate, advance) => {
1219
1196
  scene: prepare(new THREE__namespace.Scene()),
1220
1197
  controls: null,
1221
1198
  clock: new THREE__namespace.Clock(),
1222
- mouse: new THREE__namespace.Vector2(),
1199
+ pointer: new THREE__namespace.Vector2(),
1223
1200
  frameloop: 'always',
1224
1201
  onPointerMissed: undefined,
1225
1202
  performance: {
@@ -1288,6 +1265,7 @@ const createStore = (invalidate, advance) => {
1288
1265
  frameloop
1289
1266
  }));
1290
1267
  },
1268
+ previousRoot: undefined,
1291
1269
  internal: {
1292
1270
  active: false,
1293
1271
  priority: 0,
@@ -1515,6 +1493,11 @@ function loadingFn(extensions, onProgress) {
1515
1493
  };
1516
1494
  }
1517
1495
 
1496
+ function useMemoizedFn(fn) {
1497
+ const fnRef = React__namespace.useRef(fn);
1498
+ React__namespace.useLayoutEffect(() => void (fnRef.current = fn), [fn]);
1499
+ return (...args) => fnRef.current == null ? void 0 : fnRef.current(...args);
1500
+ }
1518
1501
  function useLoader(Proto, input, extensions, onProgress) {
1519
1502
  // Use suspense to load async assets
1520
1503
  const keys = Array.isArray(input) ? input : [input];
@@ -1614,9 +1597,7 @@ function createRoot(canvas) {
1614
1597
  params,
1615
1598
  ...options
1616
1599
  } = raycastOptions || {};
1617
- if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, {
1618
- enabled: true,
1619
- ...options
1600
+ if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, { ...options
1620
1601
  });
1621
1602
  if (!is.equ(params, raycaster.params, shallowLoose)) applyProps(raycaster, {
1622
1603
  params: { ...raycaster.params,
@@ -1652,7 +1633,7 @@ function createRoot(canvas) {
1652
1633
 
1653
1634
  const handleSessionChange = () => {
1654
1635
  const gl = store.getState().gl;
1655
- gl.xr.enabled = gl.xr.isPresenting; // @ts-expect-error
1636
+ gl.xr.enabled = gl.xr.isPresenting; // @ts-ignore
1656
1637
  // WebXRManager's signature is incorrect.
1657
1638
  // See: https://github.com/pmndrs/react-three-fiber/pull/2017#discussion_r790134505
1658
1639
 
@@ -1694,6 +1675,7 @@ function createRoot(canvas) {
1694
1675
  } // Set color management
1695
1676
 
1696
1677
 
1678
+ if (THREE__namespace.ColorManagement) THREE__namespace.ColorManagement.legacyMode = false;
1697
1679
  const outputEncoding = linear ? THREE__namespace.LinearEncoding : THREE__namespace.sRGBEncoding;
1698
1680
  const toneMapping = flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping;
1699
1681
  if (gl.outputEncoding !== outputEncoding) gl.outputEncoding = outputEncoding;
@@ -1769,9 +1751,10 @@ function Provider({
1769
1751
  internal: { ...state.internal,
1770
1752
  active: true
1771
1753
  }
1772
- })); // Connect events
1754
+ })); // Connect events to the targets parent, this is done to ensure events are registered on
1755
+ // a shared target, and not on the canvas itself
1773
1756
 
1774
- state.events.connect == null ? void 0 : state.events.connect(target); // Notifiy that init is completed, the scene graph exists, but nothing has yet rendered
1757
+ state.events.connect == null ? void 0 : state.events.connect(target.parentNode); // Notifiy that init is completed, the scene graph exists, but nothing has yet rendered
1775
1758
 
1776
1759
  if (onCreated) onCreated(state); // eslint-disable-next-line react-hooks/exhaustive-deps
1777
1760
  }, []);
@@ -1809,10 +1792,65 @@ function unmountComponentAtNode(canvas, callback) {
1809
1792
  }
1810
1793
  }
1811
1794
 
1812
- const act = React__namespace.unstable_act;
1795
+ function createPortal(children, container, state) {
1796
+ return /*#__PURE__*/React__namespace.createElement(Portal, {
1797
+ children: children,
1798
+ container: container,
1799
+ state: state
1800
+ });
1801
+ }
1802
+
1803
+ function Portal({
1804
+ state = {},
1805
+ children,
1806
+ container
1807
+ }) {
1808
+ /** This has to be a component because it would not be able to call useThree/useStore otherwise since
1809
+ * if this is our environment, then we are not in r3f's renderer but in react-dom, it would trigger
1810
+ * the "R3F hooks can only be used within the Canvas component!" warning:
1811
+ * <Canvas>
1812
+ * {createPortal(...)} */
1813
+ const {
1814
+ events,
1815
+ ...rest
1816
+ } = state;
1817
+ const previousRoot = useStore();
1818
+ const [raycaster] = React__namespace.useState(() => new THREE__namespace.Raycaster());
1819
+ const inject = React__namespace.useCallback((state, injectState) => {
1820
+ const intersect = { ...state
1821
+ };
1813
1822
 
1814
- function createPortal(children, container) {
1815
- return reconciler.createPortal(children, container, null, null);
1823
+ if (injectState) {
1824
+ // Only the fields of "state" that do not differ from injectState
1825
+ Object.keys(state).forEach(key => {
1826
+ if (state[key] !== injectState[key]) delete intersect[key];
1827
+ });
1828
+ }
1829
+
1830
+ return { ...intersect,
1831
+ scene: container,
1832
+ previousRoot,
1833
+ raycaster,
1834
+ events: { ...state.events,
1835
+ ...events
1836
+ },
1837
+ ...rest
1838
+ };
1839
+ }, [state]);
1840
+ const [useInjectStore] = React__namespace.useState(() => {
1841
+ const store = create__default['default']((set, get) => ({ ...inject(previousRoot.getState()),
1842
+ set,
1843
+ get
1844
+ }));
1845
+ previousRoot.subscribe(state => useInjectStore.setState(injectState => inject(state, injectState)));
1846
+ return store;
1847
+ });
1848
+ React__namespace.useEffect(() => {
1849
+ useInjectStore.setState(injectState => inject(previousRoot.getState(), injectState));
1850
+ }, [inject]);
1851
+ return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, reconciler.createPortal( /*#__PURE__*/React__namespace.createElement(context.Provider, {
1852
+ value: useInjectStore
1853
+ }, children), useInjectStore, null));
1816
1854
  }
1817
1855
 
1818
1856
  reconciler.injectIntoDevTools({
@@ -1820,6 +1858,7 @@ reconciler.injectIntoDevTools({
1820
1858
  rendererPackageName: '@react-three/fiber',
1821
1859
  version: '18.0.0'
1822
1860
  });
1861
+ const act = React__namespace.unstable_act;
1823
1862
 
1824
1863
  exports.act = act;
1825
1864
  exports.addAfterEffect = addAfterEffect;
@@ -1833,6 +1872,7 @@ exports.createPortal = createPortal;
1833
1872
  exports.createRoot = createRoot;
1834
1873
  exports.dispose = dispose;
1835
1874
  exports.extend = extend;
1875
+ exports.getRootState = getRootState;
1836
1876
  exports.invalidate = invalidate;
1837
1877
  exports.omit = omit;
1838
1878
  exports.pick = pick;
@@ -1844,5 +1884,6 @@ exports.unmountComponentAtNode = unmountComponentAtNode;
1844
1884
  exports.useFrame = useFrame;
1845
1885
  exports.useGraph = useGraph;
1846
1886
  exports.useLoader = useLoader;
1887
+ exports.useMemoizedFn = useMemoizedFn;
1847
1888
  exports.useStore = useStore;
1848
1889
  exports.useThree = useThree;