@react-three/fiber 10.0.0-canary.f50076a → 10.0.0-canary.f511bb4

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.DAl4H27x.d.cts → fiber.-1JhXWEC.d.cts} +1 -1
  16. package/dist/shared/{fiber.dvUbwHHn.mjs → fiber.B3mc9NA1.mjs} +306 -87
  17. package/dist/shared/{fiber.DNehrxK5.d.ts → fiber.Bkpap4yF.d.mts} +76 -1
  18. package/dist/shared/{fiber.TWXdbcWP.d.mts → fiber.BnIfHyTk.d.cts} +76 -1
  19. package/dist/shared/{fiber.I5Q4dVvl.d.cts → fiber.CLTHZhZp.d.cts} +30 -2
  20. package/dist/shared/{fiber.I5Q4dVvl.d.mts → fiber.CLTHZhZp.d.mts} +30 -2
  21. package/dist/shared/{fiber.I5Q4dVvl.d.ts → fiber.CLTHZhZp.d.ts} +30 -2
  22. package/dist/shared/{fiber.Cx-UAmMb.d.ts → fiber.CTEAJNmg.d.ts} +1 -1
  23. package/dist/shared/{fiber.B0oukOFO.mjs → fiber.CUKAa7Rv.mjs} +1 -1
  24. package/dist/shared/{fiber.BU0vBHc9.d.mts → fiber.CksZuiOV.d.mts} +1 -1
  25. package/dist/shared/{fiber.CEjezJYZ.cjs → fiber.DF7oitV8.cjs} +306 -87
  26. package/dist/shared/{fiber.11sXr8Eb.d.cts → fiber.NwhGYEh-.d.ts} +76 -1
  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
@@ -443,6 +443,28 @@ const VISIBILITY_EVENT_REGEX = /^on(Framed|Occluded|Visible)$/;
443
443
  const INDEX_REGEX = /-\d+$/;
444
444
  const MEMOIZED_PROTOTYPES = /* @__PURE__ */ new Map();
445
445
  const colorMaps = ["map", "emissiveMap", "sheenColorMap", "specularColorMap", "envMap"];
