@react-three/fiber 9.0.0-alpha.4 → 9.0.0-alpha.6

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.16.5
4
+
5
+ ### Patch Changes
6
+
7
+ - cb913e01: fix: use fast JSX, future JSX types
8
+
9
+ ## 8.16.4
10
+
11
+ ### Patch Changes
12
+
13
+ - 1270d24c: fix: missing dependency on inject function
14
+
15
+ ## 8.16.3
16
+
17
+ ### Patch Changes
18
+
19
+ - 9c83502c: fix(Canvas): don't override camera frustum props
20
+
3
21
  ## 8.16.2
4
22
 
5
23
  ### Patch Changes
@@ -5,11 +5,15 @@ import { ObjectMap } from "./utils.js";
5
5
  import type { Instance } from "./reconciler.js";
6
6
  /**
7
7
  * Exposes an object's {@link Instance}.
8
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#useInstanceHandle
8
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#useinstancehandle
9
9
  *
10
10
  * **Note**: this is an escape hatch to react-internal fields. Expect this to change significantly between versions.
11
11
  */
12
- export declare function useInstanceHandle<O>(ref: React.RefObject<O>): React.RefObject<Instance>;
12
+ export declare function useInstanceHandle<T>(ref: React.RefObject<T>): React.RefObject<Instance<T>>;
13
+ /**
14
+ * Returns the R3F Canvas' Zustand store. Useful for [transient updates](https://github.com/pmndrs/zustand#transient-updates-for-often-occurring-state-changes).
15
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usestore
16
+ */
13
17
  export declare function useStore(): RootStore;
14
18
  /**
15
19
  * Accesses R3F's internal state, containing renderer, canvas, scene, etc.
@@ -24,7 +28,7 @@ export declare function useThree<T = RootState>(selector?: (state: RootState) =>
24
28
  export declare function useFrame(callback: RenderCallback, renderPriority?: number): null;
25
29
  /**
26
30
  * Executes a callback in a given update stage.
27
- * Uses the stage instance to indetify which stage to target in the lifecycle.
31
+ * Uses the stage instance to identify which stage to target in the lifecycle.
28
32
  */
29
33
  export declare function useUpdate(callback: UpdateCallback, stage?: StageTypes): void;
30
34
  /**
@@ -9,7 +9,7 @@ export type { ReconcilerRoot, GLProps, CameraProps, RenderProps, InjectState } f
9
9
  export { _roots, render, createRoot, unmountComponentAtNode, createPortal } from "./renderer.js";
10
10
  export type { UpdateSubscription } from "./stages.js";
11
11
  export { Stage, FixedStage, Stages } from "./stages.js";
12
- export type { Subscription, Dpr, Size, RenderCallback, UpdateCallback, LegacyAlways, FrameloopMode, FrameloopRender, FrameloopLegacy, Frameloop, Performance, Renderer, StageTypes, XRManager, RootState, RootStore, } from "./store.js";
12
+ export type { Subscription, Dpr, Size, Viewport, RenderCallback, UpdateCallback, LegacyAlways, FrameloopMode, FrameloopRender, FrameloopLegacy, Frameloop, Performance, Renderer, StageTypes, XRManager, RootState, RootStore, } from "./store.js";
13
13
  export { context } from "./store.js";
14
14
  export type { ObjectMap, Camera, Disposable, Act } from "./utils.js";
15
15
  export { applyProps, getRootState, dispose, act, buildGraph } from "./utils.js";
@@ -35,6 +35,7 @@ export interface Instance<O = any> {
35
35
  handlers: Partial<EventHandlers>;
36
36
  attach?: AttachType<O>;
37
37
  previousAttach?: any;
38
+ isHidden: boolean;
38
39
  autoRemovedBeforeAppend?: boolean;
39
40
  }
40
41
  export declare const catalogue: Catalogue;
@@ -80,5 +80,5 @@ export type InjectState = Partial<Omit<RootState, 'events'> & {
80
80
  connected?: any;
81
81
  };
82
82
  }>;
83
- export declare function createPortal(children: React.ReactNode, container: THREE.Object3D, state?: InjectState): JSX.Element;
83
+ export declare function createPortal(children: React.ReactNode, container: THREE.Object3D, state?: InjectState): React.JSX.Element;
84
84
  export {};
@@ -21,6 +21,18 @@ export interface Size {
21
21
  top: number;
22
22
  left: number;
23
23
  }
24
+ export interface Viewport extends Size {
25
+ /** The initial pixel ratio */
26
+ initialDpr: number;
27
+ /** Current pixel ratio */
28
+ dpr: number;
29
+ /** size.width / viewport.width */
30
+ factor: number;
31
+ /** Camera distance */
32
+ distance: number;
33
+ /** Camera aspect ratio: width / height */
34
+ aspect: number;
35
+ }
24
36
  export type RenderCallback = (state: RootState, delta: number, frame?: XRFrame) => void;
