@react-three/fiber 10.0.0-canary.0d86c23 → 10.0.0-canary.0ea97c0
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 +119 -61
- package/dist/index.d.cts +180 -26
- package/dist/index.d.mts +180 -26
- package/dist/index.d.ts +180 -26
- package/dist/index.mjs +119 -61
- package/dist/legacy.cjs +115 -61
- package/dist/legacy.d.cts +179 -29
- package/dist/legacy.d.mts +179 -29
- package/dist/legacy.d.ts +179 -29
- package/dist/legacy.mjs +115 -61
- package/dist/webgpu/index.cjs +182 -98
- package/dist/webgpu/index.d.cts +204 -90
- package/dist/webgpu/index.d.mts +204 -90
- package/dist/webgpu/index.d.ts +204 -90
- package/dist/webgpu/index.mjs +182 -98
- package/package.json +2 -2
- package/readme.md +1 -1
package/dist/legacy.mjs
CHANGED
|
@@ -30,11 +30,9 @@ function _mergeNamespaces(n, m) {
|
|
|
30
30
|
|
|
31
31
|
const R3F_BUILD_LEGACY = true;
|
|
32
32
|
const R3F_BUILD_WEBGPU = false;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
};
|
|
33
|
+
async function loadInspector() {
|
|
34
|
+
throw new Error("Inspector is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
35
|
+
}
|
|
38
36
|
const WebGPURenderer = class WebGPURenderer2 {
|
|
39
37
|
constructor() {
|
|
40
38
|
throw new Error("WebGPURenderer is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
@@ -47,12 +45,12 @@ const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
47
45
|
__proto__: null,
|
|
48
46
|
CubeRenderTarget: CubeRenderTarget,
|
|
49
47
|
CubeRenderTargetCompat: WebGLCubeRenderTarget,
|
|
50
|
-
Inspector: Inspector,
|
|
51
48
|
R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
|
|
52
49
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
53
50
|
RenderTarget: RenderTarget,
|
|
54
51
|
RenderTargetCompat: WebGLRenderTarget,
|
|
55
|
-
WebGPURenderer: WebGPURenderer
|
|
52
|
+
WebGPURenderer: WebGPURenderer,
|
|
53
|
+
loadInspector: loadInspector
|
|
56
54
|
}, [three]);
|
|
57
55
|
|
|
58
56
|
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
@@ -608,7 +606,12 @@ function diffProps(instance, newProps) {
|
|
|
608
606
|
const changedProps = {};
|
|
609
607
|
for (const prop in newProps) {
|
|
610
608
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
611
|
-
if (is.equ(newProps[prop], instance.props[prop]))
|
|
609
|
+
if (is.equ(newProps[prop], instance.props[prop])) {
|
|
610
|
+
const value = newProps[prop];
|
|
611
|
+
if (!isCopyable(value)) continue;
|
|
612
|
+
const { target } = resolve(instance.object, prop);
|
|
613
|
+
if (!isCopyable(target) || target.constructor !== value.constructor) continue;
|
|
614
|
+
}
|
|
612
615
|
changedProps[prop] = newProps[prop];
|
|
613
616
|
for (const other in newProps) {
|
|
614
617
|
if (other.startsWith(`${prop}-`)) changedProps[other] = newProps[other];
|
|
@@ -911,7 +914,7 @@ const createStore = (invalidate, advance) => {
|
|
|
911
914
|
size: newSize,
|
|
912
915
|
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
913
916
|
}));
|
|
914
|
-
|
|
917
|
+
get().invalidate();
|
|
915
918
|
}
|
|
916
919
|
}
|
|
917
920
|
return;
|
|
@@ -926,15 +929,16 @@ const createStore = (invalidate, advance) => {
|
|
|
926
929
|
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
927
930
|
_sizeImperative: true
|
|
928
931
|
}));
|
|
929
|
-
|
|
932
|
+
get().invalidate();
|
|
930
933
|
},
|
|
931
934
|
setDpr: (dpr) => set((state2) => {
|
|
932
935
|
const resolved = calculateDpr(dpr);
|
|
933
936
|
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
934
937
|
}),
|
|
935
938
|
setFrameloop: (frameloop = "always") => {
|
|
939
|
+
const rootId = get().internal.rootId;
|
|
940
|
+
if (rootId) getScheduler().setRootFrameloop(rootId, frameloop);
|
|
936
941
|
set(() => ({ frameloop }));
|
|
937
|
-
getScheduler().frameloop = frameloop;
|
|
938
942
|
},
|
|
939
943
|
setError: (error) => set(() => ({ error })),
|
|
940
944
|
error: null,
|
|
@@ -1050,17 +1054,11 @@ const createStore = (invalidate, advance) => {
|
|
|
1050
1054
|
oldSize = size;
|
|
1051
1055
|
oldDpr = viewport.dpr;
|
|
1052
1056
|
updateCamera(camera, size);
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1059
|
-
if (canvasTarget) {
|
|
1060
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1061
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1057
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
1058
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
1059
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
1060
|
+
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
1061
|
+
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
1064
1062
|
}
|
|
1065
1063
|
if (camera !== oldCamera) {
|
|
1066
1064
|
oldCamera = camera;
|
|
@@ -1122,7 +1120,11 @@ function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
|
1122
1120
|
const results = cacheKeys.map(
|
|
1123
1121
|
(key, index) => suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
1124
1122
|
);
|
|
1125
|
-
|
|
1123
|
+
const stableRef = useRef(null);
|
|
1124
|
+
const previous = stableRef.current;
|
|
1125
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
1126
|
+
stableRef.current = stable;
|
|
1127
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
1126
1128
|
}
|
|
1127
1129
|
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
1128
1130
|
const inputs = Array.isArray(input) ? input : [input];
|
|
@@ -1242,6 +1244,13 @@ function useFrame(callback, priorityOrOptions) {
|
|
|
1242
1244
|
* Use for controlling the entire frame loop, adding phases, etc.
|
|
1243
1245
|
*/
|
|
1244
1246
|
scheduler: scheduler2,
|
|
1247
|
+
/**
|
|
1248
|
+
* The root that currently owns this job. Resolve on access because ambient
|
|
1249
|
+
* jobs can be adopted by a Canvas after the controls object is created.
|
|
1250
|
+
*/
|
|
1251
|
+
get rootId() {
|
|
1252
|
+
return getScheduler().getJobRootId(id);
|
|
1253
|
+
},
|
|
1245
1254
|
/**
|
|
1246
1255
|
* Manually step this job only.
|
|
1247
1256
|
* Bypasses FPS limiting - always runs.
|
|
@@ -1258,6 +1267,14 @@ function useFrame(callback, priorityOrOptions) {
|
|
|
1258
1267
|
stepAll: (timestamp) => {
|
|
1259
1268
|
getScheduler().step(timestamp);
|
|
1260
1269
|
},
|
|
1270
|
+
/**
|
|
1271
|
+
* Request frames for this job's owning root without waking sibling roots.
|
|
1272
|
+
*/
|
|
1273
|
+
invalidate: (frames, stackFrames) => {
|
|
1274
|
+
const scheduler3 = getScheduler();
|
|
1275
|
+
const rootId = scheduler3.getJobRootId(id);
|
|
1276
|
+
if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
|
|
1277
|
+
},
|
|
1261
1278
|
/**
|
|
1262
1279
|
* Pause this job (set enabled=false).
|
|
1263
1280
|
* Job remains registered but won't run.
|
|
@@ -1287,6 +1304,11 @@ function getUrls(input) {
|
|
|
1287
1304
|
if (Array.isArray(input)) return input;
|
|
1288
1305
|
return Object.values(input);
|
|
1289
1306
|
}
|
|
1307
|
+
function inputSignature(input) {
|
|
1308
|
+
if (typeof input === "string") return input;
|
|
1309
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1310
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1311
|
+
}
|
|
1290
1312
|
function allUrlsCached(urls, textureCache) {
|
|
1291
1313
|
return urls.every((url) => textureCache.has(url));
|
|
1292
1314
|
}
|
|
@@ -1312,18 +1334,19 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1312
1334
|
const onLoadRef = useRef(onLoad);
|
|
1313
1335
|
onLoadRef.current = onLoad;
|
|
1314
1336
|
const onLoadCalledForRef = useRef(null);
|
|
1315
|
-
const
|
|
1337
|
+
const inputKey = useMemo(() => inputSignature(input), [input]);
|
|
1338
|
+
const stableInput = useMemo(() => input, [inputKey]);
|
|
1339
|
+
const urls = useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1316
1340
|
const cachedResult = useMemo(() => {
|
|
1317
1341
|
if (!cache) return null;
|
|
1318
1342
|
const textures = store.getState().textures;
|
|
1319
1343
|
if (!allUrlsCached(urls, textures)) return null;
|
|
1320
|
-
return buildFromCache(
|
|
1321
|
-
}, [cache, urls,
|
|
1344
|
+
return buildFromCache(stableInput, textures);
|
|
1345
|
+
}, [cache, urls, stableInput, store]);
|
|
1322
1346
|
const loadedTextures = useLoader(
|
|
1323
1347
|
TextureLoader,
|
|
1324
|
-
IsObject(
|
|
1348
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1325
1349
|
);
|
|
1326
|
-
const inputKey = urls.join("\0");
|
|
1327
1350
|
useLayoutEffect(() => {
|
|
1328
1351
|
if (cachedResult) return;
|
|
1329
1352
|
if (onLoadCalledForRef.current === inputKey) return;
|
|
@@ -1350,28 +1373,28 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1350
1373
|
}, [renderer, loadedTextures, cachedResult]);
|
|
1351
1374
|
const mappedTextures = useMemo(() => {
|
|
1352
1375
|
if (cachedResult) return cachedResult;
|
|
1353
|
-
if (IsObject(
|
|
1376
|
+
if (IsObject(stableInput)) {
|
|
1354
1377
|
const keyed = {};
|
|
1355
1378
|
const textureArray = loadedTextures;
|
|
1356
1379
|
let i = 0;
|
|
1357
|
-
for (const key in
|
|
1380
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1358
1381
|
return keyed;
|
|
1359
1382
|
} else {
|
|
1360
1383
|
return loadedTextures;
|
|
1361
1384
|
}
|
|
1362
|
-
}, [
|
|
1385
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1363
1386
|
useEffect(() => {
|
|
1364
1387
|
if (!cache) return;
|
|
1365
1388
|
const urlTextureMap = [];
|
|
1366
|
-
if (typeof
|
|
1367
|
-
urlTextureMap.push([
|
|
1368
|
-
} else if (Array.isArray(
|
|
1389
|
+
if (typeof stableInput === "string") {
|
|
1390
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1391
|
+
} else if (Array.isArray(stableInput)) {
|
|
1369
1392
|
const textureArray = mappedTextures;
|
|
1370
|
-
|
|
1371
|
-
} else if (IsObject(
|
|
1393
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1394
|
+
} else if (IsObject(stableInput)) {
|
|
1372
1395
|
const textureRecord = mappedTextures;
|
|
1373
|
-
for (const key in
|
|
1374
|
-
const url =
|
|
1396
|
+
for (const key in stableInput) {
|
|
1397
|
+
const url = stableInput[key];
|
|
1375
1398
|
urlTextureMap.push([url, textureRecord[key]]);
|
|
1376
1399
|
}
|
|
1377
1400
|
}
|
|
@@ -1400,7 +1423,7 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1400
1423
|
}
|
|
1401
1424
|
return { _textureRefs: refs };
|
|
1402
1425
|
});
|
|
1403
|
-
}, [cache,
|
|
1426
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1404
1427
|
return mappedTextures;
|
|
1405
1428
|
}
|
|
1406
1429
|
useTexture.preload = (url) => useLoader.preload(TextureLoader, url);
|
|
@@ -1669,13 +1692,19 @@ function addTail(callback) {
|
|
|
1669
1692
|
return getScheduler().onIdle(callback);
|
|
1670
1693
|
}
|
|
1671
1694
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
1672
|
-
|
|
1695
|
+
const rootId = state?.internal?.rootId;
|
|
1696
|
+
const scheduler = getScheduler();
|
|
1697
|
+
if (rootId) scheduler.invalidateRoot(rootId, frames, stackFrames);
|
|
1698
|
+
else scheduler.invalidate(frames, stackFrames);
|
|
1673
1699
|
}
|
|
1674
|
-
function advance(timestamp) {
|
|
1675
|
-
|
|
1700
|
+
function advance(timestamp, runGlobalEffects, state) {
|
|
1701
|
+
const rootId = state?.internal?.rootId;
|
|
1702
|
+
const scheduler = getScheduler();
|
|
1703
|
+
if (rootId) scheduler.stepRoot(rootId, timestamp);
|
|
1704
|
+
else scheduler.step(timestamp);
|
|
1676
1705
|
}
|
|
1677
1706
|
|
|
1678
|
-
const version = "10.0.0-alpha.
|
|
1707
|
+
const version = "10.0.0-alpha.4";
|
|
1679
1708
|
const packageData = {
|
|
1680
1709
|
version: version};
|
|
1681
1710
|
|
|
@@ -14287,7 +14316,7 @@ function createRoot(canvas) {
|
|
|
14287
14316
|
const handleXRFrame = (timestamp, _frame) => {
|
|
14288
14317
|
const state2 = store.getState();
|
|
14289
14318
|
if (state2.frameloop === "never") return;
|
|
14290
|
-
advance(timestamp);
|
|
14319
|
+
advance(timestamp, true, state2);
|
|
14291
14320
|
};
|
|
14292
14321
|
const actualRenderer = state.internal.actualRenderer;
|
|
14293
14322
|
const handleSessionChange = () => {
|
|
@@ -14295,7 +14324,7 @@ function createRoot(canvas) {
|
|
|
14295
14324
|
const renderer2 = state2.internal.actualRenderer;
|
|
14296
14325
|
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
14297
14326
|
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
14298
|
-
if (!renderer2.xr.isPresenting) invalidate();
|
|
14327
|
+
if (!renderer2.xr.isPresenting) invalidate(state2);
|
|
14299
14328
|
};
|
|
14300
14329
|
const xr = {
|
|
14301
14330
|
connect() {
|
|
@@ -14377,14 +14406,23 @@ function createRoot(canvas) {
|
|
|
14377
14406
|
const newRootId = canvasId || scheduler.generateRootId();
|
|
14378
14407
|
const unregisterRoot = scheduler.registerRoot(newRootId, {
|
|
14379
14408
|
getState: () => store.getState(),
|
|
14380
|
-
onError: (err) => store.getState().setError(err)
|
|
14409
|
+
onError: (err) => store.getState().setError(err),
|
|
14410
|
+
frameloop: store.getState().frameloop,
|
|
14411
|
+
before: schedulerConfig?.before,
|
|
14412
|
+
after: schedulerConfig?.after,
|
|
14413
|
+
order: schedulerConfig?.order
|
|
14381
14414
|
});
|
|
14382
14415
|
const unregisterCanvasTarget = scheduler.register(
|
|
14383
14416
|
() => {
|
|
14384
14417
|
const state2 = store.getState();
|
|
14385
|
-
|
|
14418
|
+
const canvasTarget = state2.internal.canvasTarget;
|
|
14419
|
+
if (canvasTarget) {
|
|
14386
14420
|
const renderer2 = state2.internal.actualRenderer;
|
|
14387
|
-
renderer2.setCanvasTarget(
|
|
14421
|
+
if (renderer2.getCanvasTarget() !== canvasTarget) renderer2.setCanvasTarget(canvasTarget);
|
|
14422
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14423
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14424
|
+
renderer2.backend?.updateSize?.();
|
|
14425
|
+
}
|
|
14388
14426
|
}
|
|
14389
14427
|
},
|
|
14390
14428
|
{
|
|
@@ -14453,8 +14491,7 @@ function createRoot(canvas) {
|
|
|
14453
14491
|
phase: "render",
|
|
14454
14492
|
system: true,
|
|
14455
14493
|
// Internal flag: this is a system job, not user-controlled
|
|
14456
|
-
//
|
|
14457
|
-
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
14494
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
14458
14495
|
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14459
14496
|
}
|
|
14460
14497
|
);
|
|
@@ -14473,8 +14510,21 @@ function createRoot(canvas) {
|
|
|
14473
14510
|
scheduler
|
|
14474
14511
|
}
|
|
14475
14512
|
}));
|
|
14513
|
+
} else {
|
|
14514
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
14515
|
+
if (constraintsChanged) {
|
|
14516
|
+
scheduler.setRootConstraints(rootId, {
|
|
14517
|
+
before: schedulerConfig?.before,
|
|
14518
|
+
after: schedulerConfig?.after
|
|
14519
|
+
});
|
|
14520
|
+
}
|
|
14521
|
+
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
14522
|
+
scheduler.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
14523
|
+
}
|
|
14476
14524
|
}
|
|
14477
|
-
|
|
14525
|
+
lastConfiguredProps.schedulerBefore = schedulerConfig?.before;
|
|
14526
|
+
lastConfiguredProps.schedulerAfter = schedulerConfig?.after;
|
|
14527
|
+
lastConfiguredProps.schedulerOrder = schedulerConfig?.order;
|
|
14478
14528
|
onCreated = onCreatedCallback;
|
|
14479
14529
|
configured = true;
|
|
14480
14530
|
resolve();
|
|
@@ -14516,18 +14566,23 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14516
14566
|
const fiber = root?.fiber;
|
|
14517
14567
|
if (fiber) {
|
|
14518
14568
|
const state = root?.store.getState();
|
|
14519
|
-
if (state)
|
|
14569
|
+
if (state) {
|
|
14570
|
+
state.internal.active = false;
|
|
14571
|
+
const unregisterRoot = state.internal.unregisterRoot;
|
|
14572
|
+
if (unregisterRoot) {
|
|
14573
|
+
unregisterRoot();
|
|
14574
|
+
state.internal.unregisterRoot = void 0;
|
|
14575
|
+
}
|
|
14576
|
+
}
|
|
14520
14577
|
reconciler.updateContainer(null, fiber, null, () => {
|
|
14521
14578
|
if (state) {
|
|
14522
14579
|
setTimeout(() => {
|
|
14523
14580
|
try {
|
|
14524
14581
|
const renderer = state.internal.actualRenderer;
|
|
14525
|
-
const unregisterRoot = state.internal.unregisterRoot;
|
|
14526
|
-
if (unregisterRoot) unregisterRoot();
|
|
14527
14582
|
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
14528
14583
|
if (unregisterPrimary) unregisterPrimary();
|
|
14529
14584
|
const canvasTarget = state.internal.canvasTarget;
|
|
14530
|
-
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14585
|
+
if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
|
|
14531
14586
|
state.events.disconnect?.();
|
|
14532
14587
|
cleanupHelperGroup(root.store);
|
|
14533
14588
|
if (state.isLegacy && renderer) {
|
|
@@ -14971,9 +15026,9 @@ function CanvasImpl({
|
|
|
14971
15026
|
React.useMemo(() => extend(THREE), []);
|
|
14972
15027
|
const Bridge = useBridge();
|
|
14973
15028
|
const backgroundProps = React.useMemo(() => parseBackground(background), [background]);
|
|
14974
|
-
const
|
|
15029
|
+
const [hasInitialSize, setHasInitialSize] = React.useState(false);
|
|
14975
15030
|
const measureConfig = React.useMemo(() => {
|
|
14976
|
-
if (!
|
|
15031
|
+
if (!hasInitialSize) {
|
|
14977
15032
|
return {
|
|
14978
15033
|
...resize,
|
|
14979
15034
|
scroll: resize?.scroll ?? true,
|
|
@@ -14985,7 +15040,7 @@ function CanvasImpl({
|
|
|
14985
15040
|
debounce: { scroll: 50, resize: 0 },
|
|
14986
15041
|
...resize
|
|
14987
15042
|
};
|
|
14988
|
-
}, [
|
|
15043
|
+
}, [hasInitialSize, resize]);
|
|
14989
15044
|
const [containerRef, containerRect] = useMeasure(measureConfig);
|
|
14990
15045
|
const effectiveSize = React.useMemo(() => {
|
|
14991
15046
|
let w = width ?? containerRect.width;
|
|
@@ -15001,9 +15056,7 @@ function CanvasImpl({
|
|
|
15001
15056
|
left: containerRect.left
|
|
15002
15057
|
};
|
|
15003
15058
|
}, [width, height, containerRect, forceEven]);
|
|
15004
|
-
if (!
|
|
15005
|
-
hasInitialSizeRef.current = true;
|
|
15006
|
-
}
|
|
15059
|
+
if (!hasInitialSize && effectiveSize.width > 0 && effectiveSize.height > 0) setHasInitialSize(true);
|
|
15007
15060
|
const canvasRef = React.useRef(null);
|
|
15008
15061
|
const divRef = React.useRef(null);
|
|
15009
15062
|
React.useImperativeHandle(ref, () => canvasRef.current);
|
|
@@ -15117,6 +15170,7 @@ function CanvasImpl({
|
|
|
15117
15170
|
const canvas = canvasRef.current;
|
|
15118
15171
|
if (canvas) {
|
|
15119
15172
|
return () => {
|
|
15173
|
+
if (canvas.isConnected) return;
|
|
15120
15174
|
unmountComponentAtNode(canvas);
|
|
15121
15175
|
root.current = null;
|
|
15122
15176
|
};
|