@react-three/fiber 8.2.1 → 8.3.0

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.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 9c450ec: feat: improve errors
8
+
9
+ ## 8.2.3
10
+
11
+ ### Patch Changes
12
+
13
+ - b8d2eab: fix: improve useLoader signature, initial size on createRoot
14
+
15
+ ## 8.2.2
16
+
17
+ ### Patch Changes
18
+
19
+ - acd6f04: fix: warn on stray text
20
+
3
21
  ## 8.2.1
4
22
 
5
23
  ### Patch Changes
@@ -3,6 +3,7 @@ import { StateSelector, EqualityChecker } from 'zustand';
3
3
  import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader';
4
4
  import { RootState, RenderCallback } from './store';
5
5
  import { ObjectMap } from './utils';
6
+ import { LoadingManager } from 'three';
6
7
  export interface Loader<T> extends THREE.Loader {
7
8
  load(url: string, onLoad?: (result: T) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): unknown;
8
9
  }
@@ -14,7 +15,7 @@ export declare function useStore(): import("zustand").UseBoundStore<RootState, i
14
15
  export declare function useThree<T = RootState>(selector?: StateSelector<RootState, T>, equalityFn?: EqualityChecker<T>): T;
15
16
  export declare function useFrame(callback: RenderCallback, renderPriority?: number): null;
16
17
  export declare function useGraph(object: THREE.Object3D): ObjectMap;
