@react-three/fiber 8.0.7 → 8.0.10

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.
@@ -10,6 +10,48 @@ var threeTypes = /*#__PURE__*/Object.freeze({
10
10
  __proto__: null
11
11
  });
12
12
 
13
+ const isOrthographicCamera = def => def && def.isOrthographicCamera; // React currently throws a warning when using useLayoutEffect on the server.
14
+ // To get around it, we can conditionally useEffect on the server (no-op) and
15
+ // useLayoutEffect on the client.
16
+
17
+ const isSSR = typeof window === 'undefined' || !window.navigator || /ServerSideRendering|^Deno\//.test(window.navigator.userAgent);
18
+ const useIsomorphicLayoutEffect = isSSR ? React.useEffect : React.useLayoutEffect;
19
+ function useMutableCallback(fn) {
20
+ const ref = React.useRef(fn);
21
+ useIsomorphicLayoutEffect(() => void (ref.current = fn), [fn]);
22
+ return ref;
23
+ }
24
+ function Block({
25
+ set
26
+ }) {
27
+ useIsomorphicLayoutEffect(() => {
28
+ set(new Promise(() => null));
29
+ return () => set(false);
30
+ }, [set]);
31
+ return null;
32
+ }
33
+ class ErrorBoundary extends React.Component {
34
+ constructor(...args) {
35
+ super(...args);
36
+ this.state = {
37
+ error: false
38
+ };
39
+ }
40
+
41
+ componentDidCatch(error) {
42
+ this.props.set(error);
43
+ }
44
+
45
+ render() {
46
+ return this.state.error ? null : this.props.children;
47
+ }
48
+
49
+ }
50
+
51
+ ErrorBoundary.getDerivedStateFromError = () => ({
52
+ error: true
53
+ });
54
+
13
55
  const DEFAULT = '__default';
14
56
  const isDiffSet = def => def && !!def.memoized && !!def.changes;
15
57
  function calculateDpr(dpr) {
@@ -182,10 +224,7 @@ function detach(parent, child, type) {
182
224
  target,
183
225
  key
184
226
  } = resolve(parent, type);
185
- const previous = child.__r3f.previousAttach; // When the previous value was undefined, it means the value was never set to begin with
186
-
187
- if (previous === undefined) delete target[key]; // Otherwise set the previous value
188
- else target[key] = previous;
227
+ target[key] = child.__r3f.previousAttach;
189
228
  } else (_child$__r3f = child.__r3f) == null ? void 0 : _child$__r3f.previousAttach == null ? void 0 : _child$__r3f.previousAttach(parent, child);
190
229
 
191
230
  (_child$__r3f2 = child.__r3f) == null ? true : delete _child$__r3f2.previousAttach;