25
37
  export type UpdateCallback = RenderCallback;
26
38
  export type LegacyAlways = 'always';
@@ -106,10 +118,12 @@ export interface RootState {
106
118
  frameloop: FrameloopLegacy;
107
119
  /** Adaptive performance interface */
108
120
  performance: Performance;
109
- /** The current pixel ratio */
110
- dpr: number;
111
121
  /** Reactive pixel-size of the canvas */
112
122
  size: Size;
123
+ /** Reactive size of the viewport in threejs units */
124
+ viewport: Viewport & {
125
+ getCurrentViewport: (camera?: Camera, target?: THREE.Vector3 | Parameters<THREE.Vector3['set']>, size?: Size) => Omit<Viewport, 'dpr' | 'initialDpr'>;
126
+ };
113
127
  /** Flags the canvas for render, but doesn't render in itself */
114
128
  invalidate: (frames?: number) => void;
115
129
  /** Advance (render) one step */
@@ -53,4 +53,16 @@ declare module 'react' {
53
53
  }
54
54
  }
55
55
  }
56
+ declare module 'react/jsx-runtime' {
57
+ namespace JSX {
58
+ interface IntrinsicElements extends ThreeElements {
59
+ }
60
+ }
61
+ }
62
+ declare module 'react/jsx-dev-runtime' {
63
+ namespace JSX {
64
+ interface IntrinsicElements extends ThreeElements {
65
+ }
66
+ }
67
+ }
56
68
  export {};
@@ -5,9 +5,9 @@ var React = require('react');
5
5
  var constants = require('react-reconciler/constants');
6
6
  var traditional = require('zustand/traditional');
7
7
  var itsFine = require('its-fine');
8
- var _extends = require('@babel/runtime/helpers/extends');
9
8
  var Reconciler = require('react-reconciler');
10
9
  var scheduler = require('scheduler');
10
+ var jsxRuntime = require('react/jsx-runtime');
11
11
  var suspendReact = require('suspend-react');
12
12
 
13
13
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
@@ -38,10 +38,6 @@ var threeTypes = /*#__PURE__*/Object.freeze({
38
38
  __proto__: null
39
39
  });
40
40
 
41
- // TODO: handle constructor overloads
42
- // https://github.com/pmndrs/react-three-fiber/pull/2931
43
- // https://github.com/microsoft/TypeScript/issues/37079
44
-
45
41
  const catalogue = {};
46
42
  let i = 0;
47
43
  const extend = objects => {
@@ -52,15 +48,17 @@ const extend = objects => {
52
48
  // Returns a component whose name will be inferred in devtools
53
49
  // @ts-expect-error
54
50
  return /*#__PURE__*/React__namespace.forwardRef({
55
- [objects.name]: (props, ref) => /*#__PURE__*/React__namespace.createElement(Component, _extends({}, props, {
51
+ [objects.name]: (props, ref) => /*#__PURE__*/jsxRuntime.jsx(Component, {
52
+ ...props,
56
53
  ref: ref
57
- }))
54
+ })
58
55
  }[objects.name]);
59
56
  } else {
60
57
  return void Object.assign(catalogue, objects);
61
58
  }
62
59
  };
