@react-three/fiber 8.16.7 → 8.17.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.
@@ -2,17 +2,17 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('./index-4664c596.cjs.prod.js');
5
+ var events = require('./events-2e7e6eab.cjs.prod.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');
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,99 +36,187 @@ 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
- } = index.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 => {
82
- var _events$handlers;
83
- const {
84
- set,
85
- events
86
- } = store.getState();
87
- events.disconnect == null ? void 0 : events.disconnect();
88
- set(state => ({
89
- events: {
90
- ...state.events,
91
- connected: target
92
- }
93
- }));
94
- Object.entries((_events$handlers = events.handlers) != null ? _events$handlers : []).forEach(([name, event]) => {
95
- const [eventName, passive] = DOM_EVENTS[name];
96
- target.addEventListener(eventName, event, {
97
- passive
98
- });
99
- });
100
- },
101
- disconnect: () => {
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
+ });
80
+
81
+ // set actual debounce values early, so effects know if they should react accordingly
82
+ const scrollDebounce = debounce ? typeof debounce === 'number' ? debounce : debounce.scroll : null;
83
+ const resizeDebounce = debounce ? typeof debounce === 'number' ? debounce : debounce.resize : null;
84
+
85
+ // make sure to update state only as long as the component is truly mounted
86
+ const mounted = React.useRef(false);
87
+ React.useEffect(() => {
88
+ mounted.current = true;
89
+ return () => void (mounted.current = false);
90
+ });
91
+
92
+ // memoize handlers, so event-listeners know when they should update
93
+ const [forceRefresh, resizeChange, scrollChange] = React.useMemo(() => {
94
+ const callback = () => {
95
+ if (!state.current.element) return;
102
96
  const {
103
- set,
104
- events
105
- } = store.getState();
106
- if (events.connected) {
107
- var _events$handlers2;
108
- Object.entries((_events$handlers2 = events.handlers) != null ? _events$handlers2 : []).forEach(([name, event]) => {
109
- if (events && events.connected instanceof HTMLElement) {
110
- const [eventName] = DOM_EVENTS[name];
111
- events.connected.removeEventListener(eventName, event);
112
- }
113
- });
114
- set(state => ({
115
- events: {
116
- ...state.events,
117
- connected: undefined
118
- }
119
- }));
97
+ left,
98
+ top,
99
+ width,
100
+ height,
101
+ bottom,
102
+ right,
103
+ x,
104
+ y
105
+ } = state.current.element.getBoundingClientRect();
106
+ const size = {
107
+ left,
108
+ top,
109
+ width,
110
+ height,
111
+ bottom,
112
+ right,
113
+ x,
114
+ y
115
+ };
116
+ if (state.current.element instanceof HTMLElement && offsetSize) {
117
+ size.height = state.current.element.offsetHeight;
118
+ size.width = state.current.element.offsetWidth;
120
119
  }
120
+ Object.freeze(size);
121
+ if (mounted.current && !areBoundsEqual(state.current.lastBounds, size)) set(state.current.lastBounds = size);
122
+ };
123
+ return [callback, resizeDebounce ? createDebounce__default["default"](callback, resizeDebounce) : callback, scrollDebounce ? createDebounce__default["default"](callback, scrollDebounce) : callback];
124
+ }, [set, offsetSize, scrollDebounce, resizeDebounce]);
125
+
126
+ // cleanup current scroll-listeners / observers
127
+ function removeListeners() {
128
+ if (state.current.scrollContainers) {
129
+ state.current.scrollContainers.forEach(element => element.removeEventListener('scroll', scrollChange, true));
130
+ state.current.scrollContainers = null;
131
+ }
132
+ if (state.current.resizeObserver) {
133
+ state.current.resizeObserver.disconnect();
134
+ state.current.resizeObserver = null;
121
135
  }
136
+ }
137
+
138
+ // add scroll-listeners / observers
139
+ function addListeners() {
140
+ if (!state.current.element) return;
141
+ state.current.resizeObserver = new ResizeObserver(scrollChange);
142
+ state.current.resizeObserver.observe(state.current.element);
143
+ if (scroll && state.current.scrollContainers) {
144
+ state.current.scrollContainers.forEach(scrollContainer => scrollContainer.addEventListener('scroll', scrollChange, {
145
+ capture: true,
146
+ passive: true
147
+ }));
148
+ }
149
+ }
150
+
151
+ // the ref we expose to the user
152
+ const ref = node => {
153
+ if (!node || node === state.current.element) return;
154
+ removeListeners();
155
+ state.current.element = node;
156
+ state.current.scrollContainers = findScrollContainers(node);
157
+ addListeners();
122
158
  };
