@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,10 +1,10 @@
1
- import * as React from 'react';
2
- import { suspend, preload, clear } from 'suspend-react';
3
1
  import * as THREE from 'three';
2
+ import * as React from 'react';
4
3
  import { DefaultEventPriority, ContinuousEventPriority, DiscreteEventPriority, ConcurrentRoot } from 'react-reconciler/constants';
5
4
  import create from 'zustand';
6
5
  import Reconciler from 'react-reconciler';
7
6
  import { unstable_scheduleCallback, unstable_IdlePriority } from 'scheduler';
7
+ import { suspend, preload, clear } from 'suspend-react';
8
8
 
9
9
  var threeTypes = /*#__PURE__*/Object.freeze({
10
10
  __proto__: null
@@ -15,6 +15,15 @@ const isDiffSet = def => def && !!def.memoized && !!def.changes;
15
15
  function calculateDpr(dpr) {
16
16
  return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
17
17
  }
18
+ /**
19
+ * Returns instance root state
20
+ */
21
+
22
+ const getRootState = obj => {
23
+ var _r3f;
24
+
25
+ return (_r3f = obj.__r3f) == null ? void 0 : _r3f.root.getState();
26
+ };
18
27
  /**
19
28
  * Picks or omits keys from an object
20
29
  * `omit` will filter out keys, and otherwise cherry-pick them.
@@ -24,11 +33,7 @@ function filterKeys(obj, omit, ...keys) {
24
33
  const keysToSelect = new Set(keys);
25
34
  return Object.entries(obj).reduce((acc, [key, value]) => {
26
35
  const shouldInclude = !omit;
27
-
28
- if (keysToSelect.has(key) === shouldInclude) {
29
- acc[key] = value;
30
- }
31
-
36
+ if (keysToSelect.has(key) === shouldInclude) acc[key] = value;
32
37
  return acc;
33
38
  }, {});
34
39
  }
@@ -66,7 +71,7 @@ const is = {
66
71
  const isArr = is.arr(a);
67
72
  if (isArr && arrays === 'reference') return a === b; // Array or Object, shallow compare first to see if it's a match
68
73
 
69
- if ((isArr || isObj) && a == b) return true; // Last resort, go through keys
74
+ if ((isArr || isObj) && a === b) return true; // Last resort, go through keys
70
75
 
71
76
  let i;
72
77
 
@@ -74,7 +79,13 @@ const is = {
74
79
 
75
80
  for (i in strict ? b : a) if (a[i] !== b[i]) return false;
76
81
 
77
- return is.und(i) ? a === b : true;
82
+ if (is.und(i)) {
83
+ if (isArr && a.length === 0 && b.length === 0) return true;
84
+ if (isObj && Object.keys(a).length === 0 && Object.keys(b).length === 0) return true;
85
+ if (a !== b) return false;
86
+ }
87
+
88
+ return true;
78
89
  }
79
90
 
80
91
  }; // Collects nodes and materials from a THREE.Object3D
@@ -109,7 +120,9 @@ function prepare(object, state) {
109
120
 
110
121
  if (state != null && state.primitive || !instance.__r3f) {
111
122
  instance.__r3f = {
123
+ type: '',
112
124
  root: null,
125
+ previousAttach: null,
113
126
  memoizedProps: {},
114
127
  eventCount: 0,
115
128
  handlers: {},
@@ -137,32 +150,42 @@ function resolve(instance, key) {
137
150
  target,
138
151
  key
139
152
  };
140
- }
153
+ } // Checks if a dash-cased string ends with an integer
141
154
 
155
+
156
+ const INDEX_REGEX = /-\d+$/;
142
157
  function attach(parent, child, type) {
143
158
  if (is.str(type)) {
159
+ // If attaching into an array (foo-0), create one
160
+ if (INDEX_REGEX.test(type)) {
161
+ const root = type.replace(INDEX_REGEX, '');
162
+ const {
163
+ target,
164
+ key
165
+ } = resolve(parent, root);
166
+ if (!Array.isArray(target[key])) target[key] = [];
167
+ }
168
+
144
169
  const {
145
170
  target,
146
171
  key
147
172
  } = resolve(parent, type);
148
- parent.__r3f.previousAttach = target[key];
173
+ child.__r3f.previousAttach = target[key];
149
174
  target[key] = child;
150
- } else if (is.arr(type)) {
151
- const [attach] = type;
152
- if (is.str(attach)) parent[attach](child);else if (is.fun(attach)) attach(parent, child);
153
- }
175
+ } else child.__r3f.previousAttach = type(parent, child);
154
176
  }
155
177
  function detach(parent, child, type) {
178
+ var _child$__r3f, _child$__r3f2;
179
+
156
180
  if (is.str(type)) {
157
181
  const {
158
182
  target,
159
183
  key
160
184
  } = resolve(parent, type);
161
- target[key] = parent.__r3f.previousAttach;
162
- } else if (is.arr(type)) {
163
- const [, detach] = type;
164
- if (is.str(detach)) parent[detach](child);else if (is.fun(detach)) detach(parent, child);
165
- }
185
+ target[key] = child.__r3f.previousAttach;
186
+ } else (_child$__r3f = child.__r3f) == null ? void 0 : _child$__r3f.previousAttach == null ? void 0 : _child$__r3f.previousAttach(parent, child);
187
+
188
+ (_child$__r3f2 = child.__r3f) == null ? true : delete _child$__r3f2.previousAttach;
166
189
  } // This function prepares a set of changes to be applied to the instance
167
190
 
168
191
  function diffProps(instance, {
@@ -250,11 +273,11 @@ function applyProps$1(instance, data) {
250
273
  if (value === DEFAULT + 'remove') {
251
274
  if (targetProp && targetProp.constructor) {
252
275
  // use the prop constructor to find the default it should be
253
- value = new targetProp.constructor(memoized.args);
276
+ value = new targetProp.constructor(...memoized.args);
254
277
  } else if (currentInstance.constructor) {
255
278
  // create a blank slate of the instance and copy the particular parameter.
256
279
  // @ts-ignore
257
- const defaultClassCall = new currentInstance.constructor(currentInstance.__r3f.memoizedProps.args);
280
+ const defaultClassCall = new currentInstance.constructor(...currentInstance.__r3f.memoizedProps.args);
258
281
  value = defaultClassCall[targetProp]; // destory the instance
259
282
 
260
283
  if (defaultClassCall.dispose) defaultClassCall.dispose(); // instance does not have constructor, just set it to 0
@@ -282,20 +305,10 @@ function applyProps$1(instance, data) {
282
305
 
283
306
  if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
284
307
  else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers) targetProp.mask = value.mask; // Otherwise just set ...
285
- else targetProp.set(value); // Auto-convert sRGB colors, for now ...
286
- // https://github.com/pmndrs/react-three-fiber/issues/344
287
-
288
- if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
308
+ else targetProp.set(value);
289
309
  } // Else, just overwrite the value
290
310
 
291
- } else {
292
- currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
293
- // https://github.com/pmndrs/react-three-fiber/issues/344
294
-
295
- if (!rootState.linear && currentInstance[key] instanceof THREE.Texture) {
296
- currentInstance[key].encoding = THREE.sRGBEncoding;
297
- }
298
- }
311
+ } else currentInstance[key] = value;
299
312
 
300
313
  invalidateInstance(instance);
301
314
  return instance;
@@ -374,6 +387,7 @@ function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
374
387
 
375
388
  function removeInteractivity(store, object) {
376
389
  const {
390
+ events,
377
391
  internal
378
392
  } = store.getState(); // Removes every trace of an object from the data store
379
393
 
@@ -381,6 +395,7 @@ function removeInteractivity(store, object) {
381
395
  internal.initialHits = internal.initialHits.filter(o => o !== object);
382
396
  internal.hovered.forEach((value, key) => {
383
397
  if (value.eventObject === object || value.object === object) {
398
+ // Clear out intersects, they are outdated by now
384
399
  internal.hovered.delete(key);
385
400
  }
386
401
  });
@@ -390,31 +405,8 @@ function removeInteractivity(store, object) {
390
405
  }
391
406
  function createEvents(store) {
392
407
  const temp = new THREE.Vector3();
393
- /** Sets up defaultRaycaster */
394
-
395
- function prepareRay(event) {
396
- var _customOffsets$offset, _customOffsets$offset2, _customOffsets$width, _customOffsets$height;
397
-
398
- const state = store.getState();
399
- const {
400
- raycaster,
401
- mouse,
402
- camera,
403
- size
404
- } = state; // https://github.com/pmndrs/react-three-fiber/pull/782
405
- // Events trigger outside of canvas when moved
406
-
407
- const customOffsets = raycaster.computeOffsets == null ? void 0 : raycaster.computeOffsets(event, state);
408
- const offsetX = (_customOffsets$offset = customOffsets == null ? void 0 : customOffsets.offsetX) != null ? _customOffsets$offset : event.offsetX;
409
- const offsetY = (_customOffsets$offset2 = customOffsets == null ? void 0 : customOffsets.offsetY) != null ? _customOffsets$offset2 : event.offsetY;
410
- const width = (_customOffsets$width = customOffsets == null ? void 0 : customOffsets.width) != null ? _customOffsets$width : size.width;
411
- const height = (_customOffsets$height = customOffsets == null ? void 0 : customOffsets.height) != null ? _customOffsets$height : size.height;
412
- mouse.set(offsetX / width * 2 - 1, -(offsetY / height) * 2 + 1);
413
- raycaster.setFromCamera(mouse, camera);
414
- }
415
408
  /** Calculates delta */
416
409
 
417
-
418
410
  function calculateDistance(event) {
419
411
  const {
420
412
  internal
@@ -434,55 +426,70 @@ function createEvents(store) {
434
426
  }));
435
427
  }
436
428
 
437
- function intersect(filter) {
429
+ function intersect(event, filter) {
438
430
  const state = store.getState();
439
- const {
440
- raycaster,
441
- internal
442
- } = state; // Skip event handling when noEvents is set
443
-
444
- if (!raycaster.enabled) return [];
445
- const seen = new Set();
431
+ const duplicates = new Set();
446
432
  const intersections = []; // Allow callers to eliminate event objects
447
433
 
448
- const eventsObjects = filter ? filter(internal.interaction) : internal.interaction; // Intersect known handler objects and filter against duplicates
434
+ const eventsObjects = filter ? filter(state.internal.interaction) : state.internal.interaction; // Reset all raycaster cameras to undefined
435
+
436
+ eventsObjects.forEach(obj => {
437
+ const state = getRootState(obj);
438
+
439
+ if (state) {
440
+ state.raycaster.camera = undefined;
441
+ }
442
+ }); // Collect events
443
+
444
+ let hits = eventsObjects // Intersect objects
445
+ .flatMap(obj => {
446
+ const state = getRootState(obj); // Skip event handling when noEvents is set, or when the raycasters camera is null
447
+
448
+ if (!state || !state.events.enabled || state.raycaster.camera === null) return []; // When the camera is undefined we have to call the event layers update function
449
449
 
450
- let intersects = raycaster.intersectObjects(eventsObjects, true).filter(item => {
450
+ if (state.raycaster.camera === undefined) {
451
+ var _state$previousRoot;
452
+
453
+ 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
454
+
455
+ if (state.raycaster.camera === undefined) state.raycaster.camera = null;
456
+ } // Intersect object by object
457
+
458
+
459
+ return state.raycaster.camera ? state.raycaster.intersectObject(obj, true) : [];
460
+ }) // Sort by event priority and distance
461
+ .sort((a, b) => {
462
+ const aState = getRootState(a.object);
463
+ const bState = getRootState(b.object);
464
+ if (!aState || !bState) return 0;
465
+ return bState.events.priority - aState.events.priority || a.distance - b.distance;
466
+ }) // Filter out duplicates
467
+ .filter(item => {
451
468
  const id = makeId(item);
452
- if (seen.has(id)) return false;
453
- seen.add(id);
469
+ if (duplicates.has(id)) return false;
470
+ duplicates.add(id);
454
471
  return true;
455
472
  }); // https://github.com/mrdoob/three.js/issues/16031
456
- // Allow custom userland intersect sort order
473
+ // Allow custom userland intersect sort order, this likely only makes sense on the root filter
457
474
 
458
- if (raycaster.filter) intersects = raycaster.filter(intersects, state);
475
+ if (state.events.filter) hits = state.events.filter(hits, state); // Bubble up the events, find the event source (eventObject)
459
476
 
460
- for (const intersect of intersects) {
461
- let eventObject = intersect.object; // Bubble event up
477
+ for (const hit of hits) {
478
+ let eventObject = hit.object; // Bubble event up
462
479
 
463
480
  while (eventObject) {
464
481
  var _r3f2;
465
482
 
466
- if ((_r3f2 = eventObject.__r3f) != null && _r3f2.eventCount) intersections.push({ ...intersect,
483
+ if ((_r3f2 = eventObject.__r3f) != null && _r3f2.eventCount) intersections.push({ ...hit,
467
484
  eventObject
468
485
  });
469
486
  eventObject = eventObject.parent;
470
487
  }
471
- }
472
-
473
- return intersections;
474
- }
475
- /** Creates filtered intersects and returns an array of positive hits */
476
-
488
+ } // If the interaction is captured, make all capturing targets part of the intersect.
477
489
 
478
- function patchIntersects(intersections, event) {
479
- const {
480
- internal
481
- } = store.getState(); // If the interaction is captured, make all capturing targets part of the
482
- // intersect.
483
490
 
484
- if ('pointerId' in event && internal.capturedMap.has(event.pointerId)) {
485
- for (let captureData of internal.capturedMap.get(event.pointerId).values()) {
491
+ if ('pointerId' in event && state.internal.capturedMap.has(event.pointerId)) {
492
+ for (let captureData of state.internal.capturedMap.get(event.pointerId).values()) {
486
493
  intersections.push(captureData.intersection);
487
494
  }
488
495
  }
@@ -495,13 +502,13 @@ function createEvents(store) {
495
502
  function handleIntersects(intersections, event, delta, callback) {
496
503
  const {
497
504
  raycaster,
498
- mouse,
505
+ pointer,
499
506
  camera,
500
507
  internal
501
508
  } = store.getState(); // If anything has been found, forward it to the event listeners
502
509
 
503
510
  if (intersections.length) {
504
- const unprojectedPoint = temp.set(mouse.x, mouse.y, 0).unproject(camera);
511
+ const unprojectedPoint = temp.set(pointer.x, pointer.y, 0).unproject(camera);
505
512
  const localState = {
506
513
  stopped: false
507
514
  };
@@ -552,8 +559,7 @@ function createEvents(store) {
552
559
 
553
560
  let raycastEvent = { ...hit,
554
561
  ...extractEventProps,
555
- spaceX: mouse.x,
556
- spaceY: mouse.y,
562
+ pointer,
557
563
  intersections,
558
564
  stopped: localState.stopped,
559
565
  delta,
@@ -590,8 +596,6 @@ function createEvents(store) {
590
596
  setPointerCapture,
591
597
  releasePointerCapture
592
598
  },
593
- sourceEvent: event,
594
- // deprecated
595
599
  nativeEvent: event
596
600
  }; // Call subscribers
597
601
 
@@ -656,14 +660,15 @@ function createEvents(store) {
656
660
  const {
657
661
  onPointerMissed,
658
662
  internal
659
- } = store.getState();
660
- prepareRay(event);
663
+ } = store.getState(); //prepareRay(event)
664
+
661
665
  internal.lastEvent.current = event; // Get fresh intersects
662
666
 
663
667
  const isPointerMove = name === 'onPointerMove';
664
668
  const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
665
- const filter = isPointerMove ? filterPointerEvents : undefined;
666
- const hits = patchIntersects(intersect(filter), event);
669
+ const filter = isPointerMove ? filterPointerEvents : undefined; //const hits = patchIntersects(intersect(filter), event)
670
+
671
+ const hits = intersect(event, filter);
667
672
  const delta = isClickEvent ? calculateDistance(event) : 0; // Save initial coordinates on pointer-down
668
673
 
669
674
  if (name === 'onPointerDown') {
@@ -746,23 +751,6 @@ function createEvents(store) {
746
751
  };
747
752
  }
748
753
 
749
- // Type guard to tell a store from a portal
750
- const isStore = def => def && !!def.getState;
751
-
752
- const getContainer = (container, child) => {
753
- var _container$__r3f$root, _container$__r3f;
754
-
755
- return {
756
- // If the container is not a root-store then it must be a THREE.Object3D into which part of the
757
- // scene is portalled into. Now there can be two variants of this, either that object is part of
758
- // the regular jsx tree, in which case it already has __r3f with a valid root attached, or it lies
759
- // outside react, in which case we must take the root of the child that is about to be attached to it.
760
- root: isStore(container) ? container : (_container$__r3f$root = (_container$__r3f = container.__r3f) == null ? void 0 : _container$__r3f.root) != null ? _container$__r3f$root : child.__r3f.root,
761
- // The container is the eventual target into which objects are mounted, it has to be a THREE.Object3D
762
- container: isStore(container) ? container.getState().scene : container
763
- };
764
- };
765
-
766
754
  let catalogue = {};
767
755
 
768
756
  let extend = objects => void (catalogue = { ...catalogue,
@@ -774,22 +762,9 @@ function createRenderer(roots, getEventPriority) {
774
762
  args = [],
775
763
  attach,
776
764
  ...props
777
- }, root, hostContext, internalInstanceHandle) {
765
+ }, root) {
778
766
  let name = `${type[0].toUpperCase()}${type.slice(1)}`;
779
- let instance; // https://github.com/facebook/react/issues/17147
780
- // Portals do not give us a root, they are themselves treated as a root by the reconciler
781
- // In order to figure out the actual root we have to climb through fiber internals :(
782
-
783
- if (!isStore(root) && internalInstanceHandle) {
784
- const fn = node => {
785
- if (!node.return) return node.stateNode && node.stateNode.containerInfo;else return fn(node.return);
786
- };
787
-
788
- root = fn(internalInstanceHandle);
789
- } // Assert that by now we have a valid root
790
-
791
-
792
- if (!root || !isStore(root)) throw `No valid root for ${name}!`; // Auto-attach geometries and materials
767
+ let instance; // Auto-attach geometries and materials
793
768
 
794
769
  if (attach === undefined) {
795
770
  if (name.endsWith('Geometry')) attach = 'geometry';else if (name.endsWith('Material')) attach = 'material';
@@ -799,6 +774,7 @@ function createRenderer(roots, getEventPriority) {
799
774
  if (props.object === undefined) throw `Primitives without 'object' are invalid!`;
800
775
  const object = props.object;
801
776
  instance = prepare(object, {
777
+ type,
802
778
  root,
803
779
  attach,
804
780
  primitive: true
@@ -815,19 +791,21 @@ function createRenderer(roots, getEventPriority) {
815
791
  // Append memoized props with args so it's not forgotten
816
792
 
817
793
  instance = prepare(new target(...args), {
794
+ type,
818
795
  root,
819
796
  attach,
820
797
  // TODO: Figure out what this is for
821
798
  memoizedProps: {
822
- args: args.length === 0 ? null : args
799
+ args
823
800
  }
824
801
  });
825
802
  } // It should NOT call onUpdate on object instanciation, because it hasn't been added to the
826
803
  // view yet. If the callback relies on references for instance, they won't be ready yet, this is
827
804
  // why it passes "true" here
805
+ // There is no reason to apply props to injects
828
806
 
829
807
 
830
- applyProps$1(instance, props);
808
+ if (name !== 'inject') applyProps$1(instance, props);
831
809
  return instance;
832
810
  }
833
811
 
@@ -949,11 +927,11 @@ function createRenderer(roots, getEventPriority) {
949
927
  }
950
928
 
951
929
  function switchInstance(instance, type, newProps, fiber) {
952
- var _instance$__r3f;
930
+ var _instance$__r3f, _instance$__r3f2;
953
931
 
954
932
  const parent = (_instance$__r3f = instance.__r3f) == null ? void 0 : _instance$__r3f.parent;
955
933
  if (!parent) return;
956
- const newInstance = createInstance(type, newProps, instance.__r3f.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
934
+ const newInstance = createInstance(type, newProps, (_instance$__r3f2 = instance.__r3f) == null ? void 0 : _instance$__r3f2.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
957
935
  // When args change the instance has to be re-constructed, which then
958
936
  // forces r3f to re-parent the children and non-scene objects
959
937
  // This can not include primitives, which should not have declarative children
@@ -986,19 +964,38 @@ function createRenderer(roots, getEventPriority) {
986
964
  }
987
965
 
988
966
  const reconciler = Reconciler({
989
- appendChildToContainer: (parentInstance, child) => {
990
- const {
991
- container,
992
- root
993
- } = getContainer(parentInstance, child); // Link current root to the default scene
967
+ createInstance,
968
+ removeChild,
969
+ appendChild,
970
+ appendInitialChild: appendChild,
971
+ insertBefore,
972
+ supportsMicrotask: true,
973
+ warnsIfNotActing: true,
974
+ supportsMutation: true,
975
+ isPrimaryRenderer: false,
976
+ noTimeout: -1,
977
+ appendChildToContainer: (container, child) => {
978
+ const scene = container.getState().scene; // Link current root to the default scene
994
979
 
995
- container.__r3f.root = root;
996
- appendChild(container, child);
980
+ scene.__r3f.root = container;
981
+ appendChild(scene, child);
982
+ },
983
+ removeChildFromContainer: (container, child) => removeChild(container.getState().scene, child),
984
+ insertInContainerBefore: (container, child, beforeChild) => insertBefore(container.getState().scene, child, beforeChild),
985
+ getRootHostContext: () => null,
986
+ getChildHostContext: parentHostContext => parentHostContext,
987
+
988
+ finalizeInitialChildren(instance) {
989
+ var _instance$__r3f3;
990
+
991
+ const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {}; // https://github.com/facebook/react/issues/20271
992
+ // Returning true will trigger commitMount
993
+
994
+ return !!localState.handlers;
997
995
  },
998
- removeChildFromContainer: (parentInstance, child) => removeChild(getContainer(parentInstance, child).container, child),
999
- insertInContainerBefore: (parentInstance, child, beforeChild) => insertBefore(getContainer(parentInstance, child).container, child, beforeChild),
1000
996
 
1001
997
  prepareUpdate(instance, type, oldProps, newProps) {
998
+ // Create diff-sets
1002
999
  if (instance.__r3f.primitive && newProps.object && newProps.object !== instance) {
1003
1000
  return [true];
1004
1001
  } else {
@@ -1031,40 +1028,58 @@ function createRenderer(roots, getEventPriority) {
1031
1028
  else applyProps$1(instance, diff);
1032
1029
  },
1033
1030
 
1031
+ commitMount(instance, type, props, int) {
1032
+ var _instance$__r3f4;
1033
+
1034
+ // https://github.com/facebook/react/issues/20271
1035
+ // This will make sure events are only added once to the central container
1036
+ const localState = (_instance$__r3f4 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f4 : {};
1037
+
1038
+ if (instance.raycast && localState.handlers && localState.eventCount) {
1039
+ instance.__r3f.root.getState().internal.interaction.push(instance);
1040
+ }
1041
+ },
1042
+
1043
+ getPublicInstance: instance => instance,
1044
+ shouldDeprioritizeSubtree: () => false,
1045
+ prepareForCommit: () => null,
1046
+ preparePortalMount: container => prepare(container.getState().scene),
1047
+ resetAfterCommit: () => {},
1048
+ shouldSetTextContent: () => false,
1049
+ clearContainer: () => false,
1050
+ detachDeletedInstance: () => {},
1051
+ createTextInstance: () => {},
1052
+
1034
1053
  hideInstance(instance) {
1035
- var _instance$__r3f2;
1054
+ var _instance$__r3f5;
1036
1055
 
1037
1056
  // Deatch while the instance is hidden
1038
1057
  const {
1039
1058
  attach: type,
1040
1059
  parent
1041
- } = (_instance$__r3f2 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f2 : {};
1060
+ } = (_instance$__r3f5 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f5 : {};
1042
1061
  if (type && parent) detach(parent, instance, type);
1043
1062
  if (instance.isObject3D) instance.visible = false;
1044
1063
  invalidateInstance(instance);
1045
1064
  },
1046
1065
 
1047
1066
  unhideInstance(instance, props) {
1048
- var _instance$__r3f3;
1067
+ var _instance$__r3f6;
1049
1068
 
1050
1069
  // Re-attach when the instance is unhidden
1051
1070
  const {
1052
1071
  attach: type,
1053
1072
  parent
1054
- } = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
1073
+ } = (_instance$__r3f6 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f6 : {};
1055
1074
  if (type && parent) attach(parent, instance, type);
1056
1075
  if (instance.isObject3D && props.visible == null || props.visible) instance.visible = true;
1057
1076
  invalidateInstance(instance);
1058
1077
  },
1059
1078
 
1060
- createInstance,
1061
- removeChild,
1062
- appendChild,
1063
- appendInitialChild: appendChild,
1064
- insertBefore,
1065
- warnsIfNotActing: true,
1066
- supportsMutation: true,
1067
- isPrimaryRenderer: false,
1079
+ hideTextInstance: () => {
1080
+ throw new Error('Text is not allowed in the R3F tree.');
1081
+ },
1082
+ // prettier-ignore
1068
1083
  getCurrentEventPriority: () => getEventPriority ? getEventPriority() : DefaultEventPriority,
1069
1084
  // @ts-ignore
1070
1085
  now: typeof performance !== 'undefined' && is.fun(performance.now) ? performance.now : is.fun(Date.now) ? Date.now : undefined,
@@ -1073,47 +1088,7 @@ function createRenderer(roots, getEventPriority) {
1073
1088
  // @ts-ignore
1074
1089
  cancelTimeout: is.fun(clearTimeout) ? clearTimeout : undefined,
1075
1090
  setTimeout: is.fun(setTimeout) ? setTimeout : undefined,
1076
- clearTimeout: is.fun(clearTimeout) ? clearTimeout : undefined,
1077
- noTimeout: -1,
1078
- hideTextInstance: () => {
1079
- throw new Error('Text is not allowed in the R3F tree.');
1080
- },
1081
- // prettier-ignore
1082
- getPublicInstance: instance => instance,
1083
- getRootHostContext: () => null,
1084
- getChildHostContext: parentHostContext => parentHostContext,
1085
- createTextInstance: () => {},
1086
-
1087
- finalizeInitialChildren(instance) {
1088
- var _instance$__r3f4;
1089
-
1090
- // https://github.com/facebook/react/issues/20271
1091
- // Returning true will trigger commitMount
1092
- const localState = (_instance$__r3f4 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f4 : {};
1093
- return !!localState.handlers;
1094
- },
1095
-
1096
- commitMount(instance)
1097
- /*, type, props*/
1098
- {
1099
- var _instance$__r3f5;
1100
-
1101
- // https://github.com/facebook/react/issues/20271
1102
- // This will make sure events are only added once to the central container
1103
- const localState = (_instance$__r3f5 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f5 : {};
1104
-
1105
- if (instance.raycast && localState.handlers && localState.eventCount) {
1106
- instance.__r3f.root.getState().internal.interaction.push(instance);
1107
- }
1108
- },
1109
-
1110
- shouldDeprioritizeSubtree: () => false,
1111
- prepareForCommit: () => null,
1112
- preparePortalMount: containerInfo => prepare(containerInfo),
1113
- resetAfterCommit: () => {},
1114
- shouldSetTextContent: () => false,
1115
- clearContainer: () => false,
1116
- detachDeletedInstance: () => {}
1091
+ clearTimeout: is.fun(clearTimeout) ? clearTimeout : undefined
1117
1092
  });
1118
1093
  return {
1119
1094
  reconciler,
@@ -1173,16 +1148,18 @@ const createStore = (invalidate, advance) => {
1173
1148
  }));
1174
1149
 
1175
1150
  return {
1151
+ set,
1152
+ get,
1176
1153
  // Mock objects that have to be configured
1177
1154
  gl: null,
1178
1155
  camera: null,
1179
1156
  raycaster: null,
1180
1157
  events: {
1158
+ priority: 1,
1159
+ enabled: true,
1181
1160
  connected: false
1182
1161
  },
1183
1162
  xr: null,
1184
- set,
1185
- get,
1186
1163
  invalidate: () => invalidate(get()),
1187
1164
  advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
1188
1165
  linear: false,
@@ -1190,7 +1167,7 @@ const createStore = (invalidate, advance) => {
1190
1167
  scene: prepare(new THREE.Scene()),
1191
1168
  controls: null,
1192
1169
  clock: new THREE.Clock(),
1193
- mouse: new THREE.Vector2(),
1170
+ pointer: new THREE.Vector2(),
1194
1171
  frameloop: 'always',
1195
1172
  onPointerMissed: undefined,
1196
1173
  performance: {
@@ -1259,6 +1236,7 @@ const createStore = (invalidate, advance) => {
1259
1236
  frameloop
1260
1237
  }));
1261
1238
  },
1239
+ previousRoot: undefined,
1262
1240
  internal: {
1263
1241
  active: false,
1264
1242
  priority: 0,
@@ -1486,6 +1464,11 @@ function loadingFn(extensions, onProgress) {
1486
1464
  };
1487
1465
  }
1488
1466
 
1467
+ function useMemoizedFn(fn) {
1468
+ const fnRef = React.useRef(fn);
1469
+ React.useLayoutEffect(() => void (fnRef.current = fn), [fn]);
1470
+ return (...args) => fnRef.current == null ? void 0 : fnRef.current(...args);
1471
+ }
1489
1472
  function useLoader(Proto, input, extensions, onProgress) {
1490
1473
  // Use suspense to load async assets
1491
1474
  const keys = Array.isArray(input) ? input : [input];
@@ -1585,9 +1568,7 @@ function createRoot(canvas) {
1585
1568
  params,
1586
1569
  ...options
1587
1570
  } = raycastOptions || {};
1588
- if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, {
1589
- enabled: true,
1590
- ...options
1571
+ if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, { ...options
1591
1572
  });
1592
1573
  if (!is.equ(params, raycaster.params, shallowLoose)) applyProps(raycaster, {
1593
1574
  params: { ...raycaster.params,
@@ -1623,7 +1604,7 @@ function createRoot(canvas) {
1623
1604
 
1624
1605
  const handleSessionChange = () => {
1625
1606
  const gl = store.getState().gl;
1626
- gl.xr.enabled = gl.xr.isPresenting; // @ts-expect-error
1607
+ gl.xr.enabled = gl.xr.isPresenting; // @ts-ignore
1627
1608
  // WebXRManager's signature is incorrect.
1628
1609
  // See: https://github.com/pmndrs/react-three-fiber/pull/2017#discussion_r790134505
1629
1610
 
@@ -1665,6 +1646,7 @@ function createRoot(canvas) {
1665
1646
  } // Set color management
1666
1647
 
1667
1648
 
1649
+ if (THREE.ColorManagement) THREE.ColorManagement.legacyMode = false;
1668
1650
  const outputEncoding = linear ? THREE.LinearEncoding : THREE.sRGBEncoding;
1669
1651
  const toneMapping = flat ? THREE.NoToneMapping : THREE.ACESFilmicToneMapping;
1670
1652
  if (gl.outputEncoding !== outputEncoding) gl.outputEncoding = outputEncoding;
@@ -1740,9 +1722,10 @@ function Provider({
1740
1722
  internal: { ...state.internal,
1741
1723
  active: true
1742
1724
  }
1743
- })); // Connect events
1725
+ })); // Connect events to the targets parent, this is done to ensure events are registered on
1726
+ // a shared target, and not on the canvas itself
1744
1727
 
1745
- state.events.connect == null ? void 0 : state.events.connect(target); // Notifiy that init is completed, the scene graph exists, but nothing has yet rendered
1728
+ 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
1746
1729
 
1747
1730
  if (onCreated) onCreated(state); // eslint-disable-next-line react-hooks/exhaustive-deps
1748
1731
  }, []);
@@ -1780,10 +1763,65 @@ function unmountComponentAtNode(canvas, callback) {
1780
1763
  }
1781
1764
  }
1782
1765
 
1783
- const act = React.unstable_act;
1766
+ function createPortal(children, container, state) {
1767
+ return /*#__PURE__*/React.createElement(Portal, {
1768
+ children: children,
1769
+ container: container,
1770
+ state: state
1771
+ });
1772
+ }
1773
+
1774
+ function Portal({
1775
+ state = {},
1776
+ children,
1777
+ container
1778
+ }) {
1779
+ /** This has to be a component because it would not be able to call useThree/useStore otherwise since
1780
+ * if this is our environment, then we are not in r3f's renderer but in react-dom, it would trigger
1781
+ * the "R3F hooks can only be used within the Canvas component!" warning:
1782
+ * <Canvas>
1783
+ * {createPortal(...)} */
1784
+ const {
1785
+ events,
1786
+ ...rest
1787
+ } = state;
1788
+ const previousRoot = useStore();
1789
+ const [raycaster] = React.useState(() => new THREE.Raycaster());
1790
+ const inject = React.useCallback((state, injectState) => {
1791
+ const intersect = { ...state
1792
+ };
1784
1793
 
1785
- function createPortal(children, container) {
1786
- return reconciler.createPortal(children, container, null, null);
1794
+ if (injectState) {
1795
+ // Only the fields of "state" that do not differ from injectState
1796
+ Object.keys(state).forEach(key => {
1797
+ if (state[key] !== injectState[key]) delete intersect[key];
1798
+ });
1799
+ }
1800
+
1801
+ return { ...intersect,
1802
+ scene: container,
1803
+ previousRoot,
1804
+ raycaster,
1805
+ events: { ...state.events,
1806
+ ...events
1807
+ },
1808
+ ...rest
1809
+ };
1810
+ }, [state]);
1811
+ const [useInjectStore] = React.useState(() => {
1812
+ const store = create((set, get) => ({ ...inject(previousRoot.getState()),
1813
+ set,
1814
+ get
1815
+ }));
1816
+ previousRoot.subscribe(state => useInjectStore.setState(injectState => inject(state, injectState)));
1817
+ return store;
1818
+ });
1819
+ React.useEffect(() => {
1820
+ useInjectStore.setState(injectState => inject(previousRoot.getState(), injectState));
1821
+ }, [inject]);
1822
+ return /*#__PURE__*/React.createElement(React.Fragment, null, reconciler.createPortal( /*#__PURE__*/React.createElement(context.Provider, {
1823
+ value: useInjectStore
1824
+ }, children), useInjectStore, null));
1787
1825
  }
1788
1826
 
1789
1827
  reconciler.injectIntoDevTools({
@@ -1791,5 +1829,6 @@ reconciler.injectIntoDevTools({
1791
1829
  rendererPackageName: '@react-three/fiber',
1792
1830
  version: '18.0.0'
1793
1831
  });
1832
+ const act = React.unstable_act;
1794
1833
 
1795
- export { createRoot as a, context as b, createEvents as c, createPortal as d, extend as e, reconciler as f, applyProps as g, dispose as h, invalidate as i, advance as j, addEffect as k, addAfterEffect as l, addTail as m, act as n, omit as o, pick as p, roots as q, render as r, useStore as s, threeTypes as t, unmountComponentAtNode as u, useThree as v, useFrame as w, useGraph as x, useLoader as y };
1834
+ export { useLoader as A, createRoot as a, unmountComponentAtNode as b, createEvents as c, context as d, extend as e, createPortal as f, reconciler as g, applyProps as h, dispose as i, invalidate as j, advance as k, addEffect as l, addAfterEffect as m, addTail as n, omit as o, pick as p, getRootState as q, render as r, act as s, threeTypes as t, useMemoizedFn as u, roots as v, useStore as w, useThree as x, useFrame as y, useGraph as z };