@react-three/fiber 10.0.0-canary.b86abaa → 10.0.0-canary.b9d5979

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 (32) hide show
  1. package/dist/extension.d.cts +3 -3
  2. package/dist/extension.d.mts +3 -3
  3. package/dist/extension.d.ts +3 -3
  4. package/dist/extension.mjs +1 -1
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.d.cts +5 -5
  7. package/dist/index.d.mts +5 -5
  8. package/dist/index.d.ts +5 -5
  9. package/dist/index.mjs +3 -3
  10. package/dist/legacy.cjs +1 -1
  11. package/dist/legacy.d.cts +4 -4
  12. package/dist/legacy.d.mts +4 -4
  13. package/dist/legacy.d.ts +4 -4
  14. package/dist/legacy.mjs +4 -4
  15. package/dist/shared/{fiber.tsM9NKZ9.mjs → fiber.5Q8N6Hhq.mjs} +226 -57
  16. package/dist/shared/{fiber.Cx-UAmMb.d.ts → fiber.B_GGVI86.d.ts} +1 -1
  17. package/dist/shared/{fiber.DXw-SLsH.d.ts → fiber.BcNm6NAg.d.cts} +88 -4
  18. package/dist/shared/{fiber.oKEFddXj.cjs → fiber.BegWBc5_.cjs} +226 -57
  19. package/dist/shared/{fiber.BY6Yf1h-.d.cts → fiber.CQDCACCJ.d.mts} +88 -4
  20. package/dist/shared/{fiber.B0oukOFO.mjs → fiber.CUKAa7Rv.mjs} +1 -1
  21. package/dist/shared/{fiber.I5Q4dVvl.d.cts → fiber.CZLeHcML.d.cts} +24 -2
  22. package/dist/shared/{fiber.I5Q4dVvl.d.mts → fiber.CZLeHcML.d.mts} +24 -2
  23. package/dist/shared/{fiber.I5Q4dVvl.d.ts → fiber.CZLeHcML.d.ts} +24 -2
  24. package/dist/shared/{fiber.BU0vBHc9.d.mts → fiber.ColkapKS.d.mts} +1 -1
  25. package/dist/shared/{fiber.DAl4H27x.d.cts → fiber.DRfTw2kk.d.cts} +1 -1
  26. package/dist/shared/{fiber.Cu2hX1IM.d.mts → fiber.DeBIf2pk.d.ts} +88 -4
  27. package/dist/webgpu/index.cjs +1 -1
  28. package/dist/webgpu/index.d.cts +4 -4
  29. package/dist/webgpu/index.d.mts +4 -4
  30. package/dist/webgpu/index.d.ts +4 -4
  31. package/dist/webgpu/index.mjs +4 -4
  32. package/package.json +1 -1
@@ -417,6 +417,15 @@ function isOnce(value) {
417
417
  return value !== null && typeof value === "object" && ONCE in value;
418
418
  }
419
419
 
420
+ function assertNodeMaterialSupported(state, value) {
421
+ if (!state?.isLegacy) return;
422
+ const material = (Array.isArray(value) ? value : [value]).find((m) => m?.isNodeMaterial);
423
+ if (!material) return;
424
+ throw new Error(
425
+ `R3F: ${material.type ?? "Node material"} requires WebGPURenderer (it falls back to WebGL2 automatically). Pass \`renderer\` to <Canvas> from @react-three/fiber, or import from @react-three/fiber/webgpu.`
426
+ );
427
+ }
428
+
420
429
  const RESERVED_PROPS = [
421
430
  "children",
422
431
  "key",
@@ -587,6 +596,7 @@ function applyProps(object, props) {
587
596
  }
588
597
  }
