@react-three/fiber 8.0.9 → 8.0.12

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.0.12
4
+
5
+ ### Patch Changes
6
+
7
+ - 3d10413f: fix portal layers
8
+
9
+ ## 8.0.11
10
+
11
+ ### Patch Changes
12
+
13
+ - 5167b1e4: memoized.args can be undefined
14
+
15
+ ## 8.0.10
16
+
17
+ ### Patch Changes
18
+
19
+ - eb321afd: fix: remount bug, allow portals to inject custom size
20
+
3
21
  ## 8.0.9
4
22
 
5
23
  ### Patch Changes
@@ -62,7 +62,7 @@ export interface PointerCaptureTarget {
62
62
  intersection: Intersection;
63
63
  target: Element;
64
64
  }
65
- export declare function getEventPriority(): any;
65
+ export declare function getEventPriority(): 1 | 4 | 16;
66
66
  export declare function removeInteractivity(store: UseBoundStore<RootState>, object: THREE.Object3D): void;
67
67
  export declare function createEvents(store: UseBoundStore<RootState>): {
68
68
  handlePointer: (name: string) => (event: DomEvent) => void;
@@ -3,11 +3,11 @@ import * as THREE from 'three';
3
3
  import * as React from 'react';
4
4
  import { UseBoundStore } from 'zustand';
5
5
  import * as ReactThreeFiber from '../three-types';
6
- import { Renderer, context, RootState, Size, Camera, Dpr, Performance } from './store';
6
+ import { Renderer, context, RootState, Size, Dpr, Performance, PrivateKeys } from './store';
7
7
  import { extend, Root } from './renderer';
8
8
  import { addEffect, addAfterEffect, addTail } from './loop';
9
9
  import { EventManager, ComputeFunction } from './events';
10
- import { dispose, getRootState } from './utils';
10
+ import { dispose, getRootState, Camera } from './utils';
11
11
  declare const roots: Map<Element, Root>;
12
12
  declare const invalidate: (state?: RootState | undefined) => void, advance: (timestamp: number, runGlobalEffects?: boolean, state?: RootState | undefined, frame?: THREE.XRFrame | undefined) => void;
13
13
  declare const reconciler: import("react-reconciler").Reconciler<unknown, unknown, unknown, unknown, unknown>, applyProps: typeof import("./utils").applyProps;
@@ -42,13 +42,17 @@ export declare type ReconcilerRoot<TCanvas extends Element> = {
42
42
  declare function createRoot<TCanvas extends Element>(canvas: TCanvas): ReconcilerRoot<TCanvas>;
43
43
  declare function render<TCanvas extends Element>(children: React.ReactNode, canvas: TCanvas, config: RenderProps<TCanvas>): UseBoundStore<RootState>;
44
44
  declare function unmountComponentAtNode<TElement extends Element>(canvas: TElement, callback?: (canvas: TElement) => void): void;
45
- export declare type InjectState = Partial<Omit<RootState, 'set' | 'get' | 'setSize' | 'setFrameloop' | 'setDpr' | 'events' | 'invalidate' | 'advance' | 'performance' | 'internal'> & {
46
- events: {
45
+ export declare type InjectState = Partial<Omit<RootState, PrivateKeys> & {
46
+ events?: {
47
47
  enabled?: boolean;
48
48
  priority?: number;
49
49
  compute?: ComputeFunction;
50
50
  connected?: any;
51
51
  };
52
+ size?: {
53
+ width: number;
54
+ height: number;
55
+ };
52
56
  }>;
53
57
  declare function createPortal(children: React.ReactNode, container: THREE.Object3D, state?: InjectState): React.ReactNode;
54
58
  declare const act: any;
@@ -2,6 +2,9 @@ import * as THREE from 'three';
2
2
  import * as React from 'react';
3
3
  import { GetState, SetState, StoreApi, UseBoundStore } from 'zustand';
4
4
  import { DomEvent, EventManager, PointerCaptureTarget, ThreeEvent } from './events';
5
+ import { Camera } from './utils';
6
+ export declare const privateKeys: readonly ["set", "get", "setSize", "setFrameloop", "setDpr", "events", "invalidate", "advance", "size", "viewport"];
7
+ export declare type PrivateKeys = typeof privateKeys[number];
5
8
  export interface Intersection extends THREE.Intersection {
6
9
  eventObject: THREE.Object3D;
7
10
  }
@@ -22,7 +25,6 @@ export declare type Viewport = Size & {
22
25
  distance: number;
23
26
  aspect: number;
24
27
  };
25
- export declare type Camera = THREE.OrthographicCamera | THREE.PerspectiveCamera;
26
28
  export declare type RenderCallback = (state: RootState, delta: number, frame?: THREE.XRFrame) => void;
27
29
  export declare type Performance = {
28
30
  current: number;
@@ -35,7 +37,6 @@ export declare type Renderer = {
35
37
  render: (scene: THREE.Scene, camera: THREE.Camera) => any;
36
38
  };
37
39
  export declare const isRenderer: (def: any) => boolean;
38
- export declare const isOrthographicCamera: (def: any) => def is THREE.OrthographicCamera;
39
40
  export declare type InternalState = {
40
41
  active: boolean;
41
42
  priority: number;
@@ -1,7 +1,9 @@
1
1
  import * as THREE from 'three';
2
2
  import * as React from 'react';
3
3
  import { AttachType, Instance, InstanceProps, LocalState } from './renderer';
4
- import { Dpr, RootState } from './store';
4
+ import { Dpr, RootState, Size } from './store';
5
+ export declare type Camera = THREE.OrthographicCamera | THREE.PerspectiveCamera;
6
+ export declare const isOrthographicCamera: (def: Camera) => def is THREE.OrthographicCamera;
5
7
  export declare const useIsomorphicLayoutEffect: typeof React.useEffect;
6
8
  export declare function useMutableCallback<T>(fn: T): React.MutableRefObject<T>;
7
9
  export declare type SetBlock = false | Promise<null> | null;
@@ -12,6 +14,7 @@ export declare type UnblockProps = {
12
14
  export declare function Block({ set }: Omit<UnblockProps, 'children'>): null;
13
15
  export declare class ErrorBoundary extends React.Component<{
14
16
  set: React.Dispatch<any>;
17
+ children: React.ReactNode;
15
18
  }, {
16
19
  error: boolean;
17
20
  }> {
@@ -45,11 +48,6 @@ export declare type ObjectMap = {
45
48
  };
46
49
  export declare function calculateDpr(dpr: Dpr): number;
47
50
  export declare const getRootState: (obj: THREE.Object3D) => RootState | undefined;
48
- export declare function filterKeys<TObj extends {
49
- [key: string]: any;
50
- }, TOmit extends boolean, TKey extends keyof TObj>(obj: TObj, omit: TOmit, ...keys: TKey[]): TOmit extends true ? Omit<TObj, TKey> : Pick<TObj, TKey>;
51
- export declare const pick: <TObj>(obj: Partial<TObj>, keys: (keyof TObj)[]) => Pick<Partial<TObj>, keyof TObj>;
52
- export declare const omit: <TObj>(obj: Partial<TObj>, keys: (keyof TObj)[]) => Omit<Partial<TObj>, keyof TObj>;
53
51
  export declare type EquConfig = {
54
52
  arrays?: 'reference' | 'shallow';
55
53
  objects?: 'reference' | 'shallow';
@@ -78,3 +76,6 @@ export declare function diffProps(instance: Instance, { children: cN, key: kN, r
78
76
  export declare function applyProps(instance: Instance, data: InstanceProps | DiffSet): Instance;
79
77
  export declare function invalidateInstance(instance: Instance): void;
80
78
  export declare function updateInstance(instance: Instance): void;
79
+ export declare function updateCamera(camera: Camera & {
80
+ manual?: boolean;
81
+ }, size: Size): void;
@@ -2,9 +2,9 @@ export * from './three-types';
2
2
  import * as ReactThreeFiber from './three-types';
3
3
  export { ReactThreeFiber };
4
4
  export type { BaseInstance, LocalState } from './core/renderer';
5
- export type { Intersection, Subscription, Dpr, Size, Viewport, Camera, RenderCallback, Performance, RootState, } from './core/store';
6
- export type { ThreeEvent, Events, EventManager } from './core/events';
7
- export type { ObjectMap } from './core/utils';
5
+ export type { Intersection, Subscription, Dpr, Size, Viewport, RenderCallback, Performance, RootState, } from './core/store';
6
+ export type { ThreeEvent, Events, EventManager, ComputeFunction } from './core/events';
7
+ export type { ObjectMap, Camera } from './core/utils';
8
8
  export * from './web/Canvas';
9
9
  export { createPointerEvents as events } from './web/events';
10
10
  export * from './core';
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { View, ViewProps, ViewStyle } from 'react-native';
3
3
  import { RenderProps } from '../core';
4
- export interface Props extends Omit<RenderProps<HTMLCanvasElement>, 'size'>, ViewProps {
4
+ export interface Props extends Omit<RenderProps<HTMLCanvasElement>, 'size' | 'dpr'>, ViewProps {
5
5
  children: React.ReactNode;
6
6
  style?: ViewStyle;
7
7
  }
@@ -2,9 +2,9 @@ export * from './three-types';
2
2
  import * as ReactThreeFiber from './three-types';
3
3
  export { ReactThreeFiber };
4
4
  export type { BaseInstance, LocalState } from './core/renderer';
5
- export type { Intersection, Subscription, Dpr, Size, Viewport, Camera, RenderCallback, Performance, RootState, } from './core/store';
6
- export type { ThreeEvent, Events, EventManager } from './core/events';
7
- export type { ObjectMap } from './core/utils';
5
+ export type { Intersection, Subscription, Dpr, Size, Viewport, RenderCallback, Performance, RootState, } from './core/store';
6
+ export type { ThreeEvent, Events, EventManager, ComputeFunction } from './core/events';
7
+ export type { ObjectMap, Camera } from './core/utils';
8
8
  export * from './native/Canvas';
9
9
  export { createTouchEvents as events } from './native/events';
10
10
  export * from './core';
@@ -21,7 +21,7 @@ export interface NodeProps<T, P> {
21
21
  attach?: AttachType;
22
22
  args?: Args<P>;
23
23
  children?: React.ReactNode;
24
- ref?: React.RefCallback<T> | React.RefObject<React.ReactNode> | null;
24
+ ref?: React.Ref<T>;
25
25
  key?: React.Key;
26
26
  onUpdate?: (self: T) => void;
27
27
  }
@@ -102,6 +102,7 @@ export declare type ConeGeometryProps = BufferGeometryNode<THREE.ConeGeometry, t
102
102
  export declare type CylinderGeometryProps = BufferGeometryNode<THREE.CylinderGeometry, typeof THREE.CylinderGeometry>;
103
103
  export declare type CircleGeometryProps = BufferGeometryNode<THREE.CircleGeometry, typeof THREE.CircleGeometry>;
104
104
  export declare type BoxGeometryProps = BufferGeometryNode<THREE.BoxGeometry, typeof THREE.BoxGeometry>;
105
+ export declare type CapsuleGeometryProps = BufferGeometryNode<THREE.CapsuleBufferGeometry, typeof THREE.CapsuleBufferGeometry>;
105
106
  export declare type MaterialProps = MaterialNode<THREE.Material, [THREE.MaterialParameters]>;
106
107
  export declare type ShadowMaterialProps = MaterialNode<THREE.ShadowMaterial, [THREE.ShaderMaterialParameters]>;
107
108
  export declare type SpriteMaterialProps = MaterialNode<THREE.SpriteMaterial, [THREE.SpriteMaterialParameters]>;
@@ -245,6 +246,7 @@ declare global {
245
246
  cylinderGeometry: CylinderGeometryProps;
246
247
  circleGeometry: CircleGeometryProps;
247
248
  boxGeometry: BoxGeometryProps;
249
+ capsuleGeometry: CapsuleGeometryProps;
248
250
  material: MaterialProps;
249
251
  shadowMaterial: ShadowMaterialProps;
250
252
  spriteMaterial: SpriteMaterialProps;
@@ -10,9 +10,10 @@ var threeTypes = /*#__PURE__*/Object.freeze({
10
10
  __proto__: null
11
11
  });
12
12
 
13
- // React currently throws a warning when using useLayoutEffect on the server.
13
+ const isOrthographicCamera = def => def && def.isOrthographicCamera; // React currently throws a warning when using useLayoutEffect on the server.
14
14
  // To get around it, we can conditionally useEffect on the server (no-op) and
15
15
  // useLayoutEffect on the client.
16
+
16
17
  const isSSR = typeof window === 'undefined' || !window.navigator || /ServerSideRendering|^Deno\//.test(window.navigator.userAgent);
17
18
  const useIsomorphicLayoutEffect = isSSR ? React.useEffect : React.useLayoutEffect;
18
19
  function useMutableCallback(fn) {
@@ -65,29 +66,6 @@ const getRootState = obj => {
65
66
 
66
67
  return (_r3f = obj.__r3f) == null ? void 0 : _r3f.root.getState();
67
68
  };
68
- /**
69
- * Picks or omits keys from an object
70
- * `omit` will filter out keys, and otherwise cherry-pick them.
71
- */
72
-
73
- function filterKeys(obj, omit, ...keys) {
74
- const keysToSelect = new Set(keys);
75
- return Object.entries(obj).reduce((acc, [key, value]) => {
76
- const shouldInclude = !omit;
77
- if (keysToSelect.has(key) === shouldInclude) acc[key] = value;
78
- return acc;
79
- }, {});
80
- }
81
- /**
82
- * Clones an object and cherry-picks keys.
83
- */
84
-
85
- const pick = (obj, keys) => filterKeys(obj, false, ...keys);
86
- /**
87
- * Clones an object and prunes or omits keys.
88
- */
89
-
90
- const omit = (obj, keys) => filterKeys(obj, true, ...keys);
91
69
  // A collection of compare functions
92
70
  const is = {
93
71
  obj: a => a === Object(a) && !is.arr(a) && typeof a !== 'function',
@@ -313,12 +291,16 @@ function applyProps$1(instance, data) {
313
291
 
314
292
  if (value === DEFAULT + 'remove') {
315
293
  if (targetProp && targetProp.constructor) {
294
+ var _memoized$args;
295
+
316
296
  // use the prop constructor to find the default it should be
317
- value = new targetProp.constructor(...memoized.args);
297
+ value = new targetProp.constructor(...((_memoized$args = memoized.args) != null ? _memoized$args : []));
318
298
  } else if (currentInstance.constructor) {
299
+ var _currentInstance$__r;
300
+
319
301
  // create a blank slate of the instance and copy the particular parameter.
320
302
  // @ts-ignore
321
- const defaultClassCall = new currentInstance.constructor(...currentInstance.__r3f.memoizedProps.args);
303
+ const defaultClassCall = new currentInstance.constructor(...((_currentInstance$__r = currentInstance.__r3f.memoizedProps.args) != null ? _currentInstance$__r : []));
322
304
  value = defaultClassCall[targetProp]; // destory the instance
323
305
 
324
306
  if (defaultClassCall.dispose) defaultClassCall.dispose(); // instance does not have constructor, just set it to 0
@@ -333,35 +315,35 @@ function applyProps$1(instance, data) {
333
315
  localState.eventCount = Object.keys(localState.handlers).length;
334
316
  } // Special treatment for objects with support for set/copy, and layers
335
317
  else if (targetProp && targetProp.set && (targetProp.copy || targetProp instanceof THREE.Layers)) {
336
- // If value is an array
337
- if (Array.isArray(value)) {
338
- if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
339
- } // Test again target.copy(class) next ...
340
- else if (targetProp.copy && value && value.constructor && targetProp.constructor.name === value.constructor.name) {
341
- targetProp.copy(value);
342
- } // If nothing else fits, just set the single value, ignore undefined
343
- // https://github.com/pmndrs/react-three-fiber/issues/274
344
- else if (value !== undefined) {
345
- const isColor = targetProp instanceof THREE.Color; // Allow setting array scalars
346
-
347
- if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
348
- else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers) targetProp.mask = value.mask; // Otherwise just set ...
349
- else targetProp.set(value); // For versions of three which don't support THREE.ColorManagement,
350
- // Auto-convert sRGB colors
351
- // https://github.com/pmndrs/react-three-fiber/issues/344
352
-
353
- const supportsColorManagement = THREE.ColorManagement;
354
- if (!supportsColorManagement && !rootState.linear && isColor) targetProp.convertSRGBToLinear();
355
- } // Else, just overwrite the value
356
-
357
- } else {
358
- currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
318
+ // If value is an array
319
+ if (Array.isArray(value)) {
320
+ if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
321
+ } // Test again target.copy(class) next ...
322
+ else if (targetProp.copy && value && value.constructor && targetProp.constructor.name === value.constructor.name) {
323
+ targetProp.copy(value);
324
+ } // If nothing else fits, just set the single value, ignore undefined
325
+ // https://github.com/pmndrs/react-three-fiber/issues/274
326
+ else if (value !== undefined) {
327
+ const isColor = targetProp instanceof THREE.Color; // Allow setting array scalars
328
+
329
+ if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
330
+ else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers) targetProp.mask = value.mask; // Otherwise just set ...
331
+ else targetProp.set(value); // For versions of three which don't support THREE.ColorManagement,
332
+ // Auto-convert sRGB colors
359
333
  // https://github.com/pmndrs/react-three-fiber/issues/344
360
334
 
361
- if (!rootState.linear && currentInstance[key] instanceof THREE.Texture) {
362
- currentInstance[key].encoding = THREE.sRGBEncoding;
363
- }
335
+ const supportsColorManagement = THREE.ColorManagement;
336
+ if (!supportsColorManagement && !rootState.linear && isColor) targetProp.convertSRGBToLinear();
337
+ } // Else, just overwrite the value
338
+
339
+ } else {
340
+ currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
341
+ // https://github.com/pmndrs/react-three-fiber/issues/344
342
+
343
+ if (!rootState.linear && currentInstance[key] instanceof THREE.Texture) {
344
+ currentInstance[key].encoding = THREE.sRGBEncoding;
364
345
  }
346
+ }
365
347
 
366
348
  invalidateInstance(instance);
367
349
  });
@@ -387,6 +369,25 @@ function invalidateInstance(instance) {
387
369
  function updateInstance(instance) {
388
370
  instance.onUpdate == null ? void 0 : instance.onUpdate(instance);
389
371
  }
372
+ function updateCamera(camera, size) {
373
+ // https://github.com/pmndrs/react-three-fiber/issues/92
374
+ // Do not mess with the camera if it belongs to the user
375
+ if (!camera.manual) {
376
+ if (isOrthographicCamera(camera)) {
377
+ camera.left = size.width / -2;
378
+ camera.right = size.width / 2;
379
+ camera.top = size.height / 2;
380
+ camera.bottom = size.height / -2;
381
+ } else {
382
+ camera.aspect = size.width / size.height;
383
+ }
384
+
385
+ camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
386
+ // Update matrix world since the renderer is a frame late
387
+
388
+ camera.updateMatrixWorld();
389
+ }
390
+ }
390
391
 
391
392
  function makeId(event) {
392
393
  return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
@@ -1159,8 +1160,8 @@ function createRenderer(roots, getEventPriority) {
1159
1160
  };
1160
1161
  }
1161
1162
 
1163
+ const privateKeys = ['set', 'get', 'setSize', 'setFrameloop', 'setDpr', 'events', 'invalidate', 'advance', 'size', 'viewport'];
1162
1164
  const isRenderer = def => !!(def != null && def.render);
1163
- const isOrthographicCamera = def => def && def.isOrthographicCamera;
1164
1165
  const context = /*#__PURE__*/React.createContext(null);
1165
1166
 
1166
1167
  const createStore = (invalidate, advance) => {
@@ -1367,24 +1368,7 @@ const createStore = (invalidate, advance) => {
1367
1368
  } = rootState.getState();
1368
1369
 
1369
1370
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1370
- // https://github.com/pmndrs/react-three-fiber/issues/92
1371
- // Do not mess with the camera if it belongs to the user
1372
- if (!camera.manual) {
1373
- if (isOrthographicCamera(camera)) {
1374
- camera.left = size.width / -2;
1375
- camera.right = size.width / 2;
1376
- camera.top = size.height / 2;
1377
- camera.bottom = size.height / -2;
1378
- } else {
1379
- camera.aspect = size.width / size.height;
1380
- }
1381
-
1382
- camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
1383
- // Update matrix world since the renderer is a frame late
1384
-
1385
- camera.updateMatrixWorld();
1386
- } // Update renderer
1387
-
1371
+ updateCamera(camera, size); // Update renderer
1388
1372
 
1389
1373
  gl.setPixelRatio(viewport.dpr);
1390
1374
  gl.setSize(size.width, size.height);
@@ -1923,56 +1907,101 @@ function Portal({
1923
1907
  * {createPortal(...)} */
1924
1908
  const {
1925
1909
  events,
1910
+ size,
1926
1911
  ...rest
1927
1912
  } = state;
1928
1913
  const previousRoot = useStore();
1929
1914
  const [raycaster] = React.useState(() => new THREE.Raycaster());
1930
1915
  const [pointer] = React.useState(() => new THREE.Vector2());
1931
- const inject = React.useCallback((state, injectState) => {
1932
- const intersect = { ...state
1933
- };
1916
+ const inject = React.useCallback((rootState, injectState) => {
1917
+ const intersect = { ...rootState
1918
+ }; // all prev state props
1919
+ // Only the fields of "rootState" that do not differ from injectState
1920
+ // Some props should be off-limits
1921
+ // Otherwise filter out the props that are different and let the inject layer take precedence
1922
+
1923
+ Object.keys(rootState).forEach(key => {
1924
+ if ( // Some props should be off-limits
1925
+ privateKeys.includes(key) || // Otherwise filter out the props that are different and let the inject layer take precedence
1926
+ rootState[key] !== injectState[key]) {
1927
+ delete intersect[key];
1928
+ }
1929
+ });
1930
+ let viewport = undefined;
1934
1931
 
1935
- if (injectState) {
1936
- // Only the fields of "state" that do not differ from injectState
1937
- Object.keys(state).forEach(key => {
1938
- if ( // Some props should be off-limits
1939
- !['size', 'viewport', 'internal', 'performance'].includes(key) && // Otherwise filter out the props that are different and let the inject layer take precedence
1940
- state[key] !== injectState[key]) delete intersect[key];
1941
- });
1932
+ if (injectState && size) {
1933
+ const camera = injectState.camera; // Calculate the override viewport, if present
1934
+
1935
+ viewport = rootState.viewport.getCurrentViewport(camera, new THREE.Vector3(), size); // Update the portal camera, if it differs from the previous layer
1936
+
1937
+ if (camera !== rootState.camera) updateCamera(camera, size);
1942
1938
  }
1943
1939
 
1944
- return { ...intersect,
1940
+ return { // The intersect consists of the previous root state
1941
+ ...intersect,
1942
+ // Portals have their own scene, which forms the root, a raycaster and a pointer
1945
1943
  scene: container,
1946
- previousRoot,
1947
1944
  raycaster,
1948
- events: { ...state.events,
1945
+ pointer,
1946
+ mouse: pointer,
1947
+ // Their previous root is the layer before it
1948
+ previousRoot,
1949
+ // Events, size and viewport can be overridden by the inject layer
1950
+ events: { ...rootState.events,
1949
1951
  ...(injectState == null ? void 0 : injectState.events),
1950
- pointer,
1951
- mouse: pointer,
1952
1952
  ...events
1953
1953
  },
1954
+ size: { ...rootState.size,
1955
+ ...size
1956
+ },
1957
+ viewport: { ...rootState.viewport,
1958
+ ...viewport
1959
+ },
1954
1960
  ...rest
1955
1961
  };
1956
1962
  }, [state]);
1957
- const [useInjectStore] = React.useState(() => {
1958
- const store = create((set, get) => ({ ...inject(previousRoot.getState()),
1963
+ const [usePortalStore] = React.useState(() => {
1964
+ // Create a mirrored store, based on the previous root with a few overrides ...
1965
+ const previousState = previousRoot.getState();
1966
+ const store = create((set, get) => ({ ...previousState,
1967
+ scene: container,
1968
+ raycaster,
1969
+ pointer,
1970
+ mouse: pointer,
1971
+ previousRoot,
1972
+ events: { ...previousState.events,
1973
+ ...events
1974
+ },
1975
+ size: { ...previousState.size,
1976
+ ...size
1977
+ },
1978
+ ...rest,
1979
+ // Set and get refer to this root-state
1959
1980
  set,
1960
1981
  get,
1982
+ // Layers are allowed to override events
1961
1983
  setEvents: events => set(state => ({ ...state,
1962
1984
  events: { ...state.events,
1963
1985
  ...events
1964
1986
  }
1965
1987
  }))
1966
1988
  }));
1967
- previousRoot.subscribe(state => useInjectStore.setState(injectState => inject(state, injectState)));
1968
1989
  return store;
1969
1990
  });
1970
1991
  React.useEffect(() => {
1971
- useInjectStore.setState(injectState => inject(previousRoot.getState(), injectState));
1992
+ // Subscribe to previous root-state and copy changes over to the mirrored portal-state
1993
+ const unsub = previousRoot.subscribe(prev => usePortalStore.setState(state => inject(prev, state)));
1994
+ return () => {
1995
+ unsub();
1996
+ usePortalStore.destroy();
1997
+ };
1998
+ }, []);
1999
+ React.useEffect(() => {
2000
+ usePortalStore.setState(injectState => inject(previousRoot.getState(), injectState));
1972
2001
  }, [inject]);
1973
2002
  return /*#__PURE__*/React.createElement(React.Fragment, null, reconciler.createPortal( /*#__PURE__*/React.createElement(context.Provider, {
1974
- value: useInjectStore
1975
- }, children), useInjectStore, null));
2003
+ value: usePortalStore
2004
+ }, children), usePortalStore, null));
1976
2005
  }
1977
2006
 
1978
2007
  reconciler.injectIntoDevTools({
@@ -1982,4 +2011,4 @@ reconciler.injectIntoDevTools({
1982
2011
  });
1983
2012
  const act = React.unstable_act;
1984
2013
 
1985
- 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 };
2014
+ export { Block as B, 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, addTail as o, getRootState as p, act as q, render as r, roots as s, threeTypes as t, useMutableCallback as u, useStore as v, useThree as w, useFrame as x, useGraph as y, useLoader as z };