@react-three/fiber 9.8.1 → 9.8.2
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 +12 -0
- package/dist/declarations/src/core/configuration.d.ts +9 -2
- package/dist/declarations/src/core/extend.d.ts +12 -0
- package/dist/declarations/src/core/hooks.d.ts +2 -1
- package/dist/declarations/src/core/index.d.ts +5 -3
- package/dist/declarations/src/core/reconciler.d.ts +3 -9
- package/dist/declarations/src/core/renderer.d.ts +9 -0
- package/dist/declarations/src/core/root.d.ts +3 -1
- package/dist/declarations/src/core/store.d.ts +1 -1
- package/dist/declarations/src/core/utils/react.d.ts +184 -0
- package/dist/declarations/src/core/utils.d.ts +9 -184
- package/dist/declarations/src/three-types.d.ts +1 -1
- package/dist/{events-21d8cd92.cjs.dev.js → events-0dab3c53.cjs.dev.js} +361 -204
- package/dist/{events-a816cbab.cjs.prod.js → events-98e95d43.cjs.prod.js} +361 -204
- package/dist/{events-9ce18a08.esm.js → events-e51d7528.esm.js} +361 -204
- package/dist/react-three-fiber.cjs.dev.js +1 -1
- package/dist/react-three-fiber.cjs.prod.js +1 -1
- package/dist/react-three-fiber.esm.js +2 -2
- package/native/dist/react-three-fiber-native.cjs.dev.js +1 -1
- package/native/dist/react-three-fiber-native.cjs.prod.js +1 -1
- package/native/dist/react-three-fiber-native.esm.js +2 -2
- package/package.json +7 -1
- /package/dist/declarations/src/core/{promise.d.ts → utils/promise.d.ts} +0 -0
|
@@ -4,21 +4,13 @@ import * as THREE from 'three';
|
|
|
4
4
|
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { createWithEqualityFn } from 'zustand/traditional';
|
|
6
6
|
import { suspend, preload, clear } from 'suspend-react';
|
|
7
|
-
import w1, { unstable_getCurrentPriorityLevel, unstable_IdlePriority, unstable_LowPriority, unstable_NormalPriority, unstable_UserBlockingPriority, unstable_ImmediatePriority, unstable_scheduleCallback } from 'scheduler';
|
|
8
7
|
import { useFiber, useContextBridge, traverseFiber, useActivityBridge as useActivityBridge$1 } from 'its-fine';
|
|
8
|
+
import w1, { unstable_getCurrentPriorityLevel, unstable_IdlePriority, unstable_LowPriority, unstable_NormalPriority, unstable_UserBlockingPriority, unstable_ImmediatePriority, unstable_scheduleCallback } from 'scheduler';
|
|
9
9
|
|
|
10
10
|
var threeTypes = /*#__PURE__*/Object.freeze({
|
|
11
11
|
__proto__: null
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
* Returns the instance's initial (outmost) root.
|
|
16
|
-
*/
|
|
17
|
-
function findInitialRoot(instance) {
|
|
18
|
-
let root = instance.root;
|
|
19
|
-
while (root.getState().previousRoot) root = root.getState().previousRoot;
|
|
20
|
-
return root;
|
|
21
|
-
}
|
|
22
14
|
/**
|
|
23
15
|
* Safely flush async effects when testing, simulating a legacy root.
|
|
24
16
|
* @deprecated Import from React instead. import { act } from 'react'
|
|
@@ -26,9 +18,6 @@ function findInitialRoot(instance) {
|
|
|
26
18
|
// Reference with computed key to break Webpack static analysis
|
|
27
19
|
// https://github.com/webpack/webpack/issues/14814
|
|
28
20
|
const act = React['act' + ''];
|
|
29
|
-
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
30
|
-
const isRef = obj => obj && obj.hasOwnProperty('current');
|
|
31
|
-
const isColorRepresentation = value => value != null && (typeof value === 'string' || typeof value === 'number' || value.isColor);
|
|
32
21
|
|
|
33
22
|
/**
|
|
34
23
|
* An SSR-friendly useLayoutEffect.
|
|
@@ -45,7 +34,6 @@ function useMutableCallback(fn) {
|
|
|
45
34
|
useIsomorphicLayoutEffect(() => void (ref.current = fn), [fn]);
|
|
46
35
|
return ref;
|
|
47
36
|
}
|
|
48
|
-
const noop = () => {};
|
|
49
37
|
function Gate({
|
|
50
38
|
promise,
|
|
51
39
|
onSettled
|
|
@@ -60,7 +48,7 @@ function useGate() {
|
|
|
60
48
|
const [promise, setPromise] = React.useState(null);
|
|
61
49
|
const onSettled = React.useCallback(() => setPromise(null), []);
|
|
62
50
|
// Keep the first promise, or a repeated call would loop
|
|
63
|
-
const waitFor = React.useCallback(next => setPromise(current => current != null ? current : Promise.resolve(next).then(
|
|
51
|
+
const waitFor = React.useCallback(next => setPromise(current => current != null ? current : Promise.resolve(next).then(() => {}, () => {})), []);
|
|
64
52
|
const gate = promise ? /*#__PURE__*/jsx(React.Suspense, {
|
|
65
53
|
fallback: null,
|
|
66
54
|
children: /*#__PURE__*/jsx(Gate, {
|
|
@@ -121,6 +109,19 @@ const ErrorBoundary = /* @__PURE__ */(_ErrorBoundary => (_ErrorBoundary = class
|
|
|
121
109
|
}, _ErrorBoundary.getDerivedStateFromError = () => ({
|
|
122
110
|
error: true
|
|
123
111
|
}), _ErrorBoundary))();
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Returns the instance's initial (outmost) root.
|
|
115
|
+
*/
|
|
116
|
+
function findInitialRoot(instance) {
|
|
117
|
+
let root = instance.root;
|
|
118
|
+
while (root.getState().previousRoot) root = root.getState().previousRoot;
|
|
119
|
+
return root;
|
|
120
|
+
}
|
|
121
|
+
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
122
|
+
const isRef = obj => obj && obj.hasOwnProperty('current');
|
|
123
|
+
const isColorRepresentation = value => value != null && (typeof value === 'string' || typeof value === 'number' || value.isColor);
|
|
124
|
+
const noop = () => {};
|
|
124
125
|
function calculateDpr(dpr) {
|
|
125
126
|
var _window$devicePixelRa;
|
|
126
127
|
// Err on the side of progress by assuming 2x dpr if we can't detect it
|
|
@@ -129,6 +130,43 @@ function calculateDpr(dpr) {
|
|
|
129
130
|
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
|
|
130
131
|
}
|
|
131
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Calls `onChange` whenever window.devicePixelRatio changes: moving to another display or zooming.
|
|
135
|
+
* Neither resizes the canvas, so resize observers won't see it. A resolution query only matches the
|
|
136
|
+
* current ratio, so it is re-created after every change. Returns the unsubscribe function.
|
|
137
|
+
*/
|
|
138
|
+
function watchDpr(onChange) {
|
|
139
|
+
if (typeof window === 'undefined' || typeof window.matchMedia !== 'function' || !window.devicePixelRatio) {
|
|
140
|
+
return () => {};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Partial matchMedia polyfills (test setups, older environments) may return no listener methods,
|
|
144
|
+
// or throw on a query they can't parse. Following the ratio is best-effort: it runs inside
|
|
145
|
+
// configuration, which must not fail because of it
|
|
146
|
+
let query;
|
|
147
|
+
const listen = () => {
|
|
148
|
+
try {
|
|
149
|
+
var _query, _query2;
|
|
150
|
+
query = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
|
|
151
|
+
if (typeof ((_query = query) == null ? void 0 : _query.addEventListener) === 'function') query.addEventListener('change', handleChange);else (_query2 = query) == null ? void 0 : _query2.addListener == null ? void 0 : _query2.addListener(handleChange);
|
|
152
|
+
} catch {
|
|
153
|
+
query = undefined;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
const unlisten = () => {
|
|
157
|
+
var _query3, _query4;
|
|
158
|
+
if (typeof ((_query3 = query) == null ? void 0 : _query3.removeEventListener) === 'function') query.removeEventListener('change', handleChange);else (_query4 = query) == null ? void 0 : _query4.removeListener == null ? void 0 : _query4.removeListener(handleChange);
|
|
159
|
+
query = undefined;
|
|
160
|
+
};
|
|
161
|
+
const handleChange = () => {
|
|
162
|
+
unlisten();
|
|
163
|
+
listen();
|
|
164
|
+
onChange();
|
|
165
|
+
};
|
|
166
|
+
listen();
|
|
167
|
+
return unlisten;
|
|
168
|
+
}
|
|
169
|
+
|
|
132
170
|
/**
|
|
133
171
|
* Returns instance root state
|
|
134
172
|
*/
|
|
@@ -578,11 +616,24 @@ function swapInteractivity(store, object, newObject) {
|
|
|
578
616
|
internal.hovered.set(makeId(next), next);
|
|
579
617
|
}
|
|
580
618
|
});
|
|
619
|
+
|
|
620
|
+
// A capture is keyed by its eventObject, but it also carries the intersection that is replayed into
|
|
621
|
+
// every subsequent event. Both must follow the new instance, or the capture resolves to the discarded object.
|
|
581
622
|
internal.capturedMap.forEach(captures => {
|
|
582
|
-
const captureData
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
623
|
+
for (const [key, captureData] of Array.from(captures)) {
|
|
624
|
+
const {
|
|
625
|
+
intersection
|
|
626
|
+
} = captureData;
|
|
627
|
+
if (key !== object && intersection.object !== object && intersection.eventObject !== object) continue;
|
|
628
|
+
if (key === object) captures.delete(key);
|
|
629
|
+
captures.set(key === object ? newObject : key, {
|
|
630
|
+
...captureData,
|
|
631
|
+
intersection: {
|
|
632
|
+
...intersection,
|
|
633
|
+
object: intersection.object === object ? newObject : intersection.object,
|
|
634
|
+
eventObject: intersection.eventObject === object ? newObject : intersection.eventObject
|
|
635
|
+
}
|
|
636
|
+
});
|
|
586
637
|
}
|
|
587
638
|
});
|
|
588
639
|
}
|
|
@@ -981,7 +1032,109 @@ function createEvents(store) {
|
|
|
981
1032
|
};
|
|
982
1033
|
}
|
|
983
1034
|
|
|
1035
|
+
const isPromiseLike = value => typeof (value == null ? void 0 : value.then) === 'function';
|
|
1036
|
+
|
|
1037
|
+
/** A promise tagged with its state, the protocol React's `use` reads */
|
|
1038
|
+
|
|
1039
|
+
const fulfilled = value => Object.assign(Promise.resolve(value), {
|
|
1040
|
+
status: 'fulfilled',
|
|
1041
|
+
value
|
|
1042
|
+
});
|
|
1043
|
+
const rejected = reason => {
|
|
1044
|
+
const promise = Promise.reject(reason);
|
|
1045
|
+
promise.catch(() => {}); // the reason is read from `status`
|
|
1046
|
+
return Object.assign(promise, {
|
|
1047
|
+
status: 'rejected',
|
|
1048
|
+
reason
|
|
1049
|
+
});
|
|
1050
|
+
};
|
|
1051
|
+
|
|
1052
|
+
/** A pending promise, settled once from outside. Its `status` updates the moment it settles */
|
|
1053
|
+
const deferred = () => {
|
|
1054
|
+
let resolve;
|
|
1055
|
+
let reject;
|
|
1056
|
+
const promise = new Promise((yes, no) => {
|
|
1057
|
+
resolve = value => {
|
|
1058
|
+
Object.assign(promise, {
|
|
1059
|
+
status: 'fulfilled',
|
|
1060
|
+
value
|
|
1061
|
+
});
|
|
1062
|
+
yes(value);
|
|
1063
|
+
};
|
|
1064
|
+
reject = reason => {
|
|
1065
|
+
Object.assign(promise, {
|
|
1066
|
+
status: 'rejected',
|
|
1067
|
+
reason
|
|
1068
|
+
});
|
|
1069
|
+
no(reason);
|
|
1070
|
+
};
|
|
1071
|
+
});
|
|
1072
|
+
promise.status = 'pending';
|
|
1073
|
+
promise.catch(() => {}); // the reason is read from `status`
|
|
1074
|
+
return {
|
|
1075
|
+
promise,
|
|
1076
|
+
resolve,
|
|
1077
|
+
reject
|
|
1078
|
+
};
|
|
1079
|
+
};
|
|
1080
|
+
|
|
1081
|
+
/** Renderer creation and resource release. Root lifetime decides when release is safe. */
|
|
984
1082
|
const isRenderer = def => !!(def != null && def.render);
|
|
1083
|
+
|
|
1084
|
+
/** The renderer to configure, or a promise for one from an async factory */
|
|
1085
|
+
function createRenderer(canvas, gl) {
|
|
1086
|
+
const defaults = {
|
|
1087
|
+
canvas,
|
|
1088
|
+
powerPreference: 'high-performance',
|
|
1089
|
+
antialias: true,
|
|
1090
|
+
alpha: true
|
|
1091
|
+
};
|
|
1092
|
+
if (typeof gl === 'function') return gl(defaults);
|
|
1093
|
+
if (isRenderer(gl)) return gl;
|
|
1094
|
+
return new THREE.WebGLRenderer({
|
|
1095
|
+
...defaults,
|
|
1096
|
+
...gl
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
/**
|
|
1101
|
+
* Frees a renderer R3F built. WebGLRenderer.dispose() releases programs and caches but keeps its
|
|
1102
|
+
* context until garbage collection, and browsers cap live WebGL contexts, so the context is lost
|
|
1103
|
+
* after it. A WebGPURenderer (from a factory) releases its device and context inside dispose().
|
|
1104
|
+
*/
|
|
1105
|
+
function disposeRenderer(gl) {
|
|
1106
|
+
// Avoid starting initialization through three's dispose(). A factory must await init()
|
|
1107
|
+
// before returning its renderer so readiness includes initialization and teardown can wait.
|
|
1108
|
+
if ((gl.hasInitialized == null ? void 0 : gl.hasInitialized()) === false) return;
|
|
1109
|
+
const disposed = attempt$1(() => {
|
|
1110
|
+
var _gl$renderLists;
|
|
1111
|
+
return gl.dispose ? gl.dispose() : (_gl$renderLists = gl.renderLists) == null ? void 0 : _gl$renderLists.dispose == null ? void 0 : _gl$renderLists.dispose();
|
|
1112
|
+
});
|
|
1113
|
+
// WebGPURenderer.dispose() is async from three r186
|
|
1114
|
+
if (isPromiseLike(disposed)) {
|
|
1115
|
+
return Promise.resolve(disposed).catch(error => console.warn('[R3F] Error disposing renderer', error)).then(() => attempt$1(() => gl.forceContextLoss == null ? void 0 : gl.forceContextLoss()));
|
|
1116
|
+
}
|
|
1117
|
+
attempt$1(() => gl.forceContextLoss == null ? void 0 : gl.forceContextLoss());
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
/** Owned renderers are disposed. Caller-provided renderers release caches and their context. */
|
|
1121
|
+
function releaseRenderer(gl, owned) {
|
|
1122
|
+
if (!gl) return;
|
|
1123
|
+
if (owned) return disposeRenderer(gl);
|
|
1124
|
+
attempt$1(() => {
|
|
1125
|
+
var _gl$renderLists2;
|
|
1126
|
+
return (_gl$renderLists2 = gl.renderLists) == null ? void 0 : _gl$renderLists2.dispose == null ? void 0 : _gl$renderLists2.dispose();
|
|
1127
|
+
});
|
|
1128
|
+
attempt$1(() => gl.forceContextLoss == null ? void 0 : gl.forceContextLoss());
|
|
1129
|
+
}
|
|
1130
|
+
function attempt$1(step) {
|
|
1131
|
+
try {
|
|
1132
|
+
return step();
|
|
1133
|
+
} catch (error) {
|
|
1134
|
+
console.warn('[R3F] Error while unmounting root; teardown may be incomplete:', error);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
985
1138
|
const context = /* @__PURE__ */React.createContext(null);
|
|
986
1139
|
const createStore = (invalidate, advance) => {
|
|
987
1140
|
const rootStore = createWithEqualityFn((set, get) => {
|
|
@@ -1276,7 +1429,7 @@ function useGraph(object) {
|
|
|
1276
1429
|
return React.useMemo(() => buildGraph(object), [object]);
|
|
1277
1430
|
}
|
|
1278
1431
|
const memoizedLoaders = new WeakMap();
|
|
1279
|
-
const isConstructor
|
|
1432
|
+
const isConstructor = value => {
|
|
1280
1433
|
var _value$prototype;
|
|
1281
1434
|
return typeof value === 'function' && (value == null ? void 0 : (_value$prototype = value.prototype) == null ? void 0 : _value$prototype.constructor) === value;
|
|
1282
1435
|
};
|
|
@@ -1285,7 +1438,7 @@ function loadingFn(extensions, onProgress) {
|
|
|
1285
1438
|
let loader;
|
|
1286
1439
|
|
|
1287
1440
|
// Construct and cache loader if constructor was passed
|
|
1288
|
-
if (isConstructor
|
|
1441
|
+
if (isConstructor(Proto)) {
|
|
1289
1442
|
loader = memoizedLoaders.get(Proto);
|
|
1290
1443
|
if (!loader) {
|
|
1291
1444
|
loader = new Proto();
|
|
@@ -1360,22 +1513,6 @@ useLoader.clear = function (loader, input) {
|
|
|
1360
1513
|
const shallow = {
|
|
1361
1514
|
objects: 'shallow'
|
|
1362
1515
|
};
|
|
1363
|
-
|
|
1364
|
-
/** The renderer to configure, or a promise for one from an async factory */
|
|
1365
|
-
function createRenderer(canvas, gl) {
|
|
1366
|
-
const defaults = {
|
|
1367
|
-
canvas,
|
|
1368
|
-
powerPreference: 'high-performance',
|
|
1369
|
-
antialias: true,
|
|
1370
|
-
alpha: true
|
|
1371
|
-
};
|
|
1372
|
-
if (typeof gl === 'function') return gl(defaults);
|
|
1373
|
-
if (isRenderer(gl)) return gl;
|
|
1374
|
-
return new THREE.WebGLRenderer({
|
|
1375
|
-
...defaults,
|
|
1376
|
-
...gl
|
|
1377
|
-
});
|
|
1378
|
-
}
|
|
1379
1516
|
function computeInitialSize(canvas, size) {
|
|
1380
1517
|
if (!size && typeof HTMLCanvasElement !== 'undefined' && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
1381
1518
|
const {
|
|
@@ -1623,55 +1760,43 @@ function applyRootConfiguration({
|
|
|
1623
1760
|
configuration.previous = next;
|
|
1624
1761
|
}
|
|
1625
1762
|
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
const promise = Promise.reject(reason);
|
|
1636
|
-
promise.catch(() => {}); // the reason is read from `status`
|
|
1637
|
-
return Object.assign(promise, {
|
|
1638
|
-
status: 'rejected',
|
|
1639
|
-
reason
|
|
1640
|
-
});
|
|
1641
|
-
};
|
|
1642
|
-
|
|
1643
|
-
/** A pending promise, settled once from outside. Its `status` updates the moment it settles */
|
|
1644
|
-
const deferred = () => {
|
|
1645
|
-
let resolve;
|
|
1646
|
-
let reject;
|
|
1647
|
-
const promise = new Promise((yes, no) => {
|
|
1648
|
-
resolve = value => {
|
|
1649
|
-
Object.assign(promise, {
|
|
1650
|
-
status: 'fulfilled',
|
|
1651
|
-
value
|
|
1652
|
-
});
|
|
1653
|
-
yes(value);
|
|
1654
|
-
};
|
|
1655
|
-
reject = reason => {
|
|
1656
|
-
Object.assign(promise, {
|
|
1657
|
-
status: 'rejected',
|
|
1658
|
-
reason
|
|
1659
|
-
});
|
|
1660
|
-
no(reason);
|
|
1661
|
-
};
|
|
1662
|
-
});
|
|
1663
|
-
promise.status = 'pending';
|
|
1664
|
-
promise.catch(() => {}); // the reason is read from `status`
|
|
1665
|
-
return {
|
|
1666
|
-
promise,
|
|
1667
|
-
resolve,
|
|
1668
|
-
reject
|
|
1763
|
+
/**
|
|
1764
|
+
* Moving to another display or zooming changes window.devicePixelRatio without resizing the canvas,
|
|
1765
|
+
* so nothing configures the root again. Resolves the ratio the way configuration does, from the last
|
|
1766
|
+
* applied dpr. Returns the function that stops following.
|
|
1767
|
+
*/
|
|
1768
|
+
function followDpr(root) {
|
|
1769
|
+
const xr = () => {
|
|
1770
|
+
var _root$store$getState$;
|
|
1771
|
+
return (_root$store$getState$ = root.store.getState().gl) == null ? void 0 : _root$store$getState$.xr;
|
|
1669
1772
|
};
|
|
1670
|
-
|
|
1773
|
+
const follow = () => {
|
|
1774
|
+
var _xr, _xr2, _xr3, _last$dpr;
|
|
1775
|
+
const state = root.store.getState();
|
|
1776
|
+
// three doesn't resize during XR and restores its own pixel ratio once the session ends. It holds
|
|
1777
|
+
// the session before it sets isPresenting. Listeners are deduplicated, so this waits once
|
|
1778
|
+
if ((_xr = xr()) != null && _xr.isPresenting || (_xr2 = xr()) != null && _xr2.getSession != null && _xr2.getSession()) {
|
|
1779
|
+
xr().addEventListener('sessionend', follow);
|
|
1780
|
+
return;
|
|
1781
|
+
}
|
|
1782
|
+
(_xr3 = xr()) == null ? void 0 : _xr3.removeEventListener == null ? void 0 : _xr3.removeEventListener('sessionend', follow);
|
|
1783
|
+
// A failed configuration applies everything on the next one
|
|
1784
|
+
const last = root.configuration.previous;
|
|
1785
|
+
if (!last) return;
|
|
1786
|
+
const dpr = (_last$dpr = last.dpr) != null ? _last$dpr : [1, 2];
|
|
1787
|
+
if (state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
1788
|
+
};
|
|
1789
|
+
const unwatch = watchDpr(follow);
|
|
1790
|
+
return () => {
|
|
1791
|
+
var _xr4;
|
|
1792
|
+
unwatch();
|
|
1793
|
+
(_xr4 = xr()) == null ? void 0 : _xr4.removeEventListener == null ? void 0 : _xr4.removeEventListener('sessionend', follow);
|
|
1794
|
+
};
|
|
1795
|
+
}
|
|
1671
1796
|
|
|
1672
1797
|
var packageData = {
|
|
1673
1798
|
name: "@react-three/fiber",
|
|
1674
|
-
version: "9.8.
|
|
1799
|
+
version: "9.8.2",
|
|
1675
1800
|
description: "A React renderer for Threejs",
|
|
1676
1801
|
keywords: [
|
|
1677
1802
|
"react",
|
|
@@ -1703,6 +1828,12 @@ var packageData = {
|
|
|
1703
1828
|
module: "dist/react-three-fiber.esm.js",
|
|
1704
1829
|
types: "dist/react-three-fiber.cjs.d.ts",
|
|
1705
1830
|
"react-native": "native/dist/react-three-fiber-native.cjs.js",
|
|
1831
|
+
files: [
|
|
1832
|
+
"dist",
|
|
1833
|
+
"native",
|
|
1834
|
+
"react-reconciler",
|
|
1835
|
+
"CHANGELOG.md"
|
|
1836
|
+
],
|
|
1706
1837
|
sideEffects: false,
|
|
1707
1838
|
preconstruct: {
|
|
1708
1839
|
entrypoints: [
|
|
@@ -16443,6 +16574,27 @@ function G1() {
|
|
|
16443
16574
|
var J1 = G1();
|
|
16444
16575
|
const Z1 = $1(J1);
|
|
16445
16576
|
|
|
16577
|
+
/** Constructor registration and lookup for JSX elements. */
|
|
16578
|
+
|
|
16579
|
+
const catalogue = {};
|
|
16580
|
+
let i = 0;
|
|
16581
|
+
const toPascalCase = type => `${type[0].toUpperCase()}${type.slice(1)}`;
|
|
16582
|
+
function hasConstructor(name) {
|
|
16583
|
+
return name in catalogue;
|
|
16584
|
+
}
|
|
16585
|
+
function resolveConstructor(name) {
|
|
16586
|
+
return catalogue[name];
|
|
16587
|
+
}
|
|
16588
|
+
function extend(objects) {
|
|
16589
|
+
if (typeof objects === 'function') {
|
|
16590
|
+
const Component = `${i++}`;
|
|
16591
|
+
catalogue[Component] = objects;
|
|
16592
|
+
return Component;
|
|
16593
|
+
} else {
|
|
16594
|
+
Object.assign(catalogue, objects);
|
|
16595
|
+
}
|
|
16596
|
+
}
|
|
16597
|
+
|
|
16446
16598
|
function createReconciler(config) {
|
|
16447
16599
|
const reconciler = Z1(config);
|
|
16448
16600
|
|
|
@@ -16456,24 +16608,11 @@ const NoEventPriority = 0;
|
|
|
16456
16608
|
// https://github.com/pmndrs/react-three-fiber/pull/2931
|
|
16457
16609
|
// https://github.com/microsoft/TypeScript/issues/37079
|
|
16458
16610
|
|
|
16459
|
-
const catalogue = {};
|
|
16460
16611
|
const PREFIX_REGEX = /^three(?=[A-Z])/;
|
|
16461
|
-
const toPascalCase = type => `${type[0].toUpperCase()}${type.slice(1)}`;
|
|
16462
|
-
let i = 0;
|
|
16463
|
-
const isConstructor = object => typeof object === 'function';
|
|
16464
|
-
function extend(objects) {
|
|
16465
|
-
if (isConstructor(objects)) {
|
|
16466
|
-
const Component = `${i++}`;
|
|
16467
|
-
catalogue[Component] = objects;
|
|
16468
|
-
return Component;
|
|
16469
|
-
} else {
|
|
16470
|
-
Object.assign(catalogue, objects);
|
|
16471
|
-
}
|
|
16472
|
-
}
|
|
16473
16612
|
function validateInstance(type, props) {
|
|
16474
16613
|
// Get target from catalogue
|
|
16475
16614
|
const name = toPascalCase(type);
|
|
16476
|
-
const target =
|
|
16615
|
+
const target = resolveConstructor(name);
|
|
16477
16616
|
|
|
16478
16617
|
// Validate element target
|
|
16479
16618
|
if (type !== 'primitive' && !target) throw new Error(`R3F: ${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`);
|
|
@@ -16487,7 +16626,7 @@ function validateInstance(type, props) {
|
|
|
16487
16626
|
function createInstance(type, props, root) {
|
|
16488
16627
|
var _props$object;
|
|
16489
16628
|
// Remove three* prefix from elements if native element not present
|
|
16490
|
-
type = toPascalCase(type)
|
|
16629
|
+
type = hasConstructor(toPascalCase(type)) ? type : type.replace(PREFIX_REGEX, '');
|
|
16491
16630
|
validateInstance(type, props);
|
|
16492
16631
|
|
|
16493
16632
|
// Regenerate the R3F instance for primitives to simulate a new object
|
|
@@ -16534,7 +16673,7 @@ function handleContainerEffects(parent, child, beforeChild) {
|
|
|
16534
16673
|
if (!child.object) {
|
|
16535
16674
|
var _child$props$object, _child$props$args;
|
|
16536
16675
|
// Get target from catalogue
|
|
16537
|
-
const target =
|
|
16676
|
+
const target = resolveConstructor(toPascalCase(child.type));
|
|
16538
16677
|
|
|
16539
16678
|
// Create object
|
|
16540
16679
|
child.object = (_child$props$object = child.props.object) != null ? _child$props$object : new target(...((_child$props$args = child.props.args) != null ? _child$props$args : []));
|
|
@@ -16631,6 +16770,9 @@ function disposeOnIdle(object) {
|
|
|
16631
16770
|
function removeChild(parent, child, dispose) {
|
|
16632
16771
|
if (!child) return;
|
|
16633
16772
|
|
|
16773
|
+
// Unlinking clears the parent, which invalidateInstance checks, so remember it
|
|
16774
|
+
const wasLinked = !!child.parent;
|
|
16775
|
+
|
|
16634
16776
|
// Unlink instances
|
|
16635
16777
|
child.parent = null;
|
|
16636
16778
|
const childIndex = parent.children.indexOf(child);
|
|
@@ -16668,7 +16810,11 @@ function removeChild(parent, child, dispose) {
|
|
|
16668
16810
|
}
|
|
16669
16811
|
|
|
16670
16812
|
// Tree was updated, request a frame for top-level instance
|
|
16671
|
-
if (dispose === undefined)
|
|
16813
|
+
if (dispose === undefined && wasLinked) {
|
|
16814
|
+
var _child$root;
|
|
16815
|
+
const state = (_child$root = child.root) == null ? void 0 : _child$root.getState == null ? void 0 : _child$root.getState();
|
|
16816
|
+
if (state && state.internal.frames === 0) state.invalidate();
|
|
16817
|
+
}
|
|
16672
16818
|
}
|
|
16673
16819
|
function setFiberRef(fiber, publicInstance) {
|
|
16674
16820
|
for (const _fiber of [fiber, fiber.alternate]) {
|
|
@@ -16729,7 +16875,7 @@ function swapReconstructedInstances() {
|
|
|
16729
16875
|
if (parent) {
|
|
16730
16876
|
var _instance$props$objec, _instance$props$args;
|
|
16731
16877
|
// Get target from catalogue
|
|
16732
|
-
const target =
|
|
16878
|
+
const target = resolveConstructor(toPascalCase(instance.type));
|
|
16733
16879
|
|
|
16734
16880
|
// Create object
|
|
16735
16881
|
const prevObject = instance.object;
|
|
@@ -17188,6 +17334,8 @@ function createRoot(canvas) {
|
|
|
17188
17334
|
});
|
|
17189
17335
|
}
|
|
17190
17336
|
applyRootConfiguration(root, canvas, props);
|
|
17337
|
+
// Only a range, including the default one, follows the display: a fixed dpr never touches matchMedia
|
|
17338
|
+
if (!root.unwatchDpr && (props.dpr === undefined || Array.isArray(props.dpr))) root.unwatchDpr = followDpr(root);
|
|
17191
17339
|
resolve(this);
|
|
17192
17340
|
};
|
|
17193
17341
|
const run = () => {
|
|
@@ -17272,26 +17420,6 @@ function Provider({
|
|
|
17272
17420
|
children: children
|
|
17273
17421
|
});
|
|
17274
17422
|
}
|
|
17275
|
-
|
|
17276
|
-
/**
|
|
17277
|
-
* Frees a renderer R3F built. WebGLRenderer.dispose() releases programs and caches but keeps its
|
|
17278
|
-
* context until garbage collection, and browsers cap live WebGL contexts, so the context is lost
|
|
17279
|
-
* after it. A WebGPURenderer (from a factory) releases its device and context inside dispose().
|
|
17280
|
-
*/
|
|
17281
|
-
function disposeRenderer(gl) {
|
|
17282
|
-
// Avoid starting initialization through three's dispose(). A factory must await init()
|
|
17283
|
-
// before returning its renderer so readiness includes initialization and teardown can wait.
|
|
17284
|
-
if ((gl.hasInitialized == null ? void 0 : gl.hasInitialized()) === false) return;
|
|
17285
|
-
const disposed = attempt(() => {
|
|
17286
|
-
var _gl$renderLists;
|
|
17287
|
-
return gl.dispose ? gl.dispose() : (_gl$renderLists = gl.renderLists) == null ? void 0 : _gl$renderLists.dispose == null ? void 0 : _gl$renderLists.dispose();
|
|
17288
|
-
});
|
|
17289
|
-
// WebGPURenderer.dispose() is async from three r186
|
|
17290
|
-
if (isPromiseLike(disposed)) {
|
|
17291
|
-
return Promise.resolve(disposed).catch(error => console.warn('[R3F] Error disposing renderer', error)).then(() => attempt(() => gl.forceContextLoss == null ? void 0 : gl.forceContextLoss()));
|
|
17292
|
-
}
|
|
17293
|
-
attempt(() => gl.forceContextLoss == null ? void 0 : gl.forceContextLoss());
|
|
17294
|
-
}
|
|
17295
17423
|
function attempt(step) {
|
|
17296
17424
|
try {
|
|
17297
17425
|
return step();
|
|
@@ -17324,21 +17452,11 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
17324
17452
|
state.internal.active = false;
|
|
17325
17453
|
|
|
17326
17454
|
// Release what uses the renderer before the renderer itself
|
|
17455
|
+
attempt(() => root.unwatchDpr == null ? void 0 : root.unwatchDpr());
|
|
17327
17456
|
attempt(() => state.events.disconnect == null ? void 0 : state.events.disconnect());
|
|
17328
17457
|
if ((_state$gl = state.gl) != null && _state$gl.xr) attempt(() => state.xr.disconnect());
|
|
17329
17458
|
if (state.scene) attempt(() => dispose(state.scene));
|
|
17330
|
-
const
|
|
17331
|
-
let disposal = undefined;
|
|
17332
|
-
if (gl && root.ownsRenderer) {
|
|
17333
|
-
disposal = attempt(() => disposeRenderer(gl));
|
|
17334
|
-
} else if (gl) {
|
|
17335
|
-
// A renderer passed in keeps its 9.x teardown: its context is lost but it is not disposed
|
|
17336
|
-
attempt(() => {
|
|
17337
|
-
var _gl$renderLists2;
|
|
17338
|
-
return (_gl$renderLists2 = gl.renderLists) == null ? void 0 : _gl$renderLists2.dispose == null ? void 0 : _gl$renderLists2.dispose();
|
|
17339
|
-
});
|
|
17340
|
-
attempt(() => gl.forceContextLoss == null ? void 0 : gl.forceContextLoss());
|
|
17341
|
-
}
|
|
17459
|
+
const disposal = attempt(() => releaseRenderer(state.gl, root.ownsRenderer));
|
|
17342
17460
|
if (isPromiseLike(disposal)) disposal.then(() => callback == null ? void 0 : callback(canvas));else callback == null ? void 0 : callback(canvas);
|
|
17343
17461
|
};
|
|
17344
17462
|
reconciler.updateContainer(null, root.fiber, null, () => {
|
|
@@ -17508,93 +17626,132 @@ function createPortal(children, container, state) {
|
|
|
17508
17626
|
state: state
|
|
17509
17627
|
});
|
|
17510
17628
|
}
|
|
17629
|
+
function initializePortal(options, initialState) {
|
|
17630
|
+
const {
|
|
17631
|
+
parentStore,
|
|
17632
|
+
container
|
|
17633
|
+
} = options;
|
|
17634
|
+
const portalStore = createWithEqualityFn((set, get) => ({
|
|
17635
|
+
...initialState,
|
|
17636
|
+
set,
|
|
17637
|
+
get,
|
|
17638
|
+
// Create once with the store's setter, without retaining a state snapshot.
|
|
17639
|
+
setEvents: events => set(state => ({
|
|
17640
|
+
...state,
|
|
17641
|
+
events: {
|
|
17642
|
+
...state.events,
|
|
17643
|
+
...events
|
|
17644
|
+
}
|
|
17645
|
+
}))
|
|
17646
|
+
}));
|
|
17647
|
+
const parentStateRef = {
|
|
17648
|
+
current: parentStore.getState()
|
|
17649
|
+
};
|
|
17650
|
+
portalStore.setState(portalState => inject(parentStateRef.current, portalState, options));
|
|
17651
|
+
return {
|
|
17652
|
+
parentStore,
|
|
17653
|
+
container,
|
|
17654
|
+
portalStore,
|
|
17655
|
+
parentStateRef
|
|
17656
|
+
};
|
|
17657
|
+
}
|
|
17511
17658
|
function Portal({
|
|
17512
17659
|
state = {},
|
|
17513
17660
|
children,
|
|
17514
17661
|
container
|
|
17515
17662
|
}) {
|
|
17516
|
-
|
|
17517
|
-
* if this is our environment, then we are not in r3f's renderer but in react-dom, it would trigger
|
|
17518
|
-
* the "R3F hooks can only be used within the Canvas component!" warning:
|
|
17519
|
-
* <Canvas>
|
|
17520
|
-
* {createPortal(...)} */
|
|
17663
|
+
const parentStore = useStore();
|
|
17521
17664
|
const {
|
|
17522
17665
|
events,
|
|
17523
17666
|
size,
|
|
17524
17667
|
...rest
|
|
17525
17668
|
} = state;
|
|
17526
|
-
const previousRoot = useStore();
|
|
17527
17669
|
const [raycaster] = React.useState(() => new THREE.Raycaster());
|
|
17528
17670
|
const [pointer] = React.useState(() => new THREE.Vector2());
|
|
17529
|
-
const
|
|
17530
|
-
|
|
17531
|
-
|
|
17532
|
-
|
|
17533
|
-
|
|
17534
|
-
|
|
17535
|
-
|
|
17536
|
-
|
|
17537
|
-
|
|
17538
|
-
|
|
17539
|
-
|
|
17540
|
-
|
|
17541
|
-
|
|
17542
|
-
|
|
17543
|
-
|
|
17544
|
-
|
|
17545
|
-
|
|
17546
|
-
|
|
17547
|
-
|
|
17548
|
-
|
|
17549
|
-
|
|
17550
|
-
|
|
17551
|
-
|
|
17552
|
-
|
|
17553
|
-
|
|
17554
|
-
},
|
|
17555
|
-
size: {
|
|
17556
|
-
...rootState.size,
|
|
17557
|
-
...size
|
|
17558
|
-
},
|
|
17559
|
-
viewport: {
|
|
17560
|
-
...rootState.viewport,
|
|
17561
|
-
...viewport
|
|
17562
|
-
},
|
|
17563
|
-
// Layers are allowed to override events
|
|
17564
|
-
setEvents: events => injectState.set(state => ({
|
|
17565
|
-
...state,
|
|
17566
|
-
events: {
|
|
17567
|
-
...state.events,
|
|
17568
|
-
...events
|
|
17569
|
-
}
|
|
17570
|
-
}))
|
|
17671
|
+
const options = {
|
|
17672
|
+
parentStore,
|
|
17673
|
+
container,
|
|
17674
|
+
raycaster,
|
|
17675
|
+
pointer,
|
|
17676
|
+
events,
|
|
17677
|
+
size
|
|
17678
|
+
};
|
|
17679
|
+
const injectRef = useMutableCallback((parentState, portalState) => inject(parentState, portalState, options));
|
|
17680
|
+
|
|
17681
|
+
// Initialize during render. Keep the store in state so Activity can preserve it.
|
|
17682
|
+
const [portal, setPortal] = React.useState(() => initializePortal(options, rest));
|
|
17683
|
+
if (portal.parentStore !== parentStore || portal.container !== container) {
|
|
17684
|
+
setPortal(initializePortal(options, rest));
|
|
17685
|
+
}
|
|
17686
|
+
const {
|
|
17687
|
+
portalStore,
|
|
17688
|
+
parentStateRef
|
|
17689
|
+
} = portal;
|
|
17690
|
+
|
|
17691
|
+
// Subscribe after commit and update the portal on each parent change.
|
|
17692
|
+
useIsomorphicLayoutEffect(() => {
|
|
17693
|
+
const update = parentState => {
|
|
17694
|
+
parentStateRef.current = parentState;
|
|
17695
|
+
portalStore.setState(portalState => injectRef.current(parentState, portalState));
|
|
17571
17696
|
};
|
|
17572
|
-
|
|
17573
|
-
const usePortalStore = React.useMemo(() => {
|
|
17574
|
-
// Create a mirrored store, based on the previous root with a few overrides ...
|
|
17575
|
-
const store = createWithEqualityFn((set, get) => ({
|
|
17576
|
-
...rest,
|
|
17577
|
-
set,
|
|
17578
|
-
get
|
|
17579
|
-
}));
|
|
17697
|
+
const unsubscribe = parentStore.subscribe(update);
|
|
17580
17698
|
|
|
17581
|
-
//
|
|
17582
|
-
const
|
|
17583
|
-
|
|
17584
|
-
|
|
17585
|
-
|
|
17586
|
-
|
|
17587
|
-
}, [
|
|
17588
|
-
return (
|
|
17589
|
-
/*#__PURE__*/
|
|
17590
|
-
|
|
17591
|
-
|
|
17592
|
-
|
|
17593
|
-
|
|
17594
|
-
|
|
17595
|
-
|
|
17596
|
-
|
|
17597
|
-
|
|
17699
|
+
// Catch up on changes made before subscribing or while Activity was hidden.
|
|
17700
|
+
const parentState = parentStore.getState();
|
|
17701
|
+
if (parentState !== parentStateRef.current) update(parentState);
|
|
17702
|
+
|
|
17703
|
+
// Clean up when hidden, unmounted or switching stores.
|
|
17704
|
+
return unsubscribe;
|
|
17705
|
+
}, [parentStore, portalStore, parentStateRef]);
|
|
17706
|
+
return /*#__PURE__*/jsx(Fragment, {
|
|
17707
|
+
children: reconciler.createPortal( /*#__PURE__*/jsx(context.Provider, {
|
|
17708
|
+
value: portalStore,
|
|
17709
|
+
children: children
|
|
17710
|
+
}), portalStore, null)
|
|
17711
|
+
});
|
|
17712
|
+
}
|
|
17713
|
+
function inject(parentState, portalState, options) {
|
|
17714
|
+
const {
|
|
17715
|
+
parentStore,
|
|
17716
|
+
container,
|
|
17717
|
+
raycaster,
|
|
17718
|
+
pointer,
|
|
17719
|
+
events,
|
|
17720
|
+
size
|
|
17721
|
+
} = options;
|
|
17722
|
+
let viewport = undefined;
|
|
17723
|
+
if (portalState.camera && size) {
|
|
17724
|
+
const camera = portalState.camera;
|
|
17725
|
+
// Calculate the override viewport, if present
|
|
17726
|
+
viewport = parentState.viewport.getCurrentViewport(camera, new THREE.Vector3(), size);
|
|
17727
|
+
// Update the portal camera, if it differs from the previous layer
|
|
17728
|
+
if (camera !== parentState.camera) updateCamera(camera, size);
|
|
17729
|
+
}
|
|
17730
|
+
return {
|
|
17731
|
+
// Inherit parent values and preserve the portal's own state.
|
|
17732
|
+
...parentState,
|
|
17733
|
+
...portalState,
|
|
17734
|
+
// Portals have their own scene, raycaster and pointer.
|
|
17735
|
+
scene: container,
|
|
17736
|
+
raycaster,
|
|
17737
|
+
pointer,
|
|
17738
|
+
mouse: pointer,
|
|
17739
|
+
previousRoot: parentStore,
|
|
17740
|
+
// Apply the portal's event, size and viewport overrides.
|
|
17741
|
+
events: {
|
|
17742
|
+
...parentState.events,
|
|
17743
|
+
...portalState.events,
|
|
17744
|
+
...events
|
|
17745
|
+
},
|
|
17746
|
+
size: {
|
|
17747
|
+
...parentState.size,
|
|
17748
|
+
...size
|
|
17749
|
+
},
|
|
17750
|
+
viewport: {
|
|
17751
|
+
...parentState.viewport,
|
|
17752
|
+
...viewport
|
|
17753
|
+
}
|
|
17754
|
+
};
|
|
17598
17755
|
}
|
|
17599
17756
|
|
|
17600
17757
|
const DOM_EVENTS = {
|