@react-three/fiber 10.0.0-canary.9b237a7 → 10.0.0-canary.a056612

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 (37) hide show
  1. package/dist/extension.cjs +8 -7
  2. package/dist/extension.d.cts +10 -47
  3. package/dist/extension.d.mts +10 -47
  4. package/dist/extension.d.ts +10 -47
  5. package/dist/extension.mjs +1 -1
  6. package/dist/index.cjs +13 -13
  7. package/dist/index.d.cts +8 -9
  8. package/dist/index.d.mts +8 -9
  9. package/dist/index.d.ts +8 -9
  10. package/dist/index.mjs +3 -3
  11. package/dist/legacy.cjs +13 -13
  12. package/dist/legacy.d.cts +10 -7
  13. package/dist/legacy.d.mts +10 -7
  14. package/dist/legacy.d.ts +10 -7
  15. package/dist/legacy.mjs +4 -4
  16. package/dist/shared/{fiber.DAg-9ieU.d.ts → fiber.3jeDXXYd.d.mts} +183 -542
  17. package/dist/shared/{fiber.Ddgoyqql.d.mts → fiber.B_KQAb3I.d.ts} +183 -542
  18. package/dist/shared/fiber.BdXKJXa0.mjs +16533 -0
  19. package/dist/shared/fiber.Bzw3s8zU.cjs +16631 -0
  20. package/dist/shared/fiber.C6hitYDY.d.cts +48 -0
  21. package/dist/shared/{fiber.Bw8YnGg5.d.cts → fiber.C_MFx7We.d.cts} +555 -19
  22. package/dist/shared/{fiber.Bw8YnGg5.d.mts → fiber.C_MFx7We.d.mts} +555 -19
  23. package/dist/shared/{fiber.Bw8YnGg5.d.ts → fiber.C_MFx7We.d.ts} +555 -19
  24. package/dist/shared/{fiber.D9dtW9DT.cjs → fiber.CsZ092z_.cjs} +110 -51
  25. package/dist/shared/fiber.D4fD6H74.d.mts +48 -0
  26. package/dist/shared/{fiber.D9zziEOb.mjs → fiber.DlH05gco.mjs} +107 -53
  27. package/dist/shared/fiber.YgTUGbja.d.ts +48 -0
  28. package/dist/shared/{fiber.DiPB625B.d.cts → fiber.fR3DaJb1.d.cts} +183 -542
  29. package/dist/webgpu/index.cjs +13 -13
  30. package/dist/webgpu/index.d.cts +5 -6
  31. package/dist/webgpu/index.d.mts +5 -6
  32. package/dist/webgpu/index.d.ts +5 -6
  33. package/dist/webgpu/index.mjs +4 -4
  34. package/package.json +8 -8
  35. package/readme.md +1 -1
  36. package/dist/shared/fiber.COTqIf4o.mjs +0 -15031
  37. package/dist/shared/fiber.COk97oyZ.cjs +0 -15129
@@ -28,16 +28,18 @@ function useMutableCallback(fn) {
28
28
  useIsomorphicLayoutEffect(() => void (ref.current = fn), [fn]);
29
29
  return ref;
30
30
  }
31
+ const useActivityBridge = React__namespace["Activity"] ? itsFine.useActivityBridge : () => React__namespace.Fragment;
31
32
  function useBridge() {
32
33
  const fiber = itsFine.useFiber();
33
34
  const ContextBridge = itsFine.useContextBridge();
35
+ const ActivityBridge = useActivityBridge();
34
36
  return React__namespace.useMemo(
35
37
  () => ({ children }) => {
36
38
  const strict = !!itsFine.traverseFiber(fiber, true, (node) => node.type === React__namespace.StrictMode);
37
39
  const Root = strict ? React__namespace.StrictMode : React__namespace.Fragment;
38
- return /* @__PURE__ */ jsxRuntime.jsx(Root, { children: /* @__PURE__ */ jsxRuntime.jsx(ContextBridge, { children }) });
40
+ return /* @__PURE__ */ jsxRuntime.jsx(Root, { children: /* @__PURE__ */ jsxRuntime.jsx(ActivityBridge, { children: /* @__PURE__ */ jsxRuntime.jsx(ContextBridge, { children }) }) });
39
41
  },
40
- [fiber, ContextBridge]
42
+ [fiber, ContextBridge, ActivityBridge]
41
43
  );
42
44
  }
