@react-three/fiber 8.0.25 → 8.1.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @react-three/fiber
2
2
 
3
+ ## 8.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 8d0f708c: Expose position information in state.size
8
+
9
+ ## 8.0.27
10
+
11
+ ### Patch Changes
12
+
13
+ - 7940995: fix: resume on xrsession end, export internal events
14
+
15
+ ## 8.0.26
16
+
17
+ ### Patch Changes
18
+
19
+ - 7b6df9df: fix: infinite loop updating cam viewport
20
+
3
21
  ## 8.0.25
4
22
 
5
23
  ### Patch Changes
@@ -49,10 +49,7 @@ export declare type InjectState = Partial<Omit<RootState, PrivateKeys> & {
49
49
  compute?: ComputeFunction;
50
50
  connected?: any;
51
51
  };
52
- size?: {
53
- width: number;
54
- height: number;
55
- };
52
+ size?: Size;
56
53
  }>;
57
54
  declare function createPortal(children: React.ReactNode, container: THREE.Object3D, state?: InjectState): React.ReactNode;
58
55
  declare const act: any;
@@ -17,6 +17,8 @@ export declare type Dpr = number | [min: number, max: number];
17
17
  export declare type Size = {
18
18
  width: number;
19
19
  height: number;
20
+ top: number;
21
+ left: number;
20
22
  updateStyle?: boolean;
21
23
  };
