@react-three/fiber 8.0.17 → 8.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @react-three/fiber
2
2
 
3
+ ## 8.0.20
4
+
5
+ ### Patch Changes
6
+
7
+ - 4c87bce: fix: attach, devtools, and perf fixes
8
+
9
+ ## 8.0.19
10
+
11
+ ### Patch Changes
12
+
13
+ - 360b45a: fix: handle attach on reconstruct
14
+
15
+ ## 8.0.18
16
+
17
+ ### Patch Changes
18
+
19
+ - be567c1: fix: suspense attach and three compat in webpack
20
+
3
21
  ## 8.0.17
4
22
 
5
23
  ### Patch Changes
@@ -12,7 +12,7 @@ export declare type LocalState = {
12
12
  type: string;
13
13
  root: UseBoundStore<RootState>;
14
14
  objects: Instance[];
15
- parent: Instance | null;
15
+ parents: Instance[];
16
16
  primitive?: boolean;
17
17
  eventCount: number;
18
18
  handlers: Partial<EventHandlers>;
@@ -79,3 +79,4 @@ export declare function updateInstance(instance: Instance): void;
79
79
  export declare function updateCamera(camera: Camera & {
80
80
  manual?: boolean;
81
81
  }, size: Size): void;
82
+ export declare function setDeep(obj: any, value: any, keys: string[]): any;
@@ -137,7 +137,7 @@ function dispose(obj) {
137
137
  function prepare(object, state) {
138
138
  const instance = object;
139
139
 
140
- if (state != null && state.primitive || !instance.__r3f) {
140
+ if (!instance.__r3f) {
141
141
  instance.__r3f = {
142
142
  type: '',
143
143
  root: null,
@@ -146,7 +146,7 @@ function prepare(object, state) {
146
146
  eventCount: 0,
147
147
  handlers: {},
148
148
  objects: [],
149
- parent: null,
149
+ parents: [],
150
150
  ...state
151
151
  };
152
152
  }
@@ -260,10 +260,10 @@ function diffProps(instance, {
260
260
  } // This function applies a set of changes to the instance
261
261
 
262
262
  function applyProps$1(instance, data) {
263
- var _instance$__r3f3, _root$getState;
263
+ var _instance$__r3f3, _root$getState, _localState$parents;
264
264
 
265
265
  // Filter equals, events and reserved props
266
- const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
266
+ const localState = (_instance$__r3f3 = instance.__r3f) != null ? _instance$__r3f3 : {};
267
267
  const root = localState.root;
268
268
  const rootState = (_root$getState = root == null ? void 0 : root.getState == null ? void 0 : root.getState()) != null ? _root$getState : {};
269
269
  const {
@@ -335,7 +335,7 @@ function applyProps$1(instance, data) {
335
335
  // Auto-convert sRGB colors
336
336
  // https://github.com/pmndrs/react-three-fiber/issues/344
337
337
 
338
- const supportsColorManagement = THREE.ColorManagement;
338
+ const supportsColorManagement = ('ColorManagement' in THREE);
339
339
  if (!supportsColorManagement && !rootState.linear && isColor) targetProp.convertSRGBToLinear();
340
340
  } // Else, just overwrite the value
341
341
 
@@ -351,7 +351,7 @@ function applyProps$1(instance, data) {
351
351
  invalidateInstance(instance);
352
352
  });
353
353
 
354
- if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
354
+ if ((_localState$parents = localState.parents) != null && _localState$parents.length && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
355
355
  // Pre-emptively remove the instance from the interaction manager
356
356
  const index = rootState.internal.interaction.indexOf(instance);
357
357
  if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
@@ -391,6 +391,15 @@ function updateCamera(camera, size) {
391
391
  camera.updateMatrixWorld();
392
392
  }
393
393
  }
394
+ /**
395
+ * Safely sets a deeply-nested value on an object.
396
+ */
397
+
398
+ function setDeep(obj, value, keys) {
399
+ const key = keys.pop();
400
+ const target = keys.reduce((acc, key) => acc[key], obj);
401
+ return target[key] = value;
402
+ }
394
403
 
395
404
  function makeId(event) {
396
405
  return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
@@ -444,7 +453,6 @@ function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
444
453
 
445
454
  function removeInteractivity(store, object) {
446
455
  const {
447
- events,
448
456
  internal
449
457
  } = store.getState(); // Removes every trace of an object from the data store
450
458
 
@@ -671,14 +679,14 @@ function createEvents(store) {
671
679
  return intersections;
672
680
  }
673
681
 
674
- function cancelPointer(hits) {
682
+ function cancelPointer(intersections) {
675
683
  const {
676
684
  internal
677
685
  } = store.getState();
678
686
  Array.from(internal.hovered.values()).forEach(hoveredObj => {
679
687
  // When no objects were hit or the the hovered object wasn't found underneath the cursor
680
688
  // we call onPointerOut and delete the object from the hovered-elements map
681
- if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
689
+ if (!intersections.length || !intersections.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
682
690
  const eventObject = hoveredObj.eventObject;
683
691
  const instance = eventObject.__r3f;
684
692
  const handlers = instance == null ? void 0 : instance.handlers;
@@ -687,7 +695,7 @@ function createEvents(store) {
687
695
  if (instance != null && instance.eventCount) {
688
696
  // Clear out intersects, they are outdated by now
689
697
  const data = { ...hoveredObj,
690
- intersections: hits || []
698
+ intersections
691
699
  };
692
700
  handlers.onPointerOut == null ? void 0 : handlers.onPointerOut(data);
693
701
  handlers.onPointerLeave == null ? void 0 : handlers.onPointerLeave(data);
@@ -857,7 +865,7 @@ function createRenderer(roots, getEventPriority) {
857
865
  type,
858
866
  root,
859
867
  attach,
860
- // TODO: Figure out what this is for
868
+ // Save args in case we need to reconstruct later for HMR
861
869
  memoizedProps: {
862
870
  args
863
871
  }
@@ -878,10 +886,9 @@ function createRenderer(roots, getEventPriority) {
878
886
  if (child) {
879
887
  var _child$__r3f, _parentInstance$__r3f;
880
888
 
881
- // The attach attribute implies that the object attaches itself on the parent
882
- if ((_child$__r3f = child.__r3f) != null && _child$__r3f.attach) {
883
- attach(parentInstance, child, child.__r3f.attach);
884
- } else if (child.isObject3D && parentInstance.isObject3D) {
889
+ // The attach attribute implies that the object attaches itself on the parent.
890
+ // That is handled at commit to avoid duplication during Suspense
891
+ if (!((_child$__r3f = child.__r3f) != null && _child$__r3f.attach) && child.isObject3D && parentInstance.isObject3D) {
885
892
  // add in the usual parent-child way
886
893
  parentInstance.add(child);
887
894
  added = true;
@@ -891,7 +898,9 @@ function createRenderer(roots, getEventPriority) {
891
898
 
892
899
  if (!added) (_parentInstance$__r3f = parentInstance.__r3f) == null ? void 0 : _parentInstance$__r3f.objects.push(child);
893
900
  if (!child.__r3f) prepare(child, {});
894
- child.__r3f.parent = parentInstance;
901
+
902
+ child.__r3f.parents.push(parentInstance);
903
+
895
904
  updateInstance(child);
896
905
  invalidateInstance(child);
897
906
  }
@@ -903,9 +912,7 @@ function createRenderer(roots, getEventPriority) {
903
912
  if (child) {
904
913
  var _child$__r3f2, _parentInstance$__r3f2;
905
914
 
906
- if ((_child$__r3f2 = child.__r3f) != null && _child$__r3f2.attach) {
907
- attach(parentInstance, child, child.__r3f.attach);
908
- } else if (child.isObject3D && parentInstance.isObject3D) {
915
+ if (!((_child$__r3f2 = child.__r3f) != null && _child$__r3f2.attach) && child.isObject3D && parentInstance.isObject3D) {
909
916
  child.parent = parentInstance;
910
917
  child.dispatchEvent({
911
918
  type: 'added'
@@ -918,7 +925,9 @@ function createRenderer(roots, getEventPriority) {
918
925
 
919
926
  if (!added) (_parentInstance$__r3f2 = parentInstance.__r3f) == null ? void 0 : _parentInstance$__r3f2.objects.push(child);
920
927
  if (!child.__r3f) prepare(child, {});
921
- child.__r3f.parent = parentInstance;
928
+
929
+ child.__r3f.parents.push(parentInstance);
930
+
922
931
  updateInstance(child);
923
932
  invalidateInstance(child);
924
933
  }
@@ -933,7 +942,7 @@ function createRenderer(roots, getEventPriority) {
933
942
  var _parentInstance$__r3f3, _child$__r3f3, _child$__r3f5;
934
943
 
935
944
  // Clear the parent reference
936
- if (child.__r3f) child.__r3f.parent = null; // Remove child from the parents objects
945
+ if (child.__r3f) child.__r3f.parents = child.__r3f.parents.filter(parent => parent !== parentInstance); // Remove child from the parents objects
937
946
 
938
947
  if ((_parentInstance$__r3f3 = parentInstance.__r3f) != null && _parentInstance$__r3f3.objects) parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child); // Remove attachment
939
948
 
@@ -947,7 +956,7 @@ function createRenderer(roots, getEventPriority) {
947
956
  if ((_child$__r3f4 = child.__r3f) != null && _child$__r3f4.root) {
948
957
  removeInteractivity(child.__r3f.root, child);
949
958
  }
950
- } // Allow objects to bail out of recursive dispose alltogether by passing dispose={null}
959
+ } // Allow objects to bail out of recursive dispose altogether by passing dispose={null}
951
960
  // Never dispose of primitives because their state may be kept outside of React!
952
961
  // In order for an object to be able to dispose it has to have
953
962
  // - a dispose method,
@@ -994,11 +1003,11 @@ function createRenderer(roots, getEventPriority) {
994
1003
  }
995
1004
 
996
1005
  function switchInstance(instance, type, newProps, fiber) {
997
- var _instance$__r3f, _instance$__r3f2;
1006
+ var _instance$__r3f, _newInstance$__r3f;
998
1007
 
999
- const parent = (_instance$__r3f = instance.__r3f) == null ? void 0 : _instance$__r3f.parent;
1000
- if (!parent) return;
1001
- const newInstance = createInstance(type, newProps, (_instance$__r3f2 = instance.__r3f) == null ? void 0 : _instance$__r3f2.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
1008
+ const parents = (_instance$__r3f = instance.__r3f) == null ? void 0 : _instance$__r3f.parents;
1009
+ if (!(parents != null && parents.length)) return;
1010
+ const newInstance = createInstance(type, newProps, instance.__r3f.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
1002
1011
  // When args change the instance has to be re-constructed, which then
1003
1012
  // forces r3f to re-parent the children and non-scene objects
1004
1013
  // This can not include primitives, which should not have declarative children
@@ -1011,13 +1020,24 @@ function createRenderer(roots, getEventPriority) {
1011
1020
  instance.__r3f.objects.forEach(child => appendChild(newInstance, child));
1012
1021
 
1013
1022
  instance.__r3f.objects = [];
1014
- removeChild(parent, instance);
1015
- appendChild(parent, newInstance); // Re-bind event handlers
1023
+
1024
+ for (const parent of parents) {
1025
+ removeChild(parent, instance);
1026
+ appendChild(parent, newInstance);
1027
+ } // Re-bind event handlers
1028
+
1016
1029
 
1017
1030
  if (newInstance.raycast && newInstance.__r3f.eventCount) {
1018
1031
  const rootState = newInstance.__r3f.root.getState();
1019
1032
 
1020
1033
  rootState.internal.interaction.push(newInstance);
1034
+ } // The attach attribute implies that the object attaches itself on the parent
1035
+
1036
+
1037
+ if ((_newInstance$__r3f = newInstance.__r3f) != null && _newInstance$__r3f.attach) {
1038
+ for (const parent of parents) {
1039
+ attach(parent, newInstance, newInstance.__r3f.attach);
1040
+ }
1021
1041
  } // This evil hack switches the react-internal fiber node
1022
1042
  [fiber, fiber.alternate].forEach(fiber => {
1023
1043
  if (fiber !== null) {
@@ -1053,12 +1073,12 @@ function createRenderer(roots, getEventPriority) {
1053
1073
  getChildHostContext: parentHostContext => parentHostContext,
1054
1074
 
1055
1075
  finalizeInitialChildren(instance) {
1056
- var _instance$__r3f3;
1076
+ var _instance$__r3f2;
1057
1077
 
1058
- const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {}; // https://github.com/facebook/react/issues/20271
1078
+ const localState = (_instance$__r3f2 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f2 : {}; // https://github.com/facebook/react/issues/20271
1059
1079
  // Returning true will trigger commitMount
1060
1080
 
1061
- return !!localState.handlers;
1081
+ return !!localState.handlers || !!localState.attach;
1062
1082
  },
1063
1083
 
1064
1084
  prepareUpdate(instance, type, oldProps, newProps) {
@@ -1096,14 +1116,21 @@ function createRenderer(roots, getEventPriority) {
1096
1116
  },
1097
1117
 
1098
1118
  commitMount(instance, type, props, int) {
1099
- var _instance$__r3f4;
1119
+ var _instance$__r3f3;
1100
1120
 
1101
1121
  // https://github.com/facebook/react/issues/20271
1102
1122
  // This will make sure events are only added once to the central container
1103
- const localState = (_instance$__r3f4 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f4 : {};
1123
+ const localState = (_instance$__r3f3 = instance.__r3f) != null ? _instance$__r3f3 : {};
1104
1124
 
1105
1125
  if (instance.raycast && localState.handlers && localState.eventCount) {
1106
1126
  instance.__r3f.root.getState().internal.interaction.push(instance);
1127
+ } // The attach attribute implies that the object attaches itself on the parent
1128
+
1129
+
1130
+ if (localState.attach) {
1131
+ for (const parent of localState.parents) {
1132
+ attach(parent, instance, localState.attach);
1133
+ }
1107
1134
  }
1108
1135
  },
1109
1136
 
@@ -1117,27 +1144,11 @@ function createRenderer(roots, getEventPriority) {
1117
1144
  detachDeletedInstance: () => {},
1118
1145
 
1119
1146
  hideInstance(instance) {
1120
- var _instance$__r3f5;
1121
-
1122
- // Deatch while the instance is hidden
1123
- const {
1124
- attach: type,
1125
- parent
1126
- } = (_instance$__r3f5 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f5 : {};
1127
- if (type && parent) detach(parent, instance, type);
1128
1147
  if (instance.isObject3D) instance.visible = false;
1129
1148
  invalidateInstance(instance);
1130
1149
  },
1131
1150
 
1132
1151
  unhideInstance(instance, props) {
1133
- var _instance$__r3f6;
1134
-
1135
- // Re-attach when the instance is unhidden
1136
- const {
1137
- attach: type,
1138
- parent
1139
- } = (_instance$__r3f6 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f6 : {};
1140
- if (type && parent) attach(parent, instance, type);
1141
1152
  if (instance.isObject3D && props.visible == null || props.visible) instance.visible = true;
1142
1153
  invalidateInstance(instance);
1143
1154
  },
@@ -1324,35 +1335,29 @@ const createStore = (invalidate, advance) => {
1324
1335
  initialHits: [],
1325
1336
  capturedMap: new Map(),
1326
1337
  subscribe: (ref, priority, store) => {
1327
- set(({
1328
- internal
1329
- }) => ({
1330
- internal: { ...internal,
1331
- // If this subscription was given a priority, it takes rendering into its own hands
1332
- // For that reason we switch off automatic rendering and increase the manual flag
1333
- // As long as this flag is positive there can be no internal rendering at all
1334
- // because there could be multiple render subscriptions
1335
- priority: internal.priority + (priority > 0 ? 1 : 0),
1336
- // Register subscriber and sort layers from lowest to highest, meaning,
1337
- // highest priority renders last (on top of the other frames)
1338
- subscribers: [...internal.subscribers, {
1339
- ref,
1340
- priority,
1341
- store
1342
- }].sort((a, b) => a.priority - b.priority)
1343
- }
1344
- }));
1338
+ const internal = get().internal; // If this subscription was given a priority, it takes rendering into its own hands
1339
+ // For that reason we switch off automatic rendering and increase the manual flag
1340
+ // As long as this flag is positive there can be no internal rendering at all
1341
+ // because there could be multiple render subscriptions
1342
+
1343
+ internal.priority = internal.priority + (priority > 0 ? 1 : 0);
1344
+ internal.subscribers.push({
1345
+ ref,
1346
+ priority,
1347
+ store
1348
+ }); // Register subscriber and sort layers from lowest to highest, meaning,
1349
+ // highest priority renders last (on top of the other frames)
1350
+
1351
+ internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
1345
1352
  return () => {
1346
- set(({
1347
- internal
1348
- }) => ({
1349
- internal: { ...internal,
1350
- // Decrease manual flag if this subscription had a priority
1351
- priority: internal.priority - (priority > 0 ? 1 : 0),
1352
- // Remove subscriber from list
1353
- subscribers: internal.subscribers.filter(s => s.ref !== ref)
1354
- }
1355
- }));
1353
+ const internal = get().internal;
1354
+
1355
+ if (internal != null && internal.subscribers) {
1356
+ // Decrease manual flag if this subscription had a priority
1357
+ internal.priority = internal.priority - (priority > 0 ? 1 : 0); // Remove subscriber from list
1358
+
1359
+ internal.subscribers = internal.subscribers.filter(s => s.ref !== ref);
1360
+ }
1356
1361
  };
1357
1362
  }
1358
1363
  }
@@ -1761,11 +1766,12 @@ function createRoot(canvas) {
1761
1766
  if (!isBoolean) Object.assign(gl.shadowMap, shadows);else gl.shadowMap.type = THREE.PCFSoftShadowMap;
1762
1767
  if (old !== gl.shadowMap.enabled) gl.shadowMap.needsUpdate = true;
1763
1768
  }
1764
- } // Set color management
1769
+ } // Safely set color management if available.
1770
+ // Avoid accessing THREE.ColorManagement to play nice with older versions
1765
1771
 
1766
1772
 
1767
- if (THREE.ColorManagement) {
1768
- THREE.ColorManagement.legacyMode = legacy;
1773
+ if ('ColorManagement' in THREE) {
1774
+ setDeep(THREE, legacy, ['ColorManagement', 'legacyMode']);
1769
1775
  }
1770
1776
 
1771
1777
  const outputEncoding = linear ? THREE.LinearEncoding : THREE.sRGBEncoding;
@@ -2015,7 +2021,7 @@ function Portal({
2015
2021
  reconciler.injectIntoDevTools({
2016
2022
  bundleType: process.env.NODE_ENV === 'production' ? 0 : 1,
2017
2023
  rendererPackageName: '@react-three/fiber',
2018
- version: '18.0.0'
2024
+ version: React.version
2019
2025
  });
2020
2026
  const act = React.unstable_act;
2021
2027