159
+
160
+ // add general event listeners
161
+ useOnWindowScroll(scrollChange, Boolean(scroll));
162
+ useOnWindowResize(resizeChange);
163
+
164
+ // respond to changes that are relevant for the listeners
165
+ React.useEffect(() => {
166
+ removeListeners();
167
+ addListeners();
168
+ }, [scroll, scrollChange, resizeChange]);
169
+
170
+ // remove all listeners when the components unmounts
171
+ React.useEffect(() => removeListeners, []);
172
+ return [ref, bounds, forceRefresh];
173
+ }
174
+
175
+ // Adds native resize listener to window
176
+ function useOnWindowResize(onWindowResize) {
177
+ React.useEffect(() => {
178
+ const cb = onWindowResize;
179
+ window.addEventListener('resize', cb);
180
+ return () => void window.removeEventListener('resize', cb);
181
+ }, [onWindowResize]);
182
+ }
183
+ function useOnWindowScroll(onScroll, enabled) {
184
+ React.useEffect(() => {
185
+ if (enabled) {
186
+ const cb = onScroll;
187
+ window.addEventListener('scroll', cb, {
188
+ capture: true,
189
+ passive: true
190
+ });
191
+ return () => void window.removeEventListener('scroll', cb, true);
192
+ }
193
+ }, [onScroll, enabled]);
123
194
  }
124
195
 
196
+ // Returns a list of scroll offsets
197
+ function findScrollContainers(element) {
198
+ const result = [];
199
+ if (!element || element === document.body) return result;
200
+ const {
201
+ overflow,
202
+ overflowX,
203
+ overflowY
204
+ } = window.getComputedStyle(element);
205
+ if ([overflow, overflowX, overflowY].some(prop => prop === 'auto' || prop === 'scroll')) result.push(element);
206
+ return [...result, ...findScrollContainers(element.parentElement)];
207
+ }
208
+
209
+ // Checks if element boundaries are equal
210
+ const keys = ['x', 'y', 'top', 'bottom', 'left', 'right', 'width', 'height'];
211
+ const areBoundsEqual = (a, b) => keys.every(key => a[key] === b[key]);
212
+
125
213
  const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
126
214
  children,
127
215
  fallback,
128
216
  resize,
129
217
  style,
130
218
  gl,
131
- events = createPointerEvents,
219
+ events: events$1 = events.createPointerEvents,
132
220
  eventSource,
133
221
  eventPrefix,
134
222
  shadows,
@@ -149,9 +237,9 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
149
237
  // Create a known catalogue of Threejs-native elements
150
238
  // This will include the entire THREE namespace by default, users can extend
151
239
  // their own elements by using the createRoot API instead
152
- React__namespace.useMemo(() => index.extend(THREE__namespace), []);
240
+ React__namespace.useMemo(() => events.extend(THREE__namespace), []);
153
241
  const Bridge = itsFine.useContextBridge();