589
598
  } else {
599
+ if (key === "material") assertNodeMaterialSupported(rootState, value);
590
600
  root[key] = value;
591
601
  if (key.endsWith("Node") && root.isMaterial) {
592
602
  root.needsUpdate = true;
@@ -13900,11 +13910,16 @@ function validateInstance(type, props, root) {
13900
13910
  const name = toPascalCase(type);
13901
13911
  const target = resolveConstructor(name, root);
13902
13912
  if (type !== "primitive" && !target) {
13913
+ if (name.endsWith("NodeMaterial")) {
13914
+ assertNodeMaterialSupported(root.getState(), { isNodeMaterial: true, type: name });
13915
+ }
13903
13916
  throw new Error(
13904
13917
  `R3F: ${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`
13905
13918
  );
13906
13919
  }
13907
13920
  if (type === "primitive" && !props.object) throw new Error(`R3F: Primitives without 'object' are invalid!`);
13921
+ assertNodeMaterialSupported(root.getState(), props.object);
13922
+ assertNodeMaterialSupported(root.getState(), props.material);
13908
13923
  if (props.args !== void 0 && !Array.isArray(props.args)) throw new Error("R3F: The args prop must be an array!");
13909
13924
  }
13910
13925
  function createInstance(type, props, root) {
@@ -14003,6 +14018,7 @@ function disposeOnIdle(object) {
14003
14018
  }
14004
14019
  function removeChild(parent, child, dispose) {
14005
14020
  if (!child) return;
14021
+ const wasLinked = !!child.parent;
14006
14022
  child.parent = null;
14007
14023
  const childIndex = parent.children.indexOf(child);
14008
14024
  if (childIndex !== -1) parent.children.splice(childIndex, 1);
@@ -14022,7 +14038,10 @@ function removeChild(parent, child, dispose) {
14022
14038
  if (shouldDispose && child.type !== "primitive" && child.object.type !== "Scene") {
14023
14039
  disposeOnIdle(child.object);
14024
14040
  }
14025
- if (dispose === void 0) invalidateInstance(child);
14041
+ if (dispose === void 0 && wasLinked) {
14042
+ const state = findInitialRoot(child).getState();
14043
+ if (state.internal.active && state.internal.frames === 0) state.invalidate();
14044
+ }
14026
14045
  }
14027
14046
  function setFiberRef(fiber, publicInstance) {
14028
14047
  for (const _fiber of [fiber, fiber.alternate]) {
@@ -14771,6 +14790,69 @@ function getPrimaryIds() {
14771
14790
  return Array.from(primaryRegistry.keys());
14772
14791
  }
14773
14792
 
14793
+ const fulfilled = (value) => Object.assign(Promise.resolve(value), { status: "fulfilled", value });
14794
+ const tracked = (promise) => {
14795
+ const result = Promise.resolve(promise);
14796
+ result.status = "pending";
14797
+ result.then(
14798
+ (value) => {
14799
+ Object.assign(result, { status: "fulfilled", value });
14800
+ },
14801
+ (reason) => {
14802
+ Object.assign(result, { status: "rejected", reason });
14803
+ }
14804
+ );
14805
+ return result;
14806
+ };
14807
+
14808
+ const records = /* @__PURE__ */ new WeakMap();
14809
+ function take(renderer, record) {
14810
+ record.leases++;
14811
+ let released = false;
14812
+ return () => {
14813
+ if (released) return;
14814
+ released = true;
14815
+ if (--record.leases > 0) return;
14816
+ records.delete(renderer);
14817
+ if (record.owned) return disposeRenderer(renderer);
14818
+ };
14819
+ }
14820
+ function leaseRenderer(renderer, owned) {
14821
+ let record = records.get(renderer);
14822
+ if (!record) records.set(renderer, record = { owned, leases: 0 });
14823
+ return take(renderer, record);
14824
+ }
14825
+ function borrowRenderer(renderer) {
14826
+ const record = records.get(renderer);
14827
+ if (!record) throw new Error("R3F: cannot share a renderer whose canvas has already unmounted");
14828
+ return take(renderer, record);
14829
+ }
14830
+ function disposeRenderer(renderer) {
14831
+ if (renderer.hasInitialized?.() === false) return;
14832
+ const warn = (error) => console.warn("[R3F] Error disposing renderer", error);
14833
+ const loseContext = () => {
14834
+ try {
14835
+ ;
14836
+ renderer.forceContextLoss?.();
14837
+ } catch (error) {
14838
+ warn(error);
14839
+ }
14840
+ };
14841
+ let disposed;
14842
+ try {
14843
+ disposed = renderer.dispose();
14844
+ } catch (error) {
14845
+ warn(error);
14846
+ }
14847
+ if (typeof disposed?.then === "function") {
14848
+ return Promise.resolve(disposed).then(loseContext, (error) => {
14849
+ warn(error);
14850
+ loseContext();
14851
+ });
14852
+ }
14853
+ loseContext();
14854
+ }
14855
+
14774
14856
  const isRenderer = (def) => !!def?.render;
14775
14857
  const _roots = /* @__PURE__ */ new Map();
14776
14858
  function ensureStoreThreeObjects(store) {
@@ -14782,9 +14864,9 @@ function ensureStoreThreeObjects(store) {
14782
14864
  }
14783
14865
  const shallowLoose = { objects: "shallow", strict: false };
14784
14866
  async function resolveRenderer(config, defaultProps, RendererClass) {
14785
- if (typeof config === "function") return await config(defaultProps);
14786
- if (isRenderer(config)) return config;
14787
- return new RendererClass({ ...defaultProps, ...config });
14867
+ if (typeof config === "function") return { renderer: await config(defaultProps), owned: true };
14868
+ if (isRenderer(config)) return { renderer: config, owned: false };
14869
+ return { renderer: new RendererClass({ ...defaultProps, ...config }), owned: true };
14788
14870
  }
14789
14871
  function computeInitialSize(canvas, size) {
14790
14872
  if (!size && typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
@@ -14800,6 +14882,34 @@ function computeInitialSize(canvas, size) {
14800
14882
  }
14801
14883
  return { width: 0, height: 0, top: 0, left: 0, ...size };
14802
14884
  }
14885
+ function watchDpr(onChange) {
14886
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function" || !window.devicePixelRatio) {
14887
+ return () => {
14888
+ };
14889
+ }
14890
+ let query;
14891
+ const listen = () => {
14892
+ try {
14893
+ query = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
14894
+ if (typeof query?.addEventListener === "function") query.addEventListener("change", handleChange);
14895
+ else query?.addListener?.(handleChange);
14896
+ } catch {
14897
+ query = void 0;
14898
+ }
14899
+ };
14900
+ const unlisten = () => {
14901
+ if (typeof query?.removeEventListener === "function") query.removeEventListener("change", handleChange);
14902
+ else query?.removeListener?.(handleChange);
14903
+ query = void 0;
14904
+ };
14905
+ const handleChange = () => {
14906
+ unlisten();
14907
+ listen();
14908
+ onChange();
14909
+ };
14910
+ listen();
14911
+ return unlisten;
14912
+ }
14803
14913
  function createRoot(canvas, provider) {
14804
14914
  const prevRoot = _roots.get(canvas);
14805
14915
  const prevFiber = prevRoot?.fiber;
@@ -14836,15 +14946,39 @@ function createRoot(canvas, provider) {
14836
14946
  null
14837
14947
  // transitionCallbacks
14838
14948
  );
14839
- if (!prevRoot) _roots.set(canvas, { fiber, store });
14949
+ const root = prevRoot || { fiber, store, unmountClaim: null, ready: fulfilled(void 0) };
14950
+ if (!prevRoot) _roots.set(canvas, root);
14840
14951
  let onCreated;
14841
14952
  let lastCamera;
14842
14953
  const lastConfiguredProps = {};
14954
+ let resolvedDpr = 0;
14955
+ let dprChangedInXR = false;
14956
+ let unwatchDpr;
14957
+ const resolveDpr = () => {
14958
+ if (_roots.get(canvas)?.store !== store) return unwatchDpr?.();
14959
+ const state = store.getState();
14960
+ const xr = state.internal.actualRenderer?.xr;
14961
+ if (xr?.isPresenting || xr?.getSession?.()) {
14962
+ dprChangedInXR = true;
14963
+ return;
14964
+ }
14965
+ dprChangedInXR = false;
14966
+ const dpr = lastConfiguredProps.dpr;
14967
+ if (dpr === void 0 || state.viewport.dpr !== resolvedDpr || calculateDpr(dpr) === resolvedDpr) return;
14968
+ state.setDpr(dpr);
14969
+ resolvedDpr = store.getState().viewport.dpr;
14970
+ };
14843
14971
  let configured = false;
14844
14972
  let pending = null;
14845
- let rendererSetup = null;
14973
+ const cancelUnmount = () => {
14974
+ if (!root.unmountClaim) return;
14975
+ root.unmountClaim = null;
14976
+ store.getState().internal.active = true;
14977
+ };
14846
14978
  return {
14847
14979
  async configure(props = {}) {
14980
+ if (_roots.get(canvas) !== root) throw new Error("R3F: cannot configure a root after it has unmounted");
14981
+ cancelUnmount();
14848
14982
  let resolve;
14849
14983
  pending = new Promise((_resolve) => resolve = _resolve);
14850
14984
  const {
@@ -14918,20 +15052,23 @@ function createRoot(canvas, provider) {
14918
15052
  );
14919
15053
  }
14920
15054
  if (!state.internal.actualRenderer) {
14921
- if (!rendererSetup) {
14922
- rendererSetup = (async () => {
15055
+ if (root.ready.status !== "pending") {
15056
+ const setup = (async () => {
14923
15057
  const support = wantsGL ? await webgl() : await webgpu();
14924
15058
  registerThree(support.three);
14925
15059
  state.internal.support = support;
14926
15060
  ensureStoreThreeObjects(store);
14927
15061
  if (support.kind === "webgl") {
14928
- renderer = await resolveRenderer(glConfig, defaultGLProps, support.Renderer);
15062
+ const resolved = await resolveRenderer(glConfig, defaultGLProps, support.Renderer);
15063
+ renderer = resolved.renderer;
14929
15064
  state.internal.actualRenderer = renderer;
15065
+ state.internal.releaseRenderer = leaseRenderer(renderer, resolved.owned);
14930
15066
  state.set({ isLegacy: true, gl: renderer, renderer, primaryStore: store });
14931
15067
  } else if (primaryCanvas) {
14932
15068
  const primary = await waitForPrimary(primaryCanvas);
14933
15069
  renderer = primary.renderer;
14934
15070
  state.internal.actualRenderer = renderer;
15071
+ state.internal.releaseRenderer = borrowRenderer(renderer);
14935
15072
  const canvasTarget = new support.CanvasTarget(canvas);
14936
15073
  primary.store.setState((prev) => ({
14937
15074
  internal: { ...prev.internal, isMultiCanvas: true }
@@ -14949,7 +15086,8 @@ function createRoot(canvas, provider) {
14949
15086
  }
14950
15087
  }));
14951
15088
  } else {
14952
- renderer = await resolveRenderer(rendererConfig, defaultGPUProps, support.Renderer);
15089
+ const resolved = await resolveRenderer(rendererConfig, defaultGPUProps, support.Renderer);
15090
+ renderer = resolved.renderer;
14953
15091
  if (!renderer.hasInitialized?.()) {
14954
15092
  const size2 = computeInitialSize(canvas, propsSize);
14955
15093
  if (size2.width > 0 && size2.height > 0) {
@@ -14961,6 +15099,7 @@ function createRoot(canvas, provider) {
14961
15099
  const backend = renderer.backend;
14962
15100
  const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
14963
15101
  state.internal.actualRenderer = renderer;
15102
+ state.internal.releaseRenderer = leaseRenderer(renderer, resolved.owned);
14964
15103
  state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
14965
15104
  if (canvasId && !state.internal.isSecondary) {
14966
15105
  const canvasTarget = renderer.getCanvasTarget?.();
@@ -14974,12 +15113,10 @@ function createRoot(canvas, provider) {
14974
15113
  }));
14975
15114
  }
14976
15115
  }
14977
- })().catch((err) => {
14978
- rendererSetup = null;
14979
- throw err;
14980
- });
15116
+ })();
15117
+ root.ready = tracked(setup);
14981
15118
  }
14982
- await rendererSetup;
15119
+ await root.ready;
14983
15120
  state = store.getState();
14984
15121
  renderer = state.internal.actualRenderer;
14985
15122
  }
@@ -15058,6 +15195,12 @@ function createRoot(canvas, provider) {
15058
15195
  if (dpr !== void 0 && !is.equ(dpr, lastConfiguredProps.dpr, shallowLoose)) {
15059
15196
  state.setDpr(dpr);
15060
15197
  lastConfiguredProps.dpr = dpr;
15198
+ resolvedDpr = store.getState().viewport.dpr;
15199
+ }
15200
+ const internal = store.getState().internal;
15201
+ if (Array.isArray(dpr) && (!unwatchDpr || internal.unwatchDpr !== unwatchDpr)) {
15202
+ internal.unwatchDpr?.();
15203
+ internal.unwatchDpr = unwatchDpr = watchDpr(resolveDpr);
15061
15204
  }
15062
15205
  if (frameloop !== void 0 && frameloop !== lastConfiguredProps.frameloop) {
15063
15206
  state.setFrameloop(frameloop);
@@ -15086,7 +15229,10 @@ function createRoot(canvas, provider) {
15086
15229
  const renderer2 = state2.internal.actualRenderer;
15087
15230
  actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
15088
15231
  renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
15089
- if (!renderer2.xr.isPresenting) invalidate(state2);
15232
+ if (!renderer2.xr.isPresenting) {
15233
+ if (dprChangedInXR) resolveDpr();
15234
+ invalidate(state2);
15235
+ }
15090
15236
  };
15091
15237
  const xr = {
15092
15238
  connect() {
@@ -15296,8 +15442,11 @@ function createRoot(canvas, provider) {
15296
15442
  return this;
15297
15443
  },
15298
15444
  render(children) {
15445
+ if (_roots.get(canvas) !== root) return store;
15446
+ cancelUnmount();
15299
15447
  if (!configured && !pending) this.configure();
15300
15448
  pending.then(() => {
15449
+ if (_roots.get(canvas) !== root || root.unmountClaim) return;
15301
15450
  reconciler.updateContainer(
15302
15451
  /* @__PURE__ */ jsxRuntime.jsx(Provider, { store, children, onCreated, rootElement: canvas }),
15303
15452
  fiber,
@@ -15308,7 +15457,7 @@ function createRoot(canvas, provider) {
15308
15457
  return store;
15309
15458
  },
15310
15459
  unmount() {
15311
- unmountComponentAtNode(canvas);
15460
+ if (_roots.get(canvas) === root) unmountComponentAtNode(canvas);
15312
15461
  }
15313
15462
  };
15314
15463
  }
@@ -15328,46 +15477,52 @@ function Provider({
15328
15477
  }
15329
15478
  function unmountComponentAtNode(canvas, callback) {
15330
15479
  const root = _roots.get(canvas);
15331
- const fiber = root?.fiber;
15332
- if (fiber) {
15333
- const state = root?.store.getState();
15334
- if (state) {
15335
- state.internal.active = false;
15336
- const unregisterRoot = state.internal.unregisterRoot;
15337
- if (unregisterRoot) {
15338
- unregisterRoot();
15339
- state.internal.unregisterRoot = void 0;
15480
+ if (!root) return;
15481
+ const claim = root.unmountClaim = Symbol("unmount");
15482
+ root.store.getState().internal.active = false;
15483
+ reconciler.updateContainer(null, root.fiber, null, () => {
15484
+ if (root.unmountClaim !== claim) return;
15485
+ reconciler.updateContainer(null, root.fiber, null, () => {
15486
+ if (root.unmountClaim !== claim) return;
15487
+ if (root.ready.status === "pending") root.ready.then(teardown, teardown);
15488
+ else teardown();
15489
+ });
15490
+ });
15491
+ function teardown() {
15492
+ if (root.unmountClaim !== claim) return;
15493
+ root.unmountClaim = null;
15494
+ _roots.delete(canvas);
15495
+ const state = root.store.getState();
15496
+ const internal = state.internal;
15497
+ internal.active = false;
15498
+ const attempt = (step) => {
15499
+ try {
15500
+ return step();
15501
+ } catch (error) {
15502
+ console.warn("[R3F] Error while unmounting root; teardown may be incomplete:", error);
15340
15503
  }
15341
- }
15342
- reconciler.updateContainer(null, fiber, null, () => {
15343
- if (root?.store) extensions.detachRootExtensions(root.store);
15344
- if (state) {
15345
- setTimeout(() => {
15346
- try {
15347
- const renderer = state.internal.actualRenderer;
15348
- const unregisterPrimary = state.internal.unregisterPrimary;
15349
- if (unregisterPrimary) unregisterPrimary();
15350
- const canvasTarget = state.internal.canvasTarget;
15351
- if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
15352
- state.events.disconnect?.();
15353
- cleanupHelperGroup(root.store);
15354
- if (state.isLegacy && renderer) {
15355
- ;
15356
- renderer.renderLists?.dispose?.();
15357
- renderer.forceContextLoss?.();
15358
- }
15359
- if (!state.internal.isSecondary) {
15360
- if (renderer?.xr) state.xr.disconnect();
15361
- }
15362
- dispose(state.scene);
15363
- _roots.delete(canvas);
15364
- if (callback) callback(canvas);
15365
- } catch (error) {
15366
- console.warn("[R3F] Error while unmounting root; teardown may be incomplete:", error);
15367
- }
15368
- }, 500);
15504
+ };
15505
+ attempt(() => internal.unwatchDpr?.());
15506
+ internal.unwatchDpr = void 0;
15507
+ attempt(() => internal.unregisterRoot?.());
15508
+ internal.unregisterRoot = void 0;
15509
+ attempt(() => extensions.detachRootExtensions(root.store));
15510
+ attempt(() => internal.unregisterPrimary?.());
15511
+ attempt(() => state.events.disconnect?.());
15512
+ if (!internal.isSecondary && internal.actualRenderer?.xr && state.xr) attempt(() => state.xr.disconnect());
15513
+ attempt(() => cleanupHelperGroup(root.store));
15514
+ if (state.scene) attempt(() => dispose(state.scene));
15515
+ const canvasTarget = internal.canvasTarget;
15516
+ if (internal.isSecondary && canvasTarget?.dispose) attempt(() => canvasTarget.dispose());
15517
+ const released = attempt(() => internal.releaseRenderer?.());
15518
+ internal.releaseRenderer = void 0;
15519
+ if (callback) {
15520
+ if (released) {
15521
+ released.then(() => callback(canvas)).catch((error) => console.warn("[R3F] Error in unmount callback", error));
15522
+ } else {
15523
+ callback(canvas);
15369
15524
  }
15370
- });
15525
+ }
15371
15526
  }
15372
15527
  }
15373
15528
  function createPortal(children, container, state) {
@@ -15912,13 +16067,27 @@ function CanvasImpl({
15912
16067
  }
15913
16068
  };
15914
16069
  });
16070
+ const insertionMounted = React__namespace.useRef(false);
16071
+ React__namespace.useInsertionEffect(() => {
16072
+ insertionMounted.current = true;
16073
+ return () => {
16074
+ insertionMounted.current = false;
16075
+ queueMicrotask(() => {
16076
+ if (insertionMounted.current) return;
16077
+ const current = root.current;
16078
+ root.current = null;
16079
+ current?.unmount();
16080
+ });
16081
+ };
16082
+ }, []);
15915
16083
  React__namespace.useEffect(() => {
15916
16084
  const canvas = canvasRef.current;
15917
16085
  if (canvas) {
15918
16086
  return () => {
15919
16087
  if (canvas.isConnected) return;
15920
- unmountComponentAtNode(canvas);
16088
+ const current = root.current;
15921
16089
  root.current = null;
16090
+ current?.unmount();
15922
16091
  };
15923
16092
  }
15924
16093
  }, []);
@@ -15932,7 +16101,7 @@ function CanvasImpl({
15932
16101
  if (rootEntry?.store) extensions.notifyRootExtensionsHmr(rootEntry.store);
15933
16102
  });
15934
16103
  };
15935
- if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/fiber.oKEFddXj.cjs', document.baseURI).href)) }) !== "undefined" && undefined) {
16104
+ if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/fiber.BegWBc5_.cjs', document.baseURI).href)) }) !== "undefined" && undefined) {
15936
16105
  const hot = undefined;
15937
16106
  hot.on("vite:afterUpdate", handleHMR);
15938
16107
  return () => hot.off?.("vite:afterUpdate", handleHMR);
@@ -3,7 +3,7 @@ import { ReactNode, Component, RefObject, JSX } from 'react';
3
3
  import { Options } from 'react-use-measure';
4
4
  import * as THREE from 'three';
5
5
  import { ColorRepresentation, Euler as Euler$1, Loader, RenderTargetOptions as RenderTargetOptions$1, ColorSpace, Texture as Texture$1, CubeTexture, Scene, Object3D } from 'three';
6
- import { J as Properties, c as Size, F as Frameloop, e as Performance, D as Dpr, g as RootStore, p as EventManager, f as RootState, n as ComputeFunction, C as ConstructorRepresentation, _ as ObjectMap, I as InternalState, M as Mutable, O as Overwrite, y as Args, l as EventHandlers, B as InstanceProps, k as DomEvent, G as Instance, x as Catalogue, v as Root, a6 as ThreeCore, W as Bridge, Z as UnblockProps, a0 as Disposable, Q as ThreeCamera, $ as EquConfig } from './fiber.I5Q4dVvl.cjs';
6
+ import { K as Properties, c as Size, F as Frameloop, e as Performance, D as Dpr, g as RootStore, p as EventManager, f as RootState, n as ComputeFunction, C as ConstructorRepresentation, $ as ObjectMap, I as InternalState, M as Mutable, O as Overwrite, z as Args, l as EventHandlers, G as InstanceProps, k as DomEvent, H as Instance, y as Catalogue, w as Root, a7 as ThreeCore, Y as Bridge, _ as UnblockProps, a1 as Disposable, U as ThreeCamera, a0 as EquConfig } from './fiber.CZLeHcML.mjs';
7
7
  import { WebGPURenderer, WebGPURendererParameters } from 'three/webgpu';
8
8
 
9
9
  //* Base Renderer Types =====================================
@@ -155,8 +155,11 @@ interface RenderProps<TCanvas extends HTMLCanvasElement | OffscreenCanvas$1> {
155
155
  /** Dimensions to fit the renderer to. Will measure canvas dimensions if omitted */
156
156
  size?: Size
157
157
  /**
158
- * Enables shadows (by default PCFsoft). Can accept `gl.shadowMap` options for fine-tuning,
159
- * but also strings: 'basic' | 'percentage' | 'soft' | 'variance'.
158
+ * Enables shadows (`true` uses `THREE.PCFShadowMap`). Can accept `renderer.shadowMap` options for
159
+ * fine-tuning, but also strings: 'basic' | 'percentage' | 'soft' | 'variance'.
160
+ *
161
+ * `'soft'` is a deprecated alias of `'percentage'`: both map to `THREE.PCFShadowMap`, because three.js
162
+ * deprecated `PCFSoftShadowMap` and made `PCFShadowMap` soft. Using `'soft'` logs a deprecation notice.
160
163
  * @see https://threejs.org/docs/#api/en/renderers/WebGLRenderer.shadowMap
161
164
  */
162
165
  shadows?: boolean | 'basic' | 'percentage' | 'soft' | 'variance' | Partial<THREE.WebGLShadowMap>
@@ -540,8 +543,14 @@ type ThreeElement<T extends ConstructorRepresentation> = Mutable<
540
543
  Overwrite<ElementProps<T>, Omit<InstanceProps<InstanceType<T>, T>, 'object'>>
541
544
  >
542
545
 
546
+ /**
547
+ * Every constructor export of a three namespace as an uncapitalized JSX element. Non-constructor
548
+ * exports (constants, functions, nested namespaces) are dropped from the keys rather than mapped
549
+ * to `never`: a single `never`-valued key in `JSX.IntrinsicElements` collapses the props of any
550
+ * tag typed `React.ElementType` (#3898).
551
+ */
543
552
  type ThreeToJSXElements<T extends Record<string, any>> = {
544
- [K in keyof T & string as Uncapitalize<K>]: T[K] extends ConstructorRepresentation ? ThreeElement<T[K]> : never
553
+ [K in keyof T & string as T[K] extends ConstructorRepresentation ? Uncapitalize<K> : never]: ThreeElement<T[K]>
545
554
  }
546
555
 
547
556
  /** Method names of Object3D, excluded from the `primitive` element's typed props. */
@@ -2246,16 +2255,67 @@ declare namespace ReactReconciler {
2246
2255
  ): void;
2247
2256
  }
2248
2257
 
2258
+ /**
2259
+ * Registers constructors so they can be rendered as JSX elements.
2260
+ *
2261
+ * - `extend({ OrbitControls })` makes each constructor available under its camelCased key
2262
+ * (`<orbitControls />`). Values that are not constructors are skipped, so a whole module
2263
+ * namespace can be passed.
2264
+ * - `extend(MyClass)` registers one constructor and returns a component to render it with.
2265
+ *
2266
+ * Registrations are global, shared by every copy and entry of fiber, and are checked before the
2267
+ * three namespace of a root's renderer when an element name is resolved.
2268
+ *
2269
+ * @example
2270
+ * import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
2271
+ * extend({ OrbitControls })
2272
+ * // <orbitControls args={[camera, gl.domElement]} />
2273
+ *
2274
+ * @example
2275
+ * const Controls = extend(OrbitControls)
2276
+ * // <Controls args={[camera, gl.domElement]} />
2277
+ *
2278
+ * @see https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively
2279
+ */
2249
2280
  declare function extend<T extends ConstructorRepresentation>(objects: T): React$1.ExoticComponent<ThreeElement<T>>;
2281
+ /** Registers each constructor in `objects` under its key; see the first overload. */
2250
2282
  declare function extend<T extends Catalogue>(objects: T): void;
2283
+ /** Registers every constructor in a module namespace, skipping other exports; see the first overload. */
2251
2284
  declare function extend(objects: Record<string, unknown>): void;
2252
2285
 
2286
+ /**
2287
+ * R3F's React reconciler: a mutation-mode host config that turns JSX elements into three.js objects.
2288
+ * Each root's {@link RootStore} is its container, and children attach to `internal.container`
2289
+ * (a portal's target) or else the root's `scene`.
2290
+ *
2291
+ * - **Element names** resolve through `extend()` registrations first, then the three namespace of
2292
+ * the root's renderer. A `three` prefix (`<threeLine>`) is stripped when no element by the
2293
+ * prefixed name exists. `<primitive object={...}>` wraps an existing object.
2294
+ * - **Construction is deferred** until an instance is attached to a mounted parent, so a tree that
2295
+ * Suspense discards never creates three objects.
2296
+ * - **Updates** apply only changed props. Changing `args` (or a primitive's `object`) reconstructs
2297
+ * the object instead; the swap happens in `resetAfterCommit`, before layout effects, so refs
2298
+ * already point to the new object.
2299
+ * - **Removal** detaches the object and disposes it (at idle priority, or immediately in an `act`
2300
+ * test environment), unless it is a primitive, a `Scene`, or it or an ancestor has `dispose={null}`.
2301
+ * - **Priority**: not the primary renderer, so it runs alongside react-dom, and update priority
2302
+ * follows react-dom's event priorities. View-transition commits are flushed synchronously, since
2303
+ * three has nothing to animate between commits.
2304
+ *
2305
+ * `createRoot`, `createPortal` and `flushSync` drive it; app code rarely needs it directly.
2306
+ */
2253
2307
  declare const reconciler: ReactReconciler.Reconciler<RootStore, Instance<any>, void, Instance<any>, never, any>;
2254
2308
 
2255
2309
  declare const isRenderer: (def: any) => boolean;
2256
2310
  interface OffscreenCanvas extends EventTarget {
2257
2311
  }
2258
2312
  declare const _roots: Map<HTMLCanvasElement | OffscreenCanvas, Root>;
2313
+ /**
2314
+ * Unmount the root on `canvas`. The teardown runs once React has committed the unmount, and waits
2315
+ * for a renderer that is still being created. `callback` runs when the root is gone: after the
2316
+ * teardown, and when it disposed a renderer R3F created whose `dispose()` is async (WebGPURenderer
2317
+ * from three r186), after that dispose has settled.
2318
+ */
2259
2319
  declare function unmountComponentAtNode<TCanvas extends HTMLCanvasElement | OffscreenCanvas>(canvas: TCanvas, callback?: (canvas: TCanvas) => void): void;
2260
2320
  declare function createPortal(children: ReactNode, container: THREE.Object3D | RefObject<THREE.Object3D | null> | RefObject<THREE.Object3D>, state?: InjectState): JSX.Element;
2261
2321
  interface PortalProps {
@@ -2272,6 +2332,30 @@ declare function Portal({ children, container, state }: PortalProps): JSX.Elemen
2272
2332
  */
2273
2333
  declare function flushSync<R>(fn: () => R): R;
2274
2334
 
2335
+ /**
2336
+ * Creates the Zustand store that holds one root's {@link RootState}.
2337
+ *
2338
+ * The store starts unconfigured: the renderer, `camera`, `scene`, `raycaster`, `frustum` and `pointer`
2339
+ * are `null` placeholders until the root's renderer support has loaded and `configure()` in
2340
+ * `renderer.tsx` fills them in. Only core's part of `RootState` is created here; packages building on
2341
+ * fiber add their own fields through root extensions.
2342
+ *
2343
+ * Besides the initial state, the store wires up:
2344
+ * - `state.gl` and `state.renderer` as accessors over `internal.actualRenderer`. `gl` reports a
2345
+ * deprecation when user code reads it outside legacy mode.
2346
+ * - `rootScene` following `scene` whenever `scene` is set to a real `THREE.Scene`.
2347
+ * - On a size or DPR change: updating the camera and resizing the root's own canvas target (or the
2348
+ * renderer when there is none).
2349
+ * - On a camera change: adding an unparented camera to `rootScene`, then refreshing the viewport and
2350
+ * (when `autoUpdateFrustum` is set) the frustum.
2351
+ * - Calling `invalidate(state)` after every state change.
2352
+ *
2353
+ * `createRoot` calls this once per canvas.
2354
+ *
2355
+ * @param invalidate - Requests frames for a root. Bound into `state.invalidate` and called on every store change.
2356
+ * @param advance - Steps a root manually. Bound into `state.advance`.
2357
+ * @returns The root's store, which is also the reconciler container for that root.
2358
+ */
2275
2359
  declare const createStore: (invalidate: (state?: RootState, frames?: number, stackFrames?: boolean) => void, advance: (timestamp: number, runGlobalEffects?: boolean, state?: RootState, frame?: XRFrame) => void) => RootStore;
2276
2360
 
2277
2361
  /** Whether any root has loaded a renderer yet. */
@@ -361,4 +361,4 @@ function notifyRootExtensionsHmr(store) {
361
361
  for (const setUpBy of applied.values()) current(registry, setUpBy).hmr?.(store);
362
362
  }
363
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 };
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, attachRootExtensions as j, detachRootExtensions as k, notifyAlpha as l, notifyRootExtensionsHmr as m, notifyDepreciated as n, registerRootExtension as r, setRenderOverride as s, useStore as u };
@@ -477,6 +477,11 @@ interface InternalState {
477
477
  * Selected once, from the entry's provider, and copied into portals with the rest of `internal`.
478
478
  */
479
479
  support: R3FRendererSupport
480
+ /**
481
+ * Releases this root's lease on its renderer. The last release disposes a renderer R3F created;
482
+ * a renderer passed in as an instance is never disposed by R3F.
483
+ */
484
+ releaseRenderer?: () => void | Promise<void>
480
485
  /** Global scheduler reference (for useFrame hook) */
481
486
  scheduler: SchedulerApi | null
482
487
  /**
@@ -489,6 +494,8 @@ interface InternalState {
489
494
  rootId?: string
490
495
  /** Function to unregister this root from the global scheduler */
491
496
  unregisterRoot?: () => void
497
+ /** Function to stop following devicePixelRatio changes */
498
+ unwatchDpr?: () => void
492
499
  /** Container for child attachment (scene for root, original container for portals) */
493
500
  container?: THREE.Object3D
494
501
  /**
@@ -660,9 +667,17 @@ type RootStore = UseBoundStoreWithEqualityFn<StoreApi<RootState>>
660
667
  // to avoid bundling @types/react-reconciler which causes absolute path issues
661
668
  type FiberRoot = any
662
669
 
670
+ /** A promise tagged with its state, the protocol React's `use` reads */
671
+ type TrackedPromise<T> = Promise<T> &
672
+ ({ status: 'pending' } | { status: 'fulfilled'; value: T } | { status: 'rejected'; reason: unknown })
673
+
663
674
  interface Root {
664
675
  fiber: FiberRoot
665
676
  store: RootStore
677
+ /** Set while a teardown waits on React. Configure and render clear it, which cancels the teardown */
678
+ unmountClaim: symbol | null
679
+ /** Pending only while a renderer is being created */
680
+ ready: TrackedPromise<unknown>
666
681
  }
667
682
 
668
683
  type AttachFnType<O = any> = (parent: any, self: O) => () => void
@@ -772,7 +787,14 @@ declare function useStore(): RootStore;
772
787
  */
773
788
  declare function useThree<T = RootState>(selector?: (state: RootState) => T, equalityFn?: <T>(state: T, newState: T) => boolean): T;
774
789
 
790
+ /**
791
+ * React context that carries the current root's {@link RootStore}. Each root provides its store and
792
+ * each portal provides its own scoped one; `useStore`, and every hook built on it, reads it.
793
+ *
794
+ * Stored on `globalThis` under `Symbol.for('@react-three/fiber.context')`, so every copy and entry
795
+ * of fiber shares a single context.
796
+ */
775
797
  declare const context: React.Context<RootStore>;
776
798
 
777
- export { useStore as ag, useThree as ah, context as ai, registerRootExtension as r, setRenderOverride as s };
778
- export type { EquConfig as $, AttachFnType as A, InstanceProps as B, ConstructorRepresentation as C, Dpr as D, Events as E, Frameloop as F, Instance as G, HostConfig as H, InternalState as I, Properties as J, IsOptional as K, IsAllOptional as L, Mutable as M, NonFunctionKeys as N, Overwrite as O, PointerState as P, ThreeCamera as Q, R3FRenderTarget as R, Subscription as S, ThreeEvent as T, Act as U, Viewport as V, Bridge as W, XRManager as X, SetBlock as Y, UnblockProps as Z, ObjectMap as _, RootExtension as a, Disposable as a0, FrameNextState as a1, FrameState as a2, FrameNextCallback as a3, FrameCallback as a4, ThreeNamespace as a5, ThreeCore as a6, OcclusionSupport as a7, WebGLSupport as a8, WebGPUSupport as a9, RendererSupport as aa, RendererProvider as ab, Register as ac, RegisteredRenderer as ad, ForRegisteredRenderer as ae, R3FRendererSupport as af, R3FRenderer as b, Size as c, RenderCallback as d, Performance as e, RootState as f, RootStore as g, Intersection as h, Camera as i, IntersectionEvent as j, DomEvent as k, EventHandlers as l, FilterFunction as m, ComputeFunction as n, XRPointerConfig as o, EventManager as p, PointerCaptureTarget as q, VisibilityEntry as t, FiberRoot as u, Root as v, AttachType as w, Catalogue as x, Args as y, ArgsProp as z };
799
+ export { useStore as ah, useThree as ai, context as aj, registerRootExtension as r, setRenderOverride as s };
800
+ export type { ObjectMap as $, AttachFnType as A, ArgsProp as B, ConstructorRepresentation as C, Dpr as D, Events as E, Frameloop as F, InstanceProps as G, Instance as H, InternalState as I, HostConfig as J, Properties as K, IsOptional as L, Mutable as M, NonFunctionKeys as N, Overwrite as O, PointerState as P, IsAllOptional as Q, R3FRenderTarget as R, Subscription as S, ThreeEvent as T, ThreeCamera as U, Viewport as V, Act as W, XRManager as X, Bridge as Y, SetBlock as Z, UnblockProps as _, RootExtension as a, EquConfig as a0, Disposable as a1, FrameNextState as a2, FrameState as a3, FrameNextCallback as a4, FrameCallback as a5, ThreeNamespace as a6, ThreeCore as a7, OcclusionSupport as a8, WebGLSupport as a9, WebGPUSupport as aa, RendererSupport as ab, RendererProvider as ac, Register as ad, RegisteredRenderer as ae, ForRegisteredRenderer as af, R3FRendererSupport as ag, R3FRenderer as b, Size as c, RenderCallback as d, Performance as e, RootState as f, RootStore as g, Intersection as h, Camera as i, IntersectionEvent as j, DomEvent as k, EventHandlers as l, FilterFunction as m, ComputeFunction as n, XRPointerConfig as o, EventManager as p, PointerCaptureTarget as q, VisibilityEntry as t, FiberRoot as u, TrackedPromise as v, Root as w, AttachType as x, Catalogue as y, Args as z };