@react-three/fiber 9.0.0-beta.1 → 9.0.0-rc.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.
Files changed (27) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/dist/declarations/src/core/events.d.ts +91 -0
  3. package/dist/declarations/src/core/hooks.d.ts +52 -0
  4. package/dist/declarations/src/core/index.d.ts +13 -0
  5. package/dist/declarations/src/core/loop.d.ts +31 -0
  6. package/dist/declarations/src/core/reconciler.d.ts +55 -0
  7. package/dist/declarations/src/core/renderer.d.ts +87 -0
  8. package/dist/declarations/src/core/store.d.ts +130 -0
  9. package/dist/declarations/src/core/utils.d.ts +138 -0
  10. package/dist/declarations/src/index.d.ts +6 -0
  11. package/dist/declarations/src/native/Canvas.d.ts +14 -0
  12. package/dist/declarations/src/native/events.d.ts +4 -0
  13. package/dist/declarations/src/native.d.ts +6 -0
  14. package/dist/declarations/src/three-types.d.ts +62 -0
  15. package/dist/declarations/src/web/Canvas.d.ts +24 -0
  16. package/dist/declarations/src/web/events.d.ts +4 -0
  17. package/dist/declarations/src/web/use-measure.d.ts +34 -0
  18. package/dist/{loop-b00a3b86.esm.js → events-26d2636c.esm.js} +99 -17
  19. package/dist/{loop-dfcc9ca9.cjs.prod.js → events-cb1a9ea0.cjs.prod.js} +99 -16
  20. package/dist/{loop-eb3c7218.cjs.dev.js → events-df578889.cjs.dev.js} +99 -16
  21. package/dist/react-three-fiber.cjs.dev.js +230 -122
  22. package/dist/react-three-fiber.cjs.prod.js +230 -122
  23. package/dist/react-three-fiber.esm.js +193 -84
  24. package/native/dist/react-three-fiber-native.cjs.dev.js +190 -128
  25. package/native/dist/react-three-fiber-native.cjs.prod.js +190 -128
  26. package/native/dist/react-three-fiber-native.esm.js +157 -95
  27. package/package.json +88 -86
@@ -2,17 +2,17 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var loop = require('./loop-eb3c7218.cjs.dev.js');
5
+ var events = require('./events-df578889.cjs.dev.js');
6
6
  var React = require('react');
7
7
  var THREE = require('three');
8
- var useMeasure = require('react-use-measure');
8
+ var createDebounce = require('debounce');
9
9
  var itsFine = require('its-fine');
10
10
  var jsxRuntime = require('react/jsx-runtime');
11
11
  require('react-reconciler/constants');
12
12
  require('zustand/traditional');
13
+ require('suspend-react');
13
14
  require('react-reconciler');
14
15
  require('scheduler');
15
- require('suspend-react');
16
16
 
17
17
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
18
18
 