43
45
  function Block({ set }) {
@@ -62,6 +64,23 @@ const ErrorBoundary = /* @__PURE__ */ (() => {
62
64
  }
63
65
  }, __publicField(_a, "getDerivedStateFromError", () => ({ error: true })), _a;
64
66
  })();
67
+ const noop = () => {
68
+ };
69
+ function Gate({ promise, onSettled }) {
70
+ React__namespace.use(promise);
71
+ useIsomorphicLayoutEffect(onSettled, [onSettled]);
72
+ return null;
73
+ }
74
+ function useGate() {
75
+ const [promise, setPromise] = React__namespace.useState(null);
76
+ const onSettled = React__namespace.useCallback(() => setPromise(null), []);
77
+ const waitFor = React__namespace.useCallback(
78
+ (next) => setPromise((current) => current ?? Promise.resolve(next).then(noop, noop)),
79
+ []
80
+ );
81
+ const gate = promise ? /* @__PURE__ */ jsxRuntime.jsx(React__namespace.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(Gate, { promise, onSettled }) }) : null;
82
+ return [gate, waitFor];
83
+ }
65
84
 
66
85
  const shownNotices = /* @__PURE__ */ new Set();
67
86
  function notifyDepreciated({ heading, body, link }) {
@@ -119,10 +138,67 @@ function notifyAlpha({ message, link }) {
119
138
  console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
120
139
  }
121
140
  }
141
+ function isDevelopment() {
142
+ try {
143
+ return process.env.NODE_ENV !== "production";
144
+ } catch {
145
+ return true;
146
+ }
147
+ }
122
148
 
123
149
  const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
124
150
  const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React__namespace.createContext(null));
125
151
 
