@react-three/fiber 10.0.0-canary.4bc4a97 → 10.0.0-canary.4f9f64c

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.
package/dist/index.cjs CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  const webgpu = require('three/webgpu');
4
4
  const three = require('three');
5
- const Inspector_js = require('three/addons/inspector/Inspector.js');
6
5
  const jsxRuntime = require('react/jsx-runtime');
7
6
  const React = require('react');
8
7
  const useMeasure = require('react-use-measure');
@@ -12,6 +11,7 @@ const scheduler = require('@pmndrs/scheduler');
12
11
  const Tb = require('scheduler');
13
12
  const GroundedSkybox_js = require('three/examples/jsm/objects/GroundedSkybox.js');
14
13
  const HDRLoader_js = require('three/examples/jsm/loaders/HDRLoader.js');
14
+ const HDRCubeTextureLoader_js = require('three/examples/jsm/loaders/HDRCubeTextureLoader.js');
15
15
  const EXRLoader_js = require('three/examples/jsm/loaders/EXRLoader.js');
16
16
  const UltraHDRLoader_js = require('three/examples/jsm/loaders/UltraHDRLoader.js');
17
17
  const gainmapJs = require('@monogrid/gainmap-js');
@@ -52,18 +52,22 @@ const Tb__default = /*#__PURE__*/_interopDefaultCompat(Tb);
52
52
 
53
53
  const R3F_BUILD_LEGACY = true;
54
54
  const R3F_BUILD_WEBGPU = true;
55
+ async function loadInspector() {
56
+ const { Inspector } = await import('three/addons/inspector/Inspector.js');
57
+ return Inspector;
58
+ }
55
59
 
56
60
  const THREE = /*#__PURE__*/_mergeNamespaces({
57
61
  __proto__: null,
58
62
  CubeRenderTarget: webgpu.CubeRenderTarget,
59
63
  CubeRenderTargetCompat: webgpu.CubeRenderTarget,
60
- Inspector: Inspector_js.Inspector,
61
64
  R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
62
65
  R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
63
66
  RenderTargetCompat: webgpu.RenderTarget,
64
67
  WebGLCubeRenderTarget: three.WebGLCubeRenderTarget,
65
68
  WebGLRenderTarget: three.WebGLRenderTarget,
66
- WebGLRenderer: three.WebGLRenderer
69
+ WebGLRenderer: three.WebGLRenderer,
70
+ loadInspector: loadInspector
67
71
  }, [webgpu__namespace]);
68
72
 
69
73
  const primaryRegistry = /* @__PURE__ */ new Map();
@@ -526,8 +530,10 @@ function hasVisibilityHandlers(handlers) {
526
530
  }
527
531
 
528
532
  const FROM_REF = Symbol.for("@react-three/fiber.fromRef");
529
- function fromRef(ref) {
530
- return { [FROM_REF]: ref };
533
+ function fromRef(ref, transform) {
534
+ const marker = { [FROM_REF]: ref };
535
+ if (transform) marker.transform = transform;
536
+ return marker;
531
537
  }
532
538
  function isFromRef(value) {
533
539
  return value !== null && typeof value === "object" && FROM_REF in value;
@@ -628,11 +634,9 @@ function diffProps(instance, newProps) {
628
634
  for (const prop in instance.props) {
629
635
  if (RESERVED_PROPS.includes(prop) || newProps.hasOwnProperty(prop)) continue;
630
636
  const { root, key } = resolve(instance.object, prop);
631
- if (root.constructor && root.constructor.length === 0) {
637
+ if (typeof root?.constructor === "function") {
632
638
  const ctor = getMemoizedPrototype(root);
633
639
  if (!is.und(ctor)) changedProps[prop] = ctor[key];
634
- } else {
635
- changedProps[prop] = 0;
636
640
  }
637
641
  }
638
642
  return changedProps;
@@ -922,7 +926,7 @@ const createStore = (invalidate, advance) => {
922
926
  size: newSize,
923
927
  viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
924
928
  }));
925
- scheduler.getScheduler().invalidate();
929
+ get().invalidate();
926
930
  }
927
931
  }
928
932
  return;
