@react-three/fiber 8.0.0-beta.4 → 8.0.0-beta.5

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
 
@@ -95,7 +95,7 @@ const is = {
95
95
  const isArr = is.arr(a);
96
96
  if (isArr && arrays === 'reference') return a === b; // Array or Object, shallow compare first to see if it's a match
97
97
 
98
- if ((isArr || isObj) && a == b) return true; // Last resort, go through keys
98
+ if ((isArr || isObj) && a === b) return true; // Last resort, go through keys
99
99
 
100
100
  let i;
101
101
 
@@ -103,7 +103,13 @@ const is = {
103
103
 
104
104
  for (i in strict ? b : a) if (a[i] !== b[i]) return false;
105
105
 
106
- return is.und(i) ? a === b : true;
106
+ if (is.und(i)) {
107
+ if (isArr && a.length === 0 && b.length === 0) return true;
108
+ if (isObj && Object.keys(a).length === 0 && Object.keys(b).length === 0) return true;
109
+ if (a !== b) return false;
110
+ }
111
+
112
+ return true;
107
113
  }
108
114
 
109
115
  }; // Collects nodes and materials from a THREE.Object3D
@@ -139,30 +145,8 @@ function prepare(object, state) {
139
145
  if (state != null && state.primitive || !instance.__r3f) {
140
146
  instance.__r3f = {
141
147
  type: '',
142
- context: {
143
- current: null
144
- },
145
- getContext: () => {
146
- const injects = [];
147
- let inject = instance.__r3f.context.current;
148
-
149
- while (inject) {
150
- var _inject$memoizedProps, _inject, _inject$context;
151
-
152
- const {
153
- children,
154
- args,
155
- ...props
156
- } = (_inject$memoizedProps = (_inject = inject) == null ? void 0 : _inject.memoizedProps) != null ? _inject$memoizedProps : {};
157
- injects.push(props);
158
- inject = (_inject$context = inject.context) == null ? void 0 : _inject$context.current;
159
- }
160
-
161
- return injects.reverse().reduce((prev, cur) => ({ ...prev,
162
- ...cur
163
- }), {});
164
- },
165
148
  root: null,
149
+ previousAttach: null,
166
150
  memoizedProps: {},
167
151
  eventCount: 0,
168
152
  handlers: {},
@@ -190,32 +174,42 @@ function resolve(instance, key) {
190
174
  target,
191
175
  key
192
176
  };
193
- }
177
+ } // Checks if a dash-cased string ends with an integer
178
+
194
179
 
180
+ const INDEX_REGEX = /-\d+$/;
195
181
  function attach(parent, child, type) {
196
182
  if (is.str(type)) {
183
+ // If attaching into an array (foo-0), create one
184
+ if (INDEX_REGEX.test(type)) {
185
+ const root = type.replace(INDEX_REGEX, '');
186
+ const {
187
+ target,
188
+ key
189
+ } = resolve(parent, root);
190
+ if (!Array.isArray(target[key])) target[key] = [];
191
+ }
192
+
197
193
  const {
198
194
  target,
199
195
  key
200
196
  } = resolve(parent, type);
201
- parent.__r3f.previousAttach = target[key];
197
+ child.__r3f.previousAttach = target[key];
202
198
  target[key] = child;
203
- } else if (is.arr(type)) {
204
- const [attach] = type;
205
- if (is.str(attach)) parent[attach](child);else if (is.fun(attach)) attach(parent, child);
206
- }
199
+ } else child.__r3f.previousAttach = type(parent, child);
207
200
  }
208
201
  function detach(parent, child, type) {
202
+ var _child$__r3f, _child$__r3f2;
203
+
209
204
  if (is.str(type)) {
210
205
  const {
211
206
  target,
212
207
  key
213
208
  } = resolve(parent, type);
214
- target[key] = parent.__r3f.previousAttach;
215
- } else if (is.arr(type)) {
216
- const [, detach] = type;
217
- if (is.str(detach)) parent[detach](child);else if (is.fun(detach)) detach(parent, child);
218
- }
209
+ target[key] = child.__r3f.previousAttach;
210
+ } else (_child$__r3f = child.__r3f) == null ? void 0 : _child$__r3f.previousAttach == null ? void 0 : _child$__r3f.previousAttach(parent, child);
211
+
212
+ (_child$__r3f2 = child.__r3f) == null ? true : delete _child$__r3f2.previousAttach;
219
213
  } // This function prepares a set of changes to be applied to the instance