154
- const [containerRef, containerRect] = useMeasure__default["default"]({
242
+ const [containerRef, containerRect] = useMeasure({
155
243
  scroll: true,
156
244
  debounce: {
157
245
  scroll: 50,
@@ -162,7 +250,7 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
162
250
  const canvasRef = React__namespace.useRef(null);
163
251
  const divRef = React__namespace.useRef(null);
164
252
  React__namespace.useImperativeHandle(forwardedRef, () => canvasRef.current);
165
- const handlePointerMissed = index.useMutableCallback(onPointerMissed);
253
+ const handlePointerMissed = events.useMutableCallback(onPointerMissed);
166
254
  const [block, setBlock] = React__namespace.useState(false);
167
255
  const [error, setError] = React__namespace.useState(false);
168
256
 
@@ -171,13 +259,13 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
171
259
  // Throw exception outwards if anything within canvas throws
172
260
  if (error) throw error;
173
261
  const root = React__namespace.useRef(null);
174
- index.useIsomorphicLayoutEffect(() => {
262
+ events.useIsomorphicLayoutEffect(() => {
175
263
  const canvas = canvasRef.current;
176
264
  if (containerRect.width > 0 && containerRect.height > 0 && canvas) {
177
- if (!root.current) root.current = index.createRoot(canvas);
265
+ if (!root.current) root.current = events.createRoot(canvas);
178
266
  root.current.configure({
179
267
  gl,
180
- events,
268
+ events: events$1,
181
269
  shadows,
182
270
  linear,
183
271
  flat,
@@ -194,7 +282,7 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
194
282
  onPointerMissed: (...args) => handlePointerMissed.current == null ? void 0 : handlePointerMissed.current(...args),
195
283
  onCreated: state => {
196
284
  // Connect to event source
197
- state.events.connect == null ? void 0 : state.events.connect(eventSource ? index.isRef(eventSource) ? eventSource.current : eventSource : divRef.current);
285
+ state.events.connect == null ? void 0 : state.events.connect(eventSource ? events.isRef(eventSource) ? eventSource.current : eventSource : divRef.current);
198
286
  // Set up compute function
199
287
  if (eventPrefix) {
200
288
  state.setEvents({
@@ -211,10 +299,10 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
211
299
  }
212
300
  });
213
301
  root.current.render( /*#__PURE__*/jsxRuntime.jsx(Bridge, {
214
- children: /*#__PURE__*/jsxRuntime.jsx(index.ErrorBoundary, {
302
+ children: /*#__PURE__*/jsxRuntime.jsx(events.ErrorBoundary, {
215
303
  set: setError,
216
304
  children: /*#__PURE__*/jsxRuntime.jsx(React__namespace.Suspense, {
217
- fallback: /*#__PURE__*/jsxRuntime.jsx(index.Block, {
305
+ fallback: /*#__PURE__*/jsxRuntime.jsx(events.Block, {
218
306
  set: setBlock
219
307
  }),
220
308
  children: children
@@ -225,7 +313,7 @@ const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
225
313
  });
226
314
  React__namespace.useEffect(() => {
227
315
  const canvas = canvasRef.current;
228
- if (canvas) return () => index.unmountComponentAtNode(canvas);
316
+ if (canvas) return () => events.unmountComponentAtNode(canvas);
229
317
  }, []);
230
318
 
231
319
  // When the event source is not this div, we need to set pointer-events to none
@@ -272,32 +360,34 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function CanvasWrapper(p
272
360
  });
273
361
  });
274
362
 
275
- exports.ReactThreeFiber = index.threeTypes;
276
- exports._roots = index.roots;
277
- exports.act = index.act;
278
- exports.addAfterEffect = index.addAfterEffect;
279
- exports.addEffect = index.addEffect;
280
- exports.addTail = index.addTail;
281
- exports.advance = index.advance;
282
- exports.applyProps = index.applyProps;
283
- exports.buildGraph = index.buildGraph;
284
- exports.context = index.context;
285
- exports.createEvents = index.createEvents;
286
- exports.createPortal = index.createPortal;
287
- exports.createRoot = index.createRoot;
288
- exports.dispose = index.dispose;
289
- exports.extend = index.extend;
290
- exports.flushGlobalEffects = index.flushGlobalEffects;
291
- exports.getRootState = index.getRootState;
292
- exports.invalidate = index.invalidate;
293
- exports.reconciler = index.reconciler;
294
- exports.render = index.render;
295
- exports.unmountComponentAtNode = index.unmountComponentAtNode;
296
- exports.useFrame = index.useFrame;
297
- exports.useGraph = index.useGraph;
298
- exports.useInstanceHandle = index.useInstanceHandle;
299
- exports.useLoader = index.useLoader;
300
- exports.useStore = index.useStore;
301
- exports.useThree = index.useThree;
363
+ exports.ReactThreeFiber = events.threeTypes;
364
+ exports._roots = events.roots;
365
+ exports.act = events.act;
366
+ exports.addAfterEffect = events.addAfterEffect;
367
+ exports.addEffect = events.addEffect;
368
+ exports.addTail = events.addTail;
369
+ exports.advance = events.advance;
370
+ exports.applyProps = events.applyProps;
371
+ exports.buildGraph = events.buildGraph;
372
+ exports.context = events.context;
373
+ exports.createEvents = events.createEvents;
374
+ exports.createPointerEvents = events.createPointerEvents;
375
+ exports.createPortal = events.createPortal;
376
+ exports.createRoot = events.createRoot;
377
+ exports.dispose = events.dispose;
378
+ exports.events = events.createPointerEvents;
379
+ exports.extend = events.extend;
380
+ exports.flushGlobalEffects = events.flushGlobalEffects;
381
+ exports.flushSync = events.flushSync;
382
+ exports.getRootState = events.getRootState;
383
+ exports.invalidate = events.invalidate;
384
+ exports.reconciler = events.reconciler;
385
+ exports.render = events.render;
386
+ exports.unmountComponentAtNode = events.unmountComponentAtNode;
387
+ exports.useFrame = events.useFrame;
388
+ exports.useGraph = events.useGraph;
389
+ exports.useInstanceHandle = events.useInstanceHandle;
390
+ exports.useLoader = events.useLoader;
391
+ exports.useStore = events.useStore;
392
+ exports.useThree = events.useThree;
302
393
  exports.Canvas = Canvas;
303
- exports.events = createPointerEvents;