@react-three/fiber 8.0.0-beta.0 → 8.0.0-beta.1

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.
@@ -70,29 +70,38 @@ const pick = (obj, keys) => filterKeys(obj, false, ...keys);
70
70
  * Clones an object and prunes or omits keys.
71
71
  */
72
72
 
73
- const omit = (obj, keys) => filterKeys(obj, true, ...keys); // A collection of compare functions
74
-
73
+ const omit = (obj, keys) => filterKeys(obj, true, ...keys);
74
+ // A collection of compare functions
75
75
  const is = {
76
76
  obj: a => a === Object(a) && !is.arr(a) && typeof a !== 'function',
77
77
  fun: a => typeof a === 'function',
78
78
  str: a => typeof a === 'string',
79
79
  num: a => typeof a === 'number',
80
+ boo: a => typeof a === 'boolean',
80
81
  und: a => a === void 0,
81
82
  arr: a => Array.isArray(a),
82
83
 
83
- equ(a, b) {
84
+ equ(a, b, {
85
+ arrays = 'shallow',
86
+ objects = 'reference',
87
+ strict = true
88
+ } = {}) {
84
89
  // Wrong type or one of the two undefined, doesn't match
85
90
  if (typeof a !== typeof b || !!a !== !!b) return false; // Atomic, just compare a against b
86
91
 
87
- if (is.str(a) || is.num(a) || is.obj(a)) return a === b; // Array, shallow compare first to see if it's a match
92
+ if (is.str(a) || is.num(a)) return a === b;
93
+ const isObj = is.obj(a);
94
+ if (isObj && objects === 'reference') return a === b;
95
+ const isArr = is.arr(a);
96
+ if (isArr && arrays === 'reference') return a === b; // Array or Object, shallow compare first to see if it's a match
88
97
 
89
- if (is.arr(a) && a == b) return true; // Last resort, go through keys
98
+ if ((isArr || isObj) && a == b) return true; // Last resort, go through keys
90
99
 
91
100
  let i;
92
101
 
93
102
  for (i in a) if (!(i in b)) return false;
94
103
 
95
- for (i in b) if (a[i] !== b[i]) return false;
104
+ for (i in strict ? b : a) if (a[i] !== b[i]) return false;
96
105
 
97
106
  return is.und(i) ? a === b : true;
98
107
  }
@@ -183,15 +192,8 @@ function detach(parent, child, type) {
183
192
  const [, detach] = type;
184
193
  if (is.str(detach)) parent[detach](child);else if (is.fun(detach)) detach(parent, child);
185
194
  }
186
- } // Shallow check arrays, but check objects atomically
187
-
188
- function checkShallow(a, b) {
189
- if (is.arr(a) && is.equ(a, b)) return true;
190
- if (a === b) return true;
191
- return false;
192
195
  } // This function prepares a set of changes to be applied to the instance
193
196
 
194
-
195
197
  function diffProps(instance, {
196
198
  children: cN,
197
199
  key: kN,
@@ -223,7 +225,7 @@ function diffProps(instance, {
223
225
  // Bail out on primitive object
224
226
  if ((_instance$__r3f2 = instance.__r3f) != null && _instance$__r3f2.primitive && key === 'object') return; // When props match bail out
225
227
 
226
- if (checkShallow(value, previous[key])) return; // Collect handlers and bail out
228
+ if (is.equ(value, previous[key])) return; // Collect handlers and bail out
227
229
 
228
230
  if (/^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(key)) return changes.push([key, value, true, []]); // Split dashed props
229
231
 
@@ -1152,63 +1154,8 @@ const isRenderer = def => !!(def != null && def.render);
1152
1154
  const isOrthographicCamera = def => def && def.isOrthographicCamera;
1153
1155
  const context = /*#__PURE__*/React__namespace.createContext(null);
1154
1156
 
1155
- const createStore = (applyProps, invalidate, advance, props) => {
1156
- const {
1157
- gl,
1158
- size,
1159
- shadows = false,
1160
- linear = false,
1161
- flat = false,
1162
- orthographic = false,
1163
- frameloop = 'always',
1164
- dpr = [1, 2],
1165
- performance,
1166
- clock = new THREE__namespace.Clock(),
1167
- raycaster: raycastOptions,
1168
- camera: cameraOptions,
1169
- onPointerMissed
1170
- } = props; // Set shadowmap
1171
-
1172
- if (shadows) {
1173
- gl.shadowMap.enabled = true;
1174
- if (typeof shadows === 'object') Object.assign(gl.shadowMap, shadows);else gl.shadowMap.type = THREE__namespace.PCFSoftShadowMap;
1175
- } // Set color preferences
1176
-
1177
-
1178
- if (linear) gl.outputEncoding = THREE__namespace.LinearEncoding;
1179
- if (flat) gl.toneMapping = THREE__namespace.NoToneMapping; // clock.elapsedTime is updated using advance(timestamp)
1180
-
1181
- if (frameloop === 'never') {
1182
- clock.stop();
1183
- clock.elapsedTime = 0;
1184
- }
1185
-
1157
+ const createStore = (invalidate, advance) => {
1186
1158
  const rootState = create__default['default']((set, get) => {
1187
- // Create custom raycaster
1188
- const raycaster = new THREE__namespace.Raycaster();
1189
- const {
1190
- params,
1191
- ...options
1192
- } = raycastOptions || {};
1193
- applyProps(raycaster, {
1194
- enabled: true,
1195
- ...options,
1196
- params: { ...raycaster.params,
1197
- ...params
1198
- }
1199
- }); // Create default camera
1200
-
1201
- const isCamera = cameraOptions instanceof THREE__namespace.Camera;
1202
- const camera = isCamera ? cameraOptions : orthographic ? new THREE__namespace.OrthographicCamera(0, 0, 0, 0, 0.1, 1000) : new THREE__namespace.PerspectiveCamera(75, 0, 0.1, 1000);
1203
-
1204
- if (!isCamera) {
1205
- camera.position.z = 5;
1206
- if (cameraOptions) applyProps(camera, cameraOptions); // Always look at center by default
1207
-
1208
- if (!(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
1209
- }
1210
-
1211
- const initialDpr = calculateDpr(dpr);
1212
1159
  const position = new THREE__namespace.Vector3();
1213
1160
  const defaultTarget = new THREE__namespace.Vector3();
1214
1161
  const tempTarget = new THREE__namespace.Vector3();
@@ -1252,61 +1199,34 @@ const createStore = (applyProps, invalidate, advance, props) => {
1252
1199
  performance: { ...state.performance,
1253
1200
  current
1254
1201
  }
1255
- })); // Handle frame behavior in WebXR
1256
-
1257
-
1258
- const handleXRFrame = (timestamp, frame) => {
1259
- const state = get();
1260
- if (state.frameloop === 'never') return;
1261
- advance(timestamp, true, state, frame);
1262
- }; // Toggle render switching on session
1263
-
1264
-
1265
- const handleSessionChange = () => {
1266
- gl.xr.enabled = gl.xr.isPresenting; // @ts-expect-error
1267
- // WebXRManager's signature is incorrect.
1268
- // See: https://github.com/pmndrs/react-three-fiber/pull/2017#discussion_r790134505
1269
-
1270
- gl.xr.setAnimationLoop(gl.xr.isPresenting ? handleXRFrame : null);
1271
- }; // WebXR session manager
1272
-
1273
-
1274
- const xr = {
1275
- connect() {
1276
- gl.xr.addEventListener('sessionstart', handleSessionChange);
1277
- gl.xr.addEventListener('sessionend', handleSessionChange);
1278
- },
1279
-
1280
- disconnect() {
1281
- gl.xr.removeEventListener('sessionstart', handleSessionChange);
1282
- gl.xr.removeEventListener('sessionend', handleSessionChange);
1283
- }
1284
-
1285
- }; // Subscribe to WebXR session events
1202
+ }));
1286
1203
 
1287
- if (gl.xr) xr.connect();
1288
1204
  return {
1289
- gl,
1205
+ // Mock objects that have to be configured
1206
+ gl: null,
1207
+ camera: null,
1208
+ raycaster: null,
1209
+ events: {
1210
+ connected: false
1211
+ },
1212
+ xr: null,
1290
1213
  set,
1291
1214
  get,
1292
1215
  invalidate: () => invalidate(get()),
1293
1216
  advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
1294
- linear,
1295
- flat,
1217
+ linear: false,
1218
+ flat: false,
1296
1219
  scene: prepare(new THREE__namespace.Scene()),
1297
- camera,
1298
1220
  controls: null,
1299
- raycaster,
1300
- clock,
1221
+ clock: new THREE__namespace.Clock(),
1301
1222
  mouse: new THREE__namespace.Vector2(),
1302
- frameloop,
1303
- onPointerMissed,
1223
+ frameloop: 'always',
1224
+ onPointerMissed: undefined,
1304
1225
  performance: {
1305
1226
  current: 1,
1306
1227
  min: 0.5,
1307
1228
  max: 1,
1308
1229
  debounce: 200,
1309
- ...performance,
1310
1230
  regress: () => {
1311
1231
  const state = get(); // Clear timeout
1312
1232
 
@@ -1322,8 +1242,8 @@ const createStore = (applyProps, invalidate, advance, props) => {
1322
1242
  height: 0
1323
1243
  },
1324
1244
  viewport: {
1325
- initialDpr,
1326
- dpr: initialDpr,
1245
+ initialDpr: 0,
1246
+ dpr: 0,
1327
1247
  width: 0,
1328
1248
  height: 0,
1329
1249
  aspect: 0,
@@ -1332,6 +1252,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1332
1252
  getCurrentViewport
1333
1253
  },
1334
1254
  setSize: (width, height) => {
1255
+ const camera = get().camera;
1335
1256
  const size = {
1336
1257
  width,
1337
1258
  height
@@ -1343,22 +1264,34 @@ const createStore = (applyProps, invalidate, advance, props) => {
1343
1264
  }
1344
1265
  }));
1345
1266
  },
1346
- setDpr: dpr => set(state => ({
1347
- viewport: { ...state.viewport,
1348
- dpr: calculateDpr(dpr)
1267
+ setDpr: dpr => set(state => {
1268
+ const resolved = calculateDpr(dpr);
1269
+ return {
1270
+ viewport: { ...state.viewport,
1271
+ dpr: resolved,
1272
+ initialDpr: state.viewport.initialDpr || resolved
1273
+ }
1274
+ };
1275
+ }),
1276
+ setFrameloop: (frameloop = 'always') => {
1277
+ const clock = get().clock; // if frameloop === "never" clock.elapsedTime is updated using advance(timestamp)
1278
+
1279
+ clock.stop();
1280
+ clock.elapsedTime = 0;
1281
+
1282
+ if (frameloop !== 'never') {
1283
+ clock.start();
1284
+ clock.elapsedTime = 0;
1349
1285
  }
1350
- })),
1351
- setFrameloop: (frameloop = 'always') => set(() => ({
1352
- frameloop
1353
- })),
1354
- events: {
1355
- connected: false
1286
+
1287
+ set(() => ({
1288
+ frameloop
1289
+ }));
1356
1290
  },
1357
1291
  internal: {
1358
1292
  active: false,
1359
1293
  priority: 0,
1360
1294
  frames: 0,
1361
- lastProps: props,
1362
1295
  lastEvent: /*#__PURE__*/React__namespace.createRef(),
1363
1296
  interaction: [],
1364
1297
  hovered: new Map(),
@@ -1366,7 +1299,6 @@ const createStore = (applyProps, invalidate, advance, props) => {
1366
1299
  initialClick: [0, 0],
1367
1300
  initialHits: [],
1368
1301
  capturedMap: new Map(),
1369
- xr,
1370
1302
  subscribe: (ref, priority = 0) => {
1371
1303
  set(({
1372
1304
  internal
@@ -1410,13 +1342,14 @@ const createStore = (applyProps, invalidate, advance, props) => {
1410
1342
  camera,
1411
1343
  size,
1412
1344
  viewport,
1413
- internal
1345
+ internal,
1346
+ gl
1414
1347
  } = rootState.getState();
1415
1348
 
1416
1349
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1417
1350
  // https://github.com/pmndrs/react-three-fiber/issues/92
1418
1351
  // Do not mess with the camera if it belongs to the user
1419
- if (!camera.manual && !(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
1352
+ if (!camera.manual) {
1420
1353
  if (isOrthographicCamera(camera)) {
1421
1354
  camera.left = size.width / -2;
1422
1355
  camera.right = size.width / 2;
@@ -1438,9 +1371,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1438
1371
  oldSize = size;
1439
1372
  oldDpr = viewport.dpr;
1440
1373
  }
1441
- }); // Update size
1442
-
1443
- if (size) state.setSize(size.width, size.height); // Invalidate on any change
1374
+ }); // Invalidate on any change
1444
1375
 
1445
1376
  rootState.subscribe(state => invalidate(state)); // Return root state
1446
1377
 
@@ -1465,6 +1396,8 @@ function run(effects, timestamp) {
1465
1396
  for (i = 0; i < effects.length; i++) effects[i](timestamp);
1466
1397
  }
1467
1398
 
1399
+ let subscribers;
1400
+
1468
1401
  function render$1(timestamp, state, frame) {
1469
1402
  // Run local effects
1470
1403
  let delta = state.clock.getDelta(); // In frameloop='never' mode, clock times are updated using the provided timestamp
@@ -1476,7 +1409,9 @@ function render$1(timestamp, state, frame) {
1476
1409
  } // Call subscribers (useFrame)
1477
1410
 
1478
1411
 
1479
- for (i = 0; i < state.internal.subscribers.length; i++) state.internal.subscribers[i].ref.current(state, delta, frame); // Render content
1412
+ subscribers = state.internal.subscribers;
1413
+
1414
+ for (i = 0; i < subscribers.length; i++) subscribers[i].ref.current(state, delta, frame); // Render content
1480
1415
 
1481
1416
 
1482
1417
  if (!state.internal.priority && state.gl.render) state.gl.render(state.scene, state.camera); // Decrease frame count
@@ -1488,29 +1423,35 @@ function render$1(timestamp, state, frame) {
1488
1423
  function createLoop(roots) {
1489
1424
  let running = false;
1490
1425
  let repeat;
1426
+ let frame;
1427
+ let state;
1491
1428
 
1492
1429
  function loop(timestamp) {
1430
+ frame = requestAnimationFrame(loop);
1493
1431
  running = true;
1494
1432
  repeat = 0; // Run effects
1495
1433
 
1496
- run(globalEffects, timestamp); // Render all roots
1434
+ if (globalEffects.length) run(globalEffects, timestamp); // Render all roots
1497
1435
 
1498
1436
  roots.forEach(root => {
1499
1437
  var _state$gl$xr;
1500
1438
 
1501
- const state = root.store.getState(); // If the frameloop is invalidated, do not run another frame
1439
+ state = root.store.getState(); // If the frameloop is invalidated, do not run another frame
1502
1440
 
1503
1441
  if (state.internal.active && (state.frameloop === 'always' || state.internal.frames > 0) && !((_state$gl$xr = state.gl.xr) != null && _state$gl$xr.isPresenting)) {
1504
1442
  repeat += render$1(timestamp, state);
1505
1443
  }
1506
1444
  }); // Run after-effects
1507
1445
 
1508
- run(globalAfterEffects, timestamp); // Keep on looping if anything invalidates the frameloop
1446
+ if (globalAfterEffects.length) run(globalAfterEffects, timestamp); // Stop the loop if nothing invalidates it
1509
1447
 
1510
- if (repeat > 0) return requestAnimationFrame(loop); // Tail call effects, they are called when rendering stops
1511
- else run(globalTailEffects, timestamp); // Flag end of operation
1448
+ if (repeat === 0) {
1449
+ // Tail call effects, they are called when rendering stops
1450
+ if (globalTailEffects.length) run(globalTailEffects, timestamp); // Flag end of operation
1512
1451
 
1513
- running = false;
1452
+ running = false;
1453
+ return cancelAnimationFrame(frame);
1454
+ }
1514
1455
  }
1515
1456
 
1516
1457
  function invalidate(state) {
@@ -1603,113 +1544,216 @@ const {
1603
1544
  reconciler,
1604
1545
  applyProps
1605
1546
  } = createRenderer(roots, getEventPriority);
1547
+ const shallowLoose = {
1548
+ objects: 'shallow',
1549
+ strict: false
1550
+ };
1606
1551
 
1607
1552
  const createRendererInstance = (gl, canvas) => {
1608
1553
  const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
1609
- if (isRenderer(customRenderer)) return customRenderer;
1610
- const renderer = new THREE__namespace.WebGLRenderer({
1554
+ if (isRenderer(customRenderer)) return customRenderer;else return new THREE__namespace.WebGLRenderer({
1611
1555
  powerPreference: 'high-performance',
1612
1556
  canvas: canvas,
1613
1557
  antialias: true,
1614
1558
  alpha: true,
1615
1559
  ...gl
1616
- }); // Set color management
1560
+ });
1561
+ };
1617
1562
 
1618
- renderer.outputEncoding = THREE__namespace.sRGBEncoding;
1619
- renderer.toneMapping = THREE__namespace.ACESFilmicToneMapping; // Set gl props
1563
+ function createRoot(canvas) {
1564
+ // Check against mistaken use of createRoot
1565
+ let prevRoot = roots.get(canvas);
1566
+ let prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
1567
+ let prevStore = prevRoot == null ? void 0 : prevRoot.store;
1568
+ if (prevRoot) console.warn('R3F.createRoot should only be called once!'); // Create store
1620
1569
 
1621
- if (gl) applyProps(renderer, gl);
1622
- return renderer;
1623
- };
1570
+ const store = prevStore || createStore(invalidate, advance); // Create renderer
1571
+
1572
+ const fiber = prevFiber || reconciler.createContainer(store, constants.ConcurrentRoot, false, null); // Map it
1573
+
1574
+ if (!prevRoot) roots.set(canvas, {
1575
+ fiber,
1576
+ store
1577
+ }); // Locals
1624
1578
 
1625
- function createRoot(canvas, config) {
1579
+ let onCreated;
1580
+ let configured = false;
1626
1581
  return {
1627
- render: element => {
1628
- var _store;
1582
+ configure(props = {}) {
1583
+ var _canvas$parentElement, _canvas$parentElement2, _canvas$parentElement3, _canvas$parentElement4;
1629
1584
 
1630
1585
  let {
1631
- gl,
1586
+ gl: glConfig,
1632
1587
  size,
1633
1588
  events,
1634
- onCreated,
1635
- ...props
1636
- } = config || {}; // Allow size to take on container bounds initially
1589
+ onCreated: onCreatedCallback,
1590
+ shadows = false,
1591
+ linear = false,
1592
+ flat = false,
1593
+ orthographic = false,
1594
+ frameloop = 'always',
1595
+ dpr = [1, 2],
1596
+ performance,
1597
+ raycaster: raycastOptions,
1598
+ camera: cameraOptions,
1599
+ onPointerMissed
1600
+ } = props;
1601
+ let state = store.getState(); // Set up renderer (one time only!)
1602
+
1603
+ let gl = state.gl;
1604
+ if (!state.gl) state.set({
1605
+ gl: gl = createRendererInstance(glConfig, canvas)
1606
+ }); // Set up raycaster (one time only!)
1607
+
1608
+ let raycaster = state.raycaster;
1609
+ if (!raycaster) state.set({
1610
+ raycaster: raycaster = new THREE__namespace.Raycaster()
1611
+ }); // Set raycaster options
1637
1612
 
1638
- if (!size) {
1639
- var _canvas$parentElement, _canvas$parentElement2, _canvas$parentElement3, _canvas$parentElement4;
1613
+ const {
1614
+ params,
1615
+ ...options
1616
+ } = raycastOptions || {};
1617
+ if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, {
1618
+ enabled: true,
1619
+ ...options
1620
+ });
1621
+ if (!is.equ(params, raycaster.params, shallowLoose)) applyProps(raycaster, {
1622
+ params: { ...raycaster.params,
1623
+ ...params
1624
+ }
1625
+ }); // Create default camera (one time only!)
1640
1626
 
1641
- size = {
1642
- width: (_canvas$parentElement = (_canvas$parentElement2 = canvas.parentElement) == null ? void 0 : _canvas$parentElement2.clientWidth) != null ? _canvas$parentElement : 0,
1643
- height: (_canvas$parentElement3 = (_canvas$parentElement4 = canvas.parentElement) == null ? void 0 : _canvas$parentElement4.clientHeight) != null ? _canvas$parentElement3 : 0
1644
- };
1645
- }
1627
+ if (!state.camera) {
1628
+ const isCamera = cameraOptions instanceof THREE__namespace.Camera;
1629
+ const camera = isCamera ? cameraOptions : orthographic ? new THREE__namespace.OrthographicCamera(0, 0, 0, 0, 0.1, 1000) : new THREE__namespace.PerspectiveCamera(75, 0, 0.1, 1000);
1646
1630
 
1647
- let root = roots.get(canvas);
1648
- let fiber = root == null ? void 0 : root.fiber;
1649
- let store = root == null ? void 0 : root.store;
1650
- let state = (_store = store) == null ? void 0 : _store.getState();
1631
+ if (!isCamera) {
1632
+ camera.position.z = 5;
1633
+ if (cameraOptions) applyProps(camera, cameraOptions); // Always look at center by default
1651
1634
 
1652
- if (fiber && state) {
1653
- // When a root was found, see if any fundamental props must be changed or exchanged
1654
- // Check pixelratio
1655
- if (props.dpr !== undefined && state.viewport.dpr !== calculateDpr(props.dpr)) state.setDpr(props.dpr); // Check size
1635
+ if (!(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
1636
+ }
1656
1637
 
1657
- if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // Check frameloop
1638
+ state.set({
1639
+ camera
1640
+ });
1641
+ } // Set up XR (one time only!)
1658
1642
 
1659
- if (state.frameloop !== props.frameloop) state.setFrameloop(props.frameloop); // For some props we want to reset the entire root
1660
- // Changes to the color-space
1661
1643
 
1662
- const linearChanged = props.linear !== state.internal.lastProps.linear;
1644
+ if (!state.xr) {
1645
+ // Handle frame behavior in WebXR
1646
+ const handleXRFrame = (timestamp, frame) => {
1647
+ const state = store.getState();
1648
+ if (state.frameloop === 'never') return;
1649
+ advance(timestamp, true, state, frame);
1650
+ }; // Toggle render switching on session
1663
1651
 
1664
- if (linearChanged) {
1665
- unmountComponentAtNode(canvas);
1666
- fiber = undefined;
1667
- }
1668
- }
1669
1652
 
1670
- if (!fiber) {
1671
- // If no root has been found, make one
1672
- // Create gl
1673
- const glRenderer = createRendererInstance(gl, canvas); // Create store
1653
+ const handleSessionChange = () => {
1654
+ const gl = store.getState().gl;
1655
+ gl.xr.enabled = gl.xr.isPresenting; // @ts-expect-error
1656
+ // WebXRManager's signature is incorrect.
1657
+ // See: https://github.com/pmndrs/react-three-fiber/pull/2017#discussion_r790134505
1674
1658
 
1675
- store = createStore(applyProps, invalidate, advance, {
1676
- gl: glRenderer,
1677
- size,
1678
- ...props
1679
- });
1680
- const state = store.getState(); // Create renderer
1659
+ gl.xr.setAnimationLoop(gl.xr.isPresenting ? handleXRFrame : null);
1660
+ }; // WebXR session manager
1681
1661
 
1682
- fiber = reconciler.createContainer(store, constants.ConcurrentRoot, false, null); // Map it
1683
1662
 
1684
- roots.set(canvas, {
1685
- fiber,
1686
- store
1687
- }); // Store events internally
1663
+ const xr = {
1664
+ connect() {
1665
+ const gl = store.getState().gl;
1666
+ gl.xr.addEventListener('sessionstart', handleSessionChange);
1667
+ gl.xr.addEventListener('sessionend', handleSessionChange);
1668
+ },
1669
+
1670
+ disconnect() {
1671
+ const gl = store.getState().gl;
1672
+ gl.xr.removeEventListener('sessionstart', handleSessionChange);
1673
+ gl.xr.removeEventListener('sessionend', handleSessionChange);
1674
+ }
1688
1675
 
1689
- if (events) state.set({
1690
- events: events(store)
1676
+ }; // Subscribe to WebXR session events
1677
+
1678
+ if (gl.xr) xr.connect();
1679
+ state.set({
1680
+ xr
1691
1681
  });
1692
- }
1682
+ } // Set shadowmap
1693
1683
 
1694
- if (store && fiber) {
1695
- reconciler.updateContainer( /*#__PURE__*/React__namespace.createElement(Provider, {
1696
- store: store,
1697
- element: element,
1698
- onCreated: onCreated,
1699
- target: canvas
1700
- }), fiber, null, () => undefined);
1701
- return store;
1702
- } else {
1703
- throw 'Error creating root!';
1704
- }
1684
+
1685
+ if (gl.shadowMap) {
1686
+ const isBoolean = is.boo(shadows);
1687
+
1688
+ if (isBoolean && gl.shadowMap.enabled !== shadows || !is.equ(shadows, gl.shadowMap, shallowLoose)) {
1689
+ const old = gl.shadowMap.enabled;
1690
+ gl.shadowMap.enabled = !!shadows;
1691
+ if (!isBoolean) Object.assign(gl.shadowMap, shadows);else gl.shadowMap.type = THREE__namespace.PCFSoftShadowMap;
1692
+ if (old !== gl.shadowMap.enabled) gl.shadowMap.needsUpdate = true;
1693
+ }
1694
+ } // Set color management
1695
+
1696
+
1697
+ const outputEncoding = linear ? THREE__namespace.LinearEncoding : THREE__namespace.sRGBEncoding;
1698
+ const toneMapping = flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping;
1699
+ if (gl.outputEncoding !== outputEncoding) gl.outputEncoding = outputEncoding;
1700
+ if (gl.toneMapping !== toneMapping) gl.toneMapping = toneMapping; // Set gl props
1701
+
1702
+ if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig); // Store events internally
1703
+
1704
+ if (events && !state.events.handlers) state.set({
1705
+ events: events(store)
1706
+ }); // Check pixelratio
1707
+
1708
+ if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr); // Check size, allow it to take on container bounds initially
1709
+
1710
+ size = size || {
1711
+ width: (_canvas$parentElement = (_canvas$parentElement2 = canvas.parentElement) == null ? void 0 : _canvas$parentElement2.clientWidth) != null ? _canvas$parentElement : 0,
1712
+ height: (_canvas$parentElement3 = (_canvas$parentElement4 = canvas.parentElement) == null ? void 0 : _canvas$parentElement4.clientHeight) != null ? _canvas$parentElement3 : 0
1713
+ };
1714
+ if (!is.equ(size, state.size, shallowLoose)) state.setSize(size.width, size.height); // Check frameloop
1715
+
1716
+ if (state.frameloop !== frameloop) state.setFrameloop(frameloop); // Check pointer missed
1717
+
1718
+ if (!state.onPointerMissed) state.set({
1719
+ onPointerMissed
1720
+ }); // Check performance
1721
+
1722
+ if (performance && !is.equ(performance, state.performance, shallowLoose)) state.set(state => ({
1723
+ performance: { ...state.performance,
1724
+ ...performance
1725
+ }
1726
+ })); // Set locals
1727
+
1728
+ onCreated = onCreatedCallback;
1729
+ configured = true;
1730
+ return this;
1705
1731
  },
1706
- unmount: () => unmountComponentAtNode(canvas)
1732
+
1733
+ render(element) {
1734
+ // The root has to be configured before it can be rendered
1735
+ if (!configured) this.configure();
1736
+ reconciler.updateContainer( /*#__PURE__*/React__namespace.createElement(Provider, {
1737
+ store: store,
1738
+ element: element,
1739
+ onCreated: onCreated,
1740
+ target: canvas
1741
+ }), fiber, null, () => undefined);
1742
+ return store;
1743
+ },
1744
+
1745
+ unmount() {
1746
+ unmountComponentAtNode(canvas);
1747
+ }
1748
+
1707
1749
  };
1708
1750
  }
1709
1751
 
1710
1752
  function render(element, canvas, config = {}) {
1711
1753
  console.warn('R3F.render is no longer supported in React 18. Use createRoot instead!');
1712
- return createRoot(canvas, config).render(element);
1754
+ const root = createRoot(canvas);
1755
+ root.configure(config);
1756
+ return root.render(element);
1713
1757
  }
1714
1758
 
1715
1759
  function Provider({
@@ -1752,7 +1796,7 @@ function unmountComponentAtNode(canvas, callback) {
1752
1796
  state.events.disconnect == null ? void 0 : state.events.disconnect();
1753
1797
  (_state$gl = state.gl) == null ? void 0 : (_state$gl$renderLists = _state$gl.renderLists) == null ? void 0 : _state$gl$renderLists.dispose == null ? void 0 : _state$gl$renderLists.dispose();
1754
1798
  (_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
1755
- if ((_state$gl3 = state.gl) != null && _state$gl3.xr) state.internal.xr.disconnect();
1799
+ if ((_state$gl3 = state.gl) != null && _state$gl3.xr) state.xr.disconnect();
1756
1800
  dispose(state);
1757
1801
  roots.delete(canvas);
1758
1802
  if (callback) callback(canvas);