220
214
 
221
215
  function diffProps(instance, {
@@ -335,20 +329,10 @@ function applyProps$1(instance, data) {
335
329
 
336
330
  if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
337
331
  else if (targetProp instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) targetProp.mask = value.mask; // Otherwise just set ...
338
- else targetProp.set(value); // Auto-convert sRGB colors, for now ...
339
- // https://github.com/pmndrs/react-three-fiber/issues/344
340
-
341
- if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
332
+ else targetProp.set(value);
342
333
  } // Else, just overwrite the value
343
334
 
344
- } else {
345
- currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
346
- // https://github.com/pmndrs/react-three-fiber/issues/344
347
-
348
- if (!rootState.linear && currentInstance[key] instanceof THREE__namespace.Texture) {
349
- currentInstance[key].encoding = THREE__namespace.sRGBEncoding;
350
- }
351
- }
335
+ } else currentInstance[key] = value;
352
336
 
353
337
  invalidateInstance(instance);
354
338
  return instance;
@@ -799,54 +783,20 @@ function createEvents(store) {
799
783
  };
800
784
  }
801
785
 
802
- // Type guard to tell a store from a portal
803
- const isStore = def => def && !!def.getState;
804
-
805
- const getContainer = (container, child) => {
806
- var _container$__r3f$root, _container$__r3f;
807
-
808
- return {
809
- // If the container is not a root-store then it must be a THREE.Object3D into which part of the
810
- // scene is portalled into. Now there can be two variants of this, either that object is part of
811
- // the regular jsx tree, in which case it already has __r3f with a valid root attached, or it lies
812
- // outside react, in which case we must take the root of the child that is about to be attached to it.
813
- root: isStore(container) ? container : (_container$__r3f$root = (_container$__r3f = container.__r3f) == null ? void 0 : _container$__r3f.root) != null ? _container$__r3f$root : child.__r3f.root,
814
- // The container is the eventual target into which objects are mounted, it has to be a THREE.Object3D
815
- container: isStore(container) ? container.getState().scene : container
816
- };
817
- };
818
-
819
786
  let catalogue = {};
820
787
 
821
788
  let extend = objects => void (catalogue = { ...catalogue,
822
789
  ...objects
823
790
  });
824
791
 
