@react-three/fiber 10.0.0-canary.ce4bd5f → 10.0.0-canary.d5cebb9

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 (38) hide show
  1. package/dist/chunks/webgl.cjs +27 -0
  2. package/dist/chunks/webgl.mjs +11 -0
  3. package/dist/chunks/webgpu.cjs +37 -0
  4. package/dist/chunks/webgpu.mjs +21 -0
  5. package/dist/extension.cjs +13 -0
  6. package/dist/extension.d.cts +19 -0
  7. package/dist/extension.d.mts +19 -0
  8. package/dist/extension.d.ts +19 -0
  9. package/dist/extension.mjs +1 -0
  10. package/dist/index.cjs +97 -15365
  11. package/dist/index.d.cts +122 -3763
  12. package/dist/index.d.mts +122 -3763
  13. package/dist/index.d.ts +122 -3763
  14. package/dist/index.mjs +10 -15266
  15. package/dist/legacy.cjs +97 -15319
  16. package/dist/legacy.d.cts +114 -3765
  17. package/dist/legacy.d.mts +114 -3765
  18. package/dist/legacy.d.ts +114 -3765
  19. package/dist/legacy.mjs +14 -15223
  20. package/dist/shared/fiber.B0oukOFO.mjs +364 -0
  21. package/dist/shared/fiber.BU0vBHc9.d.mts +48 -0
  22. package/dist/shared/fiber.BY6Yf1h-.d.cts +2791 -0
  23. package/dist/shared/fiber.Cu2hX1IM.d.mts +2791 -0
  24. package/dist/shared/fiber.Cx-UAmMb.d.ts +48 -0
  25. package/dist/shared/fiber.DAl4H27x.d.cts +48 -0
  26. package/dist/shared/fiber.DXw-SLsH.d.ts +2791 -0
  27. package/dist/shared/fiber.I5Q4dVvl.d.cts +778 -0
  28. package/dist/shared/fiber.I5Q4dVvl.d.mts +778 -0
  29. package/dist/shared/fiber.I5Q4dVvl.d.ts +778 -0
  30. package/dist/shared/fiber.khFlPHPf.cjs +397 -0
  31. package/dist/shared/fiber.oKEFddXj.cjs +16059 -0
  32. package/dist/shared/fiber.tsM9NKZ9.mjs +15961 -0
  33. package/dist/webgpu/index.cjs +100 -16205
  34. package/dist/webgpu/index.d.cts +120 -4092
  35. package/dist/webgpu/index.d.mts +120 -4092
  36. package/dist/webgpu/index.d.ts +120 -4092
  37. package/dist/webgpu/index.mjs +15 -16089
  38. package/package.json +11 -8
