@react-three/fiber 9.1.4 → 9.2.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.
Files changed (28) hide show
  1. package/CHANGELOG.md +1160 -1154
  2. package/dist/declarations/src/core/events.d.ts +92 -92
  3. package/dist/declarations/src/core/hooks.d.ts +53 -53
  4. package/dist/declarations/src/core/index.d.ts +13 -13
  5. package/dist/declarations/src/core/loop.d.ts +31 -31
  6. package/dist/declarations/src/core/reconciler.d.ts +50 -50
  7. package/dist/declarations/src/core/renderer.d.ts +89 -89
  8. package/dist/declarations/src/core/store.d.ts +130 -130
  9. package/dist/declarations/src/core/utils.d.ts +191 -191
  10. package/dist/declarations/src/index.d.ts +6 -6
  11. package/dist/declarations/src/native/Canvas.d.ts +13 -13
  12. package/dist/declarations/src/native/events.d.ts +4 -4
  13. package/dist/declarations/src/native.d.ts +6 -6
  14. package/dist/declarations/src/three-types.d.ts +68 -68
  15. package/dist/declarations/src/web/Canvas.d.ts +23 -23
  16. package/dist/declarations/src/web/events.d.ts +4 -4
  17. package/dist/{events-a96a0963.cjs.prod.js → events-59fae97e.cjs.prod.js} +90 -79
  18. package/dist/{events-f681e724.esm.js → events-cf57b220.esm.js} +90 -80
  19. package/dist/{events-66111f5e.cjs.dev.js → events-e63d28a3.cjs.dev.js} +90 -79
  20. package/dist/react-three-fiber.cjs.dev.js +5 -4
  21. package/dist/react-three-fiber.cjs.prod.js +5 -4
  22. package/dist/react-three-fiber.esm.js +5 -5
  23. package/native/dist/react-three-fiber-native.cjs.dev.js +5 -4
  24. package/native/dist/react-three-fiber-native.cjs.prod.js +5 -4
  25. package/native/dist/react-three-fiber-native.esm.js +5 -5
  26. package/native/package.json +5 -5
  27. package/package.json +1 -1
  28. package/readme.md +253 -253
@@ -38,17 +38,17 @@ var threeTypes = /*#__PURE__*/Object.freeze({
38
38
  __proto__: null
39
39
  });
40
40
 
41
- /**
42
- * Returns the instance's initial (outmost) root.
41
+ /**
42
+ * Returns the instance's initial (outmost) root.
43
43
  */
44
44
  function findInitialRoot(instance) {
45
45
  let root = instance.root;
46
46
  while (root.getState().previousRoot) root = root.getState().previousRoot;
47
47
  return root;
48
48
  }
49
- /**
50
- * Safely flush async effects when testing, simulating a legacy root.
51
- * @deprecated Import from React instead. import { act } from 'react'
49
+ /**
50
+ * Safely flush async effects when testing, simulating a legacy root.
51
+ * @deprecated Import from React instead. import { act } from 'react'
52
52
  */
53
53
  // Reference with computed key to break Webpack static analysis
54
54
  // https://github.com/webpack/webpack/issues/14814
@@ -57,14 +57,14 @@ const isOrthographicCamera = def => def && def.isOrthographicCamera;
57
57
  const isRef = obj => obj && obj.hasOwnProperty('current');
58
58
  const isColorRepresentation = value => value != null && (typeof value === 'string' || typeof value === 'number' || value.isColor);
59
59
 
60
- /**
61
- * An SSR-friendly useLayoutEffect.
62
- *
63
- * React currently throws a warning when using useLayoutEffect on the server.
64
- * To get around it, we can conditionally useEffect on the server (no-op) and
65
- * useLayoutEffect elsewhere.
66
- *
67
- * @see https://github.com/facebook/react/issues/14927
60
+ /**
61
+ * An SSR-friendly useLayoutEffect.
62
+ *
63
+ * React currently throws a warning when using useLayoutEffect on the server.
64
+ * To get around it, we can conditionally useEffect on the server (no-op) and
65
+ * useLayoutEffect elsewhere.
66
+ *
67
+ * @see https://github.com/facebook/react/issues/14927
68
68
  */