63
- function createInstance(type, props, root) {
60
+ function createInstance(type, props, root, flushPrimitive = true) {
61
+ var _props$object;
64
62
  // Get target from catalogue
65
63
  const name = `${type[0].toUpperCase()}${type.slice(1)}`;
66
64
  const target = catalogue[name];
@@ -74,10 +72,37 @@ function createInstance(type, props, root) {
74
72
  // Throw if an object or literal was passed for args
75
73
  if (props.args !== undefined && !Array.isArray(props.args)) throw new Error('R3F: The args prop must be an array!');
76
74
 
75
+ // Regenerate the R3F instance for primitives to simulate a new object
76
+ if (flushPrimitive && type === 'primitive' && (_props$object = props.object) != null && _props$object.__r3f) delete props.object.__r3f;
77
+
77
78
  // Create instance
78
79
  const instance = prepare(props.object, root, type, props);
79
80
  return instance;
80
81
  }
82
+ function hideInstance(instance) {
83
+ if (!instance.isHidden) {
84
+ var _instance$parent;
85
+ if (instance.props.attach && (_instance$parent = instance.parent) != null && _instance$parent.object) {
86
+ detach(instance.parent, instance);
87
+ } else if (isObject3D(instance.object)) {
88
+ instance.object.visible = false;
89
+ }
90
+ instance.isHidden = true;
91
+ invalidateInstance(instance);
92
+ }
93
+ }
94
+ function unhideInstance(instance) {
95
+ if (instance.isHidden) {
96
+ var _instance$parent2;
97
+ if (instance.props.attach && (_instance$parent2 = instance.parent) != null && _instance$parent2.object) {
98
+ attach(instance.parent, instance);
99
+ } else if (isObject3D(instance.object) && instance.props.visible !== false) {
100
+ instance.object.visible = true;
101
+ }
102
+ instance.isHidden = false;
103
+ invalidateInstance(instance);
104
+ }
105
+ }
81
106
 
82
107
  // https://github.com/facebook/react/issues/20271
83
108
  // This will make sure events and attach are only handled once when trees are complete
@@ -213,8 +238,19 @@ function setFiberInstance(fiber, instance) {
213
238
  }
214
239
  }
215
240
  function switchInstance(oldInstance, type, props, fiber) {
241
+ // If the old instance is hidden, we need to unhide it.
242
+ // React assumes it can discard instances since they're pure for DOM.
243
+ // This isn't true for us since our lifetimes are impure and longliving.
244
+ // So, we manually check if an instance was hidden and unhide it.
245
+ if (oldInstance.isHidden) unhideInstance(oldInstance);
246
+
216
247
  // Create a new instance
217
- const newInstance = createInstance(type, props, oldInstance.root);
248
+ const newInstance = createInstance(type, props, oldInstance.root, false);
249
+
250
+ // Update attach props for primitives since we don't flush them
251
+ if (type === 'primitive') {
252
+ newInstance.props.attach = props.attach;
253
+ }
218
254
 
219
255
  // Move children to new instance
220
256
  for (const child of oldInstance.children) {
@@ -262,7 +298,9 @@ const reconciler = Reconciler__default["default"]({
262
298
  supportsMutation: true,
263
299
  supportsPersistence: false,
264
300
  supportsHydration: false,
265
- createInstance,
301
+ createInstance(type, props, root) {
302
+ return createInstance(type, props, root);
303
+ },
266
304
  removeChild,
267
305
  appendChild,
268
306
  appendInitialChild: appendChild,
@@ -319,8 +357,8 @@ const reconciler = Reconciler__default["default"]({
319
357
  resetAfterCommit: () => {},
320
358
  shouldSetTextContent: () => false,
321
359
  clearContainer: () => false,
322
- hideInstance() {},
323
- unhideInstance() {},
360
+ hideInstance,
361
+ unhideInstance,
324
362
  createTextInstance: handleTextInstance,
325
363
  hideTextInstance: handleTextInstance,
326
364
  unhideTextInstance: handleTextInstance,
@@ -433,7 +471,11 @@ function useBridge() {
433
471
  }) => {
434
472
  const strict = !!itsFine.traverseFiber(fiber, true, node => node.type === React__namespace.StrictMode);
435
473
  const Root = strict ? React__namespace.StrictMode : React__namespace.Fragment;
436
- return /*#__PURE__*/React__namespace.createElement(Root, null, /*#__PURE__*/React__namespace.createElement(ContextBridge, null, children));
474
+ return /*#__PURE__*/jsxRuntime.jsx(Root, {
475
+ children: /*#__PURE__*/jsxRuntime.jsx(ContextBridge, {
476
+ children: children
477
+ })
478
+ });
437
479
  }, [fiber, ContextBridge]);
438
480
  }
439
481
  function Block({
@@ -575,7 +617,8 @@ function prepare(target, root, type, props) {
575
617
  props: getInstanceProps(props),
576
618
  object,
577
619
  eventCount: 0,
578
- handlers: {}
620
+ handlers: {},
621
+ isHidden: false
579
622
  };
580
623
  if (object) {
581
624
  object.__r3f = instance;
@@ -1247,6 +1290,44 @@ const isRenderer = def => !!(def != null && def.render);
1247
1290
  const context = /*#__PURE__*/React__namespace.createContext(null);
1248
1291
  const createStore = (invalidate, advance) => {
1249
1292
  const rootStore = traditional.createWithEqualityFn((set, get) => {
1293
+ const position = new THREE__namespace.Vector3();
1294
+ const defaultTarget = new THREE__namespace.Vector3();
1295
+ const tempTarget = new THREE__namespace.Vector3();
1296
+ function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
1297
+ const {
1298
+ width,
1299
+ height,
1300
+ top,
1301
+ left
1302
+ } = size;
1303
+ const aspect = width / height;
1304
+ if (target instanceof THREE__namespace.Vector3) tempTarget.copy(target);else tempTarget.set(...target);
1305
+ const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
1306
+ if (isOrthographicCamera(camera)) {
1307
+ return {
1308
+ width: width / camera.zoom,
1309
+ height: height / camera.zoom,
1310
+ top,
1311
+ left,
1312
+ factor: 1,
1313
+ distance,
1314
+ aspect
1315
+ };
1316
+ } else {
1317
+ const fov = camera.fov * Math.PI / 180; // convert vertical fov to radians
1318
+ const h = 2 * Math.tan(fov / 2) * distance; // visible height
1319
+ const w = h * (width / height);
1320
+ return {
1321
+ width: w,
1322
+ height: h,
1323
+ top,
1324
+ left,
1325
+ factor: width / w,
1326
+ distance,
1327
+ aspect
1328
+ };
1329
+ }
1330
+ }
1250
1331
  let performanceTimeout = undefined;
1251
1332
  const setPerformanceCurrent = current => set(state => ({
1252
1333
  performance: {
@@ -1295,13 +1376,24 @@ const createStore = (invalidate, advance) => {
1295
1376
  performanceTimeout = setTimeout(() => setPerformanceCurrent(get().performance.max), state.performance.debounce);
1296
1377
  }
1297
1378
  },
1298
- dpr: 1,
1299
1379
  size: {
1300
1380
  width: 0,
1301
1381
  height: 0,
1302
1382
  top: 0,
1303
1383
  left: 0
1304
1384
  },
1385
+ viewport: {
1386
+ initialDpr: 0,
1387
+ dpr: 0,
1388
+ width: 0,
1389
+ height: 0,
1390
+ top: 0,
1391
+ left: 0,
1392
+ aspect: 0,
1393
+ distance: 0,
1394
+ factor: 0,
1395
+ getCurrentViewport
1396
+ },
1305
1397
  setEvents: events => set(state => ({
1306
1398
  ...state,
1307
1399
  events: {
@@ -1310,17 +1402,30 @@ const createStore = (invalidate, advance) => {
1310
1402
  }
1311
1403
  })),
1312
1404
  setSize: (width, height, top = 0, left = 0) => {
1313
- set({
1314
- size: {
1315
- width,
1316
- height,
1317
- top,
1318
- left
1405
+ const camera = get().camera;
1406
+ const size = {
1407
+ width,
1408
+ height,
1409
+ top,
1410
+ left
1411
+ };
1412
+ set(state => ({
1413
+ size,
1414
+ viewport: {
1415
+ ...state.viewport,
1416
+ ...getCurrentViewport(camera, defaultTarget, size)
1319
1417
  }
1320
- });
1418
+ }));
1321
1419
  },
1322
- setDpr: dpr => set({
1323
- dpr: calculateDpr(dpr)
1420
+ setDpr: dpr => set(state => {
1421
+ const resolved = calculateDpr(dpr);
1422
+ return {
1423
+ viewport: {
1424
+ ...state.viewport,
1425
+ dpr: resolved,
1426
+ initialDpr: state.viewport.initialDpr || resolved
1427
+ }
1428
+ };
1324
1429
  }),
1325
1430
  setFrameloop: frameloop => {
1326
1431
  var _frameloop$mode, _frameloop$render, _frameloop$maxDelta;
@@ -1409,23 +1514,39 @@ const createStore = (invalidate, advance) => {
1409
1514
  });
1410
1515
  const state = rootStore.getState();
1411
1516
  let oldSize = state.size;
1412
- let oldDpr = state.dpr;
1413
- rootStore.subscribe(({
1414
- camera,
1415
- size,
1416
- dpr,
1417
- gl
1418
- }) => {
1517
+ let oldDpr = state.viewport.dpr;
1518
+ let oldCamera = state.camera;
1519
+ rootStore.subscribe(() => {
1520
+ const {
1521
+ camera,
1522
+ size,
1523
+ viewport,
1524
+ gl,
1525
+ set
1526
+ } = rootStore.getState();
1527
+
1419
1528
  // Resize camera and renderer on changes to size and pixelratio
1420
- if (size !== oldSize || dpr !== oldDpr) {
1529
+ if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
1421
1530
  oldSize = size;
1422
- oldDpr = dpr;
1531
+ oldDpr = viewport.dpr;
1423
1532
  // Update camera & renderer
1424
1533
  updateCamera(camera, size);
1425
- gl.setPixelRatio(dpr);
1534
+ gl.setPixelRatio(viewport.dpr);
1426
1535
  const updateStyle = typeof HTMLCanvasElement !== 'undefined' && gl.domElement instanceof HTMLCanvasElement;
1427
1536
  gl.setSize(size.width, size.height, updateStyle);
1428
1537
  }
1538
+
1539
+ // Update viewport once the camera changes
1540
+ if (camera !== oldCamera) {
1541
+ oldCamera = camera;
1542
+ // Update viewport
1543
+ set(state => ({
1544
+ viewport: {
1545
+ ...state.viewport,
1546
+ ...state.viewport.getCurrentViewport(camera)
1547
+ }
1548
+ }));
1549
+ }
1429
1550
  });
1430
1551
 
1431
1552
  // Invalidate on any change
@@ -1570,15 +1691,20 @@ const Lifecycle = [Early, Fixed, Update, Late, Render, After];
1570
1691
 
1571
1692
  /**
1572
1693
  * Exposes an object's {@link Instance}.
1573
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#useInstanceHandle
1694
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#useinstancehandle
1574
1695
  *
1575
1696
  * **Note**: this is an escape hatch to react-internal fields. Expect this to change significantly between versions.
1576
1697
  */
1577
1698
  function useInstanceHandle(ref) {
1578
1699
  const instance = React__namespace.useRef(null);
1579
- useIsomorphicLayoutEffect(() => void (instance.current = ref.current.__r3f), [ref]);
1700
+ React__namespace.useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
1580
1701
  return instance;
1581
1702
  }
1703
+
1704
+ /**
1705
+ * Returns the R3F Canvas' Zustand store. Useful for [transient updates](https://github.com/pmndrs/zustand#transient-updates-for-often-occurring-state-changes).
1706
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usestore
1707
+ */
1582
1708
  function useStore() {
1583
1709
  const store = React__namespace.useContext(context);
1584
1710
  if (!store) throw new Error('R3F: Hooks can only be used within the Canvas component!');
@@ -1610,7 +1736,7 @@ function useFrame(callback, renderPriority = 0) {
1610
1736
 
1611
1737
  /**
1612
1738
  * Executes a callback in a given update stage.
1613
- * Uses the stage instance to indetify which stage to target in the lifecycle.
1739
+ * Uses the stage instance to identify which stage to target in the lifecycle.
1614
1740
  */
1615
1741
  function useUpdate(callback, stage = Stages.Update) {
1616
1742
  const store = useStore();
@@ -1657,6 +1783,7 @@ function loadingFn(extensions, onProgress) {
1657
1783
  return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => res(isObject3D(data == null ? void 0 : data.scene) ? Object.assign(data, buildGraph(data.scene)) : data), onProgress, error => reject(new Error(`Could not load ${input}: ${error == null ? void 0 : error.message}`))))));
1658
1784
  };
1659
1785
  }
1786
+
1660
1787
  /**
1661
1788
  * Synchronously loads and caches assets with a three loader.
1662
1789
  *
@@ -1689,9 +1816,6 @@ useLoader.clear = function (loader, input) {
1689
1816
  return suspendReact.clear([loader, ...keys]);
1690
1817
  };
1691
1818
 
1692
- // Shim for OffscreenCanvas since it was removed from DOM types
1693
- // https://github.com/DefinitelyTyped/DefinitelyTyped/pull/54988
1694
-
1695
1819
  const _roots = new Map();
1696
1820
  const shallowLoose = {
1697
1821
  objects: 'shallow',
@@ -1880,7 +2004,15 @@ function createRoot(canvas) {
1880
2004
  const camera = isCamera ? cameraOptions : orthographic ? new THREE__namespace.OrthographicCamera(0, 0, 0, 0, 0.1, 1000) : new THREE__namespace.PerspectiveCamera(75, 0, 0.1, 1000);
1881
2005
  if (!isCamera) {
1882
2006
  camera.position.z = 5;
1883
- if (cameraOptions) applyProps(camera, cameraOptions);
2007
+ if (cameraOptions) {
2008
+ applyProps(camera, cameraOptions);
2009
+ // Preserve user-defined frustum if possible
2010
+ // https://github.com/pmndrs/react-three-fiber/issues/3160
2011
+ if ('aspect' in cameraOptions || 'left' in cameraOptions || 'right' in cameraOptions || 'bottom' in cameraOptions || 'top' in cameraOptions) {
2012
+ camera.manual = true;
2013
+ camera.updateProjectionMatrix();
2014
+ }
2015
+ }
1884
2016
  // Always look at center by default
1885
2017
  if (!state.camera && !(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
1886
2018
  }
@@ -2009,7 +2141,7 @@ function createRoot(canvas) {
2009
2141
  state.setSize(size.width, size.height, size.top, size.left);
2010
2142
  }
2011
2143
  // Check pixelratio
2012
- if (dpr && state.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
2144
+ if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
2013
2145
  // Check frameloop
2014
2146
  if (state.frameloop !== frameloop) state.setFrameloop(frameloop);
2015
2147
  // Check pointer missed
@@ -2035,7 +2167,7 @@ function createRoot(canvas) {
2035
2167
  render(children) {
2036
2168
  // The root has to be configured before it can be rendered
2037
2169
  if (!configured) this.configure();
2038
- reconciler.updateContainer( /*#__PURE__*/React__namespace.createElement(Provider, {
2170
+ reconciler.updateContainer( /*#__PURE__*/jsxRuntime.jsx(Provider, {
2039
2171
  store: store,
2040
2172
  children: children,
2041
2173
  onCreated: onCreated,
@@ -2076,9 +2208,10 @@ function Provider({
2076
2208
  if (!store.getState().events.connected) state.events.connect == null ? void 0 : state.events.connect(rootElement);
2077
2209
  // eslint-disable-next-line react-hooks/exhaustive-deps
2078
2210
  }, []);
2079
- return /*#__PURE__*/React__namespace.createElement(context.Provider, {
2080
- value: store
2081
- }, children);
2211
+ return /*#__PURE__*/jsxRuntime.jsx(context.Provider, {
2212
+ value: store,
2213
+ children: children
2214
+ });
2082
2215
  }
2083
2216
  function unmountComponentAtNode(canvas, callback) {
2084
2217
  const root = _roots.get(canvas);
@@ -2107,7 +2240,7 @@ function unmountComponentAtNode(canvas, callback) {
2107
2240
  }
2108
2241
  }
2109
2242
  function createPortal(children, container, state) {
2110
- return /*#__PURE__*/React__namespace.createElement(Portal, {
2243
+ return /*#__PURE__*/jsxRuntime.jsx(Portal, {
2111
2244
  children: children,
2112
2245
  container: container,
2113
2246
  state: state
@@ -2132,8 +2265,11 @@ function Portal({
2132
2265
  const [raycaster] = React__namespace.useState(() => new THREE__namespace.Raycaster());
2133
2266
  const [pointer] = React__namespace.useState(() => new THREE__namespace.Vector2());
2134
2267
  const inject = useMutableCallback((rootState, injectState) => {
2268
+ let viewport;
2135
2269
  if (injectState.camera && size) {
2136
2270
  const camera = injectState.camera;
2271
+ // Calculate the override viewport, if present
2272
+ viewport = rootState.viewport.getCurrentViewport(camera, new THREE__namespace.Vector3(), size);
2137
2273
  // Update the portal camera, if it differs from the previous layer
2138
2274
  if (camera !== rootState.camera) updateCamera(camera, size);
2139
2275
  }
@@ -2149,7 +2285,7 @@ function Portal({
2149
2285
  mouse: pointer,
2150
2286
  // Their previous root is the layer before it
2151
2287
  previousRoot,
2152
- // Events and size can be overridden by the inject layer
2288
+ // Events, size and viewport can be overridden by the inject layer
2153
2289
  events: {
2154
2290
  ...rootState.events,
2155
2291
  ...injectState.events,
@@ -2159,6 +2295,10 @@ function Portal({
2159
2295
  ...rootState.size,
2160
2296
  ...size
2161
2297
  },
2298
+ viewport: {
2299
+ ...rootState.viewport,
2300
+ ...viewport
2301
+ },
2162
2302
  // Layers are allowed to override events
2163
2303
  setEvents: events => injectState.set(state => ({
2164
2304
  ...state,
@@ -2183,9 +2323,12 @@ function Portal({
2183
2323
  return store;
2184
2324
  // eslint-disable-next-line react-hooks/exhaustive-deps
2185
2325
  }, [previousRoot, container]);
2186
- return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, reconciler.createPortal( /*#__PURE__*/React__namespace.createElement(context.Provider, {
2187
- value: usePortalStore
2188
- }, children), usePortalStore, null));
2326
+ return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
2327
+ children: reconciler.createPortal( /*#__PURE__*/jsxRuntime.jsx(context.Provider, {
2328
+ value: usePortalStore,
2329
+ children: children
2330
+ }), usePortalStore, null)
2331
+ });
2189
2332
  }
2190
2333
  reconciler.injectIntoDevTools({
2191
2334
  bundleType: 0 ,