446
+ const programProps = /* @__PURE__ */ new Set([
447
+ "transparent",
448
+ "vertexColors",
449
+ "flatShading",
450
+ "fog",
451
+ // Culling is live, but DOUBLE_SIDED / FLIP_SIDED normal flipping is compiled in
452
+ "side",
453
+ "alphaHash",
454
+ "premultipliedAlpha",
455
+ // Both feed the OPAQUE define when the material is not transparent
456
+ "blending",
457
+ "alphaToCoverage",
458
+ "dithering",
459
+ "sizeAttenuation",
460
+ "combine",
461
+ "normalMapType",
462
+ "depthPacking"
463
+ ]);
464
+ function changesProgram(root, key, previous, next) {
465
+ if (!root?.isMaterial || previous === next) return false;
466
+ return programProps.has(key) || isTexture(previous) !== isTexture(next);
467
+ }
446
468
  function resolve(root, key) {
447
469
  if (!key.includes("-")) return { root, key, target: root[key] };
448
470
  if (key in root) return { root, key, target: root[key] };
@@ -473,6 +495,7 @@ function attach(parent, child) {
473
495
  const { root, key } = resolve(parent.object, child.props.attach);
474
496
  child.previousAttach = root[key];
475
497
  root[key] = child.object;
498
+ if (changesProgram(root, key, child.previousAttach, child.object)) root.needsUpdate = true;
476
499
  } else if (is.fun(child.props.attach)) {
477
500
  child.previousAttach = child.props.attach(parent.object, child.object);
478
501
  }
@@ -483,6 +506,7 @@ function detach(parent, child) {
483
506
  const previous = child.previousAttach;
484
507
  if (previous === void 0) delete root[key];
485
508
  else root[key] = previous;
509
+ if (changesProgram(root, key, child.object, previous)) root.needsUpdate = true;
486
510
  } else {
487
511
  child.previousAttach?.(parent.object, child.object);
488
512
  }
@@ -597,9 +621,12 @@ function applyProps(object, props) {
597
621
  }
598
622
  } else {
599
623
  if (key === "material") assertNodeMaterialSupported(rootState, value);
624
+ const previous = root[key];
600
625
  root[key] = value;
601
626
  if (key.endsWith("Node") && root.isMaterial) {
602
627
  root.needsUpdate = true;
628
+ } else if (changesProgram(root, key, previous, value)) {
629
+ root.needsUpdate = true;
603
630
  }
604
631
  const three = rootState && getThree();
605
632
  if (three && rootState.renderer?.outputColorSpace === three.SRGBColorSpace && colorMaps.includes(key) && isTexture(value) && root[key]?.isTexture && // sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
@@ -14790,6 +14817,69 @@ function getPrimaryIds() {
14790
14817
  return Array.from(primaryRegistry.keys());
14791
14818
  }
14792
14819
 
14820
+ const fulfilled = (value) => Object.assign(Promise.resolve(value), { status: "fulfilled", value });
14821
+ const tracked = (promise) => {
14822
+ const result = Promise.resolve(promise);
14823
+ result.status = "pending";
14824
+ result.then(
14825
+ (value) => {
14826
+ Object.assign(result, { status: "fulfilled", value });
14827
+ },
14828
+ (reason) => {
14829
+ Object.assign(result, { status: "rejected", reason });
14830
+ }
14831
+ );
14832
+ return result;
14833
+ };
14834
+
14835
+ const records = /* @__PURE__ */ new WeakMap();
14836
+ function take(renderer, record) {
14837
+ record.leases++;
14838
+ let released = false;
14839
+ return () => {
14840
+ if (released) return;
14841
+ released = true;
14842
+ if (--record.leases > 0) return;
14843
+ records.delete(renderer);
14844
+ if (record.owned) return disposeRenderer(renderer);
14845
+ };
14846
+ }
14847
+ function leaseRenderer(renderer, owned) {
14848
+ let record = records.get(renderer);
14849
+ if (!record) records.set(renderer, record = { owned, leases: 0 });
14850
+ return take(renderer, record);
14851
+ }
14852
+ function borrowRenderer(renderer) {
14853
+ const record = records.get(renderer);
14854
+ if (!record) throw new Error("R3F: cannot share a renderer whose canvas has already unmounted");
14855
+ return take(renderer, record);
14856
+ }
14857
+ function disposeRenderer(renderer) {
14858
+ if (renderer.hasInitialized?.() === false) return;
14859
+ const warn = (error) => console.warn("[R3F] Error disposing renderer", error);
14860
+ const loseContext = () => {
14861
+ try {
14862
+ ;
14863
+ renderer.forceContextLoss?.();
14864
+ } catch (error) {
14865
+ warn(error);
14866
+ }
14867
+ };
14868
+ let disposed;
14869
+ try {
14870
+ disposed = renderer.dispose();
14871
+ } catch (error) {
14872
+ warn(error);
14873
+ }
14874
+ if (typeof disposed?.then === "function") {
14875
+ return Promise.resolve(disposed).then(loseContext, (error) => {
14876
+ warn(error);
14877
+ loseContext();
14878
+ });
14879
+ }
14880
+ loseContext();
14881
+ }
14882
+
14793
14883
  const isRenderer = (def) => !!def?.render;
14794
14884
  const _roots = /* @__PURE__ */ new Map();
14795
14885
  function ensureStoreThreeObjects(store) {
@@ -14801,9 +14891,9 @@ function ensureStoreThreeObjects(store) {
14801
14891
  }
14802
14892
  const shallowLoose = { objects: "shallow", strict: false };
14803
14893
  async function resolveRenderer(config, defaultProps, RendererClass) {
14804
- if (typeof config === "function") return await config(defaultProps);
14805
- if (isRenderer(config)) return config;
14806
- return new RendererClass({ ...defaultProps, ...config });
14894
+ if (typeof config === "function") return { renderer: await config(defaultProps), owned: true };
14895
+ if (isRenderer(config)) return { renderer: config, owned: false };
14896
+ return { renderer: new RendererClass({ ...defaultProps, ...config }), owned: true };
14807
14897
  }
14808
14898
  function computeInitialSize(canvas, size) {
14809
14899
  if (!size && typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
@@ -14819,6 +14909,47 @@ function computeInitialSize(canvas, size) {
14819
14909
  }
14820
14910
  return { width: 0, height: 0, top: 0, left: 0, ...size };
14821
14911
  }
14912
+ function watchDpr(onChange) {
14913
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function" || !window.devicePixelRatio) {
14914
+ return () => {
14915
+ };
14916
+ }
14917
+ let query;
14918
+ const listen = () => {
14919
+ try {
14920
+ query = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
14921
+ if (typeof query?.addEventListener === "function") query.addEventListener("change", handleChange);
14922
+ else query?.addListener?.(handleChange);
14923
+ } catch {
14924
+ query = void 0;
14925
+ }
14926
+ };
14927
+ const unlisten = () => {
14928
+ if (typeof query?.removeEventListener === "function") query.removeEventListener("change", handleChange);
14929
+ else query?.removeListener?.(handleChange);
14930
+ query = void 0;
14931
+ };
14932
+ const handleChange = () => {
14933
+ unlisten();
14934
+ listen();
14935
+ onChange();
14936
+ };
14937
+ listen();
14938
+ return unlisten;
14939
+ }
14940
+ async function createOwnedWebGPURenderer(rendererConfig, defaultGPUProps, canvas, propsSize, dpr, support) {
14941
+ const resolved = await resolveRenderer(rendererConfig, defaultGPUProps, support.Renderer);
14942
+ const renderer = resolved.renderer;
14943
+ if (!renderer.hasInitialized?.()) {
14944
+ const size = computeInitialSize(canvas, propsSize);
14945
+ if (size.width > 0 && size.height > 0) {
14946
+ renderer.setPixelRatio(calculateDpr(dpr));
14947
+ renderer.setSize(size.width, size.height, false);
14948
+ }
14949
+ await renderer.init();
14950
+ }
14951
+ return { renderer, owned: resolved.owned };
14952
+ }
14822
14953
  function createRoot(canvas, provider) {
14823
14954
  const prevRoot = _roots.get(canvas);
14824
14955
  const prevFiber = prevRoot?.fiber;
@@ -14855,15 +14986,39 @@ function createRoot(canvas, provider) {
14855
14986
  null
14856
14987
  // transitionCallbacks
14857
14988
  );
14858
- if (!prevRoot) _roots.set(canvas, { fiber, store });
14989
+ const root = prevRoot || { fiber, store, unmountClaim: null, ready: fulfilled(void 0) };
14990
+ if (!prevRoot) _roots.set(canvas, root);
14859
14991
  let onCreated;
14860
14992
  let lastCamera;
14861
14993
  const lastConfiguredProps = {};
14994
+ let resolvedDpr = 0;
14995
+ let dprChangedInXR = false;
14996
+ let unwatchDpr;
14997
+ const resolveDpr = () => {
14998
+ if (_roots.get(canvas)?.store !== store) return unwatchDpr?.();
14999
+ const state = store.getState();
15000
+ const xr = state.internal.actualRenderer?.xr;
15001
+ if (xr?.isPresenting || xr?.getSession?.()) {
15002
+ dprChangedInXR = true;
15003
+ return;
15004
+ }
15005
+ dprChangedInXR = false;
15006
+ const dpr = lastConfiguredProps.dpr;
15007
+ if (dpr === void 0 || state.viewport.dpr !== resolvedDpr || calculateDpr(dpr) === resolvedDpr) return;
15008
+ state.setDpr(dpr);
15009
+ resolvedDpr = store.getState().viewport.dpr;
15010
+ };
14862
15011
  let configured = false;
14863
15012
  let pending = null;
14864
- let rendererSetup = null;
15013
+ const cancelUnmount = () => {
15014
+ if (!root.unmountClaim) return;
15015
+ root.unmountClaim = null;
15016
+ store.getState().internal.active = true;
15017
+ };
14865
15018
  return {
14866
15019
  async configure(props = {}) {
15020
+ if (_roots.get(canvas) !== root) throw new Error("R3F: cannot configure a root after it has unmounted");
15021
+ cancelUnmount();
14867
15022
  let resolve;
14868
15023
  pending = new Promise((_resolve) => resolve = _resolve);
14869
15024
  const {
@@ -14937,49 +15092,82 @@ function createRoot(canvas, provider) {
14937
15092
  );
14938
15093
  }
14939
15094
  if (!state.internal.actualRenderer) {
14940
- if (!rendererSetup) {
14941
- rendererSetup = (async () => {
15095
+ if (root.ready.status !== "pending") {
15096
+ const setup = (async () => {
14942
15097
  const support = wantsGL ? await webgl() : await webgpu();
14943
15098
  registerThree(support.three);
14944
15099
  state.internal.support = support;
14945
15100
  ensureStoreThreeObjects(store);
14946
15101
  if (support.kind === "webgl") {
14947
- renderer = await resolveRenderer(glConfig, defaultGLProps, support.Renderer);
15102
+ const resolved = await resolveRenderer(glConfig, defaultGLProps, support.Renderer);
15103
+ renderer = resolved.renderer;
14948
15104
  state.internal.actualRenderer = renderer;
15105
+ state.internal.releaseRenderer = leaseRenderer(renderer, resolved.owned);
14949
15106
  state.set({ isLegacy: true, gl: renderer, renderer, primaryStore: store });
14950
15107
  } else if (primaryCanvas) {
14951
15108
  const primary = await waitForPrimary(primaryCanvas);
14952
- renderer = primary.renderer;
14953
- state.internal.actualRenderer = renderer;
14954
- const canvasTarget = new support.CanvasTarget(canvas);
14955
- primary.store.setState((prev) => ({
14956
- internal: { ...prev.internal, isMultiCanvas: true }
14957
- }));
14958
- state.set((prev) => ({
14959
- webGPUSupported: primary.store.getState().webGPUSupported,
14960
- renderer,
14961
- primaryStore: primary.store,
14962
- internal: {
14963
- ...prev.internal,
14964
- canvasTarget,
14965
- isMultiCanvas: true,
14966
- isSecondary: true,
14967
- targetId: primaryCanvas
14968
- }
14969
- }));
14970
- } else {
14971
- renderer = await resolveRenderer(rendererConfig, defaultGPUProps, support.Renderer);
14972
- if (!renderer.hasInitialized?.()) {
14973
- const size2 = computeInitialSize(canvas, propsSize);
14974
- if (size2.width > 0 && size2.height > 0) {
14975
- renderer.setPixelRatio(calculateDpr(dpr));
14976
- renderer.setSize(size2.width, size2.height, false);
14977
- }
14978
- await renderer.init();
15109
+ if (primary.store.getState().webGPUSupported) {
15110
+ renderer = primary.renderer;
15111
+ state.internal.actualRenderer = renderer;
15112
+ state.internal.releaseRenderer = borrowRenderer(renderer);
15113
+ const canvasTarget = new support.CanvasTarget(canvas);
15114
+ primary.store.setState((prev) => ({
15115
+ internal: { ...prev.internal, isMultiCanvas: true }
15116
+ }));
15117
+ state.set((prev) => ({
15118
+ webGPUSupported: primary.store.getState().webGPUSupported,
15119
+ renderer,
15120
+ primaryStore: primary.store,
15121
+ internal: {
15122
+ ...prev.internal,
15123
+ canvasTarget,
15124
+ isMultiCanvas: true,
15125
+ isSecondary: true,
15126
+ targetId: primaryCanvas
15127
+ }
15128
+ }));
15129
+ } else {
15130
+ const isPlainConfig = is.obj(rendererConfig) && !is.fun(rendererConfig) && !isRenderer(rendererConfig);
15131
+ const { primaryCanvas: _peeled, ...rendererOptions } = isPlainConfig ? rendererConfig : {};
15132
+ const fallbackConfig = is.fun(rendererConfig) || isRenderer(rendererConfig) ? rendererConfig : { ...rendererOptions, forceWebGL: true };
15133
+ const resolved = await createOwnedWebGPURenderer(
15134
+ fallbackConfig,
15135
+ defaultGPUProps,
15136
+ canvas,
15137
+ propsSize,
15138
+ dpr,
15139
+ support
15140
+ );
15141
+ renderer = resolved.renderer;
15142
+ const backend = renderer.backend;
15143
+ const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
15144
+ state.internal.actualRenderer = renderer;
15145
+ state.internal.releaseRenderer = leaseRenderer(renderer, resolved.owned);
15146
+ state.set((prev) => ({
15147
+ webGPUSupported: isWebGPUBackend,
15148
+ renderer,
15149
+ primaryStore: store,
15150
+ internal: {
15151
+ ...prev.internal,
15152
+ canvasTarget: renderer.getCanvasTarget?.(),
15153
+ sharedRendererFallback: true
15154
+ }
15155
+ }));
14979
15156
  }
15157
+ } else {
15158
+ const resolved = await createOwnedWebGPURenderer(
15159
+ rendererConfig,
15160
+ defaultGPUProps,
15161
+ canvas,
15162
+ propsSize,
15163
+ dpr,
15164
+ support
15165
+ );
15166
+ renderer = resolved.renderer;
14980
15167
  const backend = renderer.backend;
14981
15168
  const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
14982
15169
  state.internal.actualRenderer = renderer;
15170
+ state.internal.releaseRenderer = leaseRenderer(renderer, resolved.owned);
14983
15171
  state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
14984
15172
  if (canvasId && !state.internal.isSecondary) {
14985
15173
  const canvasTarget = renderer.getCanvasTarget?.();
@@ -14993,16 +15181,15 @@ function createRoot(canvas, provider) {
14993
15181
  }));
14994
15182
  }
14995
15183
  }
14996
- })().catch((err) => {
14997
- rendererSetup = null;
14998
- throw err;
14999
- });
15184
+ })();
15185
+ root.ready = tracked(setup);
15000
15186
  }
15001
- await rendererSetup;
15187
+ await root.ready;
15002
15188
  state = store.getState();
15003
15189
  renderer = state.internal.actualRenderer;
15004
15190
  }
15005
15191
  const three = getThree();
15192
+ const borrowsRenderer = state.internal.isSecondary === true;
15006
15193
  let raycaster = state.raycaster;
15007
15194
  if (!raycaster) state.set({ raycaster: raycaster = new three.Raycaster() });
15008
15195
  const { params, ...options } = raycastOptions || {};
@@ -15077,6 +15264,12 @@ function createRoot(canvas, provider) {
15077
15264
  if (dpr !== void 0 && !is.equ(dpr, lastConfiguredProps.dpr, shallowLoose)) {
15078
15265
  state.setDpr(dpr);
15079
15266
  lastConfiguredProps.dpr = dpr;
15267
+ resolvedDpr = store.getState().viewport.dpr;
15268
+ }
15269
+ const internal = store.getState().internal;
15270
+ if (Array.isArray(dpr) && (!unwatchDpr || internal.unwatchDpr !== unwatchDpr)) {
15271
+ internal.unwatchDpr?.();
15272
+ internal.unwatchDpr = unwatchDpr = watchDpr(resolveDpr);
15080
15273
  }
15081
15274
  if (frameloop !== void 0 && frameloop !== lastConfiguredProps.frameloop) {
15082
15275
  state.setFrameloop(frameloop);
@@ -15105,7 +15298,10 @@ function createRoot(canvas, provider) {
15105
15298
  const renderer2 = state2.internal.actualRenderer;
15106
15299
  actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
15107
15300
  renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
15108
- if (!renderer2.xr.isPresenting) invalidate(state2);
15301
+ if (!renderer2.xr.isPresenting) {
15302
+ if (dprChangedInXR) resolveDpr();
15303
+ invalidate(state2);
15304
+ }
15109
15305
  };
15110
15306
  const xr = {
15111
15307
  connect() {
@@ -15121,10 +15317,10 @@ function createRoot(canvas, provider) {
15121
15317
  xrManager.removeEventListener("sessionend", handleSessionChange);
15122
15318
  }
15123
15319
  };
15124
- if (typeof renderer.xr?.addEventListener === "function") xr.connect();
15320
+ if (!borrowsRenderer && typeof renderer.xr?.addEventListener === "function") xr.connect();
15125
15321
  state.set({ xr });
15126
15322
  }
15127
- if (renderer.shadowMap && !is.equ(shadows, lastConfiguredProps.shadows, shallowLoose)) {
15323
+ if (!borrowsRenderer && renderer.shadowMap && !is.equ(shadows, lastConfiguredProps.shadows, shallowLoose)) {
15128
15324
  lastConfiguredProps.shadows = shadows;
15129
15325
  const oldEnabled = renderer.shadowMap.enabled;
15130
15326
  const oldType = renderer.shadowMap.type;
@@ -15153,7 +15349,7 @@ function createRoot(canvas, provider) {
15153
15349
  renderer.shadowMap.needsUpdate = true;
15154
15350
  }
15155
15351
  }
15156
- if (!configured) {
15352
+ if (!configured && !borrowsRenderer) {
15157
15353
  renderer.outputColorSpace = three.SRGBColorSpace;
15158
15354
  renderer.toneMapping = three.ACESFilmicToneMapping;
15159
15355
  }
@@ -15162,7 +15358,7 @@ function createRoot(canvas, provider) {
15162
15358
  if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
15163
15359
  lastConfiguredProps.textureColorSpace = textureColorSpace;
15164
15360
  }
15165
- const r3fProps = ["textureColorSpace"];
15361
+ const r3fProps = ["textureColorSpace", "primaryCanvas", "scheduler"];
15166
15362
  const constructorOnlyProps = ["samples", "antialias", "alpha", "canvas", "powerPreference"];
15167
15363
  const nonApplyProps = [...r3fProps, ...constructorOnlyProps];
15168
15364
  if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose)) {
@@ -15172,7 +15368,7 @@ function createRoot(canvas, provider) {
15172
15368
  }
15173
15369
  applyProps(renderer, glProps);
15174
15370
  }
15175
- if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer) {
15371
+ if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer && !borrowsRenderer) {
15176
15372
  const currentRenderer = state.renderer;
15177
15373
  if (!is.equ(rendererConfig, currentRenderer, shallowLoose)) {
15178
15374
  const rendererProps = {};
@@ -15315,8 +15511,11 @@ function createRoot(canvas, provider) {
15315
15511
  return this;
15316
15512
  },
15317
15513
  render(children) {
15514
+ if (_roots.get(canvas) !== root) return store;
15515
+ cancelUnmount();
15318
15516
  if (!configured && !pending) this.configure();
15319
15517
  pending.then(() => {
15518
+ if (_roots.get(canvas) !== root || root.unmountClaim) return;
15320
15519
  reconciler.updateContainer(
15321
15520
  /* @__PURE__ */ jsxRuntime.jsx(Provider, { store, children, onCreated, rootElement: canvas }),
15322
15521
  fiber,
@@ -15327,7 +15526,7 @@ function createRoot(canvas, provider) {
15327
15526
  return store;
15328
15527
  },
15329
15528
  unmount() {
15330
- unmountComponentAtNode(canvas);
15529
+ if (_roots.get(canvas) === root) unmountComponentAtNode(canvas);
15331
15530
  }
15332
15531
  };
15333
15532
  }
@@ -15347,46 +15546,52 @@ function Provider({
15347
15546
  }
15348
15547
  function unmountComponentAtNode(canvas, callback) {
15349
15548
  const root = _roots.get(canvas);
15350
- const fiber = root?.fiber;
15351
- if (fiber) {
15352
- const state = root?.store.getState();
15353
- if (state) {
15354
- state.internal.active = false;
15355
- const unregisterRoot = state.internal.unregisterRoot;
15356
- if (unregisterRoot) {
15357
- unregisterRoot();
15358
- state.internal.unregisterRoot = void 0;
15549
+ if (!root) return;
15550
+ const claim = root.unmountClaim = Symbol("unmount");
15551
+ root.store.getState().internal.active = false;
15552
+ reconciler.updateContainer(null, root.fiber, null, () => {
15553
+ if (root.unmountClaim !== claim) return;
15554
+ reconciler.updateContainer(null, root.fiber, null, () => {
15555
+ if (root.unmountClaim !== claim) return;
15556
+ if (root.ready.status === "pending") root.ready.then(teardown, teardown);
15557
+ else teardown();
15558
+ });
15559
+ });
15560
+ function teardown() {
15561
+ if (root.unmountClaim !== claim) return;
15562
+ root.unmountClaim = null;
15563
+ _roots.delete(canvas);
15564
+ const state = root.store.getState();
15565
+ const internal = state.internal;
15566
+ internal.active = false;
15567
+ const attempt = (step) => {
15568
+ try {
15569
+ return step();
15570
+ } catch (error) {
15571
+ console.warn("[R3F] Error while unmounting root; teardown may be incomplete:", error);
15359
15572
  }
15360
- }
15361
- reconciler.updateContainer(null, fiber, null, () => {
15362
- if (root?.store) extensions.detachRootExtensions(root.store);
15363
- if (state) {
15364
- setTimeout(() => {
15365
- try {
15366
- const renderer = state.internal.actualRenderer;
15367
- const unregisterPrimary = state.internal.unregisterPrimary;
15368
- if (unregisterPrimary) unregisterPrimary();
15369
- const canvasTarget = state.internal.canvasTarget;
15370
- if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
15371
- state.events.disconnect?.();
15372
- cleanupHelperGroup(root.store);
15373
- if (state.isLegacy && renderer) {
15374
- ;
15375
- renderer.renderLists?.dispose?.();
15376
- renderer.forceContextLoss?.();
15377
- }
15378
- if (!state.internal.isSecondary) {
15379
- if (renderer?.xr) state.xr.disconnect();
15380
- }
15381
- dispose(state.scene);
15382
- _roots.delete(canvas);
15383
- if (callback) callback(canvas);
15384
- } catch (error) {
15385
- console.warn("[R3F] Error while unmounting root; teardown may be incomplete:", error);
15386
- }
15387
- }, 500);
15573
+ };
15574
+ attempt(() => internal.unwatchDpr?.());
15575
+ internal.unwatchDpr = void 0;
15576
+ attempt(() => internal.unregisterRoot?.());
15577
+ internal.unregisterRoot = void 0;
15578
+ attempt(() => extensions.detachRootExtensions(root.store));
15579
+ attempt(() => internal.unregisterPrimary?.());
15580
+ attempt(() => state.events.disconnect?.());
15581
+ if (!internal.isSecondary && internal.actualRenderer?.xr && state.xr) attempt(() => state.xr.disconnect());
15582
+ attempt(() => cleanupHelperGroup(root.store));
15583
+ if (state.scene) attempt(() => dispose(state.scene));
15584
+ const canvasTarget = internal.canvasTarget;
15585
+ if (internal.isSecondary && canvasTarget?.dispose) attempt(() => canvasTarget.dispose());
15586
+ const released = attempt(() => internal.releaseRenderer?.());
15587
+ internal.releaseRenderer = void 0;
15588
+ if (callback) {
15589
+ if (released) {
15590
+ released.then(() => callback(canvas)).catch((error) => console.warn("[R3F] Error in unmount callback", error));
15591
+ } else {
15592
+ callback(canvas);
15388
15593
  }
15389
- });
15594
+ }
15390
15595
  }
15391
15596
  }
15392
15597
  function createPortal(children, container, state) {
@@ -15931,13 +16136,27 @@ function CanvasImpl({
15931
16136
  }
15932
16137
  };
15933
16138
  });
16139
+ const insertionMounted = React__namespace.useRef(false);
16140
+ React__namespace.useInsertionEffect(() => {
16141
+ insertionMounted.current = true;
16142
+ return () => {
16143
+ insertionMounted.current = false;
16144
+ queueMicrotask(() => {
16145
+ if (insertionMounted.current) return;
16146
+ const current = root.current;
16147
+ root.current = null;
16148
+ current?.unmount();
16149
+ });
16150
+ };
16151
+ }, []);
15934
16152
  React__namespace.useEffect(() => {
15935
16153
  const canvas = canvasRef.current;
15936
16154
  if (canvas) {
15937
16155
  return () => {
15938
16156
  if (canvas.isConnected) return;
15939
- unmountComponentAtNode(canvas);
16157
+ const current = root.current;
15940
16158
  root.current = null;
16159
+ current?.unmount();
15941
16160
  };
15942
16161
  }
15943
16162
  }, []);
@@ -15951,7 +16170,7 @@ function CanvasImpl({
15951
16170
  if (rootEntry?.store) extensions.notifyRootExtensionsHmr(rootEntry.store);
15952
16171
  });
15953
16172
  };
15954
- if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/fiber.CEjezJYZ.cjs', document.baseURI).href)) }) !== "undefined" && undefined) {
16173
+ if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/fiber.DF7oitV8.cjs', document.baseURI).href)) }) !== "undefined" && undefined) {
15955
16174
  const hot = undefined;
15956
16175
  hot.on("vite:afterUpdate", handleHMR);
15957
16176
  return () => hot.off?.("vite:afterUpdate", handleHMR);