@react-three/fiber 8.0.0-beta-03 → 8.0.0-beta-04

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 Reconciler from 'react-reconciler';
2
- import { unstable_scheduleCallback, unstable_IdlePriority } from 'scheduler';
3
- import { DefaultEventPriority } from 'react-reconciler/constants';
4
- import * as THREE from 'three';
5
1
  import * as React from 'react';
6
2
  import { suspend, preload, clear } from 'suspend-react';
3
+ import * as THREE from 'three';
4
+ import { DefaultEventPriority, ContinuousEventPriority, DiscreteEventPriority, ConcurrentRoot } from 'react-reconciler/constants';
7
5
  import create from 'zustand';
6
+ import Reconciler from 'react-reconciler';
7
+ import { unstable_scheduleCallback, unstable_IdlePriority } from 'scheduler';
8
8
 
9
9
  var threeTypes = /*#__PURE__*/Object.freeze({
10
10
  __proto__: null
@@ -212,7 +212,7 @@ function diffProps(instance, {
212
212
  };
213
213
  } // This function applies a set of changes to the instance
214
214
 
215
- function applyProps(instance, data) {
215
+ function applyProps$1(instance, data) {
216
216
  var _instance$__r3f3, _root$getState;
217
217
 
218
218
  // Filter equals, events and reserved props
@@ -322,13 +322,41 @@ function updateInstance(instance) {
322
322
 
323
323
  function makeId(event) {
324
324
  return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
325
+ } // https://github.com/facebook/react/tree/main/packages/react-reconciler#getcurrenteventpriority
326
+ // Gives React a clue as to how import the current interaction is
327
+
328
+
329
+ function getEventPriority() {
330
+ var _window, _window$event;
331
+
332
+ let name = (_window = window) == null ? void 0 : (_window$event = _window.event) == null ? void 0 : _window$event.type;
333
+
334
+ switch (name) {
335
+ case 'click':
336
+ case 'contextmenu':
337
+ case 'dblclick':
338
+ case 'pointercancel':
339
+ case 'pointerdown':
340
+ case 'pointerup':
341
+ return DiscreteEventPriority;
342
+
343
+ case 'pointermove':
344
+ case 'pointerout':
345
+ case 'pointerover':
346
+ case 'pointerenter':
347
+ case 'pointerleave':
348
+ case 'wheel':
349
+ return ContinuousEventPriority;
350
+
351
+ default:
352
+ return DefaultEventPriority;
353
+ }
325
354
  }
326
355
  /**
327
356
  * Release pointer captures.
328
357
  * This is called by releasePointerCapture in the API, and when an object is removed.
329
358
  */
330
359
 
331
-
332
360
  function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
333
361
  const captureData = captures.get(obj);
334
362
 
@@ -800,7 +828,7 @@ function createRenderer(roots, getEventPriority) {
800
828
  // why it passes "true" here
801
829
 
802
830
 
803
- applyProps(instance, props);
831
+ applyProps$1(instance, props);
804
832
  return instance;
805
833
  }
806
834
 
@@ -998,7 +1026,7 @@ function createRenderer(roots, getEventPriority) {
998
1026
  commitUpdate(instance, [reconstruct, diff], type, oldProps, newProps, fiber) {
999
1027
  // Reconstruct when args or <primitive object={...} have changes
1000
1028
  if (reconstruct) switchInstance(instance, type, newProps, fiber); // Otherwise just overwrite props
1001
- else applyProps(instance, diff);
1029
+ else applyProps$1(instance, diff);
1002
1030
  },
1003
1031
 
1004
1032
  hideInstance(instance) {
@@ -1087,7 +1115,7 @@ function createRenderer(roots, getEventPriority) {
1087
1115
  });
1088
1116
  return {
1089
1117
  reconciler,
1090
- applyProps
1118
+ applyProps: applyProps$1
1091
1119
  };
1092
1120
  }
1093
1121
 
@@ -1389,6 +1417,60 @@ const createStore = (applyProps, invalidate, advance, props) => {
1389
1417
  return rootState;
1390
1418
  };
1391
1419
 
1420
+ function useStore() {
1421
+ const store = React.useContext(context);
1422
+ if (!store) throw `R3F hooks can only be used within the Canvas component!`;
1423
+ return store;
1424
+ }
1425
+ function useThree(selector = state => state, equalityFn) {
1426
+ return useStore()(selector, equalityFn);
1427
+ }
1428
+ function useFrame(callback, renderPriority = 0) {
1429
+ const subscribe = useStore().getState().internal.subscribe; // Update ref
1430
+
1431
+ const ref = React.useRef(callback);
1432
+ React.useLayoutEffect(() => void (ref.current = callback), [callback]); // Subscribe on mount, unsubscribe on unmount
1433
+
1434
+ React.useLayoutEffect(() => subscribe(ref, renderPriority), [renderPriority, subscribe]);
1435
+ return null;
1436
+ }
1437
+ function useGraph(object) {
1438
+ return React.useMemo(() => buildGraph(object), [object]);
1439
+ }
1440
+
1441
+ function loadingFn(extensions, onProgress) {
1442
+ return function (Proto, ...input) {
1443
+ // Construct new loader and run extensions
1444
+ const loader = new Proto();
1445
+ if (extensions) extensions(loader); // Go through the urls and load them
1446
+
1447
+ return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => {
1448
+ if (data.scene) Object.assign(data, buildGraph(data.scene));
1449
+ res(data);
1450
+ }, onProgress, error => reject(`Could not load ${input}: ${error.message}`)))));
1451
+ };
1452
+ }
1453
+
1454
+ function useLoader(Proto, input, extensions, onProgress) {
1455
+ // Use suspense to load async assets
1456
+ const keys = Array.isArray(input) ? input : [input];
1457
+ const results = suspend(loadingFn(extensions, onProgress), [Proto, ...keys], {
1458
+ equal: is.equ
1459
+ }); // Return the object/s
1460
+
1461
+ return Array.isArray(input) ? results : results[0];
1462
+ }
1463
+
1464
+ useLoader.preload = function (Proto, input, extensions) {
1465
+ const keys = Array.isArray(input) ? input : [input];
1466
+ return preload(loadingFn(extensions), [Proto, ...keys]);
1467
+ };
1468
+
1469
+ useLoader.clear = function (Proto, input) {
1470
+ const keys = Array.isArray(input) ? input : [input];
1471
+ return clear([Proto, ...keys]);
1472
+ };
1473
+
1392
1474
  function createSubs(callback, subs) {
1393
1475
  const index = subs.length;
1394
1476
  subs.push(callback);
@@ -1407,7 +1489,7 @@ function run(effects, timestamp) {
1407
1489
  for (i = 0; i < effects.length; i++) effects[i](timestamp);
1408
1490
  }
1409
1491
 
1410
- function render(timestamp, state) {
1492
+ function render$1(timestamp, state) {
1411
1493
  // Run local effects
1412
1494
  let delta = state.clock.getDelta(); // In frameloop='never' mode, clock times are updated using the provided timestamp
1413
1495
 
@@ -1443,7 +1525,7 @@ function createLoop(roots) {
1443
1525
  const state = root.store.getState(); // If the frameloop is invalidated, do not run another frame
1444
1526
 
1445
1527
  if (state.internal.active && (state.frameloop === 'always' || state.internal.frames > 0) && !((_state$gl$xr = state.gl.xr) != null && _state$gl$xr.isPresenting)) {
1446
- repeat += render(timestamp, state);
1528
+ repeat += render$1(timestamp, state);
1447
1529
  }
1448
1530
  }); // Run after-effects
1449
1531
 
@@ -1471,7 +1553,7 @@ function createLoop(roots) {
1471
1553
 
1472
1554
  function advance(timestamp, runGlobalEffects = true, state) {
1473
1555
  if (runGlobalEffects) run(globalEffects, timestamp);
1474
- if (!state) roots.forEach(root => render(timestamp, root.store.getState()));else render(timestamp, state);
1556
+ if (!state) roots.forEach(root => render$1(timestamp, root.store.getState()));else render$1(timestamp, state);
1475
1557
  if (runGlobalEffects) run(globalAfterEffects, timestamp);
1476
1558
  }
1477
1559
 
@@ -1482,58 +1564,187 @@ function createLoop(roots) {
1482
1564
  };
1483
1565
  }
1484
1566
 
1485
- function useStore() {
1486
- const store = React.useContext(context);
1487
- if (!store) throw `R3F hooks can only be used within the Canvas component!`;
1488
- return store;
1489
- }
1490
- function useThree(selector = state => state, equalityFn) {
1491
- return useStore()(selector, equalityFn);
1492
- }
1493
- function useFrame(callback, renderPriority = 0) {
1494
- const subscribe = useStore().getState().internal.subscribe; // Update ref
1567
+ const roots = new Map();
1568
+ const {
1569
+ invalidate,
1570
+ advance
1571
+ } = createLoop(roots);
1572
+ const {
1573
+ reconciler,
1574
+ applyProps
1575
+ } = createRenderer(roots, getEventPriority);
1576
+
1577
+ const createRendererInstance = (gl, canvas) => {
1578
+ const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
1579
+ if (isRenderer(customRenderer)) return customRenderer;
1580
+ const renderer = new THREE.WebGLRenderer({
1581
+ powerPreference: 'high-performance',
1582
+ canvas: canvas,
1583
+ antialias: true,
1584
+ alpha: true,
1585
+ ...gl
1586
+ }); // Set color management
1587
+
1588
+ renderer.outputEncoding = THREE.sRGBEncoding;
1589
+ renderer.toneMapping = THREE.ACESFilmicToneMapping; // Set gl props
1590
+
1591
+ if (gl) applyProps(renderer, gl);
1592
+ return renderer;
1593
+ };
1495
1594
 
1496
- const ref = React.useRef(callback);
1497
- React.useLayoutEffect(() => void (ref.current = callback), [callback]); // Subscribe on mount, unsubscribe on unmount
1595
+ function createRoot(canvas, config) {
1596
+ return {
1597
+ render: element => {
1598
+ var _store;
1599
+
1600
+ let {
1601
+ gl,
1602
+ size,
1603
+ events,
1604
+ onCreated,
1605
+ ...props
1606
+ } = config || {}; // Allow size to take on container bounds initially
1607
+
1608
+ if (!size) {
1609
+ var _canvas$parentElement, _canvas$parentElement2, _canvas$parentElement3, _canvas$parentElement4;
1610
+
1611
+ size = {
1612
+ width: (_canvas$parentElement = (_canvas$parentElement2 = canvas.parentElement) == null ? void 0 : _canvas$parentElement2.clientWidth) != null ? _canvas$parentElement : 0,
1613
+ height: (_canvas$parentElement3 = (_canvas$parentElement4 = canvas.parentElement) == null ? void 0 : _canvas$parentElement4.clientHeight) != null ? _canvas$parentElement3 : 0
1614
+ };
1615
+ }
1498
1616
 
1499
- React.useLayoutEffect(() => subscribe(ref, renderPriority), [renderPriority, subscribe]);
1500
- return null;
1617
+ let root = roots.get(canvas);
1618
+ let fiber = root == null ? void 0 : root.fiber;
1619
+ let store = root == null ? void 0 : root.store;
1620
+ let state = (_store = store) == null ? void 0 : _store.getState();
1621
+
1622
+ if (fiber && state) {
1623
+ // When a root was found, see if any fundamental props must be changed or exchanged
1624
+ // Check pixelratio
1625
+ if (props.dpr !== undefined && state.viewport.dpr !== calculateDpr(props.dpr)) state.setDpr(props.dpr); // Check size
1626
+
1627
+ if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // Check frameloop
1628
+
1629
+ if (state.frameloop !== props.frameloop) state.setFrameloop(props.frameloop); // For some props we want to reset the entire root
1630
+ // Changes to the color-space
1631
+
1632
+ const linearChanged = props.linear !== state.internal.lastProps.linear;
1633
+
1634
+ if (linearChanged) {
1635
+ unmountComponentAtNode(canvas);
1636
+ fiber = undefined;
1637
+ }
1638
+ }
1639
+
1640
+ if (!fiber) {
1641
+ // If no root has been found, make one
1642
+ // Create gl
1643
+ const glRenderer = createRendererInstance(gl, canvas); // Create store
1644
+
1645
+ store = createStore(applyProps, invalidate, advance, {
1646
+ gl: glRenderer,
1647
+ size,
1648
+ ...props
1649
+ });
1650
+ const state = store.getState(); // Create renderer
1651
+
1652
+ fiber = reconciler.createContainer(store, ConcurrentRoot, false, null); // Map it
1653
+
1654
+ roots.set(canvas, {
1655
+ fiber,
1656
+ store
1657
+ }); // Store events internally
1658
+
1659
+ if (events) state.set({
1660
+ events: events(store)
1661
+ });
1662
+ }
1663
+
1664
+ if (store && fiber) {
1665
+ reconciler.updateContainer( /*#__PURE__*/React.createElement(Provider, {
1666
+ store: store,
1667
+ element: element,
1668
+ onCreated: onCreated,
1669
+ target: canvas
1670
+ }), fiber, null, () => undefined);
1671
+ return store;
1672
+ } else {
1673
+ throw 'Error creating root!';
1674
+ }
1675
+ },
1676
+ unmount: () => unmountComponentAtNode(canvas)
1677
+ };
1501
1678
  }
1502
- function useGraph(object) {
1503
- return React.useMemo(() => buildGraph(object), [object]);
1679
+
1680
+ function render(element, canvas, config = {}) {
1681
+ console.warn('R3F.render is no longer supported in React 18. Use createRoot instead!');
1682
+ return createRoot(canvas, config).render(element);
1504
1683
  }
1505
1684
 
1506
- function loadingFn(extensions, onProgress) {
1507
- return function (Proto, ...input) {
1508
- // Construct new loader and run extensions
1509
- const loader = new Proto();
1510
- if (extensions) extensions(loader); // Go through the urls and load them
1685
+ function Provider({
1686
+ store,
1687
+ element,
1688
+ onCreated,
1689
+ target
1690
+ }) {
1691
+ React.useEffect(() => {
1692
+ const state = store.getState(); // Flag the canvas active, rendering will now begin
1693
+
1694
+ state.set(state => ({
1695
+ internal: { ...state.internal,
1696
+ active: true
1697
+ }
1698
+ })); // Connect events
1511
1699
 
1512
- return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => {
1513
- if (data.scene) Object.assign(data, buildGraph(data.scene));
1514
- res(data);
1515
- }, onProgress, error => reject(`Could not load ${input}: ${error.message}`)))));
1516
- };
1700
+ state.events.connect == null ? void 0 : state.events.connect(target); // Notifiy that init is completed, the scene graph exists, but nothing has yet rendered
1701
+
1702
+ if (onCreated) onCreated(state); // eslint-disable-next-line react-hooks/exhaustive-deps
1703
+ }, []);
1704
+ return /*#__PURE__*/React.createElement(context.Provider, {
1705
+ value: store
1706
+ }, element);
1517
1707
  }
1518
1708
 
1519
- function useLoader(Proto, input, extensions, onProgress) {
1520
- // Use suspense to load async assets
1521
- const keys = Array.isArray(input) ? input : [input];
1522
- const results = suspend(loadingFn(extensions, onProgress), [Proto, ...keys], {
1523
- equal: is.equ
1524
- }); // Return the object/s
1709
+ function unmountComponentAtNode(canvas, callback) {
1710
+ const root = roots.get(canvas);
1711
+ const fiber = root == null ? void 0 : root.fiber;
1525
1712
 
1526
- return Array.isArray(input) ? results : results[0];
1713
+ if (fiber) {
1714
+ const state = root == null ? void 0 : root.store.getState();
1715
+ if (state) state.internal.active = false;
1716
+ reconciler.updateContainer(null, fiber, null, () => {
1717
+ if (state) {
1718
+ setTimeout(() => {
1719
+ try {
1720
+ var _state$gl, _state$gl$renderLists, _state$gl2, _state$gl3;
1721
+
1722
+ state.events.disconnect == null ? void 0 : state.events.disconnect();
1723
+ (_state$gl = state.gl) == null ? void 0 : (_state$gl$renderLists = _state$gl.renderLists) == null ? void 0 : _state$gl$renderLists.dispose == null ? void 0 : _state$gl$renderLists.dispose();
1724
+ (_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
1725
+ if ((_state$gl3 = state.gl) != null && _state$gl3.xr) state.internal.xr.disconnect();
1726
+ dispose(state);
1727
+ roots.delete(canvas);
1728
+ if (callback) callback(canvas);
1729
+ } catch (e) {
1730
+ /* ... */
1731
+ }
1732
+ }, 500);
1733
+ }
1734
+ });
1735
+ }
1527
1736
  }
1528
1737
 
1529
- useLoader.preload = function (Proto, input, extensions) {
1530
- const keys = Array.isArray(input) ? input : [input];
1531
- return preload(loadingFn(extensions), [Proto, ...keys]);
1532
- };
1738
+ const act = React.unstable_act;
1533
1739
 
1534
- useLoader.clear = function (Proto, input) {
1535
- const keys = Array.isArray(input) ? input : [input];
1536
- return clear([Proto, ...keys]);
1537
- };
1740
+ function createPortal(children, container) {
1741
+ return reconciler.createPortal(children, container, null, null);
1742
+ }
1743
+
1744
+ reconciler.injectIntoDevTools({
1745
+ bundleType: process.env.NODE_ENV === 'production' ? 0 : 1,
1746
+ rendererPackageName: '@react-three/fiber',
1747
+ version: '18.0.0'
1748
+ });
1538
1749
 
1539
- export { createLoop as a, createRenderer as b, createEvents as c, calculateDpr as d, createStore as e, context as f, dispose as g, extend as h, isRenderer as i, addEffect as j, addAfterEffect as k, addTail as l, useThree as m, useFrame as n, omit as o, pick as p, useGraph as q, useLoader as r, buildGraph as s, threeTypes as t, useStore as u, is as v };
1750
+ export { is as A, createRoot as a, useStore as b, createEvents as c, useThree as d, extend as e, useFrame as f, useGraph as g, useLoader as h, context as i, createPortal as j, reconciler as k, applyProps as l, dispose as m, invalidate as n, omit as o, pick as p, advance as q, render as r, addEffect as s, threeTypes as t, unmountComponentAtNode as u, addAfterEffect as v, addTail as w, act as x, roots as y, buildGraph as z };