22
24
  export declare type Viewport = Size & {
@@ -81,7 +83,7 @@ export declare type RootState = {
81
83
  invalidate: (frames?: number) => void;
82
84
  advance: (timestamp: number, runGlobalEffects?: boolean) => void;
83
85
  setEvents: (events: Partial<EventManager<any>>) => void;
84
- setSize: (width: number, height: number, updateStyle?: boolean) => void;
86
+ setSize: (width: number, height: number, updateStyle?: boolean, top?: number, left?: number) => void;
85
87
  setDpr: (dpr: Dpr) => void;
86
88
  setFrameloop: (frameloop?: 'always' | 'demand' | 'never') => void;
87
89
  onPointerMissed?: (event: MouseEvent) => void;
@@ -6,5 +6,6 @@ export type { Intersection, Subscription, Dpr, Size, Viewport, RenderCallback, P
6
6
  export type { ThreeEvent, Events, EventManager, ComputeFunction } from './core/events';
7
7
  export type { ObjectMap, Camera } from './core/utils';
8
8
  export * from './web/Canvas';
9
+ export { createEvents } from './core/events';
9
10
  export { createPointerEvents as events } from './web/events';
10
11
  export * from './core';
@@ -1184,7 +1184,9 @@ const createStore = (invalidate, advance) => {
1184
1184
  function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
1185
1185
  const {
1186
1186
  width,
1187
- height
1187
+ height,
1188
+ top,
1189
+ left
1188
1190
  } = size;
1189
1191
  const aspect = width / height;
1190
1192
  if (target instanceof THREE.Vector3) tempTarget.copy(target);else tempTarget.set(...target);
@@ -1194,6 +1196,8 @@ const createStore = (invalidate, advance) => {
1194
1196
  return {
1195
1197
  width: width / camera.zoom,
1196
1198
  height: height / camera.zoom,
1199
+ top,
1200
+ left,
1197
1201
  factor: 1,
1198
1202
  distance,
1199
1203
  aspect
@@ -1207,6 +1211,8 @@ const createStore = (invalidate, advance) => {
1207
1211
  return {
1208
1212
  width: w,
1209
1213
  height: h,
1214
+ top,
1215
+ left,
1210
1216
  factor: width / w,
1211
1217
  distance,
1212
1218
  aspect
@@ -1223,7 +1229,7 @@ const createStore = (invalidate, advance) => {
1223
1229
  }));
1224
1230
 
1225
1231
  const pointer = new THREE.Vector2();
1226
- return {
1232
+ const rootState = {
1227
1233
  set,
1228
1234
  get,
1229
1235
  // Mock objects that have to be configured
@@ -1266,6 +1272,8 @@ const createStore = (invalidate, advance) => {
1266
1272
  size: {
1267
1273
  width: 0,
1268
1274
  height: 0,
1275
+ top: 0,
1276
+ left: 0,
1269
1277
  updateStyle: false
1270
1278
  },
1271
1279
  viewport: {
@@ -1273,6 +1281,8 @@ const createStore = (invalidate, advance) => {
1273
1281
  dpr: 0,
1274
1282
  width: 0,
1275
1283
  height: 0,
1284
+ top: 0,
1285
+ left: 0,
1276
1286
  aspect: 0,
1277
1287
  distance: 0,
1278
1288
  factor: 0,
@@ -1283,11 +1293,13 @@ const createStore = (invalidate, advance) => {
1283
1293
  ...events
1284
1294
  }
1285
1295
  })),
1286
- setSize: (width, height, updateStyle) => {
1296
+ setSize: (width, height, updateStyle, top, left) => {
1287
1297
  const camera = get().camera;
1288
1298
  const size = {
1289
1299
  width,
1290
1300
  height,
1301
+ top: top || 0,
1302
+ left: left || 0,
1291
1303
  updateStyle
1292
1304
  };
1293
1305
  set(state => ({
@@ -1361,43 +1373,39 @@ const createStore = (invalidate, advance) => {
1361
1373
  }
1362
1374
  }
1363
1375
  };
1376
+ return rootState;
1364
1377
  });
1365
- const state = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
1366
-
1378
+ const state = rootState.getState();
1367
1379
  let oldSize = state.size;
1368
1380
  let oldDpr = state.viewport.dpr;
1381
+ let oldCamera = state.camera;
1369
1382
  rootState.subscribe(() => {
1370
1383
  const {
1371
1384
  camera,
1372
1385
  size,
1373
1386
  viewport,
1374
- gl
1375
- } = rootState.getState();
1387
+ gl,
1388
+ set
1389
+ } = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
1376
1390
 
1377
1391
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1378
- updateCamera(camera, size); // Update renderer
1392
+ oldSize = size;
1393
+ oldDpr = viewport.dpr; // Update camera & renderer
1379
1394
 
1395
+ updateCamera(camera, size);
1380
1396
  gl.setPixelRatio(viewport.dpr);
1381
1397
  gl.setSize(size.width, size.height, size.updateStyle);
1382
- oldSize = size;
1383
- oldDpr = viewport.dpr;
1384
- }
1385
- }); // Update viewport once the camera changes
1398
+ } // Update viewport once the camera changes
1386
1399
 
1387
- let oldCamera = state.camera;
1388
- rootState.subscribe(() => {
1389
- const {
1390
- camera,
1391
- set
1392
- } = rootState.getState();
1393
1400
 
1394
1401
  if (camera !== oldCamera) {
1402
+ oldCamera = camera; // Update viewport
1403
+
1395
1404
  set(state => ({
1396
1405
  viewport: { ...state.viewport,
1397
1406
  ...state.viewport.getCurrentViewport(camera)
1398
1407
  }
1399
1408
  }));
1400
- oldCamera = camera;
1401
1409
  }
1402
1410
  }); // Invalidate on any change
1403
1411
 
@@ -1407,15 +1415,17 @@ const createStore = (invalidate, advance) => {
1407
1415
  };
1408
1416
 
1409
1417
  function createSubs(callback, subs) {
1410
- const index = subs.length;
1411
- subs.push(callback);
1412
- return () => void subs.splice(index, 1);
1418
+ const sub = {
1419
+ callback
1420
+ };
1421
+ subs.add(sub);
1422
+ return () => void subs.delete(sub);
1413
1423
  }
1414
1424
 
1415
1425
  let i;
1416
- let globalEffects = [];
1417
- let globalAfterEffects = [];
1418
- let globalTailEffects = [];
1426
+ let globalEffects = new Set();
1427
+ let globalAfterEffects = new Set();
1428
+ let globalTailEffects = new Set();
1419
1429
  /**
1420
1430
  * Adds a global render callback which is called each frame.
1421
1431
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
@@ -1436,7 +1446,9 @@ const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
1436
1446
  const addTail = callback => createSubs(callback, globalTailEffects);
1437
1447
 
1438
1448
  function run(effects, timestamp) {
1439
- for (i = 0; i < effects.length; i++) effects[i](timestamp);
1449
+ effects.forEach(({
1450
+ callback
1451
+ }) => callback(timestamp));
1440
1452
  }
1441
1453
 
1442
1454
  let subscribers;
@@ -1478,7 +1490,7 @@ function createLoop(roots) {
1478
1490
  running = true;
1479
1491
  repeat = 0; // Run effects
1480
1492
 
1481
- if (globalEffects.length) run(globalEffects, timestamp); // Render all roots
1493
+ if (globalEffects.size) run(globalEffects, timestamp); // Render all roots
1482
1494
 
1483
1495
  roots.forEach(root => {
1484
1496
  var _state$gl$xr;
@@ -1490,11 +1502,11 @@ function createLoop(roots) {
1490
1502
  }
1491
1503
  }); // Run after-effects
1492
1504
 
1493
- if (globalAfterEffects.length) run(globalAfterEffects, timestamp); // Stop the loop if nothing invalidates it
1505
+ if (globalAfterEffects.size) run(globalAfterEffects, timestamp); // Stop the loop if nothing invalidates it
1494
1506
 
1495
1507
  if (repeat === 0) {
1496
1508
  // Tail call effects, they are called when rendering stops
1497
- if (globalTailEffects.length) run(globalTailEffects, timestamp); // Flag end of operation
1509
+ if (globalTailEffects.size) run(globalTailEffects, timestamp); // Flag end of operation
1498
1510
 
1499
1511
  running = false;
1500
1512
  return cancelAnimationFrame(frame);
@@ -1673,8 +1685,6 @@ function createRoot(canvas) {
1673
1685
  let configured = false;
1674
1686
  return {
1675
1687
  configure(props = {}) {
1676
- var _canvas$parentElement, _canvas$parentElement2, _canvas$parentElement3, _canvas$parentElement4;
1677
-
1678
1688
  let {
1679
1689
  gl: glConfig,
1680
1690
  size,
@@ -1743,12 +1753,10 @@ function createRoot(canvas) {
1743
1753
 
1744
1754
 
1745
1755
  const handleSessionChange = () => {
1746
- const gl = store.getState().gl;
1747
- gl.xr.enabled = gl.xr.isPresenting; // @ts-ignore
1748
- // WebXRManager's signature is incorrect.
1749
- // See: https://github.com/pmndrs/react-three-fiber/pull/2017#discussion_r790134505
1750
-
1751
- gl.xr.setAnimationLoop(gl.xr.isPresenting ? handleXRFrame : null);
1756
+ const state = store.getState();
1757
+ state.gl.xr.enabled = state.gl.xr.isPresenting;
1758
+ state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
1759
+ if (!state.gl.xr.isPresenting) invalidate(state);
1752
1760
  }; // WebXR session manager
1753
1761
 
1754
1762
 
@@ -1814,11 +1822,22 @@ function createRoot(canvas) {
1814
1822
 
1815
1823
  if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr); // Check size, allow it to take on container bounds initially
1816
1824
 
1817
- size = size || {
1818
- width: (_canvas$parentElement = (_canvas$parentElement2 = canvas.parentElement) == null ? void 0 : _canvas$parentElement2.clientWidth) != null ? _canvas$parentElement : 0,
1819
- height: (_canvas$parentElement3 = (_canvas$parentElement4 = canvas.parentElement) == null ? void 0 : _canvas$parentElement4.clientHeight) != null ? _canvas$parentElement3 : 0
1820
- };
1821
- if (!is.equ(size, state.size, shallowLoose)) state.setSize(size.width, size.height, size.updateStyle); // Check frameloop
1825
+ size = size || (canvas.parentElement ? {
1826
+ width: canvas.parentElement.clientWidth,
1827
+ height: canvas.parentElement.clientHeight,
1828
+ top: canvas.parentElement.clientTop,
1829
+ left: canvas.parentElement.clientLeft
1830
+ } : {
1831
+ width: 0,
1832
+ height: 0,
1833
+ top: 0,
1834
+ left: 0
1835
+ });
1836
+
1837
+ if (!is.equ(size, state.size, shallowLoose)) {
1838
+ state.setSize(size.width, size.height, size.updateStyle, size.top, size.left);
1839
+ } // Check frameloop
1840
+
1822
1841
 
1823
1842
  if (state.frameloop !== frameloop) state.setFrameloop(frameloop); // Check pointer missed
1824
1843
 
@@ -1211,7 +1211,9 @@ const createStore = (invalidate, advance) => {
1211
1211
  function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
1212
1212
  const {
1213
1213
  width,
1214
- height
1214
+ height,
1215
+ top,
1216
+ left
1215
1217
  } = size;
1216
1218
  const aspect = width / height;
1217
1219
  if (target instanceof THREE__namespace.Vector3) tempTarget.copy(target);else tempTarget.set(...target);
@@ -1221,6 +1223,8 @@ const createStore = (invalidate, advance) => {
1221
1223
  return {
1222
1224
  width: width / camera.zoom,
1223
1225
  height: height / camera.zoom,
1226
+ top,
1227
+ left,
1224
1228
  factor: 1,
1225
1229
  distance,
1226
1230
  aspect
@@ -1234,6 +1238,8 @@ const createStore = (invalidate, advance) => {
1234
1238
  return {
1235
1239
  width: w,
1236
1240
  height: h,
1241
+ top,
1242
+ left,
1237
1243
  factor: width / w,
1238
1244
  distance,
1239
1245
  aspect
@@ -1250,7 +1256,7 @@ const createStore = (invalidate, advance) => {
1250
1256
  }));
1251
1257
 
1252
1258
  const pointer = new THREE__namespace.Vector2();
1253
- return {
1259
+ const rootState = {
1254
1260
  set,
1255
1261
  get,
1256
1262
  // Mock objects that have to be configured
@@ -1293,6 +1299,8 @@ const createStore = (invalidate, advance) => {
1293
1299
  size: {
1294
1300
  width: 0,
1295
1301
  height: 0,
1302
+ top: 0,
1303
+ left: 0,
1296
1304
  updateStyle: false
1297
1305
  },
1298
1306
  viewport: {
@@ -1300,6 +1308,8 @@ const createStore = (invalidate, advance) => {
1300
1308
  dpr: 0,
1301
1309
  width: 0,
1302
1310
  height: 0,
1311
+ top: 0,
1312
+ left: 0,
1303
1313
  aspect: 0,
1304
1314
  distance: 0,
1305
1315
  factor: 0,
@@ -1310,11 +1320,13 @@ const createStore = (invalidate, advance) => {
1310
1320
  ...events
1311
1321
  }
1312
1322
  })),
1313
- setSize: (width, height, updateStyle) => {
1323
+ setSize: (width, height, updateStyle, top, left) => {
1314
1324
  const camera = get().camera;
1315
1325
  const size = {
1316
1326
  width,
1317
1327
  height,
1328
+ top: top || 0,
1329
+ left: left || 0,
1318
1330
  updateStyle
1319
1331
  };
1320
1332
  set(state => ({
@@ -1388,43 +1400,39 @@ const createStore = (invalidate, advance) => {
1388
1400
  }
1389
1401
  }
1390
1402
  };
1403
+ return rootState;
1391
1404
  });
1392
- const state = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
1393
-
1405
+ const state = rootState.getState();
1394
1406
  let oldSize = state.size;
1395
1407
  let oldDpr = state.viewport.dpr;
1408
+ let oldCamera = state.camera;
1396
1409
  rootState.subscribe(() => {
1397
1410
  const {
1398
1411
  camera,
1399
1412
  size,
1400
1413
  viewport,
1401
- gl
1402
- } = rootState.getState();
1414
+ gl,
1415
+ set
1416
+ } = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
1403
1417
 
1404
1418
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1405
- updateCamera(camera, size); // Update renderer
1419
+ oldSize = size;
1420
+ oldDpr = viewport.dpr; // Update camera & renderer
1406
1421
 
1422
+ updateCamera(camera, size);
1407
1423
  gl.setPixelRatio(viewport.dpr);
1408
1424
  gl.setSize(size.width, size.height, size.updateStyle);
1409
- oldSize = size;
1410
- oldDpr = viewport.dpr;
1411
- }
1412
- }); // Update viewport once the camera changes
1425
+ } // Update viewport once the camera changes
1413
1426
 
1414
- let oldCamera = state.camera;
1415
- rootState.subscribe(() => {
1416
- const {
1417
- camera,
1418
- set
1419
- } = rootState.getState();
1420
1427
 
1421
1428
  if (camera !== oldCamera) {
1429
+ oldCamera = camera; // Update viewport
1430
+
1422
1431
  set(state => ({
1423
1432
  viewport: { ...state.viewport,
1424
1433
  ...state.viewport.getCurrentViewport(camera)
1425
1434
  }
1426
1435
  }));
1427
- oldCamera = camera;
1428
1436
  }
1429
1437
  }); // Invalidate on any change
1430
1438
 
@@ -1434,15 +1442,17 @@ const createStore = (invalidate, advance) => {
1434
1442
  };
1435
1443
 
1436
1444
  function createSubs(callback, subs) {
1437
- const index = subs.length;
1438
- subs.push(callback);
1439
- return () => void subs.splice(index, 1);
1445
+ const sub = {
1446
+ callback
1447
+ };
1448
+ subs.add(sub);
1449
+ return () => void subs.delete(sub);
1440
1450
  }
1441
1451
 
1442
1452
  let i;
1443
- let globalEffects = [];
1444
- let globalAfterEffects = [];
1445
- let globalTailEffects = [];
1453
+ let globalEffects = new Set();
1454
+ let globalAfterEffects = new Set();
1455
+ let globalTailEffects = new Set();
1446
1456
  /**
1447
1457
  * Adds a global render callback which is called each frame.
1448
1458
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
@@ -1463,7 +1473,9 @@ const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
1463
1473
  const addTail = callback => createSubs(callback, globalTailEffects);
1464
1474
 
1465
1475
  function run(effects, timestamp) {
1466
- for (i = 0; i < effects.length; i++) effects[i](timestamp);
1476
+ effects.forEach(({
1477
+ callback
1478
+ }) => callback(timestamp));
1467
1479
  }
1468
1480
 
1469
1481
  let subscribers;
@@ -1505,7 +1517,7 @@ function createLoop(roots) {
1505
1517
  running = true;
1506
1518
  repeat = 0; // Run effects
1507
1519
 
1508
- if (globalEffects.length) run(globalEffects, timestamp); // Render all roots
1520
+ if (globalEffects.size) run(globalEffects, timestamp); // Render all roots
1509
1521
 
1510
1522
  roots.forEach(root => {
1511
1523
  var _state$gl$xr;
@@ -1517,11 +1529,11 @@ function createLoop(roots) {
1517
1529
  }
1518
1530
  }); // Run after-effects
1519
1531
 
1520
- if (globalAfterEffects.length) run(globalAfterEffects, timestamp); // Stop the loop if nothing invalidates it
1532
+ if (globalAfterEffects.size) run(globalAfterEffects, timestamp); // Stop the loop if nothing invalidates it
1521
1533
 
1522
1534
  if (repeat === 0) {
1523
1535
  // Tail call effects, they are called when rendering stops
1524
- if (globalTailEffects.length) run(globalTailEffects, timestamp); // Flag end of operation
1536
+ if (globalTailEffects.size) run(globalTailEffects, timestamp); // Flag end of operation
1525
1537
 
1526
1538
  running = false;
1527
1539
  return cancelAnimationFrame(frame);
@@ -1700,8 +1712,6 @@ function createRoot(canvas) {
1700
1712
  let configured = false;
1701
1713
  return {
1702
1714
  configure(props = {}) {
1703
- var _canvas$parentElement, _canvas$parentElement2, _canvas$parentElement3, _canvas$parentElement4;
1704
-
1705
1715
  let {
1706
1716
  gl: glConfig,
1707
1717
  size,
@@ -1770,12 +1780,10 @@ function createRoot(canvas) {
1770
1780
 
1771
1781
 
1772
1782
  const handleSessionChange = () => {
1773
- const gl = store.getState().gl;
1774
- gl.xr.enabled = gl.xr.isPresenting; // @ts-ignore
1775
- // WebXRManager's signature is incorrect.
1776
- // See: https://github.com/pmndrs/react-three-fiber/pull/2017#discussion_r790134505
1777
-
1778
- gl.xr.setAnimationLoop(gl.xr.isPresenting ? handleXRFrame : null);
1783
+ const state = store.getState();
1784
+ state.gl.xr.enabled = state.gl.xr.isPresenting;
1785
+ state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
1786
+ if (!state.gl.xr.isPresenting) invalidate(state);
1779
1787
  }; // WebXR session manager
1780
1788
 
1781
1789
 
@@ -1841,11 +1849,22 @@ function createRoot(canvas) {
1841
1849
 
1842
1850
  if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr); // Check size, allow it to take on container bounds initially
1843
1851
 
1844
- size = size || {
1845
- width: (_canvas$parentElement = (_canvas$parentElement2 = canvas.parentElement) == null ? void 0 : _canvas$parentElement2.clientWidth) != null ? _canvas$parentElement : 0,
1846
- height: (_canvas$parentElement3 = (_canvas$parentElement4 = canvas.parentElement) == null ? void 0 : _canvas$parentElement4.clientHeight) != null ? _canvas$parentElement3 : 0
1847
- };
1848
- if (!is.equ(size, state.size, shallowLoose)) state.setSize(size.width, size.height, size.updateStyle); // Check frameloop
1852
+ size = size || (canvas.parentElement ? {
1853
+ width: canvas.parentElement.clientWidth,
1854
+ height: canvas.parentElement.clientHeight,
1855
+ top: canvas.parentElement.clientTop,
1856
+ left: canvas.parentElement.clientLeft
1857
+ } : {
1858
+ width: 0,
1859
+ height: 0,
1860
+ top: 0,
1861
+ left: 0
1862
+ });
1863
+
1864
+ if (!is.equ(size, state.size, shallowLoose)) {
1865
+ state.setSize(size.width, size.height, size.updateStyle, size.top, size.left);
1866
+ } // Check frameloop
1867
+
1849
1868
 
1850
1869
  if (state.frameloop !== frameloop) state.setFrameloop(frameloop); // Check pointer missed
1851
1870
 
@@ -1211,7 +1211,9 @@ const createStore = (invalidate, advance) => {
1211
1211
  function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
1212
1212
  const {
1213
1213
  width,
1214
- height
1214
+ height,
1215
+ top,
1216
+ left
1215
1217
  } = size;
1216
1218
  const aspect = width / height;
1217
1219
  if (target instanceof THREE__namespace.Vector3) tempTarget.copy(target);else tempTarget.set(...target);
@@ -1221,6 +1223,8 @@ const createStore = (invalidate, advance) => {
1221
1223
  return {
1222
1224
  width: width / camera.zoom,
1223
1225
  height: height / camera.zoom,
1226
+ top,
1227
+ left,
1224
1228
  factor: 1,
1225
1229
  distance,
1226
1230
  aspect
@@ -1234,6 +1238,8 @@ const createStore = (invalidate, advance) => {
1234
1238
  return {
1235
1239
  width: w,
1236
1240
  height: h,
1241
+ top,
1242
+ left,
1237
1243
  factor: width / w,
1238
1244
  distance,
1239
1245
  aspect
@@ -1250,7 +1256,7 @@ const createStore = (invalidate, advance) => {
1250
1256
  }));
1251
1257
 
1252
1258
  const pointer = new THREE__namespace.Vector2();
1253
- return {
1259
+ const rootState = {
1254
1260
  set,
1255
1261
  get,
1256
1262
  // Mock objects that have to be configured
@@ -1293,6 +1299,8 @@ const createStore = (invalidate, advance) => {
1293
1299
  size: {
1294
1300
  width: 0,
1295
1301
  height: 0,
1302
+ top: 0,
1303
+ left: 0,
1296
1304
  updateStyle: false
1297
1305
  },
1298
1306
  viewport: {
@@ -1300,6 +1308,8 @@ const createStore = (invalidate, advance) => {
1300
1308
  dpr: 0,
1301
1309
  width: 0,
1302
1310
  height: 0,
1311
+ top: 0,
1312
+ left: 0,
1303
1313
  aspect: 0,
1304
1314
  distance: 0,
1305
1315
  factor: 0,
@@ -1310,11 +1320,13 @@ const createStore = (invalidate, advance) => {
1310
1320
  ...events
1311
1321
  }
1312
1322
  })),
1313
- setSize: (width, height, updateStyle) => {
1323
+ setSize: (width, height, updateStyle, top, left) => {
1314
1324
  const camera = get().camera;
1315
1325
  const size = {
1316
1326
  width,
1317
1327
  height,
1328
+ top: top || 0,
1329
+ left: left || 0,
1318
1330
  updateStyle
1319
1331
  };
1320
1332
  set(state => ({
@@ -1388,43 +1400,39 @@ const createStore = (invalidate, advance) => {
1388
1400
  }
1389
1401
  }
1390
1402
  };
1403
+ return rootState;
1391
1404
  });
1392
- const state = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
1393
-
1405
+ const state = rootState.getState();
1394
1406
  let oldSize = state.size;
1395
1407
  let oldDpr = state.viewport.dpr;
1408
+ let oldCamera = state.camera;
1396
1409
  rootState.subscribe(() => {
1397
1410
  const {
1398
1411
  camera,
1399
1412
  size,
1400
1413
  viewport,
1401
- gl
1402
- } = rootState.getState();
1414
+ gl,
1415
+ set
1416
+ } = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
1403
1417
 
1404
1418
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1405
- updateCamera(camera, size); // Update renderer
1419
+ oldSize = size;
1420
+ oldDpr = viewport.dpr; // Update camera & renderer
1406
1421
 
1422
+ updateCamera(camera, size);
1407
1423
  gl.setPixelRatio(viewport.dpr);
1408
1424
  gl.setSize(size.width, size.height, size.updateStyle);
1409
- oldSize = size;
1410
- oldDpr = viewport.dpr;
1411
- }
1412
- }); // Update viewport once the camera changes
1425
+ } // Update viewport once the camera changes
1413
1426
 
1414
- let oldCamera = state.camera;
1415
- rootState.subscribe(() => {
1416
- const {
1417
- camera,
1418
- set
1419
- } = rootState.getState();
1420
1427
 
1421
1428
  if (camera !== oldCamera) {
1429
+ oldCamera = camera; // Update viewport
1430
+
1422
1431
  set(state => ({
1423
1432
  viewport: { ...state.viewport,
1424
1433
  ...state.viewport.getCurrentViewport(camera)
1425
1434
  }
1426
1435
  }));
1427
- oldCamera = camera;
1428
1436
  }
1429
1437
  }); // Invalidate on any change
1430
1438
 
@@ -1434,15 +1442,17 @@ const createStore = (invalidate, advance) => {
1434
1442
  };
1435
1443
 
1436
1444
  function createSubs(callback, subs) {
1437
- const index = subs.length;
1438
- subs.push(callback);
1439
- return () => void subs.splice(index, 1);
1445
+ const sub = {
1446
+ callback
1447
+ };
1448
+ subs.add(sub);
1449
+ return () => void subs.delete(sub);
1440
1450
  }
1441
1451
 
1442
1452
  let i;
1443
- let globalEffects = [];
1444
- let globalAfterEffects = [];
1445
- let globalTailEffects = [];
1453
+ let globalEffects = new Set();
1454
+ let globalAfterEffects = new Set();
1455
+ let globalTailEffects = new Set();
1446
1456
  /**
1447
1457
  * Adds a global render callback which is called each frame.
1448
1458
  * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
@@ -1463,7 +1473,9 @@ const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
1463
1473
  const addTail = callback => createSubs(callback, globalTailEffects);
1464
1474
 
1465
1475
  function run(effects, timestamp) {
1466
- for (i = 0; i < effects.length; i++) effects[i](timestamp);
1476
+ effects.forEach(({
1477
+ callback
1478
+ }) => callback(timestamp));
1467
1479
  }
1468
1480
 
1469
1481
  let subscribers;
@@ -1505,7 +1517,7 @@ function createLoop(roots) {
1505
1517
  running = true;
1506
1518
  repeat = 0; // Run effects
1507
1519
 
1508
- if (globalEffects.length) run(globalEffects, timestamp); // Render all roots
1520
+ if (globalEffects.size) run(globalEffects, timestamp); // Render all roots
1509
1521
 
1510
1522
  roots.forEach(root => {
1511
1523
  var _state$gl$xr;
@@ -1517,11 +1529,11 @@ function createLoop(roots) {
1517
1529
  }
1518
1530
  }); // Run after-effects
1519
1531
 
1520
- if (globalAfterEffects.length) run(globalAfterEffects, timestamp); // Stop the loop if nothing invalidates it
1532
+ if (globalAfterEffects.size) run(globalAfterEffects, timestamp); // Stop the loop if nothing invalidates it
1521
1533
 
1522
1534
  if (repeat === 0) {
1523
1535
  // Tail call effects, they are called when rendering stops
1524
- if (globalTailEffects.length) run(globalTailEffects, timestamp); // Flag end of operation
1536
+ if (globalTailEffects.size) run(globalTailEffects, timestamp); // Flag end of operation
1525
1537
 
1526
1538
  running = false;
1527
1539
  return cancelAnimationFrame(frame);
@@ -1700,8 +1712,6 @@ function createRoot(canvas) {
1700
1712
  let configured = false;
1701
1713
  return {
1702
1714
  configure(props = {}) {
1703
- var _canvas$parentElement, _canvas$parentElement2, _canvas$parentElement3, _canvas$parentElement4;
1704
-
1705
1715
  let {
1706
1716
  gl: glConfig,
1707
1717
  size,
@@ -1770,12 +1780,10 @@ function createRoot(canvas) {
1770
1780
 
1771
1781
 
1772
1782
  const handleSessionChange = () => {
1773
- const gl = store.getState().gl;
1774
- gl.xr.enabled = gl.xr.isPresenting; // @ts-ignore
1775
- // WebXRManager's signature is incorrect.
1776
- // See: https://github.com/pmndrs/react-three-fiber/pull/2017#discussion_r790134505
1777
-
1778
- gl.xr.setAnimationLoop(gl.xr.isPresenting ? handleXRFrame : null);
1783
+ const state = store.getState();
1784
+ state.gl.xr.enabled = state.gl.xr.isPresenting;
1785
+ state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
1786
+ if (!state.gl.xr.isPresenting) invalidate(state);
1779
1787
  }; // WebXR session manager
1780
1788
 
1781
1789
 
@@ -1841,11 +1849,22 @@ function createRoot(canvas) {
1841
1849
 
1842
1850
  if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr); // Check size, allow it to take on container bounds initially
1843
1851
 
1844
- size = size || {
1845
- width: (_canvas$parentElement = (_canvas$parentElement2 = canvas.parentElement) == null ? void 0 : _canvas$parentElement2.clientWidth) != null ? _canvas$parentElement : 0,
1846
- height: (_canvas$parentElement3 = (_canvas$parentElement4 = canvas.parentElement) == null ? void 0 : _canvas$parentElement4.clientHeight) != null ? _canvas$parentElement3 : 0
1847
- };
1848
- if (!is.equ(size, state.size, shallowLoose)) state.setSize(size.width, size.height, size.updateStyle); // Check frameloop
1852
+ size = size || (canvas.parentElement ? {
1853
+ width: canvas.parentElement.clientWidth,
1854
+ height: canvas.parentElement.clientHeight,
1855
+ top: canvas.parentElement.clientTop,
1856
+ left: canvas.parentElement.clientLeft
1857
+ } : {
1858
+ width: 0,
1859
+ height: 0,
1860
+ top: 0,
1861
+ left: 0
1862
+ });
1863
+
1864
+ if (!is.equ(size, state.size, shallowLoose)) {
1865
+ state.setSize(size.width, size.height, size.updateStyle, size.top, size.left);
1866
+ } // Check frameloop
1867
+
1849
1868
 
1850
1869
  if (state.frameloop !== frameloop) state.setFrameloop(frameloop); // Check pointer missed
1851
1870
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('./index-63f47889.cjs.dev.js');
5
+ var index = require('./index-c13c7c31.cjs.dev.js');
6
6
  var _extends = require('@babel/runtime/helpers/extends');
7
7
  var React = require('react');
8
8
  var THREE = require('three');
@@ -144,10 +144,7 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
144
144
  // This will include the entire THREE namespace by default, users can extend
145
145
  // their own elements by using the createRoot API instead
146
146
  React__namespace.useMemo(() => index.extend(THREE__namespace), []);
147
- const [containerRef, {
148
- width,
149
- height
150
- }] = useMeasure__default["default"]({
147
+ const [containerRef, containerRect] = useMeasure__default["default"]({
151
148
  scroll: true,
152
149
  debounce: {
153
150
  scroll: 50,
@@ -168,7 +165,7 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
168
165
  if (error) throw error;
169
166
  const root = React__namespace.useRef(null);
170
167
 
171
- if (width > 0 && height > 0 && canvas) {
168
+ if (containerRect.width > 0 && containerRect.height > 0 && canvas) {
172
169
  if (!root.current) root.current = index.createRoot(canvas);
173
170
  root.current.configure({
174
171
  gl,
@@ -183,10 +180,7 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
183
180
  performance,
184
181
  raycaster,
185
182
  camera,
186
- size: {
187
- width,
188
- height
189
- },
183
+ size: containerRect,
190
184
  // Pass mutable reference to onPointerMissed so it's free to update
191
185
  onPointerMissed: (...args) => handlePointerMissed.current == null ? void 0 : handlePointerMissed.current(...args),
192
186
  onCreated: state => {
@@ -241,6 +235,7 @@ exports.addTail = index.addTail;
241
235
  exports.advance = index.advance;
242
236
  exports.applyProps = index.applyProps;
243
237
  exports.context = index.context;
238
+ exports.createEvents = index.createEvents;
244
239
  exports.createPortal = index.createPortal;
245
240
  exports.createRoot = index.createRoot;
246
241
  exports.dispose = index.dispose;
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('./index-cd0062f1.cjs.prod.js');
5
+ var index = require('./index-ab905875.cjs.prod.js');
6
6
  var _extends = require('@babel/runtime/helpers/extends');
7
7
  var React = require('react');
8
8
  var THREE = require('three');
@@ -144,10 +144,7 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
144
144
  // This will include the entire THREE namespace by default, users can extend
145
145
  // their own elements by using the createRoot API instead
146
146
  React__namespace.useMemo(() => index.extend(THREE__namespace), []);
147
- const [containerRef, {
148
- width,
149
- height
150
- }] = useMeasure__default["default"]({
147
+ const [containerRef, containerRect] = useMeasure__default["default"]({
151
148
  scroll: true,
152
149
  debounce: {
153
150
  scroll: 50,
@@ -168,7 +165,7 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
168
165
  if (error) throw error;
169
166
  const root = React__namespace.useRef(null);
170
167
 
171
- if (width > 0 && height > 0 && canvas) {
168
+ if (containerRect.width > 0 && containerRect.height > 0 && canvas) {
172
169
  if (!root.current) root.current = index.createRoot(canvas);
173
170
  root.current.configure({
174
171
  gl,
@@ -183,10 +180,7 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
183
180
  performance,
184
181
  raycaster,
185
182
  camera,
186
- size: {
187
- width,
188
- height
189
- },
183
+ size: containerRect,
190
184
  // Pass mutable reference to onPointerMissed so it's free to update
191
185
  onPointerMissed: (...args) => handlePointerMissed.current == null ? void 0 : handlePointerMissed.current(...args),
192
186
  onCreated: state => {
@@ -241,6 +235,7 @@ exports.addTail = index.addTail;
241
235
  exports.advance = index.advance;
242
236
  exports.applyProps = index.applyProps;
243
237
  exports.context = index.context;
238
+ exports.createEvents = index.createEvents;
244
239
  exports.createPortal = index.createPortal;
245
240
  exports.createRoot = index.createRoot;
246
241
  exports.dispose = index.dispose;
@@ -1,5 +1,5 @@
1
- import { c as createEvents, e as extend, u as useMutableCallback, a as createRoot, E as ErrorBoundary, B as Block, b as useIsomorphicLayoutEffect, d as unmountComponentAtNode } from './index-8d5cf4a3.esm.js';
2
- export { t as ReactThreeFiber, s as _roots, q as act, n as addAfterEffect, m as addEffect, o as addTail, l as advance, i as applyProps, f as context, g as createPortal, a as createRoot, j as dispose, e as extend, p as getRootState, k as invalidate, h as reconciler, r as render, d as unmountComponentAtNode, x as useFrame, y as useGraph, z as useLoader, v as useStore, w as useThree } from './index-8d5cf4a3.esm.js';
1
+ import { c as createEvents, e as extend, u as useMutableCallback, a as createRoot, E as ErrorBoundary, B as Block, b as useIsomorphicLayoutEffect, d as unmountComponentAtNode } from './index-9b4af973.esm.js';
2
+ export { t as ReactThreeFiber, s as _roots, q as act, n as addAfterEffect, m as addEffect, o as addTail, l as advance, i as applyProps, f as context, c as createEvents, g as createPortal, a as createRoot, j as dispose, e as extend, p as getRootState, k as invalidate, h as reconciler, r as render, d as unmountComponentAtNode, x as useFrame, y as useGraph, z as useLoader, v as useStore, w as useThree } from './index-9b4af973.esm.js';
3
3
  import _extends from '@babel/runtime/helpers/esm/extends';
4
4
  import * as React from 'react';
5
5
  import * as THREE from 'three';
@@ -117,10 +117,7 @@ const Canvas = /*#__PURE__*/React.forwardRef(function Canvas({
117
117
  // This will include the entire THREE namespace by default, users can extend
118
118
  // their own elements by using the createRoot API instead
119
119
  React.useMemo(() => extend(THREE), []);
120
- const [containerRef, {
121
- width,
122
- height
123
- }] = useMeasure({
120
+ const [containerRef, containerRect] = useMeasure({
124
121
  scroll: true,
125
122
  debounce: {
126
123
  scroll: 50,
@@ -141,7 +138,7 @@ const Canvas = /*#__PURE__*/React.forwardRef(function Canvas({
141
138
  if (error) throw error;
142
139
  const root = React.useRef(null);
143
140
 
144
- if (width > 0 && height > 0 && canvas) {
141
+ if (containerRect.width > 0 && containerRect.height > 0 && canvas) {
145
142
  if (!root.current) root.current = createRoot(canvas);
146
143
  root.current.configure({
147
144
  gl,
@@ -156,10 +153,7 @@ const Canvas = /*#__PURE__*/React.forwardRef(function Canvas({
156
153
  performance,
157
154
  raycaster,
158
155
  camera,
159
- size: {
160
- width,
161
- height
162
- },
156
+ size: containerRect,
163
157
  // Pass mutable reference to onPointerMissed so it's free to update
164
158
  onPointerMissed: (...args) => handlePointerMissed.current == null ? void 0 : handlePointerMissed.current(...args),
165
159
  onCreated: state => {
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('../../dist/index-63f47889.cjs.dev.js');
5
+ var index = require('../../dist/index-c13c7c31.cjs.dev.js');
6
6
  var _extends = require('@babel/runtime/helpers/extends');
7
7
  var React = require('react');
8
8
  var THREE = require('three');
@@ -258,10 +258,14 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(({
258
258
  React__namespace.useMemo(() => index.extend(THREE__namespace), []);
259
259
  const [{
260
260
  width,
261
- height
261
+ height,
262
+ top,
263
+ left
262
264
  }, setSize] = React__namespace.useState({
263
265
  width: 0,
264
- height: 0
266
+ height: 0,
267
+ top: 0,
268
+ left: 0
265
269
  });
266
270
  const [canvas, setCanvas] = React__namespace.useState(null);
267
271
  const [bind, setBind] = React__namespace.useState();
@@ -280,11 +284,15 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(({
280
284
  const onLayout = React__namespace.useCallback(e => {
281
285
  const {
282
286
  width,
283
- height
287
+ height,
288
+ x,
289
+ y
284
290
  } = e.nativeEvent.layout;
285
291
  setSize({
286
292
  width,
287
- height
293
+ height,
294
+ top: y,
295
+ left: x
288
296
  });
289
297
  }, []); // Called on context create or swap
290
298
  // https://github.com/pmndrs/react-three-fiber/pull/2297
@@ -321,7 +329,9 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(({
321
329
  dpr: reactNative.PixelRatio.get(),
322
330
  size: {
323
331
  width,
324
- height
332
+ height,
333
+ top,
334
+ left
325
335
  },
326
336
  // Pass mutable reference to onPointerMissed so it's free to update
327
337
  onPointerMissed: (...args) => handlePointerMissed.current == null ? void 0 : handlePointerMissed.current(...args),
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('../../dist/index-cd0062f1.cjs.prod.js');
5
+ var index = require('../../dist/index-ab905875.cjs.prod.js');
6
6
  var _extends = require('@babel/runtime/helpers/extends');
7
7
  var React = require('react');
8
8
  var THREE = require('three');
@@ -258,10 +258,14 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(({
258
258
  React__namespace.useMemo(() => index.extend(THREE__namespace), []);
259
259
  const [{
260
260
  width,
261
- height
261
+ height,
262
+ top,
263
+ left
262
264
  }, setSize] = React__namespace.useState({
263
265
  width: 0,
264
- height: 0
266
+ height: 0,
267
+ top: 0,
268
+ left: 0
265
269
  });
266
270
  const [canvas, setCanvas] = React__namespace.useState(null);
267
271
  const [bind, setBind] = React__namespace.useState();
@@ -280,11 +284,15 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(({
280
284
  const onLayout = React__namespace.useCallback(e => {
281
285
  const {
282
286
  width,
283
- height
287
+ height,
288
+ x,
289
+ y
284
290
  } = e.nativeEvent.layout;
285
291
  setSize({
286
292
  width,
287
- height
293
+ height,
294
+ top: y,
295
+ left: x
288
296
  });
289
297
  }, []); // Called on context create or swap
290
298
  // https://github.com/pmndrs/react-three-fiber/pull/2297
@@ -321,7 +329,9 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(({
321
329
  dpr: reactNative.PixelRatio.get(),
322
330
  size: {
323
331
  width,
324
- height
332
+ height,
333
+ top,
334
+ left
325
335
  },
326
336
  // Pass mutable reference to onPointerMissed so it's free to update
327
337
  onPointerMissed: (...args) => handlePointerMissed.current == null ? void 0 : handlePointerMissed.current(...args),
@@ -1,5 +1,5 @@
1
- import { c as createEvents, e as extend, u as useMutableCallback, a as createRoot, E as ErrorBoundary, B as Block, d as unmountComponentAtNode } from '../../dist/index-8d5cf4a3.esm.js';
2
- export { t as ReactThreeFiber, s as _roots, q as act, n as addAfterEffect, m as addEffect, o as addTail, l as advance, i as applyProps, f as context, g as createPortal, a as createRoot, j as dispose, e as extend, p as getRootState, k as invalidate, h as reconciler, r as render, d as unmountComponentAtNode, x as useFrame, y as useGraph, z as useLoader, v as useStore, w as useThree } from '../../dist/index-8d5cf4a3.esm.js';
1
+ import { c as createEvents, e as extend, u as useMutableCallback, a as createRoot, E as ErrorBoundary, B as Block, d as unmountComponentAtNode } from '../../dist/index-9b4af973.esm.js';
2
+ export { t as ReactThreeFiber, s as _roots, q as act, n as addAfterEffect, m as addEffect, o as addTail, l as advance, i as applyProps, f as context, g as createPortal, a as createRoot, j as dispose, e as extend, p as getRootState, k as invalidate, h as reconciler, r as render, d as unmountComponentAtNode, x as useFrame, y as useGraph, z as useLoader, v as useStore, w as useThree } from '../../dist/index-9b4af973.esm.js';
3
3
  import _extends from '@babel/runtime/helpers/esm/extends';
4
4
  import * as React from 'react';
5
5
  import * as THREE from 'three';
@@ -231,10 +231,14 @@ const Canvas = /*#__PURE__*/React.forwardRef(({
231
231
  React.useMemo(() => extend(THREE), []);
232
232
  const [{
233
233
  width,
234
- height
234
+ height,
235
+ top,
236
+ left
235
237
  }, setSize] = React.useState({
236
238
  width: 0,
237
- height: 0
239
+ height: 0,
240
+ top: 0,
241
+ left: 0
238
242
  });
239
243
  const [canvas, setCanvas] = React.useState(null);
240
244
  const [bind, setBind] = React.useState();
@@ -253,11 +257,15 @@ const Canvas = /*#__PURE__*/React.forwardRef(({
253
257
  const onLayout = React.useCallback(e => {
254
258
  const {
255
259
  width,
256
- height
260
+ height,
261
+ x,
262
+ y
257
263
  } = e.nativeEvent.layout;
258
264
  setSize({
259
265
  width,
260
- height
266
+ height,
267
+ top: y,
268
+ left: x
261
269
  });
262
270
  }, []); // Called on context create or swap
263
271
  // https://github.com/pmndrs/react-three-fiber/pull/2297
@@ -294,7 +302,9 @@ const Canvas = /*#__PURE__*/React.forwardRef(({
294
302
  dpr: PixelRatio.get(),
295
303
  size: {
296
304
  width,
297
- height
305
+ height,
306
+ top,
307
+ left
298
308
  },
299
309
  // Pass mutable reference to onPointerMissed so it's free to update
300
310
  onPointerMissed: (...args) => handlePointerMissed.current == null ? void 0 : handlePointerMissed.current(...args),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/fiber",
3
- "version": "8.0.25",
3
+ "version": "8.1.0",
4
4
  "description": "A React renderer for Threejs",
5
5
  "keywords": [
6
6
  "react",