@@ -937,15 +941,16 @@ const createStore = (invalidate, advance) => {
937
941
  viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
938
942
  _sizeImperative: true
939
943
  }));
940
- scheduler.getScheduler().invalidate();
944
+ get().invalidate();
941
945
  },
942
946
  setDpr: (dpr) => set((state2) => {
943
947
  const resolved = calculateDpr(dpr);
944
948
  return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
945
949
  }),
946
950
  setFrameloop: (frameloop = "always") => {
951
+ const rootId = get().internal.rootId;
952
+ if (rootId) scheduler.getScheduler().setRootFrameloop(rootId, frameloop);
947
953
  set(() => ({ frameloop }));
948
- scheduler.getScheduler().frameloop = frameloop;
949
954
  },
950
955
  setError: (error) => set(() => ({ error })),
951
956
  error: null,
@@ -1061,17 +1066,11 @@ const createStore = (invalidate, advance) => {
1061
1066
  oldSize = size;
1062
1067
  oldDpr = viewport.dpr;
1063
1068
  updateCamera(camera, size);
1064
- if (internal.isSecondary && canvasTarget) {
1065
- if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
1066
- canvasTarget.setSize(size.width, size.height, false);
1067
- } else {
1068
- if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
1069
- actualRenderer.setSize(size.width, size.height, false);
1070
- if (canvasTarget) {
1071
- if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
1072
- canvasTarget.setSize(size.width, size.height, false);
1073
- }
1074
- }
1069
+ const resizeTarget = canvasTarget ?? actualRenderer;
1070
+ if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
1071
+ resizeTarget.setSize(size.width, size.height, false);
1072
+ const activeTarget = actualRenderer.getCanvasTarget?.();
1073
+ if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
1075
1074
  }