152
+ const R3F_EXTENSIONS = Symbol.for("@react-three/fiber.extensions");
153
+ function getRegistry() {
154
+ return globalThis[R3F_EXTENSIONS] ?? (globalThis[R3F_EXTENSIONS] = {
155
+ extensions: /* @__PURE__ */ new Map(),
156
+ roots: /* @__PURE__ */ new Set(),
157
+ applied: /* @__PURE__ */ new WeakMap()
158
+ });
159
+ }
160
+ function setupRoot(registry, store, extension) {
161
+ let applied = registry.applied.get(store);
162
+ if (!applied) registry.applied.set(store, applied = /* @__PURE__ */ new Map());
163
+ if (applied.has(extension.name)) return;
164
+ applied.set(extension.name, extension);
165
+ const patch = extension.setup?.(store);
166
+ if (patch) store.setState(patch);
167
+ }
168
+ function registerRootExtension(extension) {
169
+ const registry = getRegistry();
170
+ registry.extensions.set(extension.name, extension);
171
+ for (const store of registry.roots) setupRoot(registry, store, extension);
172
+ return () => {
173
+ if (registry.extensions.get(extension.name) === extension) registry.extensions.delete(extension.name);
174
+ };
175
+ }
176
+ function setRenderOverride(store, render) {
177
+ store.getState().internal.renderOverride = render;
178
+ }
179
+ function attachRootExtensions(store) {
180
+ const registry = getRegistry();
181
+ registry.roots.add(store);
182
+ for (const extension of registry.extensions.values()) setupRoot(registry, store, extension);
183
+ }
184
+ function current(registry, setUpBy) {
185
+ return registry.extensions.get(setUpBy.name) ?? setUpBy;
186
+ }
187
+ function detachRootExtensions(store) {
188
+ const registry = getRegistry();
189
+ if (!registry.roots.delete(store)) return;
190
+ const applied = registry.applied.get(store);
191
+ registry.applied.delete(store);
192
+ if (!applied) return;
193
+ for (const setUpBy of applied.values()) current(registry, setUpBy).dispose?.(store);
194
+ }
195
+ function notifyRootExtensionsHmr(store) {
196
+ const registry = getRegistry();
197
+ const applied = registry.applied.get(store);
198
+ if (!applied) return;
199
+ for (const setUpBy of applied.values()) current(registry, setUpBy).hmr?.(store);
200
+ }
201
+
126
202
  function useStore() {
127
203
  const store = React.useContext(context);
128
204
  if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
@@ -149,8 +225,8 @@ function useFrame(callback, priorityOrOptions) {
149
225
  const options = React__namespace.useMemo(() => {
150
226
  return typeof priorityOrOptions === "number" ? { priority: priorityOrOptions } : priorityOrOptions ?? {};
151
227
  }, [optionsKey]);
152
- const reactId = React__namespace.useId();
153
- const id = options.id ?? reactId;
228
+ const [generatedId] = React__namespace.useState(() => scheduler$1.generateJobId());
229
+ const id = options.id ?? generatedId;
154
230
  const callbackRef = useMutableCallback(callback);
155
231
  const isLegacyPriority = typeof priorityOrOptions === "number" && priorityOrOptions > 0;
156
232
  const isLegacyOrdering = typeof priorityOrOptions === "number" && priorityOrOptions < 0;
@@ -187,7 +263,8 @@ function useFrame(callback, priorityOrOptions) {
187
263
  time: frameState.time,
188
264
  delta: frameState.delta,
189
265
  elapsed: frameState.elapsed,
190
- frame: frameState.frame
266
+ frame: frameState.frame,
267
+ overstep: frameState.overstep
191
268
  };
192
269
  callbackRef.current?.(mergedState, delta);
193
270
  };
@@ -299,54 +376,31 @@ function useFrame(callback, priorityOrOptions) {
299
376
  return controls;
300
377
  }
301
378
 
302
- const R3F_EXTENSIONS = Symbol.for("@react-three/fiber.extensions");
303
- function getRegistry() {
304
- return globalThis[R3F_EXTENSIONS] ?? (globalThis[R3F_EXTENSIONS] = {
305
- extensions: /* @__PURE__ */ new Map(),
306
- roots: /* @__PURE__ */ new Set(),
307
- applied: /* @__PURE__ */ new WeakMap()
308
- });
309
- }
310
- function setupRoot(registry, store, extension) {
311
- let applied = registry.applied.get(store);
312
- if (!applied) registry.applied.set(store, applied = /* @__PURE__ */ new Map());
313
- if (applied.has(extension.name)) return;
314
- applied.set(extension.name, extension);
315
- const patch = extension.setup?.(store);
316
- if (patch) store.setState(patch);
317
- }
318
- function registerRootExtension(extension) {
319
- const registry = getRegistry();
320
- registry.extensions.set(extension.name, extension);
321
- for (const store of registry.roots) setupRoot(registry, store, extension);
322
- return () => {
323
- if (registry.extensions.get(extension.name) === extension) registry.extensions.delete(extension.name);
324
- };
325
- }
326
- function setRenderOverride(store, render) {
327
- store.getState().internal.renderOverride = render;
328
- }
329
- function attachRootExtensions(store) {
330
- const registry = getRegistry();
331
- registry.roots.add(store);
332
- for (const extension of registry.extensions.values()) setupRoot(registry, store, extension);
379
+ const R3F_STAGED_TEXTURES = Symbol.for("@react-three/fiber.stagedTextures");
380
+ const globalStaging = globalThis;
381
+ const staging = globalStaging[R3F_STAGED_TEXTURES] ?? (globalStaging[R3F_STAGED_TEXTURES] = /* @__PURE__ */ new WeakMap());
382
+ function stageTextures(store, entries) {
383
+ const registered = store.getState().textures;
384
+ let staged = staging.get(store);
385
+ for (const [url, texture] of entries) {
386
+ if (registered.has(url)) continue;
387
+ if (!staged) staging.set(store, staged = /* @__PURE__ */ new Map());
388
+ staged.set(url, texture);
389
+ }
333
390
  }
334
- function current(registry, setUpBy) {
335
- return registry.extensions.get(setUpBy.name) ?? setUpBy;
391
+ function unstageTextures(store, urls) {
392
+ const staged = staging.get(store);
393
+ if (!staged) return;
394
+ for (const url of urls) staged.delete(url);
395
+ if (staged.size === 0) staging.delete(store);
336
396
  }
337
- function detachRootExtensions(store) {
338
- const registry = getRegistry();
339
- if (!registry.roots.delete(store)) return;
340
- const applied = registry.applied.get(store);
341
- registry.applied.delete(store);
342
- if (!applied) return;
343
- for (const setUpBy of applied.values()) current(registry, setUpBy).dispose?.(store);
344
- }
345
- function notifyRootExtensionsHmr(store) {
346
- const registry = getRegistry();
347
- const applied = registry.applied.get(store);
348
- if (!applied) return;
349
- for (const setUpBy of applied.values()) current(registry, setUpBy).hmr?.(store);
397
+ function getTextureView(store) {
398
+ const registered = store.getState().textures;
399
+ const staged = staging.get(store);
400
+ if (!staged) return registered;
401
+ const view = new Map(registered);
402
+ for (const [url, texture] of staged) if (!view.has(url)) view.set(url, texture);
403
+ return view;
350
404
  }
351
405
 
352
406
  exports.Block = Block;
@@ -354,13 +408,18 @@ exports.ErrorBoundary = ErrorBoundary;
354
408
  exports.attachRootExtensions = attachRootExtensions;
355
409
  exports.context = context;
356
410
  exports.detachRootExtensions = detachRootExtensions;
411
+ exports.getTextureView = getTextureView;
412
+ exports.isDevelopment = isDevelopment;
357
413
  exports.notifyAlpha = notifyAlpha;
358
414
  exports.notifyDepreciated = notifyDepreciated;
359
415
  exports.notifyRootExtensionsHmr = notifyRootExtensionsHmr;
360
416
  exports.registerRootExtension = registerRootExtension;
361
417
  exports.setRenderOverride = setRenderOverride;
418
+ exports.stageTextures = stageTextures;
419
+ exports.unstageTextures = unstageTextures;
362
420
  exports.useBridge = useBridge;
363
421
  exports.useFrame = useFrame;
422
+ exports.useGate = useGate;
364
423
  exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect;
365
424
  exports.useMutableCallback = useMutableCallback;
366
425
  exports.useStore = useStore;
@@ -0,0 +1,48 @@
1
+ import { aO as FrameNextCallback } from './fiber.C_MFx7We.mjs';
2
+ import { UseFrameNextOptions, FrameNextControls } from '@pmndrs/scheduler';
3
+
4
+ /**
5
+ * Frame hook with phase-based ordering, priority, and FPS throttling.
6
+ *
7
+ * Always delivers full RootState — works both inside and outside Canvas context:
8
+ * - Inside Canvas: Full RootState (renderer, scene, camera, etc.)
9
+ * - Outside Canvas: The job registers immediately but the callback is held until a
10
+ * Canvas adopts it, then runs with full RootState. For hostless / standalone
11
+ * frame loops with no Canvas, use `@pmndrs/scheduler` directly.
12
+ *
13
+ * Returns a controls object for manual stepping, pausing, and resuming.
14
+ *
15
+ * @param callback - Function called each frame with (state, delta). Optional if you only need scheduler access.
16
+ * @param priorityOrOptions - Either a priority number (backwards compat) or options object
17
+ * @returns Controls object with step(), stepAll(), invalidate(), pause(), resume(), isPaused, id, rootId, scheduler
18
+ *
19
+ * @example
20
+ * // Simple priority (backwards compat)
21
+ * useFrame((state, delta) => { ... }, 5)
22
+ *
23
+ * @example
24
+ * // With phase-based ordering
25
+ * useFrame((state, delta) => { ... }, { phase: 'physics' })
26
+ *
27
+ * @example
28
+ * // Outside Canvas - callback waits for a Canvas, then always has full state
29
+ * function UI() {
30
+ * useFrame((state, delta) => { syncUI(state.camera) });
31
+ * return <button>...</button>;
32
+ * }
33
+ *
34
+ * @example
35
+ * // Hostless / standalone loop (no Canvas) - use @pmndrs/scheduler directly
36
+ * import { getScheduler } from '@pmndrs/scheduler'
37
+ * getScheduler().register((state, delta) => { updateGame(delta) })
38
+ *
39
+ * @example
40
+ * // Scheduler-only access (no callback)
41
+ * const { scheduler } = useFrame()
42
+ * scheduler.pauseJob('some-job-id')
43
+ *
44
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
45
+ */
46
+ declare function useFrame(callback?: FrameNextCallback, priorityOrOptions?: number | UseFrameNextOptions): FrameNextControls;
47
+
48
+ export { useFrame as u };
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { useContext } from 'react';
3
3
  import { jsx } from 'react/jsx-runtime';
4
- import { useFiber, useContextBridge, traverseFiber } from 'its-fine';
4
+ import { useFiber, useContextBridge, useActivityBridge as useActivityBridge$1, traverseFiber } from 'its-fine';
5
5
  import { getScheduler } from '@pmndrs/scheduler';
6
6
 
7
7
  var __defProp = Object.defineProperty;
@@ -13,16 +13,18 @@ function useMutableCallback(fn) {
13
13
  useIsomorphicLayoutEffect(() => void (ref.current = fn), [fn]);
14
14
  return ref;
15
15
  }
16
+ const useActivityBridge = React["Activity"] ? useActivityBridge$1 : () => React.Fragment;
16
17
  function useBridge() {
17
18
  const fiber = useFiber();
18
19
  const ContextBridge = useContextBridge();
20
+ const ActivityBridge = useActivityBridge();
19
21
  return React.useMemo(
20
22
  () => ({ children }) => {
21
23
  const strict = !!traverseFiber(fiber, true, (node) => node.type === React.StrictMode);
22
24
  const Root = strict ? React.StrictMode : React.Fragment;
23
- return /* @__PURE__ */ jsx(Root, { children: /* @__PURE__ */ jsx(ContextBridge, { children }) });
25
+ return /* @__PURE__ */ jsx(Root, { children: /* @__PURE__ */ jsx(ActivityBridge, { children: /* @__PURE__ */ jsx(ContextBridge, { children }) }) });
24
26
  },
25
- [fiber, ContextBridge]
27
+ [fiber, ContextBridge, ActivityBridge]
26
28
  );
27
29
  }
28
30
  function Block({ set }) {
@@ -47,6 +49,23 @@ const ErrorBoundary = /* @__PURE__ */ (() => {
47
49
  }
48
50
  }, __publicField(_a, "getDerivedStateFromError", () => ({ error: true })), _a;
49
51
  })();
52
+ const noop = () => {
53
+ };
54
+ function Gate({ promise, onSettled }) {
55
+ React.use(promise);
56
+ useIsomorphicLayoutEffect(onSettled, [onSettled]);
57
+ return null;
58
+ }
59
+ function useGate() {
60
+ const [promise, setPromise] = React.useState(null);
61
+ const onSettled = React.useCallback(() => setPromise(null), []);
62
+ const waitFor = React.useCallback(
63
+ (next) => setPromise((current) => current ?? Promise.resolve(next).then(noop, noop)),
64
+ []
65
+ );
66
+ const gate = promise ? /* @__PURE__ */ jsx(React.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(Gate, { promise, onSettled }) }) : null;
67
+ return [gate, waitFor];
68
+ }
50
69
 
51
70
  const shownNotices = /* @__PURE__ */ new Set();
52
71
  function notifyDepreciated({ heading, body, link }) {
@@ -104,10 +123,67 @@ function notifyAlpha({ message, link }) {
104
123
  console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
105
124
  }
106
125
  }
126
+ function isDevelopment() {
127
+ try {
128
+ return process.env.NODE_ENV !== "production";
129
+ } catch {
130
+ return true;
131
+ }
132
+ }
107
133
 
108
134
  const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
109
135
  const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
110
136
 
137
+ const R3F_EXTENSIONS = Symbol.for("@react-three/fiber.extensions");
138
+ function getRegistry() {
139
+ return globalThis[R3F_EXTENSIONS] ?? (globalThis[R3F_EXTENSIONS] = {
140
+ extensions: /* @__PURE__ */ new Map(),
141
+ roots: /* @__PURE__ */ new Set(),
142
+ applied: /* @__PURE__ */ new WeakMap()
143
+ });
144
+ }
145
+ function setupRoot(registry, store, extension) {
146
+ let applied = registry.applied.get(store);
147
+ if (!applied) registry.applied.set(store, applied = /* @__PURE__ */ new Map());
148
+ if (applied.has(extension.name)) return;
149
+ applied.set(extension.name, extension);
150
+ const patch = extension.setup?.(store);
151
+ if (patch) store.setState(patch);
152
+ }
153
+ function registerRootExtension(extension) {
154
+ const registry = getRegistry();
155
+ registry.extensions.set(extension.name, extension);
156
+ for (const store of registry.roots) setupRoot(registry, store, extension);
157
+ return () => {
158
+ if (registry.extensions.get(extension.name) === extension) registry.extensions.delete(extension.name);
159
+ };
160
+ }
161
+ function setRenderOverride(store, render) {
162
+ store.getState().internal.renderOverride = render;
163
+ }
164
+ function attachRootExtensions(store) {
165
+ const registry = getRegistry();
166
+ registry.roots.add(store);
167
+ for (const extension of registry.extensions.values()) setupRoot(registry, store, extension);
168
+ }
169
+ function current(registry, setUpBy) {
170
+ return registry.extensions.get(setUpBy.name) ?? setUpBy;
171
+ }
172
+ function detachRootExtensions(store) {
173
+ const registry = getRegistry();
174
+ if (!registry.roots.delete(store)) return;
175
+ const applied = registry.applied.get(store);
176
+ registry.applied.delete(store);
177
+ if (!applied) return;
178
+ for (const setUpBy of applied.values()) current(registry, setUpBy).dispose?.(store);
179
+ }
180
+ function notifyRootExtensionsHmr(store) {
181
+ const registry = getRegistry();
182
+ const applied = registry.applied.get(store);
183
+ if (!applied) return;
184
+ for (const setUpBy of applied.values()) current(registry, setUpBy).hmr?.(store);
185
+ }
186
+
111
187
  function useStore() {
112
188
  const store = useContext(context);
113
189
  if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
@@ -134,8 +210,8 @@ function useFrame(callback, priorityOrOptions) {
134
210
  const options = React.useMemo(() => {
135
211
  return typeof priorityOrOptions === "number" ? { priority: priorityOrOptions } : priorityOrOptions ?? {};
136
212
  }, [optionsKey]);
137
- const reactId = React.useId();
138
- const id = options.id ?? reactId;
213
+ const [generatedId] = React.useState(() => scheduler.generateJobId());
214
+ const id = options.id ?? generatedId;
139
215
  const callbackRef = useMutableCallback(callback);
140
216
  const isLegacyPriority = typeof priorityOrOptions === "number" && priorityOrOptions > 0;
141
217
  const isLegacyOrdering = typeof priorityOrOptions === "number" && priorityOrOptions < 0;
@@ -172,7 +248,8 @@ function useFrame(callback, priorityOrOptions) {
172
248
  time: frameState.time,
173
249
  delta: frameState.delta,
174
250
  elapsed: frameState.elapsed,
175
- frame: frameState.frame
251
+ frame: frameState.frame,
252
+ overstep: frameState.overstep
176
253
  };
177
254
  callbackRef.current?.(mergedState, delta);
178
255
  };
@@ -284,54 +361,31 @@ function useFrame(callback, priorityOrOptions) {
284
361
  return controls;
285
362
  }
286
363
 
287
- const R3F_EXTENSIONS = Symbol.for("@react-three/fiber.extensions");
288
- function getRegistry() {
289
- return globalThis[R3F_EXTENSIONS] ?? (globalThis[R3F_EXTENSIONS] = {
290
- extensions: /* @__PURE__ */ new Map(),
291
- roots: /* @__PURE__ */ new Set(),
292
- applied: /* @__PURE__ */ new WeakMap()
293
- });
294
- }
295
- function setupRoot(registry, store, extension) {
296
- let applied = registry.applied.get(store);
297
- if (!applied) registry.applied.set(store, applied = /* @__PURE__ */ new Map());
298
- if (applied.has(extension.name)) return;
299
- applied.set(extension.name, extension);
300
- const patch = extension.setup?.(store);
301
- if (patch) store.setState(patch);
302
- }
303
- function registerRootExtension(extension) {
304
- const registry = getRegistry();
305
- registry.extensions.set(extension.name, extension);
306
- for (const store of registry.roots) setupRoot(registry, store, extension);
307
- return () => {
308
- if (registry.extensions.get(extension.name) === extension) registry.extensions.delete(extension.name);
309
- };
310
- }
311
- function setRenderOverride(store, render) {
312
- store.getState().internal.renderOverride = render;
313
- }
314
- function attachRootExtensions(store) {
315
- const registry = getRegistry();
316
- registry.roots.add(store);
317
- for (const extension of registry.extensions.values()) setupRoot(registry, store, extension);
364
+ const R3F_STAGED_TEXTURES = Symbol.for("@react-three/fiber.stagedTextures");
365
+ const globalStaging = globalThis;
366
+ const staging = globalStaging[R3F_STAGED_TEXTURES] ?? (globalStaging[R3F_STAGED_TEXTURES] = /* @__PURE__ */ new WeakMap());
367
+ function stageTextures(store, entries) {
368
+ const registered = store.getState().textures;
369
+ let staged = staging.get(store);
370
+ for (const [url, texture] of entries) {
371
+ if (registered.has(url)) continue;
372
+ if (!staged) staging.set(store, staged = /* @__PURE__ */ new Map());
373
+ staged.set(url, texture);
374
+ }
318
375
  }
319
- function current(registry, setUpBy) {
320
- return registry.extensions.get(setUpBy.name) ?? setUpBy;
376
+ function unstageTextures(store, urls) {
377
+ const staged = staging.get(store);
378
+ if (!staged) return;
379
+ for (const url of urls) staged.delete(url);
380
+ if (staged.size === 0) staging.delete(store);
321
381
  }
322
- function detachRootExtensions(store) {
323
- const registry = getRegistry();
324
- if (!registry.roots.delete(store)) return;
325
- const applied = registry.applied.get(store);
326
- registry.applied.delete(store);
327
- if (!applied) return;
328
- for (const setUpBy of applied.values()) current(registry, setUpBy).dispose?.(store);
329
- }
330
- function notifyRootExtensionsHmr(store) {
331
- const registry = getRegistry();
332
- const applied = registry.applied.get(store);
333
- if (!applied) return;
334
- for (const setUpBy of applied.values()) current(registry, setUpBy).hmr?.(store);
382
+ function getTextureView(store) {
383
+ const registered = store.getState().textures;
384
+ const staged = staging.get(store);
385
+ if (!staged) return registered;
386
+ const view = new Map(registered);
387
+ for (const [url, texture] of staged) if (!view.has(url)) view.set(url, texture);
388
+ return view;
335
389
  }
336
390
 
337
- export { Block as B, ErrorBoundary as E, useThree as a, useFrame as b, context as c, useIsomorphicLayoutEffect as d, useMutableCallback as e, useBridge as f, detachRootExtensions as g, attachRootExtensions as h, notifyAlpha as i, notifyRootExtensionsHmr as j, notifyDepreciated as n, registerRootExtension as r, setRenderOverride as s, useStore as u };
391
+ export { Block as B, ErrorBoundary as E, useThree as a, useFrame as b, context as c, useIsomorphicLayoutEffect as d, useMutableCallback as e, useBridge as f, getTextureView as g, detachRootExtensions as h, isDevelopment as i, attachRootExtensions as j, unstageTextures as k, stageTextures as l, useGate as m, notifyDepreciated as n, notifyAlpha as o, notifyRootExtensionsHmr as p, registerRootExtension as r, setRenderOverride as s, useStore as u };
@@ -0,0 +1,48 @@
1
+ import { aO as FrameNextCallback } from './fiber.C_MFx7We.js';
2
+ import { UseFrameNextOptions, FrameNextControls } from '@pmndrs/scheduler';
3
+
4
+ /**
5
+ * Frame hook with phase-based ordering, priority, and FPS throttling.
6
+ *
7
+ * Always delivers full RootState — works both inside and outside Canvas context:
8
+ * - Inside Canvas: Full RootState (renderer, scene, camera, etc.)
9
+ * - Outside Canvas: The job registers immediately but the callback is held until a
10
+ * Canvas adopts it, then runs with full RootState. For hostless / standalone
11
+ * frame loops with no Canvas, use `@pmndrs/scheduler` directly.
12
+ *
13
+ * Returns a controls object for manual stepping, pausing, and resuming.
14
+ *
15
+ * @param callback - Function called each frame with (state, delta). Optional if you only need scheduler access.
16
+ * @param priorityOrOptions - Either a priority number (backwards compat) or options object
17
+ * @returns Controls object with step(), stepAll(), invalidate(), pause(), resume(), isPaused, id, rootId, scheduler
18
+ *
19
+ * @example
20
+ * // Simple priority (backwards compat)
21
+ * useFrame((state, delta) => { ... }, 5)
22
+ *
23
+ * @example
24
+ * // With phase-based ordering
25
+ * useFrame((state, delta) => { ... }, { phase: 'physics' })
26
+ *
27
+ * @example
28
+ * // Outside Canvas - callback waits for a Canvas, then always has full state
29
+ * function UI() {
30
+ * useFrame((state, delta) => { syncUI(state.camera) });
31
+ * return <button>...</button>;
32
+ * }
33
+ *
34
+ * @example
35
+ * // Hostless / standalone loop (no Canvas) - use @pmndrs/scheduler directly
36
+ * import { getScheduler } from '@pmndrs/scheduler'
37
+ * getScheduler().register((state, delta) => { updateGame(delta) })
38
+ *
39
+ * @example
40
+ * // Scheduler-only access (no callback)
41
+ * const { scheduler } = useFrame()
42
+ * scheduler.pauseJob('some-job-id')
43
+ *
44
+ * @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
45
+ */
46
+ declare function useFrame(callback?: FrameNextCallback, priorityOrOptions?: number | UseFrameNextOptions): FrameNextControls;
47
+
48
+ export { useFrame as u };