69
69
  const useIsomorphicLayoutEffect = /* @__PURE__ */((_window$document, _window$navigator) => typeof window !== 'undefined' && (((_window$document = window.document) == null ? void 0 : _window$document.createElement) || ((_window$navigator = window.navigator) == null ? void 0 : _window$navigator.product) === 'ReactNative'))() ? React__namespace.useLayoutEffect : React__namespace.useEffect;
70
70
  function useMutableCallback(fn) {
@@ -72,8 +72,8 @@ function useMutableCallback(fn) {
72
72
  useIsomorphicLayoutEffect(() => void (ref.current = fn), [fn]);
73
73
  return ref;
74
74
  }
75
- /**
76
- * Bridges renderer Context and StrictMode from a primary renderer.
75
+ /**
76
+ * Bridges renderer Context and StrictMode from a primary renderer.
77
77
  */
78
78
  function useBridge() {
79
79
  const fiber = itsFine.useFiber();
@@ -125,8 +125,8 @@ function calculateDpr(dpr) {
125
125
  return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
126
126
  }
127
127
 
128
- /**
129
- * Returns instance root state
128
+ /**
129
+ * Returns instance root state
130
130
  */
131
131
  function getRootState(obj) {
132
132
  var _r3f;
@@ -489,9 +489,9 @@ function makeId(event) {
489
489
  return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
490
490
  }
491
491
 
492
- /**
493
- * Release pointer captures.
494
- * This is called by releasePointerCapture in the API, and when an object is removed.
492
+ /**
493
+ * Release pointer captures.
494
+ * This is called by releasePointerCapture in the API, and when an object is removed.
495
495
  */
496
496
  function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
497
497
  const captureData = captures.get(obj);
@@ -838,19 +838,19 @@ function createEvents(store) {
838
838
  if (!(instance != null && instance.eventCount)) return;
839
839
  const handlers = instance.handlers;
840
840
 
841
- /*
842
- MAYBE TODO, DELETE IF NOT:
843
- Check if the object is captured, captured events should not have intersects running in parallel
844
- But wouldn't it be better to just replace capturedMap with a single entry?
845
- Also, are we OK with straight up making picking up multiple objects impossible?
846
-
847
- const pointerId = (data as ThreeEvent<PointerEvent>).pointerId
848
- if (pointerId !== undefined) {
849
- const capturedMeshSet = internal.capturedMap.get(pointerId)
850
- if (capturedMeshSet) {
851
- const captured = capturedMeshSet.get(eventObject)
852
- if (captured && captured.localState.stopped) return
853
- }
841
+ /*
842
+ MAYBE TODO, DELETE IF NOT:
843
+ Check if the object is captured, captured events should not have intersects running in parallel
844
+ But wouldn't it be better to just replace capturedMap with a single entry?
845
+ Also, are we OK with straight up making picking up multiple objects impossible?
846
+
847
+ const pointerId = (data as ThreeEvent<PointerEvent>).pointerId
848
+ if (pointerId !== undefined) {
849
+ const capturedMeshSet = internal.capturedMap.get(pointerId)
850
+ if (capturedMeshSet) {
851
+ const captured = capturedMeshSet.get(eventObject)
852
+ if (captured && captured.localState.stopped) return
853
+ }
854
854
  }*/
855
855
 
856
856
  if (isPointerMove) {
@@ -1141,11 +1141,11 @@ const createStore = (invalidate, advance) => {
1141
1141
  return rootStore;
1142
1142
  };
1143
1143
 
1144
- /**
1145
- * Exposes an object's {@link Instance}.
1146
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#useInstanceHandle
1147
- *
1148
- * **Note**: this is an escape hatch to react-internal fields. Expect this to change significantly between versions.
1144
+ /**
1145
+ * Exposes an object's {@link Instance}.
1146
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#useInstanceHandle
1147
+ *
1148
+ * **Note**: this is an escape hatch to react-internal fields. Expect this to change significantly between versions.
1149
1149
  */
1150
1150
  function useInstanceHandle(ref) {
1151
1151
  const instance = React__namespace.useRef(null);
@@ -1153,9 +1153,9 @@ function useInstanceHandle(ref) {
1153
1153
  return instance;
1154
1154
  }
1155
1155
 
1156
- /**
1157
- * Returns the R3F Canvas' Zustand store. Useful for [transient updates](https://github.com/pmndrs/zustand#transient-updates-for-often-occurring-state-changes).
1158
- * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usestore
1156
+ /**
1157
+ * Returns the R3F Canvas' Zustand store. Useful for [transient updates](https://github.com/pmndrs/zustand#transient-updates-for-often-occurring-state-changes).
1158
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usestore
1159
1159
  */
1160
1160
  function useStore() {
1161
1161
  const store = React__namespace.useContext(context);
@@ -1163,18 +1163,18 @@ function useStore() {
1163
1163
  return store;
1164
1164
  }
1165
1165
 
1166
- /**
1167
- * Accesses R3F's internal state, containing renderer, canvas, scene, etc.
1168
- * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usethree
1166
+ /**
1167
+ * Accesses R3F's internal state, containing renderer, canvas, scene, etc.
1168
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usethree
1169
1169
  */
1170
1170
  function useThree(selector = state => state, equalityFn) {
1171
1171
  return useStore()(selector, equalityFn);
1172
1172
  }
1173
1173
 
1174
- /**
1175
- * Executes a callback before render in a shared frame loop.
1176
- * Can order effects with render priority or manually render with a positive priority.
1177
- * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
1174
+ /**
1175
+ * Executes a callback before render in a shared frame loop.
1176
+ * Can order effects with render priority or manually render with a positive priority.
1177
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
1178
1178
  */
1179
1179
  function useFrame(callback, renderPriority = 0) {
1180
1180
  const store = useStore();
@@ -1186,9 +1186,9 @@ function useFrame(callback, renderPriority = 0) {
1186
1186
  return null;
1187
1187
  }
1188
1188
 
1189
- /**
1190
- * Returns a node graph of an object with named nodes & materials.
1191
- * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
1189
+ /**
1190
+ * Returns a node graph of an object with named nodes & materials.
1191
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
1192
1192
  */
1193
1193
  function useGraph(object) {
1194
1194
  return React__namespace.useMemo(() => buildGraph(object), [object]);
@@ -1224,11 +1224,11 @@ function loadingFn(extensions, onProgress) {
1224
1224
  };
1225
1225
  }
1226
1226
 
1227
- /**
1228
- * Synchronously loads and caches assets with a three loader.
1229
- *
1230
- * Note: this hook's caller must be wrapped with `React.Suspense`
1231
- * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useloader
1227
+ /**
1228
+ * Synchronously loads and caches assets with a three loader.
1229
+ *
1230
+ * Note: this hook's caller must be wrapped with `React.Suspense`
1231
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useloader
1232
1232
  */
1233
1233
  function useLoader(loader, input, extensions, onProgress) {
1234
1234
  // Use suspense to load async assets
@@ -1240,16 +1240,16 @@ function useLoader(loader, input, extensions, onProgress) {
1240
1240
  return Array.isArray(input) ? results : results[0];
1241
1241
  }
1242
1242
 
1243
- /**
1244
- * Preloads an asset into cache as a side-effect.
1243
+ /**
1244
+ * Preloads an asset into cache as a side-effect.
1245
1245
  */
1246
1246
  useLoader.preload = function (loader, input, extensions) {
1247
1247
  const keys = Array.isArray(input) ? input : [input];
1248
1248
  return suspendReact.preload(loadingFn(extensions), [loader, ...keys]);
1249
1249
  };
1250
1250
 
1251
- /**
1252
- * Removes a loaded asset from cache.
1251
+ /**
1252
+ * Removes a loaded asset from cache.
1253
1253
  */
1254
1254
  useLoader.clear = function (loader, input) {
1255
1255
  const keys = Array.isArray(input) ? input : [input];
@@ -2083,10 +2083,10 @@ function Portal({
2083
2083
  children,
2084
2084
  container
2085
2085
  }) {
2086
- /** This has to be a component because it would not be able to call useThree/useStore otherwise since
2087
- * if this is our environment, then we are not in r3f's renderer but in react-dom, it would trigger
2088
- * the "R3F hooks can only be used within the Canvas component!" warning:
2089
- * <Canvas>
2086
+ /** This has to be a component because it would not be able to call useThree/useStore otherwise since
2087
+ * if this is our environment, then we are not in r3f's renderer but in react-dom, it would trigger
2088
+ * the "R3F hooks can only be used within the Canvas component!" warning:
2089
+ * <Canvas>
2090
2090
  * {createPortal(...)} */
2091
2091
  const {
2092
2092
  events,
@@ -2167,6 +2167,16 @@ function Portal({
2167
2167
  );
2168
2168
  }
2169
2169
 
2170
+ /**
2171
+ * Force React to flush any updates inside the provided callback synchronously and immediately.
2172
+ * All the same caveats documented for react-dom's `flushSync` apply here (see https://react.dev/reference/react-dom/flushSync).
2173
+ * Nevertheless, sometimes one needs to render synchronously, for example to keep DOM and 3D changes in lock-step without
2174
+ * having to revert to a non-React solution.
2175
+ */
2176
+ function flushSync(fn) {
2177
+ return reconciler.flushSync(fn);
2178
+ }
2179
+
2170
2180
  function createSubs(callback, subs) {
2171
2181
  const sub = {
2172
2182
  callback
@@ -2178,21 +2188,21 @@ const globalEffects = new Set();
2178
2188
  const globalAfterEffects = new Set();
2179
2189
  const globalTailEffects = new Set();
2180
2190
 
2181
- /**
2182
- * Adds a global render callback which is called each frame.
2183
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
2191
+ /**
2192
+ * Adds a global render callback which is called each frame.
2193
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
2184
2194
  */
2185
2195
  const addEffect = callback => createSubs(callback, globalEffects);
2186
2196
 
2187
- /**
2188
- * Adds a global after-render callback which is called each frame.
2189
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
2197
+ /**
2198
+ * Adds a global after-render callback which is called each frame.
2199
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
2190
2200
  */
2191
2201
  const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
2192
2202
 
2193
- /**
2194
- * Adds a global callback which is called when rendering stops.
2195
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
2203
+ /**
2204
+ * Adds a global callback which is called when rendering stops.
2205
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
2196
2206
  */
2197
2207
  const addTail = callback => createSubs(callback, globalTailEffects);
2198
2208
  function run(effects, timestamp) {
@@ -2280,9 +2290,9 @@ function loop(timestamp) {
2280
2290
  }
2281
2291
  }
2282
2292
 
2283
- /**
2284
- * Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
2285
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
2293
+ /**
2294
+ * Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
2295
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
2286
2296
  */
2287
2297
  function invalidate(state, frames = 1) {
2288
2298
  var _state$gl$xr2;
@@ -2309,9 +2319,9 @@ function invalidate(state, frames = 1) {
2309
2319
  }
2310
2320
  }
2311
2321
 
2312
- /**
2313
- * Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
2314
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
2322
+ /**
2323
+ * Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
2324
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
2315
2325
  */
2316
2326
  function advance(timestamp, runGlobalEffects = true, state, frame) {
2317
2327
  if (runGlobalEffects) flushGlobalEffects('before', timestamp);
@@ -2423,6 +2433,7 @@ exports.createRoot = createRoot;
2423
2433
  exports.dispose = dispose;
2424
2434
  exports.extend = extend;
2425
2435
  exports.flushGlobalEffects = flushGlobalEffects;
2436
+ exports.flushSync = flushSync;
2426
2437
  exports.getRootState = getRootState;
2427
2438
  exports.invalidate = invalidate;
2428
2439
  exports.isRef = isRef;
@@ -12,17 +12,17 @@ var threeTypes = /*#__PURE__*/Object.freeze({
12
12
  __proto__: null
13
13
  });
14
14
 
15
- /**
16
- * Returns the instance's initial (outmost) root.
15
+ /**
16
+ * Returns the instance's initial (outmost) root.
17
17
  */
18
18
  function findInitialRoot(instance) {
19
19
  let root = instance.root;
20
20
  while (root.getState().previousRoot) root = root.getState().previousRoot;
21
21
  return root;
22
22
  }
23
- /**
24
- * Safely flush async effects when testing, simulating a legacy root.
25
- * @deprecated Import from React instead. import { act } from 'react'
23
+ /**
24
+ * Safely flush async effects when testing, simulating a legacy root.
25
+ * @deprecated Import from React instead. import { act } from 'react'
26
26
  */
27
27
  // Reference with computed key to break Webpack static analysis
28
28
  // https://github.com/webpack/webpack/issues/14814
@@ -31,14 +31,14 @@ const isOrthographicCamera = def => def && def.isOrthographicCamera;
31
31
  const isRef = obj => obj && obj.hasOwnProperty('current');
32
32
  const isColorRepresentation = value => value != null && (typeof value === 'string' || typeof value === 'number' || value.isColor);
33
33
 
34
- /**
35
- * An SSR-friendly useLayoutEffect.
36
- *
37
- * React currently throws a warning when using useLayoutEffect on the server.
38
- * To get around it, we can conditionally useEffect on the server (no-op) and
39
- * useLayoutEffect elsewhere.
40
- *
41
- * @see https://github.com/facebook/react/issues/14927
34
+ /**
35
+ * An SSR-friendly useLayoutEffect.
36
+ *
37
+ * React currently throws a warning when using useLayoutEffect on the server.
38
+ * To get around it, we can conditionally useEffect on the server (no-op) and
39
+ * useLayoutEffect elsewhere.
40
+ *
41
+ * @see https://github.com/facebook/react/issues/14927
42
42
  */
43
43
  const useIsomorphicLayoutEffect = /* @__PURE__ */((_window$document, _window$navigator) => typeof window !== 'undefined' && (((_window$document = window.document) == null ? void 0 : _window$document.createElement) || ((_window$navigator = window.navigator) == null ? void 0 : _window$navigator.product) === 'ReactNative'))() ? React.useLayoutEffect : React.useEffect;
44
44
  function useMutableCallback(fn) {
@@ -46,8 +46,8 @@ function useMutableCallback(fn) {
46
46
  useIsomorphicLayoutEffect(() => void (ref.current = fn), [fn]);
47
47
  return ref;
48
48
  }
49
- /**
50
- * Bridges renderer Context and StrictMode from a primary renderer.
49
+ /**
50
+ * Bridges renderer Context and StrictMode from a primary renderer.
51
51
  */
52
52
  function useBridge() {
53
53
  const fiber = useFiber();
@@ -99,8 +99,8 @@ function calculateDpr(dpr) {
99
99
  return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
100
100
  }
101
101
 
102
- /**
103
- * Returns instance root state
102
+ /**
103
+ * Returns instance root state
104
104
  */
105
105
  function getRootState(obj) {
106
106
  var _r3f;
@@ -463,9 +463,9 @@ function makeId(event) {
463
463
  return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
464
464
  }
465
465
 
466
- /**
467
- * Release pointer captures.
468
- * This is called by releasePointerCapture in the API, and when an object is removed.
466
+ /**
467
+ * Release pointer captures.
468
+ * This is called by releasePointerCapture in the API, and when an object is removed.
469
469
  */
470
470
  function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
471
471
  const captureData = captures.get(obj);
@@ -812,19 +812,19 @@ function createEvents(store) {
812
812
  if (!(instance != null && instance.eventCount)) return;
813
813
  const handlers = instance.handlers;
814
814
 
815
- /*
816
- MAYBE TODO, DELETE IF NOT:
817
- Check if the object is captured, captured events should not have intersects running in parallel
818
- But wouldn't it be better to just replace capturedMap with a single entry?
819
- Also, are we OK with straight up making picking up multiple objects impossible?
820
-
821
- const pointerId = (data as ThreeEvent<PointerEvent>).pointerId
822
- if (pointerId !== undefined) {
823
- const capturedMeshSet = internal.capturedMap.get(pointerId)
824
- if (capturedMeshSet) {
825
- const captured = capturedMeshSet.get(eventObject)
826
- if (captured && captured.localState.stopped) return
827
- }
815
+ /*
816
+ MAYBE TODO, DELETE IF NOT:
817
+ Check if the object is captured, captured events should not have intersects running in parallel
818
+ But wouldn't it be better to just replace capturedMap with a single entry?
819
+ Also, are we OK with straight up making picking up multiple objects impossible?
820
+
821
+ const pointerId = (data as ThreeEvent<PointerEvent>).pointerId
822
+ if (pointerId !== undefined) {
823
+ const capturedMeshSet = internal.capturedMap.get(pointerId)
824
+ if (capturedMeshSet) {
825
+ const captured = capturedMeshSet.get(eventObject)
826
+ if (captured && captured.localState.stopped) return
827
+ }
828
828
  }*/
829
829
 
830
830
  if (isPointerMove) {
@@ -1115,11 +1115,11 @@ const createStore = (invalidate, advance) => {
1115
1115
  return rootStore;
1116
1116
  };
1117
1117
 
1118
- /**
1119
- * Exposes an object's {@link Instance}.
1120
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#useInstanceHandle
1121
- *
1122
- * **Note**: this is an escape hatch to react-internal fields. Expect this to change significantly between versions.
1118
+ /**
1119
+ * Exposes an object's {@link Instance}.
1120
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#useInstanceHandle
1121
+ *
1122
+ * **Note**: this is an escape hatch to react-internal fields. Expect this to change significantly between versions.
1123
1123
  */
1124
1124
  function useInstanceHandle(ref) {
1125
1125
  const instance = React.useRef(null);
@@ -1127,9 +1127,9 @@ function useInstanceHandle(ref) {
1127
1127
  return instance;
1128
1128
  }
1129
1129
 
1130
- /**
1131
- * Returns the R3F Canvas' Zustand store. Useful for [transient updates](https://github.com/pmndrs/zustand#transient-updates-for-often-occurring-state-changes).
1132
- * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usestore
1130
+ /**
1131
+ * Returns the R3F Canvas' Zustand store. Useful for [transient updates](https://github.com/pmndrs/zustand#transient-updates-for-often-occurring-state-changes).
1132
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usestore
1133
1133
  */
1134
1134
  function useStore() {
1135
1135
  const store = React.useContext(context);
@@ -1137,18 +1137,18 @@ function useStore() {
1137
1137
  return store;
1138
1138
  }
1139
1139
 
1140
- /**
1141
- * Accesses R3F's internal state, containing renderer, canvas, scene, etc.
1142
- * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usethree
1140
+ /**
1141
+ * Accesses R3F's internal state, containing renderer, canvas, scene, etc.
1142
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usethree
1143
1143
  */
1144
1144
  function useThree(selector = state => state, equalityFn) {
1145
1145
  return useStore()(selector, equalityFn);
1146
1146
  }
1147
1147
 
1148
- /**
1149
- * Executes a callback before render in a shared frame loop.
1150
- * Can order effects with render priority or manually render with a positive priority.
1151
- * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
1148
+ /**
1149
+ * Executes a callback before render in a shared frame loop.
1150
+ * Can order effects with render priority or manually render with a positive priority.
1151
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
1152
1152
  */
1153
1153
  function useFrame(callback, renderPriority = 0) {
1154
1154
  const store = useStore();
@@ -1160,9 +1160,9 @@ function useFrame(callback, renderPriority = 0) {
1160
1160
  return null;
1161
1161
  }
1162
1162
 
1163
- /**
1164
- * Returns a node graph of an object with named nodes & materials.
1165
- * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
1163
+ /**
1164
+ * Returns a node graph of an object with named nodes & materials.
1165
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
1166
1166
  */
1167
1167
  function useGraph(object) {
1168
1168
  return React.useMemo(() => buildGraph(object), [object]);
@@ -1198,11 +1198,11 @@ function loadingFn(extensions, onProgress) {
1198
1198
  };
1199
1199
  }
1200
1200
 
1201
- /**
1202
- * Synchronously loads and caches assets with a three loader.
1203
- *
1204
- * Note: this hook's caller must be wrapped with `React.Suspense`
1205
- * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useloader
1201
+ /**
1202
+ * Synchronously loads and caches assets with a three loader.
1203
+ *
1204
+ * Note: this hook's caller must be wrapped with `React.Suspense`
1205
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useloader
1206
1206
  */
1207
1207
  function useLoader(loader, input, extensions, onProgress) {
1208
1208
  // Use suspense to load async assets
@@ -1214,16 +1214,16 @@ function useLoader(loader, input, extensions, onProgress) {
1214
1214
  return Array.isArray(input) ? results : results[0];
1215
1215
  }
1216
1216
 
1217
- /**
1218
- * Preloads an asset into cache as a side-effect.
1217
+ /**
1218
+ * Preloads an asset into cache as a side-effect.
1219
1219
  */
1220
1220
  useLoader.preload = function (loader, input, extensions) {
1221
1221
  const keys = Array.isArray(input) ? input : [input];
1222
1222
  return preload(loadingFn(extensions), [loader, ...keys]);
1223
1223
  };
1224
1224
 
1225
- /**
1226
- * Removes a loaded asset from cache.
1225
+ /**
1226
+ * Removes a loaded asset from cache.
1227
1227
  */
1228
1228
  useLoader.clear = function (loader, input) {
1229
1229
  const keys = Array.isArray(input) ? input : [input];
@@ -2057,10 +2057,10 @@ function Portal({
2057
2057
  children,
2058
2058
  container
2059
2059
  }) {
2060
- /** This has to be a component because it would not be able to call useThree/useStore otherwise since
2061
- * if this is our environment, then we are not in r3f's renderer but in react-dom, it would trigger
2062
- * the "R3F hooks can only be used within the Canvas component!" warning:
2063
- * <Canvas>
2060
+ /** This has to be a component because it would not be able to call useThree/useStore otherwise since
2061
+ * if this is our environment, then we are not in r3f's renderer but in react-dom, it would trigger
2062
+ * the "R3F hooks can only be used within the Canvas component!" warning:
2063
+ * <Canvas>
2064
2064
  * {createPortal(...)} */
2065
2065
  const {
2066
2066
  events,
@@ -2141,6 +2141,16 @@ function Portal({
2141
2141
  );
2142
2142
  }
2143
2143
 
2144
+ /**
2145
+ * Force React to flush any updates inside the provided callback synchronously and immediately.
2146
+ * All the same caveats documented for react-dom's `flushSync` apply here (see https://react.dev/reference/react-dom/flushSync).
2147
+ * Nevertheless, sometimes one needs to render synchronously, for example to keep DOM and 3D changes in lock-step without
2148
+ * having to revert to a non-React solution.
2149
+ */
2150
+ function flushSync(fn) {
2151
+ return reconciler.flushSync(fn);
2152
+ }
2153
+
2144
2154
  function createSubs(callback, subs) {
2145
2155
  const sub = {
2146
2156
  callback
@@ -2152,21 +2162,21 @@ const globalEffects = new Set();
2152
2162
  const globalAfterEffects = new Set();
2153
2163
  const globalTailEffects = new Set();
2154
2164
 
2155
- /**
2156
- * Adds a global render callback which is called each frame.
2157
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
2165
+ /**
2166
+ * Adds a global render callback which is called each frame.
2167
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
2158
2168
  */
2159
2169
  const addEffect = callback => createSubs(callback, globalEffects);
2160
2170
 
2161
- /**
2162
- * Adds a global after-render callback which is called each frame.
2163
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
2171
+ /**
2172
+ * Adds a global after-render callback which is called each frame.
2173
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
2164
2174
  */
2165
2175
  const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
2166
2176
 
2167
- /**
2168
- * Adds a global callback which is called when rendering stops.
2169
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
2177
+ /**
2178
+ * Adds a global callback which is called when rendering stops.
2179
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
2170
2180
  */
2171
2181
  const addTail = callback => createSubs(callback, globalTailEffects);
2172
2182
  function run(effects, timestamp) {
@@ -2254,9 +2264,9 @@ function loop(timestamp) {
2254
2264
  }
2255
2265
  }
2256
2266
 
2257
- /**
2258
- * Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
2259
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
2267
+ /**
2268
+ * Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
2269
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
2260
2270
  */
2261
2271
  function invalidate(state, frames = 1) {
2262
2272
  var _state$gl$xr2;
@@ -2283,9 +2293,9 @@ function invalidate(state, frames = 1) {
2283
2293
  }
2284
2294
  }
2285
2295
 
2286
- /**
2287
- * Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
2288
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
2296
+ /**
2297
+ * Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
2298
+ * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
2289
2299
  */
2290
2300
  function advance(timestamp, runGlobalEffects = true, state, frame) {
2291
2301
  if (runGlobalEffects) flushGlobalEffects('before', timestamp);
@@ -2379,4 +2389,4 @@ function createPointerEvents(store) {
2379
2389
  };
2380
2390
  }
2381
2391
 
2382
- export { useThree as A, Block as B, useFrame as C, useGraph as D, ErrorBoundary as E, useLoader as F, _roots as _, useMutableCallback as a, useIsomorphicLayoutEffect as b, createRoot as c, unmountComponentAtNode as d, extend as e, createPointerEvents as f, createEvents as g, flushGlobalEffects as h, isRef as i, addEffect as j, addAfterEffect as k, addTail as l, invalidate as m, advance as n, createPortal as o, context as p, applyProps as q, reconciler as r, getRootState as s, threeTypes as t, useBridge as u, dispose as v, act as w, buildGraph as x, useInstanceHandle as y, useStore as z };
2392
+ export { useStore as A, Block as B, useThree as C, useFrame as D, ErrorBoundary as E, useGraph as F, useLoader as G, _roots as _, useMutableCallback as a, useIsomorphicLayoutEffect as b, createRoot as c, unmountComponentAtNode as d, extend as e, createPointerEvents as f, createEvents as g, flushGlobalEffects as h, isRef as i, addEffect as j, addAfterEffect as k, addTail as l, invalidate as m, advance as n, createPortal as o, flushSync as p, context as q, reconciler as r, applyProps as s, threeTypes as t, useBridge as u, getRootState as v, dispose as w, act as x, buildGraph as y, useInstanceHandle as z };