@@ -36,93 +36,201 @@ function _interopNamespace(e) {
36
36
 
37
37
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
38
38
  var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
39
- var useMeasure__default = /*#__PURE__*/_interopDefault(useMeasure);
39
+ var createDebounce__default = /*#__PURE__*/_interopDefault(createDebounce);
40
40
 
41
- const DOM_EVENTS = {
42
- onClick: ['click', false],
43
- onContextMenu: ['contextmenu', false],
44
- onDoubleClick: ['dblclick', false],
45
- onWheel: ['wheel', true],
46
- onPointerDown: ['pointerdown', true],
47
- onPointerUp: ['pointerup', true],
48
- onPointerLeave: ['pointerleave', true],
49
- onPointerMove: ['pointermove', true],
50
- onPointerCancel: ['pointercancel', true],
51
- onLostPointerCapture: ['lostpointercapture', true]
52
- };
41
+ /* eslint-disable react-hooks/rules-of-hooks */
42
+ function useMeasure({
43
+ debounce,
44
+ scroll,
45
+ polyfill,
46
+ offsetSize
47
+ } = {
48
+ debounce: 0,
49
+ scroll: false,
50
+ offsetSize: false
51
+ }) {
52
+ const ResizeObserver = polyfill || typeof window !== 'undefined' && window.ResizeObserver;
53
+ const [bounds, set] = React.useState({
54
+ left: 0,
55
+ top: 0,
56
+ width: 0,
57
+ height: 0,
58
+ bottom: 0,
59
+ right: 0,
60
+ x: 0,
61
+ y: 0
62
+ });
53
63
 
54
- /** Default R3F event manager for web */
55
- function createPointerEvents(store) {
56
- const {
57
- handlePointer
58
- } = loop.createEvents(store);
59
- return {
60
- priority: 1,
61
- enabled: true,
62
- compute(event, state, previous) {
63
- // https://github.com/pmndrs/react-three-fiber/pull/782
64
- // Events trigger outside of canvas when moved, use offsetX/Y by default and allow overrides
65
- state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
66
- state.raycaster.setFromCamera(state.pointer, state.camera);
67
- },
68
- connected: undefined,
69
- handlers: Object.keys(DOM_EVENTS).reduce((acc, key) => ({
70
- ...acc,
71
- [key]: handlePointer(key)
72
- }), {}),
73
- update: () => {
74
- var _internal$lastEvent;
75
- const {
76
- events,
77
- internal
78
- } = store.getState();
79
- if ((_internal$lastEvent = internal.lastEvent) != null && _internal$lastEvent.current && events.handlers) events.handlers.onPointerMove(internal.lastEvent.current);
80
- },
81
- connect: target => {
64
+ // In test mode
65
+ if (!ResizeObserver) {
66
+ // @ts-ignore
67
+ bounds.width = 1280;
68
+ // @ts-ignore
69
+ bounds.height = 800;
70
+ return [() => {}, bounds, () => {}];
71
+ }
72
+
73
+ // keep all state in a ref
74
+ const state = React.useRef({
75
+ element: null,
76
+ scrollContainers: null,
77
+ resizeObserver: null,
78
+ lastBounds: bounds,
79
+ orientationHandler: null
80
+ });
81
+
82
+ // set actual debounce values early, so effects know if they should react accordingly
83
+ const scrollDebounce = debounce ? typeof debounce === 'number' ? debounce : debounce.scroll : null;
84
+ const resizeDebounce = debounce ? typeof debounce === 'number' ? debounce : debounce.resize : null;
85
+
86
+ // make sure to update state only as long as the component is truly mounted
87
+ const mounted = React.useRef(false);
88
+ React.useEffect(() => {
89
+ mounted.current = true;
90
+ return () => void (mounted.current = false);
91
+ });
92
+
93
+ // memoize handlers, so event-listeners know when they should update
94
+ const [forceRefresh, resizeChange, scrollChange] = React.useMemo(() => {
95
+ const callback = () => {
96
+ if (!state.current.element) return;
82
97
  const {
83
- set,
84
- events
85
- } = store.getState();
86
- events.disconnect == null ? void 0 : events.disconnect();
87
- set(state => ({
88
- events: {
89
- ...state.events,
90
- connected: target
91
- }
92
- }));
93
- if (events.handlers) {
94
- for (const name in events.handlers) {
95
- const event = events.handlers[name];
96
- const [eventName, passive] = DOM_EVENTS[name];
97
- target.addEventListener(eventName, event, {
98
- passive
99
- });
100
- }
98
+ left,
99
+ top,
100
+ width,
101
+ height,
102
+ bottom,
103
+ right,
104
+ x,
105
+ y
106
+ } = state.current.element.getBoundingClientRect();
107
+ const size = {
108
+ left,
109
+ top,
110
+ width,
111
+ height,
112
+ bottom,
113
+ right,
114
+ x,
115
+ y
116
+ };
117
+ if (state.current.element instanceof HTMLElement && offsetSize) {
118
+ size.height = state.current.element.offsetHeight;
119
+ size.width = state.current.element.offsetWidth;
101
120
  }
102
- },
103
- disconnect: () => {
104
- const {
105
- set,
106
- events
107
- } = store.getState();
108
- if (events.connected) {
109
- if (events.handlers) {
110
- for (const name in events.handlers) {
111
- const event = events.handlers[name];
112
- const [eventName] = DOM_EVENTS[name];
113
- events.connected.removeEventListener(eventName, event);
114
- }
115
- }
116
- set(state => ({
117
- events: {
118
- ...state.events,
119
- connected: undefined
120
- }
121
- }));
121
+ Object.freeze(size);
122
+ if (mounted.current && !areBoundsEqual(state.current.lastBounds, size)) set(state.current.lastBounds = size);
123
+ };
124
+ return [callback, resizeDebounce ? createDebounce__default["default"](callback, resizeDebounce) : callback, scrollDebounce ? createDebounce__default["default"](callback, scrollDebounce) : callback];
125
+ }, [set, offsetSize, scrollDebounce, resizeDebounce]);
126
+
127
+ // cleanup current scroll-listeners / observers
128
+ function removeListeners() {
129
+ if (state.current.scrollContainers) {
130
+ state.current.scrollContainers.forEach(element => element.removeEventListener('scroll', scrollChange, true));
131
+ state.current.scrollContainers = null;
132
+ }
133
+ if (state.current.resizeObserver) {
134
+ state.current.resizeObserver.disconnect();
135
+ state.current.resizeObserver = null;
136
+ }
137
+ if (state.current.orientationHandler) {
138
+ if ('orientation' in screen && 'removeEventListener' in screen.orientation) {
139
+ screen.orientation.removeEventListener('change', state.current.orientationHandler);
140
+ } else if ('onorientationchange' in window) {
141
+ window.removeEventListener('orientationchange', state.current.orientationHandler);
122
142
  }
123
143
  }
144
+ }
145
+
146
+ // add scroll-listeners / observers
147
+ function addListeners() {
148
+ var _state$current$resize;
149
+ if (!state.current.element) return;
150
+ state.current.resizeObserver = new ResizeObserver(resizeChange);
151
+ (_state$current$resize = state.current.resizeObserver) == null ? void 0 : _state$current$resize.observe(state.current.element);
152
+ if (scroll && state.current.scrollContainers) {
153
+ state.current.scrollContainers.forEach(scrollContainer => scrollContainer.addEventListener('scroll', scrollChange, {
154
+ capture: true,
155
+ passive: true
156
+ }));
157
+ }
158
+
159
+ // Handle orientation changes
160
+ state.current.orientationHandler = () => {
161
+ scrollChange();
162
+ };
163
+
164
+ // Use screen.orientation if available
165
+ if ('orientation' in screen && 'addEventListener' in screen.orientation) {
166
+ screen.orientation.addEventListener('change', state.current.orientationHandler);
167
+ } else if ('onorientationchange' in window) {
168
+ // Fallback to orientationchange event
169
+ window.addEventListener('orientationchange', state.current.orientationHandler);
170
+ }
171
+ }
172
+
173
+ // the ref we expose to the user
174
+ const ref = node => {
175
+ if (!node || node === state.current.element) return;
176
+ removeListeners();
177
+ state.current.element = node;
178
+ state.current.scrollContainers = findScrollContainers(node);
179
+ addListeners();
124
180
  };
181
+
182
+ // add general event listeners
183
+ useOnWindowScroll(scrollChange, Boolean(scroll));
184
+ useOnWindowResize(resizeChange);
185
+
186
+ // respond to changes that are relevant for the listeners
187
+ React.useEffect(() => {
188
+ removeListeners();
189
+ addListeners();
190
+ }, [scroll, scrollChange, resizeChange]);
191
+
192
+ // remove all listeners when the components unmounts
193
+ React.useEffect(() => removeListeners, []);
194
+ return [ref, bounds, forceRefresh];
195
+ }
196
+
197
+ // Adds native resize listener to window
198
+ function useOnWindowResize(onWindowResize) {
199
+ React.useEffect(() => {
200
+ const cb = onWindowResize;
201
+ window.addEventListener('resize', cb);
202
+ return () => void window.removeEventListener('resize', cb);
203
+ }, [onWindowResize]);
125
204
  }
205
+ function useOnWindowScroll(onScroll, enabled) {
206
+ React.useEffect(() => {
207
+ if (enabled) {
208
+ const cb = onScroll;
209
+ window.addEventListener('scroll', cb, {
210
+ capture: true,
211
+ passive: true
212
+ });
213
+ return () => void window.removeEventListener('scroll', cb, true);
214
+ }
215
+ }, [onScroll, enabled]);
216
+ }
217
+
218
+ // Returns a list of scroll offsets
219
+ function findScrollContainers(element) {
220
+ const result = [];
221
+ if (!element || element === document.body) return result;
222
+ const {
223
+ overflow,
224
+ overflowX,
225
+ overflowY
226
+ } = window.getComputedStyle(element);
227
+ if ([overflow, overflowX, overflowY].some(prop => prop === 'auto' || prop === 'scroll')) result.push(element);
228
+ return [...result, ...findScrollContainers(element.parentElement)];
229
+ }
230
+
231
+ // Checks if element boundaries are equal
232
+ const keys = ['x', 'y', 'top', 'bottom', 'left', 'right', 'width', 'height'];
233
+ const areBoundsEqual = (a, b) => keys.every(key => a[key] === b[key]);
126
234
 
127
235
  const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
128
236
  children,
@@ -130,7 +238,7 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
130
238
  resize,
131
239
  style,
132
240
  gl,
133
- events = createPointerEvents,
241
+ events: events$1 = events.createPointerEvents,
134
242
  eventSource,
135
243
  eventPrefix,
136
244
  shadows,
@@ -151,9 +259,9 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
151
259
  // Create a known catalogue of Threejs-native elements
152
260
  // This will include the entire THREE namespace by default, users can extend
153
261
  // their own elements by using the createRoot API instead
154
- React__namespace.useMemo(() => loop.extend(THREE__namespace), []);
155
- const Bridge = loop.useBridge();
156
- const [containerRef, containerRect] = useMeasure__default["default"]({
262
+ React__namespace.useMemo(() => events.extend(THREE__namespace), []);
263
+ const Bridge = events.useBridge();
264
+ const [containerRef, containerRect] = useMeasure({
157
265
  scroll: true,
158
266
  debounce: {
159
267
  scroll: 50,
@@ -164,7 +272,7 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
164
272
  const canvasRef = React__namespace.useRef(null);
165
273
  const divRef = React__namespace.useRef(null);
166
274
  React__namespace.useImperativeHandle(forwardedRef, () => canvasRef.current);
167
- const handlePointerMissed = loop.useMutableCallback(onPointerMissed);
275
+ const handlePointerMissed = events.useMutableCallback(onPointerMissed);
168
276
  const [block, setBlock] = React__namespace.useState(false);
169
277
  const [error, setError] = React__namespace.useState(false);
170
278
 
@@ -173,14 +281,14 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
173
281
  // Throw exception outwards if anything within canvas throws
174
282
  if (error) throw error;
175
283
  const root = React__namespace.useRef(null);
176
- loop.useIsomorphicLayoutEffect(() => {
284
+ events.useIsomorphicLayoutEffect(() => {
177
285
  const canvas = canvasRef.current;
178
286
  if (containerRect.width > 0 && containerRect.height > 0 && canvas) {
179
- if (!root.current) root.current = loop.createRoot(canvas);
287
+ if (!root.current) root.current = events.createRoot(canvas);
180
288
  root.current.configure({
181
289
  gl,
182
290
  scene,
183
- events,
291
+ events: events$1,
184
292
  shadows,
185
293
  linear,
186
294
  flat,
@@ -196,7 +304,7 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
196
304
  onPointerMissed: (...args) => handlePointerMissed.current == null ? void 0 : handlePointerMissed.current(...args),
197
305
  onCreated: state => {
198
306
  // Connect to event source
199
- state.events.connect == null ? void 0 : state.events.connect(eventSource ? loop.isRef(eventSource) ? eventSource.current : eventSource : divRef.current);
307
+ state.events.connect == null ? void 0 : state.events.connect(eventSource ? events.isRef(eventSource) ? eventSource.current : eventSource : divRef.current);
200
308
  // Set up compute function
201
309
  if (eventPrefix) {
202
310
  state.setEvents({
@@ -213,10 +321,10 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
213
321
  }
214
322
  });
215
323
  root.current.render( /*#__PURE__*/jsxRuntime.jsx(Bridge, {
216
- children: /*#__PURE__*/jsxRuntime.jsx(loop.ErrorBoundary, {
324
+ children: /*#__PURE__*/jsxRuntime.jsx(events.ErrorBoundary, {
217
325
  set: setError,
218
326
  children: /*#__PURE__*/jsxRuntime.jsx(React__namespace.Suspense, {
219
- fallback: /*#__PURE__*/jsxRuntime.jsx(loop.Block, {
327
+ fallback: /*#__PURE__*/jsxRuntime.jsx(events.Block, {
220
328
  set: setBlock
221
329
  }),
222
330
  children: children
@@ -227,7 +335,7 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
227
335
  });
228
336
  React__namespace.useEffect(() => {
229
337
  const canvas = canvasRef.current;
230
- if (canvas) return () => loop.unmountComponentAtNode(canvas);
338
+ if (canvas) return () => events.unmountComponentAtNode(canvas);
231
339
  }, []);
232
340
 
233
341
  // When the event source is not this div, we need to set pointer-events to none
@@ -274,32 +382,32 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function CanvasWrapper(p
274
382
  });
275
383
  });
276
384
 
277
- exports.ReactThreeFiber = loop.threeTypes;
278
- exports._roots = loop._roots;
279
- exports.act = loop.act;
280
- exports.addAfterEffect = loop.addAfterEffect;
281
- exports.addEffect = loop.addEffect;
282
- exports.addTail = loop.addTail;
283
- exports.advance = loop.advance;
284
- exports.applyProps = loop.applyProps;
285
- exports.buildGraph = loop.buildGraph;
286
- exports.context = loop.context;
287
- exports.createEvents = loop.createEvents;
288
- exports.createPortal = loop.createPortal;
289
- exports.createRoot = loop.createRoot;
290
- exports.dispose = loop.dispose;
291
- exports.extend = loop.extend;
292
- exports.flushGlobalEffects = loop.flushGlobalEffects;
293
- exports.getRootState = loop.getRootState;
294
- exports.invalidate = loop.invalidate;
295
- exports.reconciler = loop.reconciler;
296
- exports.render = loop.render;
297
- exports.unmountComponentAtNode = loop.unmountComponentAtNode;
298
- exports.useFrame = loop.useFrame;
299
- exports.useGraph = loop.useGraph;
300
- exports.useInstanceHandle = loop.useInstanceHandle;
301
- exports.useLoader = loop.useLoader;
302
- exports.useStore = loop.useStore;
303
- exports.useThree = loop.useThree;
385
+ exports.ReactThreeFiber = events.threeTypes;
386
+ exports._roots = events._roots;
387
+ exports.act = events.act;
388
+ exports.addAfterEffect = events.addAfterEffect;
389
+ exports.addEffect = events.addEffect;
390
+ exports.addTail = events.addTail;
391
+ exports.advance = events.advance;
392
+ exports.applyProps = events.applyProps;
393
+ exports.buildGraph = events.buildGraph;
394
+ exports.context = events.context;
395
+ exports.createEvents = events.createEvents;
396
+ exports.createPortal = events.createPortal;
397
+ exports.createRoot = events.createRoot;
398
+ exports.dispose = events.dispose;
399
+ exports.events = events.createPointerEvents;
400
+ exports.extend = events.extend;
401
+ exports.flushGlobalEffects = events.flushGlobalEffects;
402
+ exports.getRootState = events.getRootState;
403
+ exports.invalidate = events.invalidate;
404
+ exports.reconciler = events.reconciler;
405
+ exports.render = events.render;
406
+ exports.unmountComponentAtNode = events.unmountComponentAtNode;
407
+ exports.useFrame = events.useFrame;
408
+ exports.useGraph = events.useGraph;
409
+ exports.useInstanceHandle = events.useInstanceHandle;
410
+ exports.useLoader = events.useLoader;
411
+ exports.useStore = events.useStore;
412
+ exports.useThree = events.useThree;
304
413
  exports.Canvas = Canvas;
305
- exports.events = createPointerEvents;