@@ -278,11 +317,9 @@ function applyProps$1(instance, data) {
278
317
  // use the prop constructor to find the default it should be
279
318
  value = new targetProp.constructor(...memoized.args);
280
319
  } else if (currentInstance.constructor) {
281
- var _currentInstance$__r, _currentInstance$__r2;
282
-
283
320
  // create a blank slate of the instance and copy the particular parameter.
284
321
  // @ts-ignore
285
- const defaultClassCall = new currentInstance.constructor(...((_currentInstance$__r = (_currentInstance$__r2 = currentInstance.__r3f) == null ? void 0 : _currentInstance$__r2.memoizedProps.args) != null ? _currentInstance$__r : []));
322
+ const defaultClassCall = new currentInstance.constructor(...currentInstance.__r3f.memoizedProps.args);
286
323
  value = defaultClassCall[targetProp]; // destory the instance
287
324
 
288
325
  if (defaultClassCall.dispose) defaultClassCall.dispose(); // instance does not have constructor, just set it to 0
@@ -351,6 +388,25 @@ function invalidateInstance(instance) {
351
388
  function updateInstance(instance) {
352
389
  instance.onUpdate == null ? void 0 : instance.onUpdate(instance);
353
390
  }
391
+ function updateCamera(camera, size) {
392
+ // https://github.com/pmndrs/react-three-fiber/issues/92
393
+ // Do not mess with the camera if it belongs to the user
394
+ if (!camera.manual) {
395
+ if (isOrthographicCamera(camera)) {
396
+ camera.left = size.width / -2;
397
+ camera.right = size.width / 2;
398
+ camera.top = size.height / 2;
399
+ camera.bottom = size.height / -2;
400
+ } else {
401
+ camera.aspect = size.width / size.height;
402
+ }
403
+
404
+ camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
405
+ // Update matrix world since the renderer is a frame late
406
+
407
+ camera.updateMatrixWorld();
408
+ }
409
+ }
354
410
 
355
411
  function makeId(event) {
356
412
  return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
@@ -1124,7 +1180,6 @@ function createRenderer(roots, getEventPriority) {
1124
1180
  }
1125
1181
 
1126
1182
  const isRenderer = def => !!(def != null && def.render);
1127
- const isOrthographicCamera = def => def && def.isOrthographicCamera;
1128
1183
  const context = /*#__PURE__*/React.createContext(null);
1129
1184
 
1130
1185
  const createStore = (invalidate, advance) => {
@@ -1331,24 +1386,7 @@ const createStore = (invalidate, advance) => {
1331
1386
  } = rootState.getState();
1332
1387
 
1333
1388
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1334
- // https://github.com/pmndrs/react-three-fiber/issues/92
1335
- // Do not mess with the camera if it belongs to the user
1336
- if (!camera.manual) {
1337
- if (isOrthographicCamera(camera)) {
1338
- camera.left = size.width / -2;
1339
- camera.right = size.width / 2;
1340
- camera.top = size.height / 2;
1341
- camera.bottom = size.height / -2;
1342
- } else {
1343
- camera.aspect = size.width / size.height;
1344
- }
1345
-
1346
- camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
1347
- // Update matrix world since the renderer is a frame late
1348
-
1349
- camera.updateMatrixWorld();
1350
- } // Update renderer
1351
-
1389
+ updateCamera(camera, size); // Update renderer
1352
1390
 
1353
1391
  gl.setPixelRatio(viewport.dpr);
1354
1392
  gl.setSize(size.width, size.height);
@@ -1372,8 +1410,23 @@ let i;
1372
1410
  let globalEffects = [];
1373
1411
  let globalAfterEffects = [];
1374
1412
  let globalTailEffects = [];
1413
+ /**
1414
+ * Adds a global render callback which is called each frame.
1415
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
1416
+ */
1417
+
1375
1418
  const addEffect = callback => createSubs(callback, globalEffects);
1419
+ /**
1420
+ * Adds a global after-render callback which is called each frame.
1421
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
1422
+ */
1423
+
1376
1424
  const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
1425
+ /**
1426
+ * Adds a global callback which is called when rendering stops.
1427
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
1428
+ */
1429
+
1377
1430
  const addTail = callback => createSubs(callback, globalTailEffects);
1378
1431
 
1379
1432
  function run(effects, timestamp) {
@@ -1382,11 +1435,10 @@ function run(effects, timestamp) {
1382
1435
 
1383
1436
  let subscribers;
1384
1437
  let subscription;
1385
- let delta;
1386
1438
 
1387
1439
  function render$1(timestamp, state, frame) {
1388
1440
  // Run local effects
1389
- delta = state.clock.getDelta(); // In frameloop='never' mode, clock times are updated using the provided timestamp
1441
+ let delta = state.clock.getDelta(); // In frameloop='never' mode, clock times are updated using the provided timestamp
1390
1442
 
1391
1443
  if (state.frameloop === 'never' && typeof timestamp === 'number') {
1392
1444
  delta = timestamp - state.clock.elapsedTime;
@@ -1465,7 +1517,17 @@ function createLoop(roots) {
1465
1517
 
1466
1518
  return {
1467
1519
  loop,
1520
+
1521
+ /**
1522
+ * Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
1523
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
1524
+ */
1468
1525
  invalidate,
1526
+
1527
+ /**
1528
+ * Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
1529
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
1530
+ */
1469
1531
  advance
1470
1532
  };
1471
1533
  }
@@ -1475,19 +1537,34 @@ function useStore() {
1475
1537
  if (!store) throw `R3F hooks can only be used within the Canvas component!`;
1476
1538
  return store;
1477
1539
  }
1540
+ /**
1541
+ * Accesses R3F's internal state, containing renderer, canvas, scene, etc.
1542
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usethree
1543
+ */
1544
+
1478
1545
  function useThree(selector = state => state, equalityFn) {
1479
1546
  return useStore()(selector, equalityFn);
1480
1547
  }
1548
+ /**
1549
+ * Executes a callback before render in a shared frame loop.
1550
+ * Can order effects with render priority or manually render with a positive priority.
1551
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
1552
+ */
1553
+
1481
1554
  function useFrame(callback, renderPriority = 0) {
1482
1555
  const store = useStore();
1483
- const subscribe = store.getState().internal.subscribe; // Update ref
1556
+ const subscribe = store.getState().internal.subscribe; // Memoize ref
1484
1557
 
1485
- const ref = React.useRef(callback);
1486
- React.useLayoutEffect(() => void (ref.current = callback), [callback]); // Subscribe on mount, unsubscribe on unmount
1558
+ const ref = useMutableCallback(callback); // Subscribe on mount, unsubscribe on unmount
1487
1559
 
1488
- React.useLayoutEffect(() => subscribe(ref, renderPriority, store), [renderPriority, subscribe, store]);
1560
+ useIsomorphicLayoutEffect(() => subscribe(ref, renderPriority, store), [renderPriority, subscribe, store]);
1489
1561
  return null;
1490
1562
  }
1563
+ /**
1564
+ * Returns a node graph of an object with named nodes & materials.
1565
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
1566
+ */
1567
+
1491
1568
  function useGraph(object) {
1492
1569
  return React.useMemo(() => buildGraph(object), [object]);
1493
1570
  }
@@ -1504,12 +1581,14 @@ function loadingFn(extensions, onProgress) {
1504
1581
  }, onProgress, error => reject(`Could not load ${input}: ${error.message}`)))));
1505
1582
  };
1506
1583
  }
1584
+ /**
1585
+ * Synchronously loads and caches assets with a three loader.
1586
+ *
1587
+ * Note: this hook's caller must be wrapped with `React.Suspense`
1588
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useloader
1589
+ */
1590
+
1507
1591
 
1508
- function useMemoizedFn(fn) {
1509
- const fnRef = React.useRef(fn);
1510
- React.useLayoutEffect(() => void (fnRef.current = fn), [fn]);
1511
- return (...args) => fnRef.current == null ? void 0 : fnRef.current(...args);
1512
- }
1513
1592
  function useLoader(Proto, input, extensions, onProgress) {
1514
1593
  // Use suspense to load async assets
1515
1594
  const keys = Array.isArray(input) ? input : [input];
@@ -1519,11 +1598,18 @@ function useLoader(Proto, input, extensions, onProgress) {
1519
1598
 
1520
1599
  return Array.isArray(input) ? results : results[0];
1521
1600
  }
1601
+ /**
1602
+ * Preloads an asset into cache as a side-effect.
1603
+ */
1522
1604
 
1523
1605
  useLoader.preload = function (Proto, input, extensions) {
1524
1606
  const keys = Array.isArray(input) ? input : [input];
1525
1607
  return preload(loadingFn(extensions), [Proto, ...keys]);
1526
1608
  };
1609
+ /**
1610
+ * Removes a loaded asset from cache.
1611
+ */
1612
+
1527
1613
 
1528
1614
  useLoader.clear = function (Proto, input) {
1529
1615
  const keys = Array.isArray(input) ? input : [input];
@@ -1770,7 +1856,7 @@ function Provider({
1770
1856
  onCreated,
1771
1857
  rootElement
1772
1858
  }) {
1773
- React.useLayoutEffect(() => {
1859
+ useIsomorphicLayoutEffect(() => {
1774
1860
  const state = store.getState(); // Flag the canvas active, rendering will now begin
1775
1861
 
1776
1862
  state.set(state => ({
@@ -1839,6 +1925,7 @@ function Portal({
1839
1925
  * {createPortal(...)} */
1840
1926
  const {
1841
1927
  events,
1928
+ size,
1842
1929
  ...rest
1843
1930
  } = state;
1844
1931
  const previousRoot = useStore();
@@ -1850,45 +1937,79 @@ function Portal({
1850
1937
 
1851
1938
  if (injectState) {
1852
1939
  // Only the fields of "state" that do not differ from injectState
1940
+ // Some props should be off-limits
1941
+ // Otherwise filter out the props that are different and let the inject layer take precedence
1853
1942
  Object.keys(state).forEach(key => {
1854
- if ( // Some props should be off-limits
1855
- !['size', 'viewport', 'internal', 'performance'].includes(key) && // Otherwise filter out the props that are different and let the inject layer take precedence
1856
- state[key] !== injectState[key]) delete intersect[key];
1943
+ if (state[key] !== injectState[key] && !['internal', 'performance'].includes(key)) {
1944
+ delete intersect[key];
1945
+ }
1857
1946
  });
1858
1947
  }
1859
1948
 
1860
- return { ...intersect,
1949
+ let viewport = undefined;
1950
+
1951
+ if (injectState && size) {
1952
+ const camera = injectState.camera; // Calculate the override viewport, if present
1953
+
1954
+ viewport = state.viewport.getCurrentViewport(camera, new THREE.Vector3(), size); // Update the portal camera, if it differs from the previous layer
1955
+
1956
+ if (camera !== state.camera) updateCamera(camera, size);
1957
+ }
1958
+
1959
+ return { // The intersect consists of the previous root state
1960
+ ...intersect,
1961
+ // Portals have their own scene, which forms the root, a raycaster and a pointer
1861
1962
  scene: container,
1862
- previousRoot,
1863
1963
  raycaster,
1964
+ pointer,
1965
+ mouse: pointer,
1966
+ // Their previous root is the layer before it
1967
+ previousRoot,
1968
+ // Events, size and viewport can be overridden by the inject layer
1864
1969
  events: { ...state.events,
1865
1970
  ...(injectState == null ? void 0 : injectState.events),
1866
- pointer,
1867
- mouse: pointer,
1868
1971
  ...events
1869
1972
  },
1973
+ size: { ...state.size,
1974
+ ...size
1975
+ },
1976
+ viewport: { ...state.viewport,
1977
+ ...viewport
1978
+ },
1870
1979
  ...rest
1871
1980
  };
1872
1981
  }, [state]);
1873
- const [useInjectStore] = React.useState(() => {
1874
- const store = create((set, get) => ({ ...inject(previousRoot.getState()),
1982
+ const [usePortalStore] = React.useState(() => {
1983
+ // Create a mirrored store, based on the previous root with a few overrides ...
1984
+ new THREE.Vector3();
1985
+ const previousState = previousRoot.getState();
1986
+ const store = create((set, get) => ({ ...inject(previousState),
1987
+ // Set and get refer to this root-state
1875
1988
  set,
1876
1989
  get,
1990
+ // Layers are allowed to override events
1877
1991
  setEvents: events => set(state => ({ ...state,
1878
1992
  events: { ...state.events,
1879
1993
  ...events
1880
1994
  }
1881
1995
  }))
1882
1996
  }));
1883
- previousRoot.subscribe(state => useInjectStore.setState(injectState => inject(state, injectState)));
1884
1997
  return store;
1885
1998
  });
1886
1999
  React.useEffect(() => {
1887
- useInjectStore.setState(injectState => inject(previousRoot.getState(), injectState));
2000
+ // Subscribe to previous root-state and copy changes over to the mirrored portal-state
2001
+ const unsub = previousRoot.subscribe(prev => usePortalStore.setState(state => inject(prev, state)));
2002
+ return () => {
2003
+ unsub();
2004
+ usePortalStore.destroy();
2005
+ };
2006
+ }, []);
2007
+ React.useEffect(() => {
2008
+ usePortalStore.setState(injectState => inject(previousRoot.getState(), injectState));
1888
2009
  }, [inject]);
1889
2010
  return /*#__PURE__*/React.createElement(React.Fragment, null, reconciler.createPortal( /*#__PURE__*/React.createElement(context.Provider, {
1890
- value: useInjectStore
1891
- }, children), useInjectStore, null));
2011
+ value: usePortalStore
2012
+ }, children), usePortalStore, null));
1892
2013
  }
1893
2014
 
1894
2015
  reconciler.injectIntoDevTools({
@@ -1898,4 +2019,4 @@ reconciler.injectIntoDevTools({
1898
2019
  });
1899
2020
  const act = React.unstable_act;
1900
2021
 
1901
- 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 };
2022
+ export { useGraph as A, Block as B, useLoader as C, ErrorBoundary as E, createRoot as a, useIsomorphicLayoutEffect as b, createEvents as c, unmountComponentAtNode as d, extend as e, context as f, createPortal as g, reconciler as h, applyProps as i, dispose as j, invalidate as k, advance as l, addEffect as m, addAfterEffect as n, omit as o, pick as p, addTail as q, render as r, getRootState as s, threeTypes as t, useMutableCallback as u, act as v, roots as w, useStore as x, useThree as y, useFrame as z };