825
- extend({
826
- Inject: THREE__namespace.Group
827
- });
828
-
829
792
  function createRenderer(roots, getEventPriority) {
830
793
  function createInstance(type, {
831
794
  args = [],
832
795
  attach,
833
796
  ...props
834
- }, root, context, internalInstanceHandle) {
797
+ }, root) {
835
798
  let name = `${type[0].toUpperCase()}${type.slice(1)}`;
836
- let instance; // https://github.com/facebook/react/issues/17147
837
- // Portals do not give us a root, they are themselves treated as a root by the reconciler
838
- // In order to figure out the actual root we have to climb through fiber internals :(
839
-
840
- if (!isStore(root) && internalInstanceHandle) {
841
- const fn = node => {
842
- if (!node.return) return node.stateNode && node.stateNode.containerInfo;else return fn(node.return);
843
- };
844
-
845
- root = fn(internalInstanceHandle);
846
- } // Assert that by now we have a valid root
847
-
848
-
849
- if (!root || !isStore(root)) throw `No valid root for ${name}!`; // Auto-attach geometries and materials
799
+ let instance; // Auto-attach geometries and materials
850
800
 
851
801
  if (attach === undefined) {
852
802
  if (name.endsWith('Geometry')) attach = 'geometry';else if (name.endsWith('Material')) attach = 'material';
@@ -858,7 +808,6 @@ function createRenderer(roots, getEventPriority) {
858
808
  instance = prepare(object, {
859
809
  type,
860
810
  root,
861
- context,
862
811
  attach,
863
812
  primitive: true
864
813
  });
@@ -876,7 +825,6 @@ function createRenderer(roots, getEventPriority) {
876
825
  instance = prepare(new target(...args), {
877
826
  type,
878
827
  root,
879
- context,
880
828
  attach,
881
829
  // TODO: Figure out what this is for
882
830
  memoizedProps: {
@@ -894,15 +842,6 @@ function createRenderer(roots, getEventPriority) {
894
842
  }
895
843
 
896
844
  function appendChild(parentInstance, child) {
897
- // https://github.com/facebook/react/issues/24138
898
- // Injects are special purpose "onion layers" that inject contextual information into the scene graph.
899
- // Since react-reconciler does not allow us to access the current host context we trick it by leading
900
- // back to it from the first child that is added to it. We just connect the inject to it's own host context.
901
- if ((parentInstance == null ? void 0 : parentInstance.__r3f.type) === 'inject') {
902
- const context = child == null ? void 0 : child.__r3f.context;
903
- if (context) context.current = parentInstance.__r3f;
904
- }
905
-
906
845
  let added = false;
907
846
 
908
847
  if (child) {
@@ -998,7 +937,6 @@ function createRenderer(roots, getEventPriority) {
998
937
 
999
938
  if (child.__r3f) {
1000
939
  delete child.__r3f.root;
1001
- delete child.__r3f.context;
1002
940
  delete child.__r3f.objects;
1003
941
  delete child.__r3f.handlers;
1004
942
  delete child.__r3f.memoizedProps;
@@ -1021,11 +959,11 @@ function createRenderer(roots, getEventPriority) {
1021
959
  }
1022
960
 
1023
961
  function switchInstance(instance, type, newProps, fiber) {
1024
- var _instance$__r3f;
962
+ var _instance$__r3f, _instance$__r3f2;
1025
963
 
1026
964
  const parent = (_instance$__r3f = instance.__r3f) == null ? void 0 : _instance$__r3f.parent;
1027
965
  if (!parent) return;
1028
- const newInstance = createInstance(type, newProps, instance.__r3f.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
966
+ const newInstance = createInstance(type, newProps, (_instance$__r3f2 = instance.__r3f) == null ? void 0 : _instance$__r3f2.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
1029
967
  // When args change the instance has to be re-constructed, which then
1030
968
  // forces r3f to re-parent the children and non-scene objects
1031
969
  // This can not include primitives, which should not have declarative children
@@ -1068,46 +1006,28 @@ function createRenderer(roots, getEventPriority) {
1068
1006
  supportsMutation: true,
1069
1007
  isPrimaryRenderer: false,
1070
1008
  noTimeout: -1,
1071
- appendChildToContainer: (parentInstance, child) => {
1072
- const {
1073
- container,
1074
- root
1075
- } = getContainer(parentInstance, child); // Link current root to the default scene
1009
+ appendChildToContainer: (container, child) => {
1010
+ const scene = container.getState().scene; // Link current root to the default scene
1076
1011
 
1077
- container.__r3f.root = root;
1078
- appendChild(container, child);
1079
- },
1080
- removeChildFromContainer: (parentInstance, child) => removeChild(getContainer(parentInstance, child).container, child),
1081
- insertInContainerBefore: (parentInstance, child, beforeChild) => insertBefore(getContainer(parentInstance, child).container, child, beforeChild),
1082
- getRootHostContext: () => ({
1083
- current: null
1084
- }),
1085
- getChildHostContext: (parentHostContext, type) => {
1086
- // This is a little misleading, this function does not determine the host context for the element at hand,
1087
- // but rather for all the children of it. The context for an inject is and will be the scene, everything
1088
- // within an inject is contextual to it.
1089
- if (type === 'inject') return {
1090
- current: null
1091
- };
1092
- return parentHostContext;
1012
+ scene.__r3f.root = container;
1013
+ appendChild(scene, child);
1093
1014
  },
1015
+ removeChildFromContainer: (container, child) => removeChild(container.getState().scene, child),
1016
+ insertInContainerBefore: (container, child, beforeChild) => insertBefore(container.getState().scene, child, beforeChild),
1017
+ getRootHostContext: () => null,
1018
+ getChildHostContext: parentHostContext => parentHostContext,
1094
1019
 
1095
1020
  finalizeInitialChildren(instance) {
1096
- var _instance$__r3f2;
1021
+ var _instance$__r3f3;
1097
1022
 
1098
- const localState = (_instance$__r3f2 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f2 : {}; // https://github.com/facebook/react/issues/20271
1023
+ const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {}; // https://github.com/facebook/react/issues/20271
1099
1024
  // Returning true will trigger commitMount
1100
1025
 
1101
1026
  return !!localState.handlers;
1102
1027
  },
1103
1028
 
1104
1029
  prepareUpdate(instance, type, oldProps, newProps) {
1105
- // Injects are special purpose "onion layers" that inject contextual information into the scene graph
1106
- // Because the context of an inject is still the scene we have to rely on children to give us the inject-context
1107
- // so that we can set up props.
1108
- if (type === 'inject' && instance.children.length) ; // Create diff-sets
1109
-
1110
-
1030
+ // Create diff-sets
1111
1031
  if (instance.__r3f.primitive && newProps.object && newProps.object !== instance) {
1112
1032
  return [true];
1113
1033
  } else {
@@ -1141,11 +1061,11 @@ function createRenderer(roots, getEventPriority) {
1141
1061
  },
1142
1062
 
1143
1063
  commitMount(instance, type, props, int) {
1144
- var _instance$__r3f3;
1064
+ var _instance$__r3f4;
1145
1065
 
1146
1066
  // https://github.com/facebook/react/issues/20271
1147
1067
  // This will make sure events are only added once to the central container
1148
- const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
1068
+ const localState = (_instance$__r3f4 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f4 : {};
1149
1069
 
1150
1070
  if (instance.raycast && localState.handlers && localState.eventCount) {
1151
1071
  instance.__r3f.root.getState().internal.interaction.push(instance);
@@ -1155,7 +1075,7 @@ function createRenderer(roots, getEventPriority) {
1155
1075
  getPublicInstance: instance => instance,
1156
1076
  shouldDeprioritizeSubtree: () => false,
1157
1077
  prepareForCommit: () => null,
1158
- preparePortalMount: containerInfo => prepare(containerInfo),
1078
+ preparePortalMount: container => prepare(container.getState().scene),
1159
1079
  resetAfterCommit: () => {},
1160
1080
  shouldSetTextContent: () => false,
1161
1081
  clearContainer: () => false,
@@ -1163,26 +1083,26 @@ function createRenderer(roots, getEventPriority) {
1163
1083
  createTextInstance: () => {},
1164
1084
 
1165
1085
  hideInstance(instance) {
1166
- var _instance$__r3f4;
1086
+ var _instance$__r3f5;
1167
1087
 
1168
1088
  // Deatch while the instance is hidden
1169
1089
  const {
1170
1090
  attach: type,
1171
1091
  parent
1172
- } = (_instance$__r3f4 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f4 : {};
1092
+ } = (_instance$__r3f5 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f5 : {};
1173
1093
  if (type && parent) detach(parent, instance, type);
1174
1094
  if (instance.isObject3D) instance.visible = false;
1175
1095
  invalidateInstance(instance);
1176
1096
  },
1177
1097
 
1178
1098
  unhideInstance(instance, props) {
1179
- var _instance$__r3f5;
1099
+ var _instance$__r3f6;
1180
1100
 
1181
1101
  // Re-attach when the instance is unhidden
1182
1102
  const {
1183
1103
  attach: type,
1184
1104
  parent
1185
- } = (_instance$__r3f5 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f5 : {};
1105
+ } = (_instance$__r3f6 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f6 : {};
1186
1106
  if (type && parent) attach(parent, instance, type);
1187
1107
  if (instance.isObject3D && props.visible == null || props.visible) instance.visible = true;
1188
1108
  invalidateInstance(instance);
@@ -1547,6 +1467,43 @@ function useStore() {
1547
1467
  function useThree(selector = state => state, equalityFn) {
1548
1468
  return useStore()(selector, equalityFn);
1549
1469
  }
1470
+ function useInject(state) {
1471
+ const useOriginalStore = useStore();
1472
+ const useInjectStore = React__namespace.useMemo(() => {
1473
+ const useInjected = (sel = state => state) => {
1474
+ // Execute the useStore hook with the selector once, to maintain reactivity, result doesn't matter
1475
+ useOriginalStore(sel); // Inject data and return the result, either selected or raw
1476
+
1477
+ return sel({ ...useOriginalStore.getState(),
1478
+ ...state
1479
+ });
1480
+ };
1481
+
1482
+ useInjected.setState = useOriginalStore.setState;
1483
+ useInjected.destroy = useOriginalStore.destroy; // Patch getState
1484
+
1485
+ useInjected.getState = () => {
1486
+ return { ...useOriginalStore.getState(),
1487
+ ...state
1488
+ };
1489
+ }; // Patch subscribe
1490
+
1491
+
1492
+ useInjected.subscribe = listener => {
1493
+ return useOriginalStore.subscribe((current, previous) => listener({ ...current,
1494
+ ...state
1495
+ }, previous));
1496
+ };
1497
+
1498
+ return useInjected;
1499
+ }, [useOriginalStore, state]); // Return the patched store and a provider component
1500
+
1501
+ return React__namespace.useMemo(() => [({
1502
+ children
1503
+ }) => /*#__PURE__*/React__namespace.createElement(context.Provider, {
1504
+ value: useInjectStore
1505
+ }, children), useInjectStore], [useInjectStore]);
1506
+ }
1550
1507
  function useFrame(callback, renderPriority = 0) {
1551
1508
  const subscribe = useStore().getState().internal.subscribe; // Update ref
1552
1509
 
@@ -1710,7 +1667,7 @@ function createRoot(canvas) {
1710
1667
 
1711
1668
  const handleSessionChange = () => {
1712
1669
  const gl = store.getState().gl;
1713
- gl.xr.enabled = gl.xr.isPresenting; // @ts-expect-error
1670
+ gl.xr.enabled = gl.xr.isPresenting; // @ts-ignore
1714
1671
  // WebXRManager's signature is incorrect.
1715
1672
  // See: https://github.com/pmndrs/react-three-fiber/pull/2017#discussion_r790134505
1716
1673
 
@@ -1752,6 +1709,7 @@ function createRoot(canvas) {
1752
1709
  } // Set color management
1753
1710
 
1754
1711
 
1712
+ if (THREE__namespace.ColorManagement) THREE__namespace.ColorManagement.legacyMode = false;
1755
1713
  const outputEncoding = linear ? THREE__namespace.LinearEncoding : THREE__namespace.sRGBEncoding;
1756
1714
  const toneMapping = flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping;
1757
1715
  if (gl.outputEncoding !== outputEncoding) gl.outputEncoding = outputEncoding;
@@ -1867,10 +1825,29 @@ function unmountComponentAtNode(canvas, callback) {
1867
1825
  }
1868
1826
  }
1869
1827
 
1870
- const act = React__namespace.unstable_act;
1828
+ function createPortal(children, container, state) {
1829
+ return /*#__PURE__*/React__namespace.createElement(Portal, {
1830
+ children: children,
1831
+ container: container,
1832
+ state: state
1833
+ });
1834
+ }
1871
1835
 
1872
- function createPortal(children, container) {
1873
- return reconciler.createPortal(children, container, null, null);
1836
+ function Portal({
1837
+ state,
1838
+ children,
1839
+ container
1840
+ }) {
1841
+ /** This has to be a component because it would not be able to call useThree/useStore otherwise since
1842
+ * if this is our environment, then we are in in r3f's renderer but in react-dom, it would trigger
1843
+ * the "R3F hooks can only be used within the Canvas component!" warning:
1844
+ * <Canvas>
1845
+ * {createPortal(...)} */
1846
+ const portalState = React__namespace.useMemo(() => ({ ...state,
1847
+ scene: container
1848
+ }), [state, container]);
1849
+ const [PortalProvider, portalRoot] = useInject(portalState);
1850
+ return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, reconciler.createPortal( /*#__PURE__*/React__namespace.createElement(PortalProvider, null, children), portalRoot, null));
1874
1851
  }
1875
1852
 
1876
1853
  reconciler.injectIntoDevTools({
@@ -1878,6 +1855,7 @@ reconciler.injectIntoDevTools({
1878
1855
  rendererPackageName: '@react-three/fiber',
1879
1856
  version: '18.0.0'
1880
1857
  });
1858
+ const act = React__namespace.unstable_act;
1881
1859
 
1882
1860
  exports.act = act;
1883
1861
  exports.addAfterEffect = addAfterEffect;
@@ -1901,6 +1879,7 @@ exports.threeTypes = threeTypes;
1901
1879
  exports.unmountComponentAtNode = unmountComponentAtNode;
1902
1880
  exports.useFrame = useFrame;
1903
1881
  exports.useGraph = useGraph;
1882
+ exports.useInject = useInject;
1904
1883
  exports.useLoader = useLoader;
1905
1884
  exports.useStore = useStore;
1906
1885
  exports.useThree = useThree;