1076
1075
  if (camera !== oldCamera) {
1077
1076
  oldCamera = camera;
@@ -1133,7 +1132,11 @@ function useLoader(loader, input, extensions, onProgress, cacheKey) {
1133
1132
  const results = cacheKeys.map(
1134
1133
  (key, index) => suspendReact.suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
1135
1134
  );
1136
- return Array.isArray(input) ? results : results[0];
1135
+ const stableRef = React.useRef(null);
1136
+ const previous = stableRef.current;
1137
+ const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
1138
+ stableRef.current = stable;
1139
+ return Array.isArray(input) ? stable : stable[0];
1137
1140
  }
1138
1141
  useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
1139
1142
  const inputs = Array.isArray(input) ? input : [input];
@@ -1253,6 +1256,13 @@ function useFrame(callback, priorityOrOptions) {
1253
1256
  * Use for controlling the entire frame loop, adding phases, etc.
1254
1257
  */
1255
1258
  scheduler: scheduler2,
1259
+ /**
1260
+ * The root that currently owns this job. Resolve on access because ambient
1261
+ * jobs can be adopted by a Canvas after the controls object is created.
1262
+ */
1263
+ get rootId() {
1264
+ return scheduler.getScheduler().getJobRootId(id);
1265
+ },
1256
1266
  /**
1257
1267
  * Manually step this job only.
1258
1268
  * Bypasses FPS limiting - always runs.
@@ -1269,6 +1279,14 @@ function useFrame(callback, priorityOrOptions) {
1269
1279
  stepAll: (timestamp) => {
1270
1280
  scheduler.getScheduler().step(timestamp);
1271
1281
  },
1282
+ /**
1283
+ * Request frames for this job's owning root without waking sibling roots.
1284
+ */
1285
+ invalidate: (frames, stackFrames) => {
1286
+ const scheduler3 = scheduler.getScheduler();
1287
+ const rootId = scheduler3.getJobRootId(id);
1288
+ if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
1289
+ },
1272
1290
  /**
1273
1291
  * Pause this job (set enabled=false).
1274
1292
  * Job remains registered but won't run.
@@ -1298,6 +1316,11 @@ function getUrls(input) {
1298
1316
  if (Array.isArray(input)) return input;
1299
1317
  return Object.values(input);
1300
1318
  }
1319
+ function inputSignature(input) {
1320
+ if (typeof input === "string") return input;
1321
+ if (Array.isArray(input)) return input.join("\0");
1322
+ return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
1323
+ }
1301
1324
  function allUrlsCached(urls, textureCache) {
1302
1325
  return urls.every((url) => textureCache.has(url));
1303
1326
  }
@@ -1323,24 +1346,37 @@ function useTexture(input, optionsOrOnLoad) {
1323
1346
  const onLoadRef = React.useRef(onLoad);
1324
1347
  onLoadRef.current = onLoad;
1325
1348
  const onLoadCalledForRef = React.useRef(null);
1326
- const urls = React.useMemo(() => getUrls(input), [input]);
1349
+ const inputKey = React.useMemo(() => inputSignature(input), [input]);
1350
+ const stableInput = React.useMemo(() => input, [inputKey]);
1351
+ const urls = React.useMemo(() => getUrls(stableInput), [stableInput]);
1327
1352
  const cachedResult = React.useMemo(() => {
1328
1353
  if (!cache) return null;
1329
1354
  const textures = store.getState().textures;
1330
1355
  if (!allUrlsCached(urls, textures)) return null;
1331
- return buildFromCache(input, textures);
1332
- }, [cache, urls, input, store]);
1356
+ return buildFromCache(stableInput, textures);
1357
+ }, [cache, urls, stableInput, store]);
1333
1358
  const loadedTextures = useLoader(
1334
1359
  webgpu.TextureLoader,
1335
- IsObject(input) ? Object.values(input) : input
1360
+ IsObject(stableInput) ? Object.values(stableInput) : stableInput
1336
1361
  );
1337
- const inputKey = urls.join("\0");
1362
+ const mappedTextures = React.useMemo(() => {
1363
+ if (cachedResult) return cachedResult;
1364
+ if (IsObject(stableInput)) {
1365
+ const keyed = {};
1366
+ const textureArray = loadedTextures;
1367
+ let i = 0;
1368
+ for (const key in stableInput) keyed[key] = textureArray[i++];
1369
+ return keyed;
1370
+ } else {
1371
+ return loadedTextures;
1372
+ }
1373
+ }, [stableInput, loadedTextures, cachedResult]);
1338
1374
  React.useLayoutEffect(() => {
1339
1375
  if (cachedResult) return;
1340
1376
  if (onLoadCalledForRef.current === inputKey) return;
1341
1377
  onLoadCalledForRef.current = inputKey;
1342
- onLoadRef.current?.(loadedTextures);
1343
- }, [cachedResult, loadedTextures, inputKey]);
1378
+ onLoadRef.current?.(mappedTextures);
1379
+ }, [cachedResult, mappedTextures, inputKey]);
1344
1380
  React.useEffect(() => {
1345
1381
  if (cachedResult) return;
1346
1382
  if ("initTexture" in renderer) {
@@ -1359,30 +1395,18 @@ function useTexture(input, optionsOrOnLoad) {
1359
1395
  });
1360
1396
  }
1361
1397
  }, [renderer, loadedTextures, cachedResult]);
1362
- const mappedTextures = React.useMemo(() => {
1363
- if (cachedResult) return cachedResult;
1364
- if (IsObject(input)) {
1365
- const keyed = {};
1366
- const textureArray = loadedTextures;
1367
- let i = 0;
1368
- for (const key in input) keyed[key] = textureArray[i++];
1369
- return keyed;
1370
- } else {
1371
- return loadedTextures;
1372
- }
1373
- }, [input, loadedTextures, cachedResult]);
1374
1398
  React.useEffect(() => {
1375
1399
  if (!cache) return;
1376
1400
  const urlTextureMap = [];
1377
- if (typeof input === "string") {
1378
- urlTextureMap.push([input, mappedTextures]);
1379
- } else if (Array.isArray(input)) {
1401
+ if (typeof stableInput === "string") {
1402
+ urlTextureMap.push([stableInput, mappedTextures]);
1403
+ } else if (Array.isArray(stableInput)) {
1380
1404
  const textureArray = mappedTextures;
1381
- input.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
1382
- } else if (IsObject(input)) {
1405
+ stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
1406
+ } else if (IsObject(stableInput)) {
1383
1407
  const textureRecord = mappedTextures;
1384
- for (const key in input) {
1385
- const url = input[key];
1408
+ for (const key in stableInput) {
1409
+ const url = stableInput[key];
1386
1410
  urlTextureMap.push([url, textureRecord[key]]);
1387
1411
  }
1388
1412
  }
@@ -1411,7 +1435,7 @@ function useTexture(input, optionsOrOnLoad) {
1411
1435
  }
1412
1436
  return { _textureRefs: refs };
1413
1437
  });
1414
- }, [cache, input, mappedTextures, store]);
1438
+ }, [cache, stableInput, mappedTextures, store]);
1415
1439
  return mappedTextures;
1416
1440
  }
1417
1441
  useTexture.preload = (url) => useLoader.preload(webgpu.TextureLoader, url);
@@ -1574,7 +1598,7 @@ function useEnvironment({
1574
1598
  texture = texture.renderTarget?.texture;
1575
1599
  }
1576
1600
  texture.mapping = isCubemap ? webgpu.CubeReflectionMapping : webgpu.EquirectangularReflectionMapping;
1577
- texture.colorSpace = colorSpace ?? (isCubemap ? "srgb" : "srgb-linear");
1601
+ texture.colorSpace = colorSpace ?? (isCubemap && extension !== "hdr-cube" ? "srgb" : "srgb-linear");
1578
1602
  return texture;
1579
1603
  }
1580
1604
  const preloadDefaultOptions = {
@@ -1627,11 +1651,12 @@ function getExtension(files) {
1627
1651
  const isCubemap = isArray(files) && files.length === 6;
1628
1652
  const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
1629
1653
  const firstEntry = isArray(files) ? files[0] : files;
1630
- const extension = isCubemap ? "cube" : isGainmap ? "webp" : firstEntry.startsWith("data:application/exr") ? "exr" : firstEntry.startsWith("data:application/hdr") ? "hdr" : firstEntry.startsWith("data:image/jpeg") ? "jpg" : firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
1654
+ const firstExtension = firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
1655
+ const extension = isCubemap ? firstExtension === "hdr" ? "hdr-cube" : "cube" : isGainmap ? "webp" : firstEntry.startsWith("data:application/exr") ? "exr" : firstEntry.startsWith("data:application/hdr") ? "hdr" : firstEntry.startsWith("data:image/jpeg") ? "jpg" : firstExtension;
1631
1656
  return { extension, isCubemap, isGainmap };
1632
1657
  }
1633
1658
  function getLoader(extension) {
1634
- const loader = extension === "cube" ? webgpu.CubeTextureLoader : extension === "hdr" ? HDRLoader_js.HDRLoader : extension === "exr" ? EXRLoader_js.EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader_js.UltraHDRLoader : extension === "webp" ? gainmapJs.GainMapLoader : null;
1659
+ const loader = extension === "cube" ? webgpu.CubeTextureLoader : extension === "hdr-cube" ? HDRCubeTextureLoader_js.HDRCubeTextureLoader : extension === "hdr" ? HDRLoader_js.HDRLoader : extension === "exr" ? EXRLoader_js.EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader_js.UltraHDRLoader : extension === "webp" ? gainmapJs.GainMapLoader : null;
1635
1660
  return loader;
1636
1661
  }
1637
1662
 
@@ -1682,13 +1707,19 @@ function addTail(callback) {
1682
1707
  return scheduler.getScheduler().onIdle(callback);
1683
1708
  }
1684
1709
  function invalidate(state, frames = 1, stackFrames = false) {
1685
- scheduler.getScheduler().invalidate(frames, stackFrames);
1710
+ const rootId = state?.internal?.rootId;
1711
+ const scheduler$1 = scheduler.getScheduler();
1712
+ if (rootId) scheduler$1.invalidateRoot(rootId, frames, stackFrames);
1713
+ else scheduler$1.invalidate(frames, stackFrames);
1686
1714
  }
1687
- function advance(timestamp) {
1688
- scheduler.getScheduler().step(timestamp);
1715
+ function advance(timestamp, runGlobalEffects, state) {
1716
+ const rootId = state?.internal?.rootId;
1717
+ const scheduler$1 = scheduler.getScheduler();
1718
+ if (rootId) scheduler$1.stepRoot(rootId, timestamp);
1719
+ else scheduler$1.step(timestamp);
1689
1720
  }
1690
1721
 
1691
- const version = "10.0.0-alpha.3";
1722
+ const version = "10.0.0-alpha.5";
1692
1723
  const packageData = {
1693
1724
  version: version};
1694
1725
 
@@ -13547,7 +13578,10 @@ function extend(objects) {
13547
13578
  catalogue[Component] = objects;
13548
13579
  return Component;
13549
13580
  } else {
13550
- Object.assign(catalogue, objects);
13581
+ for (const name in objects) {
13582
+ const object = objects[name];
13583
+ if (isConstructor(object)) catalogue[name] = object;
13584
+ }
13551
13585
  }
13552
13586
  }
13553
13587
  function validateInstance(type, props) {
@@ -13895,7 +13929,7 @@ const reconciler = /* @__PURE__ */ createReconciler({
13895
13929
  getRootHostContext: () => NO_CONTEXT,
13896
13930
  getChildHostContext: () => NO_CONTEXT,
13897
13931
  commitUpdate(instance, type, oldProps, newProps, fiber) {
13898
- validateInstance(type, newProps);
13932
+ validateInstance(instance.type, newProps);
13899
13933
  let reconstruct = false;
13900
13934
  if (instance.type === "primitive" && oldProps.object !== newProps.object) reconstruct = true;
13901
13935
  else if (newProps.args?.length !== oldProps.args?.length) reconstruct = true;
@@ -13922,8 +13956,8 @@ const reconciler = /* @__PURE__ */ createReconciler({
13922
13956
  for (const prop in instance.props) {
13923
13957
  const value = instance.props[prop];
13924
13958
  if (isFromRef(value)) {
13925
- const ref = value[FROM_REF];
13926
- if (ref.current != null) resolved[prop] = ref.current;
13959
+ const { [FROM_REF]: ref, transform } = value;
13960
+ if (ref.current != null) resolved[prop] = transform ? transform(ref.current) : ref.current;
13927
13961
  }
13928
13962
  }
13929
13963
  if (Object.keys(resolved).length) applyProps(instance.object, resolved);
@@ -14222,9 +14256,8 @@ function createRoot(canvas) {
14222
14256
  if (!renderer.hasInitialized?.()) {
14223
14257
  const size2 = computeInitialSize(canvas, propsSize);
14224
14258
  if (size2.width > 0 && size2.height > 0) {
14225
- const pixelRatio = calculateDpr(dpr);
14226
- canvas.width = size2.width * pixelRatio;
14227
- canvas.height = size2.height * pixelRatio;
14259
+ renderer.setPixelRatio(calculateDpr(dpr));
14260
+ renderer.setSize(size2.width, size2.height, false);
14228
14261
  }
14229
14262
  await renderer.init();
14230
14263
  }
@@ -14233,7 +14266,7 @@ function createRoot(canvas) {
14233
14266
  state.internal.actualRenderer = renderer;
14234
14267
  state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
14235
14268
  if (canvasId && !state.internal.isSecondary) {
14236
- const canvasTarget = new webgpu.CanvasTarget(canvas);
14269
+ const canvasTarget = renderer.getCanvasTarget?.();
14237
14270
  const unregisterPrimary = registerPrimary(canvasId, renderer, store);
14238
14271
  state.set((prev) => ({
14239
14272
  internal: {
@@ -14347,7 +14380,7 @@ function createRoot(canvas) {
14347
14380
  const handleXRFrame = (timestamp, _frame) => {
14348
14381
  const state2 = store.getState();
14349
14382
  if (state2.frameloop === "never") return;
14350
- advance(timestamp);
14383
+ advance(timestamp, true, state2);
14351
14384
  };
14352
14385
  const actualRenderer = state.internal.actualRenderer;
14353
14386
  const handleSessionChange = () => {
@@ -14355,7 +14388,7 @@ function createRoot(canvas) {
14355
14388
  const renderer2 = state2.internal.actualRenderer;
14356
14389
  actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
14357
14390
  renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
14358
- if (!renderer2.xr.isPresenting) invalidate();
14391
+ if (!renderer2.xr.isPresenting) invalidate(state2);
14359
14392
  };
14360
14393
  const xr = {
14361
14394
  connect() {
@@ -14437,14 +14470,23 @@ function createRoot(canvas) {
14437
14470
  const newRootId = canvasId || scheduler$1.generateRootId();
14438
14471
  const unregisterRoot = scheduler$1.registerRoot(newRootId, {
14439
14472
  getState: () => store.getState(),
14440
- onError: (err) => store.getState().setError(err)
14473
+ onError: (err) => store.getState().setError(err),
14474
+ frameloop: store.getState().frameloop,
14475
+ before: schedulerConfig?.before,
14476
+ after: schedulerConfig?.after,
14477
+ order: schedulerConfig?.order
14441
14478
  });
14442
14479
  const unregisterCanvasTarget = scheduler$1.register(
14443
14480
  () => {
14444
14481
  const state2 = store.getState();
14445
- if (state2.internal.isMultiCanvas && state2.internal.canvasTarget) {
14482
+ const canvasTarget = state2.internal.canvasTarget;
14483
+ if (canvasTarget) {
14446
14484
  const renderer2 = state2.internal.actualRenderer;
14447
- renderer2.setCanvasTarget(state2.internal.canvasTarget);
14485
+ if (renderer2.getCanvasTarget() !== canvasTarget) renderer2.setCanvasTarget(canvasTarget);
14486
+ if (state2.internal.canvasTargetSizeDirty) {
14487
+ state2.internal.canvasTargetSizeDirty = false;
14488
+ renderer2.backend?.updateSize?.();
14489
+ }
14448
14490
  }
14449
14491
  },
14450
14492
  {
@@ -14513,8 +14555,7 @@ function createRoot(canvas) {
14513
14555
  phase: "render",
14514
14556
  system: true,
14515
14557
  // Internal flag: this is a system job, not user-controlled
14516
- // Apply scheduler config for render ordering and rate limiting
14517
- ...schedulerConfig?.after && { after: schedulerConfig.after },
14558
+ // FPS throttles only the default render job; Canvas ordering belongs to the root.
14518
14559
  ...schedulerConfig?.fps && { fps: schedulerConfig.fps }
14519
14560
  }
14520
14561
  );
@@ -14533,8 +14574,21 @@ function createRoot(canvas) {
14533
14574
  scheduler: scheduler$1
14534
14575
  }
14535
14576
  }));
14577
+ } else {
14578
+ const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
14579
+ if (constraintsChanged) {
14580
+ scheduler$1.setRootConstraints(rootId, {
14581
+ before: schedulerConfig?.before,
14582
+ after: schedulerConfig?.after
14583
+ });
14584
+ }
14585
+ if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
14586
+ scheduler$1.setRootOrder(rootId, schedulerConfig?.order ?? 0);
14587
+ }
14536
14588
  }
14537
- scheduler$1.frameloop = frameloop;
14589
+ lastConfiguredProps.schedulerBefore = schedulerConfig?.before;
14590
+ lastConfiguredProps.schedulerAfter = schedulerConfig?.after;
14591
+ lastConfiguredProps.schedulerOrder = schedulerConfig?.order;
14538
14592
  onCreated = onCreatedCallback;
14539
14593
  configured = true;
14540
14594
  resolve();
@@ -14576,18 +14630,23 @@ function unmountComponentAtNode(canvas, callback) {
14576
14630
  const fiber = root?.fiber;
14577
14631
  if (fiber) {
14578
14632
  const state = root?.store.getState();
14579
- if (state) state.internal.active = false;
14633
+ if (state) {
14634
+ state.internal.active = false;
14635
+ const unregisterRoot = state.internal.unregisterRoot;
14636
+ if (unregisterRoot) {
14637
+ unregisterRoot();
14638
+ state.internal.unregisterRoot = void 0;
14639
+ }
14640
+ }
14580
14641
  reconciler.updateContainer(null, fiber, null, () => {
14581
14642
  if (state) {
14582
14643
  setTimeout(() => {
14583
14644
  try {
14584
14645
  const renderer = state.internal.actualRenderer;
14585
- const unregisterRoot = state.internal.unregisterRoot;
14586
- if (unregisterRoot) unregisterRoot();
14587
14646
  const unregisterPrimary = state.internal.unregisterPrimary;
14588
14647
  if (unregisterPrimary) unregisterPrimary();
14589
14648
  const canvasTarget = state.internal.canvasTarget;
14590
- if (canvasTarget?.dispose) canvasTarget.dispose();
14649
+ if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
14591
14650
  state.events.disconnect?.();
14592
14651
  cleanupHelperGroup(root.store);
14593
14652
  if (state.isLegacy && renderer) {
@@ -14728,16 +14787,11 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
14728
14787
  const oldbg = target.background;
14729
14788
  const oldenv = target.environment;
14730
14789
  const oldSceneProps = {
14731
- // @ts-ignore
14732
14790
  backgroundBlurriness: target.backgroundBlurriness,
14733
- // @ts-ignore
14734
14791
  backgroundIntensity: target.backgroundIntensity,
14735
- // @ts-ignore
14736
- backgroundRotation: target.backgroundRotation?.clone?.() ?? [0, 0, 0],
14737
- // @ts-ignore
14792
+ backgroundRotation: target.backgroundRotation.clone(),
14738
14793
  environmentIntensity: target.environmentIntensity,
14739
- // @ts-ignore
14740
- environmentRotation: target.environmentRotation?.clone?.() ?? [0, 0, 0]
14794
+ environmentRotation: target.environmentRotation.clone()
14741
14795
  };
14742
14796
  if (background !== "only") target.environment = texture;
14743
14797
  if (background) target.background = texture;
@@ -15031,9 +15085,9 @@ function CanvasImpl({
15031
15085
  React__namespace.useMemo(() => extend(THREE), []);
15032
15086
  const Bridge = useBridge();
15033
15087
  const backgroundProps = React__namespace.useMemo(() => parseBackground(background), [background]);
15034
- const hasInitialSizeRef = React__namespace.useRef(false);
15088
+ const [hasInitialSize, setHasInitialSize] = React__namespace.useState(false);
15035
15089
  const measureConfig = React__namespace.useMemo(() => {
15036
- if (!hasInitialSizeRef.current) {
15090
+ if (!hasInitialSize) {
15037
15091
  return {
15038
15092
  ...resize,
15039
15093
  scroll: resize?.scroll ?? true,
@@ -15045,7 +15099,7 @@ function CanvasImpl({
15045
15099
  debounce: { scroll: 50, resize: 0 },
15046
15100
  ...resize
15047
15101
  };
15048
- }, [resize, hasInitialSizeRef.current]);
15102
+ }, [hasInitialSize, resize]);
15049
15103
  const [containerRef, containerRect] = useMeasure__default(measureConfig);
15050
15104
  const effectiveSize = React__namespace.useMemo(() => {
15051
15105
  let w = width ?? containerRect.width;
@@ -15061,9 +15115,7 @@ function CanvasImpl({
15061
15115
  left: containerRect.left
15062
15116
  };
15063
15117
  }, [width, height, containerRect, forceEven]);
15064
- if (!hasInitialSizeRef.current && effectiveSize.width > 0 && effectiveSize.height > 0) {
15065
- hasInitialSizeRef.current = true;
15066
- }
15118
+ if (!hasInitialSize && effectiveSize.width > 0 && effectiveSize.height > 0) setHasInitialSize(true);
15067
15119
  const canvasRef = React__namespace.useRef(null);
15068
15120
  const divRef = React__namespace.useRef(null);
15069
15121
  React__namespace.useImperativeHandle(ref, () => canvasRef.current);
@@ -15177,6 +15229,7 @@ function CanvasImpl({
15177
15229
  const canvas = canvasRef.current;
15178
15230
  if (canvas) {
15179
15231
  return () => {
15232
+ if (canvas.isConnected) return;
15180
15233
  unmountComponentAtNode(canvas);
15181
15234
  root.current = null;
15182
15235
  };