17
- export declare function useLoader<T, U extends string | string[]>(Proto: new () => LoaderResult<T>, input: U, extensions?: Extensions, onProgress?: (event: ProgressEvent<EventTarget>) => void): U extends any[] ? BranchingReturn<T, GLTF, GLTF & ObjectMap>[] : BranchingReturn<T, GLTF, GLTF & ObjectMap>;
18
+ export declare function useLoader<T, U extends string | string[]>(Proto: new (manager?: LoadingManager) => LoaderResult<T>, input: U, extensions?: Extensions, onProgress?: (event: ProgressEvent<EventTarget>) => void): U extends any[] ? BranchingReturn<T, GLTF, GLTF & ObjectMap>[] : BranchingReturn<T, GLTF, GLTF & ObjectMap>;
18
19
  export declare namespace useLoader {
19
20
  var preload: <T, U extends string | string[]>(Proto: new () => LoaderResult<T>, input: U, extensions?: Extensions | undefined) => undefined;
20
21
  var clear: <T, U extends string | string[]>(Proto: new () => LoaderResult<T>, input: U) => void;
@@ -10,7 +10,7 @@ import { EventManager, ComputeFunction } from './events';
10
10
  import { dispose, getRootState, Camera } from './utils';
11
11
  declare const roots: Map<Element, Root>;
12
12
  declare const invalidate: (state?: RootState | undefined, frames?: number) => void, advance: (timestamp: number, runGlobalEffects?: boolean, state?: RootState | undefined, frame?: THREE.XRFrame | undefined) => void;
13
- declare const reconciler: import("react-reconciler").Reconciler<UseBoundStore<RootState, import("zustand").StoreApi<RootState>>, import("./renderer").Instance, never, import("./renderer").Instance, import("./renderer").Instance>, applyProps: typeof import("./utils").applyProps;
13
+ declare const reconciler: import("react-reconciler").Reconciler<UseBoundStore<RootState, import("zustand").StoreApi<RootState>>, import("./renderer").Instance, void, import("./renderer").Instance, import("./renderer").Instance>, applyProps: typeof import("./utils").applyProps;
14
14
  declare type Properties<T> = Pick<T, {
15
15
  [K in keyof T]: T[K] extends (_: any) => any ? never : K;
16
16
  }[keyof T]>;
@@ -45,7 +45,7 @@ export declare type InstanceProps = {
45
45
  };
46
46
  declare let extend: (objects: object) => void;
47
47
  declare function createRenderer<TCanvas>(_roots: Map<TCanvas, Root>, _getEventPriority?: () => any): {
48
- reconciler: Reconciler.Reconciler<UseBoundStore<RootState, import("zustand").StoreApi<RootState>>, Instance, never, Instance, Instance>;
48
+ reconciler: Reconciler.Reconciler<UseBoundStore<RootState, import("zustand").StoreApi<RootState>>, Instance, void, Instance, Instance>;
49
49
  applyProps: typeof applyProps;
50
50
  };
51
51
  export { prepare, createRenderer, extend };
@@ -13,7 +13,7 @@ export declare type UnblockProps = {
13
13
  };
14
14
  export declare function Block({ set }: Omit<UnblockProps, 'children'>): null;
15
15
  export declare class ErrorBoundary extends React.Component<{
16
- set: React.Dispatch<any>;
16
+ set: React.Dispatch<Error | undefined>;
17
17
  children: React.ReactNode;
18
18
  }, {
19
19
  error: boolean;
@@ -24,7 +24,7 @@ export declare class ErrorBoundary extends React.Component<{
24
24
  static getDerivedStateFromError: () => {
25
25
  error: boolean;
26
26
  };
27
- componentDidCatch(error: any): void;
27
+ componentDidCatch(err: Error): void;
28
28
  render(): React.ReactNode;
29
29
  }
30
30
  export declare const DEFAULT = "__default";
@@ -45,8 +45,8 @@ class ErrorBoundary extends React.Component {
45
45
  };
46
46
  }
47
47
 
48
- componentDidCatch(error) {
49
- this.props.set(error);
48
+ componentDidCatch(err) {
49
+ this.props.set(err);
50
50
  }
51
51
 
52
52
  render() {
@@ -849,7 +849,7 @@ function createRenderer(_roots, _getEventPriority) {
849
849
  }
850
850
 
851
851
  if (type === 'primitive') {
852
- if (props.object === undefined) throw `Primitives without 'object' are invalid!`;
852
+ if (props.object === undefined) throw new Error("R3F: Primitives without 'object' are invalid!");
853
853
  const object = props.object;
854
854
  instance = prepare(object, {
855
855
  type,
@@ -861,11 +861,11 @@ function createRenderer(_roots, _getEventPriority) {
861
861
  const target = catalogue[name];
862
862
 
863
863
  if (!target) {
864
- throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`;
864
+ throw new Error(`R3F: ${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`);
865
865
  } // Throw if an object or literal was passed for args
866
866
 
867
867
 
868
- if (!Array.isArray(args)) throw 'The args prop must be an array!'; // Instanciate new object, link it to the root
868
+ if (!Array.isArray(args)) throw new Error('R3F: The args prop must be an array!'); // Instanciate new object, link it to the root
869
869
  // Append memoized props with args so it's not forgotten
870
870
 
871
871
  instance = prepare(new target(...args), {
@@ -1043,7 +1043,10 @@ function createRenderer(_roots, _getEventPriority) {
1043
1043
  }
1044
1044
  }
1045
1045
  });
1046
- }
1046
+ } // Don't handle text instances, warn on undefined behavior
1047
+
1048
+
1049
+ const handleTextInstance = () => console.warn('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
1047
1050
 
1048
1051
  const reconciler = Reconciler({
1049
1052
  createInstance,
@@ -1057,13 +1060,20 @@ function createRenderer(_roots, _getEventPriority) {
1057
1060
  supportsHydration: false,
1058
1061
  noTimeout: -1,
1059
1062
  appendChildToContainer: (container, child) => {
1063
+ if (!child) return;
1060
1064
  const scene = container.getState().scene; // Link current root to the default scene
1061
1065
 
1062
1066
  scene.__r3f.root = container;
1063
1067
  appendChild(scene, child);
1064
1068
  },
1065
- removeChildFromContainer: (container, child) => removeChild(container.getState().scene, child),
1066
- insertInContainerBefore: (container, child, beforeChild) => insertBefore(container.getState().scene, child, beforeChild),
1069
+ removeChildFromContainer: (container, child) => {
1070
+ if (!child) return;
1071
+ removeChild(container.getState().scene, child);
1072
+ },
1073
+ insertInContainerBefore: (container, child, beforeChild) => {
1074
+ if (!child || !beforeChild) return;
1075
+ insertBefore(container.getState().scene, child, beforeChild);
1076
+ },
1067
1077
  getRootHostContext: () => null,
1068
1078
  getChildHostContext: parentHostContext => parentHostContext,
1069
1079
 
@@ -1093,7 +1103,7 @@ function createRenderer(_roots, _getEventPriority) {
1093
1103
  ...restOld
1094
1104
  } = oldProps; // Throw if an object or literal was passed for args
1095
1105
 
1096
- if (!Array.isArray(argsNew)) throw 'The args prop must be an array!'; // If it has new props or arguments, then it needs to be re-instantiated
1106
+ if (!Array.isArray(argsNew)) throw new Error('R3F: the args prop must be an array!'); // If it has new props or arguments, then it needs to be re-instantiated
1097
1107
 
1098
1108
  if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
1099
1109
 
@@ -1155,13 +1165,9 @@ function createRenderer(_roots, _getEventPriority) {
1155
1165
  invalidateInstance(instance);
1156
1166
  },
1157
1167
 
1158
- createTextInstance: () => {
1159
- throw new Error('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
1160
- },
1161
- hideTextInstance: () => {
1162
- throw new Error('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
1163
- },
1164
- unhideTextInstance: () => {},
1168
+ createTextInstance: handleTextInstance,
1169
+ hideTextInstance: handleTextInstance,
1170
+ unhideTextInstance: handleTextInstance,
1165
1171
  // https://github.com/pmndrs/react-three-fiber/pull/2360#discussion_r916356874
1166
1172
  // @ts-ignore
1167
1173
  getCurrentEventPriority: () => _getEventPriority ? _getEventPriority() : DefaultEventPriority,
@@ -1560,7 +1566,7 @@ function createLoop(roots) {
1560
1566
 
1561
1567
  function useStore() {
1562
1568
  const store = React.useContext(context);
1563
- if (!store) throw `R3F hooks can only be used within the Canvas component!`;
1569
+ if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
1564
1570
  return store;
1565
1571
  }
1566
1572
  /**
@@ -1604,7 +1610,7 @@ function loadingFn(extensions, onProgress) {
1604
1610
  return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => {
1605
1611
  if (data.scene) Object.assign(data, buildGraph(data.scene));
1606
1612
  res(data);
1607
- }, onProgress, error => reject(`Could not load ${input}: ${error.message}`)))));
1613
+ }, onProgress, error => reject(new Error(`Could not load ${input}: ${error.message})`))))));
1608
1614
  };
1609
1615
  }
1610
1616
  /**
@@ -1667,11 +1673,43 @@ const createRendererInstance = (gl, canvas) => {
1667
1673
  });
1668
1674
  };
1669
1675
 
1676
+ function isCanvas(maybeCanvas) {
1677
+ return maybeCanvas instanceof HTMLCanvasElement;
1678
+ }
1679
+
1680
+ function computeInitialSize(canvas, defaultSize) {
1681
+ if (defaultSize) {
1682
+ return defaultSize;
1683
+ }
1684
+
1685
+ if (isCanvas(canvas) && canvas.parentElement) {
1686
+ const {
1687
+ width,
1688
+ height,
1689
+ top,
1690
+ left
1691
+ } = canvas.parentElement.getBoundingClientRect();
1692
+ return {
1693
+ width,
1694
+ height,
1695
+ top,
1696
+ left
1697
+ };
1698
+ }
1699
+
1700
+ return {
1701
+ width: 0,
1702
+ height: 0,
1703
+ top: 0,
1704
+ left: 0
1705
+ };
1706
+ }
1707
+
1670
1708
  function createRoot(canvas) {
1671
1709
  // Check against mistaken use of createRoot
1672
- let prevRoot = roots.get(canvas);
1673
- let prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
1674
- let prevStore = prevRoot == null ? void 0 : prevRoot.store;
1710
+ const prevRoot = roots.get(canvas);
1711
+ const prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
1712
+ const prevStore = prevRoot == null ? void 0 : prevRoot.store;
1675
1713
  if (prevRoot) console.warn('R3F.createRoot should only be called once!'); // Report when an error was detected in a previous render
1676
1714
  // https://github.com/pmndrs/react-three-fiber/pull/2261
1677
1715
 
@@ -1695,7 +1733,7 @@ function createRoot(canvas) {
1695
1733
  configure(props = {}) {
1696
1734
  let {
1697
1735
  gl: glConfig,
1698
- size,
1736
+ size: propsSize,
1699
1737
  events,
1700
1738
  onCreated: onCreatedCallback,
1701
1739
  shadows = false,
@@ -1830,17 +1868,7 @@ function createRoot(canvas) {
1830
1868
 
1831
1869
  if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr); // Check size, allow it to take on container bounds initially
1832
1870
 
1833
- size = size || (canvas.parentElement ? {
1834
- width: canvas.parentElement.clientWidth,
1835
- height: canvas.parentElement.clientHeight,
1836
- top: canvas.parentElement.clientTop,
1837
- left: canvas.parentElement.clientLeft
1838
- } : {
1839
- width: 0,
1840
- height: 0,
1841
- top: 0,
1842
- left: 0
1843
- });
1871
+ const size = computeInitialSize(canvas, propsSize);
1844
1872
 
1845
1873
  if (!is.equ(size, state.size, shallowLoose)) {
1846
1874
  state.setSize(size.width, size.height, size.updateStyle, size.top, size.left);
@@ -72,8 +72,8 @@ class ErrorBoundary extends React__namespace.Component {
72
72
  };
73
73
  }
74
74
 
75
- componentDidCatch(error) {
76
- this.props.set(error);
75
+ componentDidCatch(err) {
76
+ this.props.set(err);
77
77
  }
78
78
 
79
79
  render() {
@@ -876,7 +876,7 @@ function createRenderer(_roots, _getEventPriority) {
876
876
  }
877
877
 
878
878
  if (type === 'primitive') {
879
- if (props.object === undefined) throw `Primitives without 'object' are invalid!`;
879
+ if (props.object === undefined) throw new Error("R3F: Primitives without 'object' are invalid!");
880
880
  const object = props.object;
881
881
  instance = prepare(object, {
882
882
  type,
@@ -888,11 +888,11 @@ function createRenderer(_roots, _getEventPriority) {
888
888
  const target = catalogue[name];
889
889
 
890
890
  if (!target) {
891
- throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`;
891
+ throw new Error(`R3F: ${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`);
892
892
  } // Throw if an object or literal was passed for args
893
893
 
894
894
 
895
- if (!Array.isArray(args)) throw 'The args prop must be an array!'; // Instanciate new object, link it to the root
895
+ if (!Array.isArray(args)) throw new Error('R3F: The args prop must be an array!'); // Instanciate new object, link it to the root
896
896
  // Append memoized props with args so it's not forgotten
897
897
 
898
898
  instance = prepare(new target(...args), {
@@ -1070,7 +1070,10 @@ function createRenderer(_roots, _getEventPriority) {
1070
1070
  }
1071
1071
  }
1072
1072
  });
1073
- }
1073
+ } // Don't handle text instances, warn on undefined behavior
1074
+
1075
+
1076
+ const handleTextInstance = () => console.warn('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
1074
1077
 
1075
1078
  const reconciler = Reconciler__default["default"]({
1076
1079
  createInstance,
@@ -1084,13 +1087,20 @@ function createRenderer(_roots, _getEventPriority) {
1084
1087
  supportsHydration: false,
1085
1088
  noTimeout: -1,
1086
1089
  appendChildToContainer: (container, child) => {
1090
+ if (!child) return;
1087
1091
  const scene = container.getState().scene; // Link current root to the default scene
1088
1092
 
1089
1093
  scene.__r3f.root = container;
1090
1094
  appendChild(scene, child);
1091
1095
  },
1092
- removeChildFromContainer: (container, child) => removeChild(container.getState().scene, child),
1093
- insertInContainerBefore: (container, child, beforeChild) => insertBefore(container.getState().scene, child, beforeChild),
1096
+ removeChildFromContainer: (container, child) => {
1097
+ if (!child) return;
1098
+ removeChild(container.getState().scene, child);
1099
+ },
1100
+ insertInContainerBefore: (container, child, beforeChild) => {
1101
+ if (!child || !beforeChild) return;
1102
+ insertBefore(container.getState().scene, child, beforeChild);
1103
+ },
1094
1104
  getRootHostContext: () => null,
1095
1105
  getChildHostContext: parentHostContext => parentHostContext,
1096
1106
 
@@ -1120,7 +1130,7 @@ function createRenderer(_roots, _getEventPriority) {
1120
1130
  ...restOld
1121
1131
  } = oldProps; // Throw if an object or literal was passed for args
1122
1132
 
1123
- if (!Array.isArray(argsNew)) throw 'The args prop must be an array!'; // If it has new props or arguments, then it needs to be re-instantiated
1133
+ if (!Array.isArray(argsNew)) throw new Error('R3F: the args prop must be an array!'); // If it has new props or arguments, then it needs to be re-instantiated
1124
1134
 
1125
1135
  if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
1126
1136
 
@@ -1182,13 +1192,9 @@ function createRenderer(_roots, _getEventPriority) {
1182
1192
  invalidateInstance(instance);
1183
1193
  },
1184
1194
 
1185
- createTextInstance: () => {
1186
- throw new Error('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
1187
- },
1188
- hideTextInstance: () => {
1189
- throw new Error('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
1190
- },
1191
- unhideTextInstance: () => {},
1195
+ createTextInstance: handleTextInstance,
1196
+ hideTextInstance: handleTextInstance,
1197
+ unhideTextInstance: handleTextInstance,
1192
1198
  // https://github.com/pmndrs/react-three-fiber/pull/2360#discussion_r916356874
1193
1199
  // @ts-ignore
1194
1200
  getCurrentEventPriority: () => _getEventPriority ? _getEventPriority() : constants.DefaultEventPriority,
@@ -1587,7 +1593,7 @@ function createLoop(roots) {
1587
1593
 
1588
1594
  function useStore() {
1589
1595
  const store = React__namespace.useContext(context);
1590
- if (!store) throw `R3F hooks can only be used within the Canvas component!`;
1596
+ if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
1591
1597
  return store;
1592
1598
  }
1593
1599
  /**
@@ -1631,7 +1637,7 @@ function loadingFn(extensions, onProgress) {
1631
1637
  return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => {
1632
1638
  if (data.scene) Object.assign(data, buildGraph(data.scene));
1633
1639
  res(data);
1634
- }, onProgress, error => reject(`Could not load ${input}: ${error.message}`)))));
1640
+ }, onProgress, error => reject(new Error(`Could not load ${input}: ${error.message})`))))));
1635
1641
  };
1636
1642
  }
1637
1643
  /**
@@ -1694,11 +1700,43 @@ const createRendererInstance = (gl, canvas) => {
1694
1700
  });
1695
1701
  };
1696
1702
 
1703
+ function isCanvas(maybeCanvas) {
1704
+ return maybeCanvas instanceof HTMLCanvasElement;
1705
+ }
1706
+
1707
+ function computeInitialSize(canvas, defaultSize) {
1708
+ if (defaultSize) {
1709
+ return defaultSize;
1710
+ }
1711
+
1712
+ if (isCanvas(canvas) && canvas.parentElement) {
1713
+ const {
1714
+ width,
1715
+ height,
1716
+ top,
1717
+ left
1718
+ } = canvas.parentElement.getBoundingClientRect();
1719
+ return {
1720
+ width,
1721
+ height,
1722
+ top,
1723
+ left
1724
+ };
1725
+ }
1726
+
1727
+ return {
1728
+ width: 0,
1729
+ height: 0,
1730
+ top: 0,
1731
+ left: 0
1732
+ };
1733
+ }
1734
+
1697
1735
  function createRoot(canvas) {
1698
1736
  // Check against mistaken use of createRoot
1699
- let prevRoot = roots.get(canvas);
1700
- let prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
1701
- let prevStore = prevRoot == null ? void 0 : prevRoot.store;
1737
+ const prevRoot = roots.get(canvas);
1738
+ const prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
1739
+ const prevStore = prevRoot == null ? void 0 : prevRoot.store;
1702
1740
  if (prevRoot) console.warn('R3F.createRoot should only be called once!'); // Report when an error was detected in a previous render
1703
1741
  // https://github.com/pmndrs/react-three-fiber/pull/2261
1704
1742
 
@@ -1722,7 +1760,7 @@ function createRoot(canvas) {
1722
1760
  configure(props = {}) {
1723
1761
  let {
1724
1762
  gl: glConfig,
1725
- size,
1763
+ size: propsSize,
1726
1764
  events,
1727
1765
  onCreated: onCreatedCallback,
1728
1766
  shadows = false,
@@ -1857,17 +1895,7 @@ function createRoot(canvas) {
1857
1895
 
1858
1896
  if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr); // Check size, allow it to take on container bounds initially
1859
1897
 
1860
- size = size || (canvas.parentElement ? {
1861
- width: canvas.parentElement.clientWidth,
1862
- height: canvas.parentElement.clientHeight,
1863
- top: canvas.parentElement.clientTop,
1864
- left: canvas.parentElement.clientLeft
1865
- } : {
1866
- width: 0,
1867
- height: 0,
1868
- top: 0,
1869
- left: 0
1870
- });
1898
+ const size = computeInitialSize(canvas, propsSize);
1871
1899
 
1872
1900
  if (!is.equ(size, state.size, shallowLoose)) {
1873
1901
  state.setSize(size.width, size.height, size.updateStyle, size.top, size.left);
@@ -72,8 +72,8 @@ class ErrorBoundary extends React__namespace.Component {
72
72
  };
73
73
  }
74
74
 
75
- componentDidCatch(error) {
76
- this.props.set(error);
75
+ componentDidCatch(err) {
76
+ this.props.set(err);
77
77
  }
78
78
 
79
79
  render() {
@@ -876,7 +876,7 @@ function createRenderer(_roots, _getEventPriority) {
876
876
  }
877
877
 
878
878
  if (type === 'primitive') {
879
- if (props.object === undefined) throw `Primitives without 'object' are invalid!`;
879
+ if (props.object === undefined) throw new Error("R3F: Primitives without 'object' are invalid!");
880
880
  const object = props.object;
881
881
  instance = prepare(object, {
882
882
  type,
@@ -888,11 +888,11 @@ function createRenderer(_roots, _getEventPriority) {
888
888
  const target = catalogue[name];
889
889
 
890
890
  if (!target) {
891
- throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`;
891
+ throw new Error(`R3F: ${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`);
892
892
  } // Throw if an object or literal was passed for args
893
893
 
894
894
 
895
- if (!Array.isArray(args)) throw 'The args prop must be an array!'; // Instanciate new object, link it to the root
895
+ if (!Array.isArray(args)) throw new Error('R3F: The args prop must be an array!'); // Instanciate new object, link it to the root
896
896
  // Append memoized props with args so it's not forgotten
897
897
 
898
898
  instance = prepare(new target(...args), {
@@ -1070,7 +1070,10 @@ function createRenderer(_roots, _getEventPriority) {
1070
1070
  }
1071
1071
  }
1072
1072
  });
1073
- }
1073
+ } // Don't handle text instances, warn on undefined behavior
1074
+
1075
+
1076
+ const handleTextInstance = () => console.warn('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
1074
1077
 
1075
1078
  const reconciler = Reconciler__default["default"]({
1076
1079
  createInstance,
@@ -1084,13 +1087,20 @@ function createRenderer(_roots, _getEventPriority) {
1084
1087
  supportsHydration: false,
1085
1088
  noTimeout: -1,
1086
1089
  appendChildToContainer: (container, child) => {
1090
+ if (!child) return;
1087
1091
  const scene = container.getState().scene; // Link current root to the default scene
1088
1092
 
1089
1093
  scene.__r3f.root = container;
1090
1094
  appendChild(scene, child);
1091
1095
  },
1092
- removeChildFromContainer: (container, child) => removeChild(container.getState().scene, child),
1093
- insertInContainerBefore: (container, child, beforeChild) => insertBefore(container.getState().scene, child, beforeChild),
1096
+ removeChildFromContainer: (container, child) => {
1097
+ if (!child) return;
1098
+ removeChild(container.getState().scene, child);
1099
+ },
1100
+ insertInContainerBefore: (container, child, beforeChild) => {
1101
+ if (!child || !beforeChild) return;
1102
+ insertBefore(container.getState().scene, child, beforeChild);
1103
+ },
1094
1104
  getRootHostContext: () => null,
1095
1105
  getChildHostContext: parentHostContext => parentHostContext,
1096
1106
 
@@ -1120,7 +1130,7 @@ function createRenderer(_roots, _getEventPriority) {
1120
1130
  ...restOld
1121
1131
  } = oldProps; // Throw if an object or literal was passed for args
1122
1132
 
1123
- if (!Array.isArray(argsNew)) throw 'The args prop must be an array!'; // If it has new props or arguments, then it needs to be re-instantiated
1133
+ if (!Array.isArray(argsNew)) throw new Error('R3F: the args prop must be an array!'); // If it has new props or arguments, then it needs to be re-instantiated
1124
1134
 
1125
1135
  if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
1126
1136
 
@@ -1182,13 +1192,9 @@ function createRenderer(_roots, _getEventPriority) {
1182
1192
  invalidateInstance(instance);
1183
1193
  },
1184
1194
 
1185
- createTextInstance: () => {
1186
- throw new Error('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
1187
- },
1188
- hideTextInstance: () => {
1189
- throw new Error('Text is not allowed in the R3F tree! This could be stray whitespace or characters.');
1190
- },
1191
- unhideTextInstance: () => {},
1195
+ createTextInstance: handleTextInstance,
1196
+ hideTextInstance: handleTextInstance,
1197
+ unhideTextInstance: handleTextInstance,
1192
1198
  // https://github.com/pmndrs/react-three-fiber/pull/2360#discussion_r916356874
1193
1199
  // @ts-ignore
1194
1200
  getCurrentEventPriority: () => _getEventPriority ? _getEventPriority() : constants.DefaultEventPriority,
@@ -1587,7 +1593,7 @@ function createLoop(roots) {
1587
1593
 
1588
1594
  function useStore() {
1589
1595
  const store = React__namespace.useContext(context);
1590
- if (!store) throw `R3F hooks can only be used within the Canvas component!`;
1596
+ if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
1591
1597
  return store;
1592
1598
  }
1593
1599
  /**
@@ -1631,7 +1637,7 @@ function loadingFn(extensions, onProgress) {
1631
1637
  return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => {
1632
1638
  if (data.scene) Object.assign(data, buildGraph(data.scene));
1633
1639
  res(data);
1634
- }, onProgress, error => reject(`Could not load ${input}: ${error.message}`)))));
1640
+ }, onProgress, error => reject(new Error(`Could not load ${input}: ${error.message})`))))));
1635
1641
  };
1636
1642
  }
1637
1643
  /**
@@ -1694,11 +1700,43 @@ const createRendererInstance = (gl, canvas) => {
1694
1700
  });
1695
1701
  };
1696
1702
 
1703
+ function isCanvas(maybeCanvas) {
1704
+ return maybeCanvas instanceof HTMLCanvasElement;
1705
+ }
1706
+
1707
+ function computeInitialSize(canvas, defaultSize) {
1708
+ if (defaultSize) {
1709
+ return defaultSize;
1710
+ }
1711
+
1712
+ if (isCanvas(canvas) && canvas.parentElement) {
1713
+ const {
1714
+ width,
1715
+ height,
1716
+ top,
1717
+ left
1718
+ } = canvas.parentElement.getBoundingClientRect();
1719
+ return {
1720
+ width,
1721
+ height,
1722
+ top,
1723
+ left
1724
+ };
1725
+ }
1726
+
1727
+ return {
1728
+ width: 0,
1729
+ height: 0,
1730
+ top: 0,
1731
+ left: 0
1732
+ };
1733
+ }
1734
+
1697
1735
  function createRoot(canvas) {
1698
1736
  // Check against mistaken use of createRoot
1699
- let prevRoot = roots.get(canvas);
1700
- let prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
1701
- let prevStore = prevRoot == null ? void 0 : prevRoot.store;
1737
+ const prevRoot = roots.get(canvas);
1738
+ const prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
1739
+ const prevStore = prevRoot == null ? void 0 : prevRoot.store;
1702
1740
  if (prevRoot) console.warn('R3F.createRoot should only be called once!'); // Report when an error was detected in a previous render
1703
1741
  // https://github.com/pmndrs/react-three-fiber/pull/2261
1704
1742
 
@@ -1722,7 +1760,7 @@ function createRoot(canvas) {
1722
1760
  configure(props = {}) {
1723
1761
  let {
1724
1762
  gl: glConfig,
1725
- size,
1763
+ size: propsSize,
1726
1764
  events,
1727
1765
  onCreated: onCreatedCallback,
1728
1766
  shadows = false,
@@ -1857,17 +1895,7 @@ function createRoot(canvas) {
1857
1895
 
1858
1896
  if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr); // Check size, allow it to take on container bounds initially
1859
1897
 
1860
- size = size || (canvas.parentElement ? {
1861
- width: canvas.parentElement.clientWidth,
1862
- height: canvas.parentElement.clientHeight,
1863
- top: canvas.parentElement.clientTop,
1864
- left: canvas.parentElement.clientLeft
1865
- } : {
1866
- width: 0,
1867
- height: 0,
1868
- top: 0,
1869
- left: 0
1870
- });
1898
+ const size = computeInitialSize(canvas, propsSize);
1871
1899
 
1872
1900
  if (!is.equ(size, state.size, shallowLoose)) {
1873
1901
  state.setSize(size.width, size.height, size.updateStyle, size.top, size.left);
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('./index-6716e497.cjs.dev.js');
5
+ var index = require('./index-bcd3e47c.cjs.dev.js');
6
6
  var _extends = require('@babel/runtime/helpers/extends');
7
7
  var React = require('react');
8
8
  var THREE = require('three');
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('./index-8296e46a.cjs.prod.js');
5
+ var index = require('./index-e086bd20.cjs.prod.js');
6
6
  var _extends = require('@babel/runtime/helpers/extends');
7
7
  var React = require('react');
8
8
  var THREE = require('three');
@@ -1,5 +1,5 @@
1
- import { c as createEvents, e as extend, u as useMutableCallback, a as createRoot, E as ErrorBoundary, B as Block, b as useIsomorphicLayoutEffect, d as unmountComponentAtNode } from './index-2e68c2a1.esm.js';
2
- export { t as ReactThreeFiber, s as _roots, q as act, n as addAfterEffect, m as addEffect, o as addTail, l as advance, i as applyProps, f as context, c as createEvents, g as createPortal, a as createRoot, j as dispose, e as extend, p as getRootState, k as invalidate, h as reconciler, r as render, d as unmountComponentAtNode, x as useFrame, y as useGraph, z as useLoader, v as useStore, w as useThree } from './index-2e68c2a1.esm.js';
1
+ import { c as createEvents, e as extend, u as useMutableCallback, a as createRoot, E as ErrorBoundary, B as Block, b as useIsomorphicLayoutEffect, d as unmountComponentAtNode } from './index-212b30d8.esm.js';
2
+ export { t as ReactThreeFiber, s as _roots, q as act, n as addAfterEffect, m as addEffect, o as addTail, l as advance, i as applyProps, f as context, c as createEvents, g as createPortal, a as createRoot, j as dispose, e as extend, p as getRootState, k as invalidate, h as reconciler, r as render, d as unmountComponentAtNode, x as useFrame, y as useGraph, z as useLoader, v as useStore, w as useThree } from './index-212b30d8.esm.js';
3
3
  import _extends from '@babel/runtime/helpers/esm/extends';
4
4
  import * as React from 'react';
5
5
  import * as THREE from 'three';
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('../../dist/index-6716e497.cjs.dev.js');
5
+ var index = require('../../dist/index-bcd3e47c.cjs.dev.js');
6
6
  var _extends = require('@babel/runtime/helpers/extends');
7
7
  var React = require('react');
8
8
  var THREE = require('three');
@@ -39,6 +39,8 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
39
39
  var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
40
40
  var Pressability__default = /*#__PURE__*/_interopDefault(Pressability);
41
41
 
42
+ /* eslint-enable import/default, import/no-named-as-default, import/no-named-as-default-member */
43
+
42
44
  const EVENTS = {
43
45
  PRESS: 'onPress',
44
46
  PRESSIN: 'onPressIn',
@@ -144,7 +146,7 @@ function getAsset(input) {
144
146
  return expAsset.fromModule(input);
145
147
 
146
148
  default:
147
- throw 'Invalid asset! Must be a URI or module.';
149
+ throw new Error('R3F: Invalid asset! Must be a URI or module.');
148
150
  }
149
151
  }
150
152
 
@@ -272,7 +274,7 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(({
272
274
  React__namespace.useImperativeHandle(forwardedRef, () => viewRef.current);
273
275
  const handlePointerMissed = index.useMutableCallback(onPointerMissed);
274
276
  const [block, setBlock] = React__namespace.useState(false);
275
- const [error, setError] = React__namespace.useState(false); // Suspend this component if block is a promise (2nd run)
277
+ const [error, setError] = React__namespace.useState(undefined); // Suspend this component if block is a promise (2nd run)
276
278
 
277
279
  if (block) throw block; // Throw exception outwards if anything within canvas throws
278
280
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('../../dist/index-8296e46a.cjs.prod.js');
5
+ var index = require('../../dist/index-e086bd20.cjs.prod.js');
6
6
  var _extends = require('@babel/runtime/helpers/extends');
7
7
  var React = require('react');
8
8
  var THREE = require('three');
@@ -39,6 +39,8 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
39
39
  var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
40
40
  var Pressability__default = /*#__PURE__*/_interopDefault(Pressability);
41
41
 
42
+ /* eslint-enable import/default, import/no-named-as-default, import/no-named-as-default-member */
43
+
42
44
  const EVENTS = {
43
45
  PRESS: 'onPress',
44
46
  PRESSIN: 'onPressIn',
@@ -144,7 +146,7 @@ function getAsset(input) {
144
146
  return expAsset.fromModule(input);
145
147
 
146
148
  default:
147
- throw 'Invalid asset! Must be a URI or module.';
149
+ throw new Error('R3F: Invalid asset! Must be a URI or module.');
148
150
  }
149
151
  }
150
152
 
@@ -272,7 +274,7 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(({
272
274
  React__namespace.useImperativeHandle(forwardedRef, () => viewRef.current);
273
275
  const handlePointerMissed = index.useMutableCallback(onPointerMissed);
274
276
  const [block, setBlock] = React__namespace.useState(false);
275
- const [error, setError] = React__namespace.useState(false); // Suspend this component if block is a promise (2nd run)
277
+ const [error, setError] = React__namespace.useState(undefined); // Suspend this component if block is a promise (2nd run)
276
278
 
277
279
  if (block) throw block; // Throw exception outwards if anything within canvas throws
278
280
 
@@ -1,5 +1,5 @@
1
- import { c as createEvents, e as extend, u as useMutableCallback, a as createRoot, E as ErrorBoundary, B as Block, d as unmountComponentAtNode } from '../../dist/index-2e68c2a1.esm.js';
2
- export { t as ReactThreeFiber, s as _roots, q as act, n as addAfterEffect, m as addEffect, o as addTail, l as advance, i as applyProps, f as context, g as createPortal, a as createRoot, j as dispose, e as extend, p as getRootState, k as invalidate, h as reconciler, r as render, d as unmountComponentAtNode, x as useFrame, y as useGraph, z as useLoader, v as useStore, w as useThree } from '../../dist/index-2e68c2a1.esm.js';
1
+ import { c as createEvents, e as extend, u as useMutableCallback, a as createRoot, E as ErrorBoundary, B as Block, d as unmountComponentAtNode } from '../../dist/index-212b30d8.esm.js';
2
+ export { t as ReactThreeFiber, s as _roots, q as act, n as addAfterEffect, m as addEffect, o as addTail, l as advance, i as applyProps, f as context, g as createPortal, a as createRoot, j as dispose, e as extend, p as getRootState, k as invalidate, h as reconciler, r as render, d as unmountComponentAtNode, x as useFrame, y as useGraph, z as useLoader, v as useStore, w as useThree } from '../../dist/index-212b30d8.esm.js';
3
3
  import _extends from '@babel/runtime/helpers/esm/extends';
4
4
  import * as React from 'react';
5
5
  import * as THREE from 'three';
@@ -12,6 +12,8 @@ import 'react-reconciler';
12
12
  import 'scheduler';
13
13
  import 'suspend-react';
14
14
 
15
+ /* eslint-enable import/default, import/no-named-as-default, import/no-named-as-default-member */
16
+
15
17
  const EVENTS = {
16
18
  PRESS: 'onPress',
17
19
  PRESSIN: 'onPressIn',
@@ -117,7 +119,7 @@ function getAsset(input) {
117
119
  return expAsset.fromModule(input);
118
120
 
119
121
  default:
120
- throw 'Invalid asset! Must be a URI or module.';
122
+ throw new Error('R3F: Invalid asset! Must be a URI or module.');
121
123
  }
122
124
  }
123
125
 
@@ -245,7 +247,7 @@ const Canvas = /*#__PURE__*/React.forwardRef(({
245
247
  React.useImperativeHandle(forwardedRef, () => viewRef.current);
246
248
  const handlePointerMissed = useMutableCallback(onPointerMissed);
247
249
  const [block, setBlock] = React.useState(false);
248
- const [error, setError] = React.useState(false); // Suspend this component if block is a promise (2nd run)
250
+ const [error, setError] = React.useState(undefined); // Suspend this component if block is a promise (2nd run)
249
251
 
250
252
  if (block) throw block; // Throw exception outwards if anything within canvas throws
251
253
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/fiber",
3
- "version": "8.2.1",
3
+ "version": "8.3.0",
4
4
  "description": "A React renderer for Threejs",
5
5
  "keywords": [
6
6
  "react",