@@ -0,0 +1,364 @@
1
+ import * as React from 'react';
2
+ import { useContext } from 'react';
3
+ import { jsx } from 'react/jsx-runtime';
4
+ import { useFiber, useContextBridge, traverseFiber } from 'its-fine';
5
+ import { getScheduler } from '@pmndrs/scheduler';
6
+
7
+ var __defProp = Object.defineProperty;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
10
+ const useIsomorphicLayoutEffect = /* @__PURE__ */ (() => typeof window !== "undefined" && (window.document?.createElement || window.navigator?.product === "ReactNative"))() ? React.useLayoutEffect : React.useEffect;
11
+ function useMutableCallback(fn) {
12
+ const ref = React.useRef(fn);
13
+ useIsomorphicLayoutEffect(() => void (ref.current = fn), [fn]);
14
+ return ref;
15
+ }
16
+ function useBridge() {
17
+ const fiber = useFiber();
18
+ const ContextBridge = useContextBridge();
19
+ return React.useMemo(
20
+ () => ({ children }) => {
21
+ const strict = !!traverseFiber(fiber, true, (node) => node.type === React.StrictMode);
22
+ const Root = strict ? React.StrictMode : React.Fragment;
23
+ return /* @__PURE__ */ jsx(Root, { children: /* @__PURE__ */ jsx(ContextBridge, { children }) });
24
+ },
25
+ [fiber, ContextBridge]
26
+ );
27
+ }
28
+ function Block({ set }) {
29
+ useIsomorphicLayoutEffect(() => {
30
+ set(new Promise(() => null));
31
+ return () => set(false);
32
+ }, [set]);
33
+ return null;
34
+ }
35
+ const ErrorBoundary = /* @__PURE__ */ (() => {
36
+ var _a;
37
+ return _a = class extends React.Component {
38
+ constructor() {
39
+ super(...arguments);
40
+ __publicField(this, "state", { error: false });
41
+ }
42
+ componentDidCatch(err) {
43
+ this.props.set(err);
44
+ }
45
+ render() {
46
+ return this.state.error ? null : this.props.children;
47
+ }
48
+ }, __publicField(_a, "getDerivedStateFromError", () => ({ error: true })), _a;
49
+ })();
50
+
51
+ const shownNotices = /* @__PURE__ */ new Set();
52
+ function notifyDepreciated({ heading, body, link }) {
53
+ if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_DEPRECATION_WARNINGS !== "true") {
54
+ return;
55
+ }
56
+ if (shownNotices.has(heading)) return;
57
+ shownNotices.add(heading);
58
+ const caller = getCallerFrame();
59
+ if (caller) {
60
+ console.log();
61
+ }
62
+ const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
63
+ if (caller) {
64
+ console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
65
+ }
66
+ if (body || link) {
67
+ let message = "";
68
+ if (body) message += body;
69
+ if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
70
+ console.warn(`%c${message}`, "font-weight: bold;");
71
+ }
72
+ }
73
+ function getCallerFrame(depth = 3) {
74
+ const stack = new Error().stack;
75
+ if (!stack) return null;
76
+ const lines = stack.split("\n");
77
+ const frame = lines[depth];
78
+ if (!frame) return null;
79
+ let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
80
+ if (!match) {
81
+ match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
82
+ }
83
+ if (!match) return null;
84
+ const [, fn, url, line] = match;
85
+ return {
86
+ functionName: fn ?? "<anonymous>",
87
+ location: formatLocation(url, Number(line))
88
+ };
89
+ }
90
+ function formatLocation(url, line) {
91
+ const clean = url.split("?")[0];
92
+ const file = clean.split("/").pop() ?? clean;
93
+ return `${file}:${line}`;
94
+ }
95
+ function notifyAlpha({ message, link }) {
96
+ if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_ALPHA_WARNINGS !== "true") {
97
+ return;
98
+ }
99
+ if (shownNotices.has(message)) return;
100
+ shownNotices.add(message);
101
+ const boxStyle = "background: #6366f1; color: #ffffff; padding: 6px 10px; border-radius: 4px; font-weight: 500;";
102
+ console.log(`%c\u{1F52C} ${message}`, boxStyle);
103
+ {
104
+ console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
105
+ }
106
+ }
107
+
108
+ const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
109
+ const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
110
+
111
+ function useStore() {
112
+ const store = useContext(context);
113
+ if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
114
+ return store;
115
+ }
116
+ function useThree(selector = (state) => state, equalityFn) {
117
+ return useStore()(selector, equalityFn);
118
+ }
119
+
120
+ function useFrame(callback, priorityOrOptions) {
121
+ const store = React.useContext(context);
122
+ const isInsideCanvas = store !== null;
123
+ const scheduler = getScheduler();
124
+ const optionsKey = typeof priorityOrOptions === "number" ? `p:${priorityOrOptions}` : priorityOrOptions ? JSON.stringify({
125
+ id: priorityOrOptions.id,
126
+ phase: priorityOrOptions.phase,
127
+ priority: priorityOrOptions.priority,
128
+ fps: priorityOrOptions.fps,
129
+ drop: priorityOrOptions.drop,
130
+ enabled: priorityOrOptions.enabled,
131
+ before: priorityOrOptions.before,
132
+ after: priorityOrOptions.after
133
+ }) : "";
134
+ const options = React.useMemo(() => {
135
+ return typeof priorityOrOptions === "number" ? { priority: priorityOrOptions } : priorityOrOptions ?? {};
136
+ }, [optionsKey]);
137
+ const reactId = React.useId();
138
+ const id = options.id ?? reactId;
139
+ const callbackRef = useMutableCallback(callback);
140
+ const isLegacyPriority = typeof priorityOrOptions === "number" && priorityOrOptions > 0;
141
+ const isLegacyOrdering = typeof priorityOrOptions === "number" && priorityOrOptions < 0;
142
+ useIsomorphicLayoutEffect(() => {
143
+ if (!callback) return;
144
+ if (isLegacyOrdering) {
145
+ notifyDepreciated({
146
+ heading: "useFrame numeric priority order is reversed in v10",
147
+ body: "useFrame(callback, number) is deprecated and its ordering direction is reversed from v9: v9 ran lower numbers first, v10 maps the number to { priority } and runs higher numbers first, so a negative priority now runs after default-priority jobs.\n\nUse { before, after } to name the dependency, or { priority } with the v10 direction (higher = earlier).",
148
+ link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
149
+ });
150
+ }
151
+ if (isInsideCanvas) {
152
+ const state = store.getState();
153
+ const rootId = state.internal.rootId;
154
+ if (isLegacyPriority) {
155
+ state.internal.priority++;
156
+ let parentRoot = state.previousRoot;
157
+ while (parentRoot) {
158
+ const parentState = parentRoot.getState();
159
+ if (parentState?.internal) parentState.internal.priority++;
160
+ parentRoot = parentState?.previousRoot;
161
+ }
162
+ notifyDepreciated({
163
+ heading: "useFrame with numeric priority is deprecated",
164
+ body: 'Using useFrame(callback, number) to control render order is deprecated.\n\nFor custom rendering, use: useFrame(callback, { phase: "render" })\nFor execution order within a phase, use: useFrame(callback, { priority: number }) \u2014 higher runs first, the reverse of v9',
165
+ link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
166
+ });
167
+ }
168
+ const wrappedCallback = (frameState, delta) => {
169
+ const localState = store.getState();
170
+ const mergedState = {
171
+ ...localState,
172
+ time: frameState.time,
173
+ delta: frameState.delta,
174
+ elapsed: frameState.elapsed,
175
+ frame: frameState.frame
176
+ };
177
+ callbackRef.current?.(mergedState, delta);
178
+ };
179
+ const unregister = scheduler.register(wrappedCallback, {
180
+ id,
181
+ rootId,
182
+ ...options
183
+ });
184
+ return () => {
185
+ unregister();
186
+ if (isLegacyPriority) {
187
+ const currentState = store.getState();
188
+ if (currentState.internal) {
189
+ currentState.internal.priority--;
190
+ let parentRoot = currentState.previousRoot;
191
+ while (parentRoot) {
192
+ const parentState = parentRoot.getState();
193
+ if (parentState?.internal) parentState.internal.priority--;
194
+ parentRoot = parentState?.previousRoot;
195
+ }
196
+ }
197
+ }
198
+ };
199
+ } else {
200
+ return scheduler.register(
201
+ (state, delta) => {
202
+ const frameState = state;
203
+ if (!frameState.renderer) return;
204
+ callbackRef.current?.(frameState, delta);
205
+ },
206
+ { id, ...options }
207
+ );
208
+ }
209
+ }, [store, scheduler, id, optionsKey, isLegacyPriority, isLegacyOrdering, isInsideCanvas]);
210
+ const isPaused = React.useSyncExternalStore(
211
+ // Subscribe function
212
+ React.useCallback(
213
+ (onStoreChange) => {
214
+ return getScheduler().subscribeJobState(id, onStoreChange);
215
+ },
216
+ [id]
217
+ ),
218
+ // getSnapshot function
219
+ React.useCallback(() => getScheduler().isJobPaused(id), [id]),
220
+ // getServerSnapshot function (SSR)
221
+ React.useCallback(() => false, [])
222
+ );
223
+ const controls = React.useMemo(() => {
224
+ const scheduler2 = getScheduler();
225
+ return {
226
+ /** The job's unique ID */
227
+ id,
228
+ /**
229
+ * Access to the global scheduler for frame loop control.
230
+ * Use for controlling the entire frame loop, adding phases, etc.
231
+ */
232
+ scheduler: scheduler2,
233
+ /**
234
+ * The root that currently owns this job. Resolve on access because ambient
235
+ * jobs can be adopted by a Canvas after the controls object is created.
236
+ */
237
+ get rootId() {
238
+ return getScheduler().getJobRootId(id);
239
+ },
240
+ /**
241
+ * Manually step this job only.
242
+ * Bypasses FPS limiting - always runs.
243
+ * @param timestamp Optional timestamp (defaults to performance.now())
244
+ */
245
+ step: (timestamp) => {
246
+ getScheduler().stepJob(id, timestamp);
247
+ },
248
+ /**
249
+ * Manually step ALL jobs in the scheduler.
250
+ * Useful for frameloop='never' mode.
251
+ * @param timestamp Optional timestamp (defaults to performance.now())
252
+ */
253
+ stepAll: (timestamp) => {
254
+ getScheduler().step(timestamp);
255
+ },
256
+ /**
257
+ * Request frames for this job's owning root without waking sibling roots.
258
+ */
259
+ invalidate: (frames, stackFrames) => {
260
+ const scheduler3 = getScheduler();
261
+ const rootId = scheduler3.getJobRootId(id);
262
+ if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
263
+ },
264
+ /**
265
+ * Pause this job (set enabled=false).
266
+ * Job remains registered but won't run.
267
+ */
268
+ pause: () => {
269
+ getScheduler().pauseJob(id);
270
+ },
271
+ /**
272
+ * Resume this job (set enabled=true).
273
+ */
274
+ resume: () => {
275
+ getScheduler().resumeJob(id);
276
+ },
277
+ /**
278
+ * Reactive paused state - automatically updates when pause/resume is called.
279
+ * No need for forceUpdate() in your components.
280
+ */
281
+ isPaused
282
+ };
283
+ }, [id, isPaused]);
284
+ return controls;
285
+ }
286
+
287
+ const R3F_STAGED_TEXTURES = Symbol.for("@react-three/fiber.stagedTextures");
288
+ const globalStaging = globalThis;
289
+ const staging = globalStaging[R3F_STAGED_TEXTURES] ?? (globalStaging[R3F_STAGED_TEXTURES] = /* @__PURE__ */ new WeakMap());
290
+ function stageTextures(store, entries) {
291
+ const registered = store.getState().textures;
292
+ let staged = staging.get(store);
293
+ for (const [url, texture] of entries) {
294
+ if (registered.has(url)) continue;
295
+ if (!staged) staging.set(store, staged = /* @__PURE__ */ new Map());
296
+ staged.set(url, texture);
297
+ }
298
+ }
299
+ function unstageTextures(store, urls) {
300
+ const staged = staging.get(store);
301
+ if (!staged) return;
302
+ for (const url of urls) staged.delete(url);
303
+ if (staged.size === 0) staging.delete(store);
304
+ }
305
+ function getTextureView(store) {
306
+ const registered = store.getState().textures;
307
+ const staged = staging.get(store);
308
+ if (!staged) return registered;
309
+ const view = new Map(registered);
310
+ for (const [url, texture] of staged) if (!view.has(url)) view.set(url, texture);
311
+ return view;
312
+ }
313
+
314
+ const R3F_EXTENSIONS = Symbol.for("@react-three/fiber.extensions");
315
+ function getRegistry() {
316
+ return globalThis[R3F_EXTENSIONS] ?? (globalThis[R3F_EXTENSIONS] = {
317
+ extensions: /* @__PURE__ */ new Map(),
318
+ roots: /* @__PURE__ */ new Set(),
319
+ applied: /* @__PURE__ */ new WeakMap()
320
+ });
321
+ }
322
+ function setupRoot(registry, store, extension) {
323
+ let applied = registry.applied.get(store);
324
+ if (!applied) registry.applied.set(store, applied = /* @__PURE__ */ new Map());
325
+ if (applied.has(extension.name)) return;
326
+ applied.set(extension.name, extension);
327
+ const patch = extension.setup?.(store);
328
+ if (patch) store.setState(patch);
329
+ }
330
+ function registerRootExtension(extension) {
331
+ const registry = getRegistry();
332
+ registry.extensions.set(extension.name, extension);
333
+ for (const store of registry.roots) setupRoot(registry, store, extension);
334
+ return () => {
335
+ if (registry.extensions.get(extension.name) === extension) registry.extensions.delete(extension.name);
336
+ };
337
+ }
338
+ function setRenderOverride(store, render) {
339
+ store.getState().internal.renderOverride = render;
340
+ }
341
+ function attachRootExtensions(store) {
342
+ const registry = getRegistry();
343
+ registry.roots.add(store);
344
+ for (const extension of registry.extensions.values()) setupRoot(registry, store, extension);
345
+ }
346
+ function current(registry, setUpBy) {
347
+ return registry.extensions.get(setUpBy.name) ?? setUpBy;
348
+ }
349
+ function detachRootExtensions(store) {
350
+ const registry = getRegistry();
351
+ if (!registry.roots.delete(store)) return;
352
+ const applied = registry.applied.get(store);
353
+ registry.applied.delete(store);
354
+ if (!applied) return;
355
+ for (const setUpBy of applied.values()) current(registry, setUpBy).dispose?.(store);
356
+ }
357
+ function notifyRootExtensionsHmr(store) {
358
+ const registry = getRegistry();
359
+ const applied = registry.applied.get(store);
360
+ if (!applied) return;
361
+ for (const setUpBy of applied.values()) current(registry, setUpBy).hmr?.(store);
362
+ }
363
+
364
+ 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, unstageTextures as h, stageTextures as i, detachRootExtensions as j, attachRootExtensions as k, notifyAlpha as l, notifyRootExtensionsHmr as m, notifyDepreciated as n, registerRootExtension as r, setRenderOverride as s, useStore as u };
@@ -0,0 +1,48 @@
1
+ import { a3 as FrameNextCallback } from './fiber.I5Q4dVvl.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 };