@react-three/fiber 8.0.0-alpha-08 → 8.0.0-beta-02

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 (32) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/dist/declarations/src/core/events.d.ts +63 -59
  3. package/dist/declarations/src/core/hooks.d.ts +21 -29
  4. package/dist/declarations/src/core/loop.d.ts +12 -12
  5. package/dist/declarations/src/core/renderer.d.ts +50 -62
  6. package/dist/declarations/src/core/store.d.ts +111 -106
  7. package/dist/declarations/src/core/utils.d.ts +43 -0
  8. package/dist/declarations/src/index.d.ts +7 -7
  9. package/dist/declarations/src/native/Canvas.d.ts +16 -0
  10. package/dist/declarations/src/native/events.d.ts +6 -0
  11. package/dist/declarations/src/native/hooks.d.ts +9 -0
  12. package/dist/declarations/src/native/index.d.ts +37 -0
  13. package/dist/declarations/src/native.d.ts +7 -0
  14. package/dist/declarations/src/three-types.d.ts +320 -319
  15. package/dist/declarations/src/web/Canvas.d.ts +13 -13
  16. package/dist/declarations/src/web/events.d.ts +5 -4
  17. package/dist/declarations/src/web/index.d.ts +34 -30
  18. package/dist/hooks-c89a6f88.esm.js +1455 -0
  19. package/dist/hooks-dd693347.cjs.dev.js +1501 -0
  20. package/dist/hooks-e01f12ec.cjs.prod.js +1501 -0
  21. package/dist/react-three-fiber.cjs.dev.js +140 -1482
  22. package/dist/react-three-fiber.cjs.prod.js +140 -1482
  23. package/dist/react-three-fiber.esm.js +121 -1460
  24. package/native/dist/react-three-fiber-native.cjs.d.ts +1 -0
  25. package/native/dist/react-three-fiber-native.cjs.dev.js +590 -0
  26. package/native/dist/react-three-fiber-native.cjs.js +7 -0
  27. package/native/dist/react-three-fiber-native.cjs.prod.js +590 -0
  28. package/native/dist/react-three-fiber-native.esm.js +538 -0
  29. package/native/package.json +5 -0
  30. package/package.json +16 -5
  31. package/__mocks__/react-use-measure/index.ts +0 -22
  32. package/dist/declarations/src/core/is.d.ts +0 -9
@@ -2,16 +2,18 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var hooks = require('./hooks-dd693347.cjs.dev.js');
5
6
  var THREE = require('three');
6
7
  var React = require('react');
7
8
  var constants = require('react-reconciler/constants');
8
- var create = require('zustand');
9
- var shallow = require('zustand/shallow');
10
- var Reconciler = require('react-reconciler');
11
- var scheduler = require('scheduler');
12
- var useAsset = require('use-asset');
9
+ var _extends = require('@babel/runtime/helpers/extends');
13
10
  var mergeRefs = require('react-merge-refs');
14
11
  var useMeasure = require('react-use-measure');
12
+ var pick = require('lodash-es/pick');
13
+ var omit = require('lodash-es/omit');
14
+ require('react-reconciler');
15
+ require('suspend-react');
16
+ require('zustand');
15
17
 
16
18
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
17
19
 
@@ -24,1356 +26,77 @@ function _interopNamespace(e) {
24
26
  var d = Object.getOwnPropertyDescriptor(e, k);
25
27
  Object.defineProperty(n, k, d.get ? d : {
26
28
  enumerable: true,
27
- get: function () {
28
- return e[k];
29
- }
29
+ get: function () { return e[k]; }
30
30
  });
31
31
  }
32
32
  });
33
33
  }
34
- n['default'] = e;
34
+ n["default"] = e;
35
35
  return Object.freeze(n);
36
36
  }
37
37
 
38
38
  var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
39
39
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
40
- var create__default = /*#__PURE__*/_interopDefault(create);
41
- var shallow__default = /*#__PURE__*/_interopDefault(shallow);
42
- var Reconciler__default = /*#__PURE__*/_interopDefault(Reconciler);
43
40
  var mergeRefs__default = /*#__PURE__*/_interopDefault(mergeRefs);
44
41
  var useMeasure__default = /*#__PURE__*/_interopDefault(useMeasure);
45
-
46
- var threeTypes = /*#__PURE__*/Object.freeze({
47
- __proto__: null
48
- });
49
-
50
- const is = {
51
- obj: a => a === Object(a) && !is.arr(a) && typeof a !== 'function',
52
- fun: a => typeof a === 'function',
53
- str: a => typeof a === 'string',
54
- num: a => typeof a === 'number',
55
- und: a => a === void 0,
56
- arr: a => Array.isArray(a),
57
-
58
- equ(a, b) {
59
- // Wrong type or one of the two undefined, doesn't match
60
- if (typeof a !== typeof b || !!a !== !!b) return false; // Atomic, just compare a against b
61
-
62
- if (is.str(a) || is.num(a) || is.obj(a)) return a === b; // Array, shallow compare first to see if it's a match
63
-
64
- if (is.arr(a) && a == b) return true; // Last resort, go through keys
65
-
66
- let i;
67
-
68
- for (i in a) if (!(i in b)) return false;
69
-
70
- for (i in b) if (a[i] !== b[i]) return false;
71
-
72
- return is.und(i) ? a === b : true;
42
+ var pick__default = /*#__PURE__*/_interopDefault(pick);
43
+ var omit__default = /*#__PURE__*/_interopDefault(omit);
44
+
45
+ // @ts-ignore
46
+ const CLICK = 'click';
47
+ const CONTEXTMENU = 'contextmenu';
48
+ const DBLCLICK = 'dblclick';
49
+ const POINTERCANCEL = 'pointercancel';
50
+ const POINTERDOWN = 'pointerdown';
51
+ const POINTERUP = 'pointerup';
52
+ const POINTERMOVE = 'pointermove';
53
+ const POINTEROUT = 'pointerout';
54
+ const POINTEROVER = 'pointerover';
55
+ const POINTERENTER = 'pointerenter';
56
+ const POINTERLEAVE = 'pointerleave';
57
+ const WHEEL = 'wheel'; // https://github.com/facebook/react/tree/main/packages/react-reconciler#getcurrenteventpriority
58
+ // Gives React a clue as to how import the current interaction is
59
+
60
+ function getEventPriority() {
61
+ var _window, _window$event;
62
+
63
+ let name = (_window = window) == null ? void 0 : (_window$event = _window.event) == null ? void 0 : _window$event.type;
64
+
65
+ switch (name) {
66
+ case CLICK:
67
+ case CONTEXTMENU:
68
+ case DBLCLICK:
69
+ case POINTERCANCEL:
70
+ case POINTERDOWN:
71
+ case POINTERUP:
72
+ return constants.DiscreteEventPriority;
73
+
74
+ case POINTERMOVE:
75
+ case POINTEROUT:
76
+ case POINTEROVER:
77
+ case POINTERENTER:
78
+ case POINTERLEAVE:
79
+ case WHEEL:
80
+ return constants.ContinuousEventPriority;
81
+
82
+ default:
83
+ return constants.DefaultEventPriority;
73
84
  }
74
-
75
- };
76
-
77
- function makeId(event) {
78
- return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
79
85
  }
80
-
81
- function removeInteractivity(store, object) {
82
- const {
83
- internal
84
- } = store.getState(); // Removes every trace of an object from the data store
85
-
86
- internal.interaction = internal.interaction.filter(o => o !== object);
87
- internal.initialHits = internal.initialHits.filter(o => o !== object);
88
- internal.hovered.forEach((value, key) => {
89
- if (value.eventObject === object || value.object === object) {
90
- internal.hovered.delete(key);
91
- }
92
- });
93
- }
94
- function createEvents(store) {
95
- const temp = new THREE__namespace.Vector3();
96
- /** Sets up defaultRaycaster */
97
-
98
- function prepareRay(event) {
99
- var _raycaster$computeOff;
100
-
101
- const state = store.getState();
102
- const {
103
- raycaster,
104
- mouse,
105
- camera,
106
- size
107
- } = state; // https://github.com/pmndrs/react-three-fiber/pull/782
108
- // Events trigger outside of canvas when moved
109
-
110
- const {
111
- offsetX,
112
- offsetY
113
- } = (_raycaster$computeOff = raycaster.computeOffsets == null ? void 0 : raycaster.computeOffsets(event, state)) != null ? _raycaster$computeOff : event;
114
- const {
115
- width,
116
- height
117
- } = size;
118
- mouse.set(offsetX / width * 2 - 1, -(offsetY / height) * 2 + 1);
119
- raycaster.setFromCamera(mouse, camera);
120
- }
121
- /** Calculates delta */
122
-
123
-
124
- function calculateDistance(event) {
125
- const {
126
- internal
127
- } = store.getState();
128
- const dx = event.offsetX - internal.initialClick[0];
129
- const dy = event.offsetY - internal.initialClick[1];
130
- return Math.round(Math.sqrt(dx * dx + dy * dy));
131
- }
132
- /** Returns true if an instance has a valid pointer-event registered, this excludes scroll, clicks etc */
133
-
134
-
135
- function filterPointerEvents(objects) {
136
- return objects.filter(obj => ['Move', 'Over', 'Enter', 'Out', 'Leave'].some(name => obj.__r3f.handlers['onPointer' + name]));
137
- }
138
-
139
- function intersect(filter) {
140
- const state = store.getState();
141
- const {
142
- raycaster,
143
- internal
144
- } = state; // Skip event handling when noEvents is set
145
-
146
- if (!raycaster.enabled) return [];
147
- const seen = new Set();
148
- const intersections = []; // Allow callers to eliminate event objects
149
-
150
- const eventsObjects = filter ? filter(internal.interaction) : internal.interaction; // Intersect known handler objects and filter against duplicates
151
-
152
- let intersects = raycaster.intersectObjects(eventsObjects, true).filter(item => {
153
- const id = makeId(item);
154
- if (seen.has(id)) return false;
155
- seen.add(id);
156
- return true;
157
- }); // https://github.com/mrdoob/three.js/issues/16031
158
- // Allow custom userland intersect sort order
159
-
160
- if (raycaster.filter) intersects = raycaster.filter(intersects, state);
161
-
162
- for (const intersect of intersects) {
163
- let eventObject = intersect.object; // Bubble event up
164
-
165
- while (eventObject) {
166
- if (eventObject.__r3f.handlers.count) intersections.push({ ...intersect,
167
- eventObject
168
- });
169
- eventObject = eventObject.parent;
170
- }
171
- }
172
-
173
- return intersections;
174
- }
175
- /** Creates filtered intersects and returns an array of positive hits */
176
-
177
-
178
- function patchIntersects(intersections, event) {
179
- const {
180
- internal
181
- } = store.getState(); // If the interaction is captured, make all capturing targets part of the
182
- // intersect.
183
-
184
- if ('pointerId' in event && internal.capturedMap.has(event.pointerId)) {
185
- intersections.push(...internal.capturedMap.get(event.pointerId).values());
186
- }
187
-
188
- return intersections;
189
- }
190
- /** Handles intersections by forwarding them to handlers */
191
-
192
-
193
- function handleIntersects(intersections, event, callback) {
194
- const {
195
- raycaster,
196
- mouse,
197
- camera,
198
- internal
199
- } = store.getState(); // If anything has been found, forward it to the event listeners
200
-
201
- if (intersections.length) {
202
- const unprojectedPoint = temp.set(mouse.x, mouse.y, 0).unproject(camera);
203
- const delta = event.type === 'click' ? calculateDistance(event) : 0;
204
-
205
- const releasePointerCapture = id => event.target.releasePointerCapture(id);
206
-
207
- const localState = {
208
- stopped: false
209
- };
210
-
211
- for (const hit of intersections) {
212
- const hasPointerCapture = id => {
213
- var _internal$capturedMap, _internal$capturedMap2;
214
-
215
- return (_internal$capturedMap = (_internal$capturedMap2 = internal.capturedMap.get(id)) == null ? void 0 : _internal$capturedMap2.has(hit.eventObject)) != null ? _internal$capturedMap : false;
216
- };
217
-
218
- const setPointerCapture = id => {
219
- if (internal.capturedMap.has(id)) {
220
- // if the pointerId was previously captured, we add the hit to the
221
- // event capturedMap.
222
- internal.capturedMap.get(id).set(hit.eventObject, hit);
223
- } else {
224
- // if the pointerId was not previously captured, we create a map
225
- // containing the hitObject, and the hit. hitObject is used for
226
- // faster access.
227
- internal.capturedMap.set(id, new Map([[hit.eventObject, hit]]));
228
- } // Call the original event now
229
- event.target.setPointerCapture(id);
230
- }; // Add native event props
231
-
232
-
233
- let extractEventProps = {};
234
-
235
- for (let prop in Object.getPrototypeOf(event)) {
236
- let property = event[prop]; // Only copy over atomics, leave functions alone as these should be
237
- // called as event.nativeEvent.fn()
238
-
239
- if (typeof property !== 'function') extractEventProps[prop] = property;
240
- }
241
-
242
- let raycastEvent = { ...hit,
243
- ...extractEventProps,
244
- spaceX: mouse.x,
245
- spaceY: mouse.y,
246
- intersections,
247
- stopped: localState.stopped,
248
- delta,
249
- unprojectedPoint,
250
- ray: raycaster.ray,
251
- camera: camera,
252
- // Hijack stopPropagation, which just sets a flag
253
- stopPropagation: () => {
254
- // https://github.com/pmndrs/react-three-fiber/issues/596
255
- // Events are not allowed to stop propagation if the pointer has been captured
256
- const capturesForPointer = 'pointerId' in event && internal.capturedMap.get(event.pointerId); // We only authorize stopPropagation...
257
-
258
- if ( // ...if this pointer hasn't been captured
259
- !capturesForPointer || // ... or if the hit object is capturing the pointer
260
- capturesForPointer.has(hit.eventObject)) {
261
- raycastEvent.stopped = localState.stopped = true; // Propagation is stopped, remove all other hover records
262
- // An event handler is only allowed to flush other handlers if it is hovered itself
263
-
264
- if (internal.hovered.size && Array.from(internal.hovered.values()).find(i => i.eventObject === hit.eventObject)) {
265
- // Objects cannot flush out higher up objects that have already caught the event
266
- const higher = intersections.slice(0, intersections.indexOf(hit));
267
- cancelPointer([...higher, hit]);
268
- }
269
- }
270
- },
271
- // there should be a distinction between target and currentTarget
272
- target: {
273
- hasPointerCapture,
274
- setPointerCapture,
275
- releasePointerCapture
276
- },
277
- currentTarget: {
278
- hasPointerCapture,
279
- setPointerCapture,
280
- releasePointerCapture
281
- },
282
- sourceEvent: event,
283
- // deprecated
284
- nativeEvent: event
285
- }; // Call subscribers
286
-
287
- callback(raycastEvent); // Event bubbling may be interrupted by stopPropagation
288
-
289
- if (localState.stopped === true) break;
290
- }
291
- }
292
-
293
- return intersections;
294
- }
295
-
296
- function cancelPointer(hits) {
297
- const {
298
- internal
299
- } = store.getState();
300
- Array.from(internal.hovered.values()).forEach(hoveredObj => {
301
- // When no objects were hit or the the hovered object wasn't found underneath the cursor
302
- // we call onPointerOut and delete the object from the hovered-elements map
303
- if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
304
- const eventObject = hoveredObj.eventObject;
305
- const handlers = eventObject.__r3f.handlers;
306
- internal.hovered.delete(makeId(hoveredObj));
307
-
308
- if (handlers.count) {
309
- // Clear out intersects, they are outdated by now
310
- const data = { ...hoveredObj,
311
- intersections: hits || []
312
- };
313
- handlers.onPointerOut == null ? void 0 : handlers.onPointerOut(data);
314
- handlers.onPointerLeave == null ? void 0 : handlers.onPointerLeave(data);
315
- }
316
- }
317
- });
318
- }
319
-
320
- const handlePointer = name => {
321
- // Deal with cancelation
322
- switch (name) {
323
- case 'onPointerLeave':
324
- case 'onPointerCancel':
325
- return () => cancelPointer([]);
326
-
327
- case 'onLostPointerCapture':
328
- return event => {
329
- if ('pointerId' in event) {
330
- // this will be a problem if one target releases the pointerId
331
- // and another one is still keeping it, as the line below
332
- // indifferently deletes all capturing references.
333
- store.getState().internal.capturedMap.delete(event.pointerId);
334
- }
335
-
336
- cancelPointer([]);
337
- };
338
- } // Any other pointer goes here ...
339
-
340
-
341
- return event => {
342
- const {
343
- onPointerMissed,
344
- internal
345
- } = store.getState();
346
- prepareRay(event); // Get fresh intersects
347
-
348
- const isPointerMove = name === 'onPointerMove';
349
- const filter = isPointerMove ? filterPointerEvents : undefined;
350
- const hits = patchIntersects(intersect(filter), event); // Take care of unhover
351
-
352
- if (isPointerMove) cancelPointer(hits);
353
- handleIntersects(hits, event, data => {
354
- const eventObject = data.eventObject;
355
- const handlers = eventObject.__r3f.handlers; // Check presence of handlers
356
-
357
- if (!handlers.count) return;
358
-
359
- if (isPointerMove) {
360
- // Move event ...
361
- if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
362
- // When enter or out is present take care of hover-state
363
- const id = makeId(data);
364
- const hoveredItem = internal.hovered.get(id);
365
-
366
- if (!hoveredItem) {
367
- // If the object wasn't previously hovered, book it and call its handler
368
- internal.hovered.set(id, data);
369
- handlers.onPointerOver == null ? void 0 : handlers.onPointerOver(data);
370
- handlers.onPointerEnter == null ? void 0 : handlers.onPointerEnter(data);
371
- } else if (hoveredItem.stopped) {
372
- // If the object was previously hovered and stopped, we shouldn't allow other items to proceed
373
- data.stopPropagation();
374
- }
375
- } // Call mouse move
376
-
377
-
378
- handlers.onPointerMove == null ? void 0 : handlers.onPointerMove(data);
379
- } else {
380
- // All other events ...
381
- const handler = handlers[name];
382
-
383
- if (handler) {
384
- // Forward all events back to their respective handlers with the exception of click events,
385
- // which must use the initial target
386
- if (name !== 'onClick' && name !== 'onContextMenu' && name !== 'onDoubleClick' || internal.initialHits.includes(eventObject)) {
387
- handler(data);
388
- pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
389
- }
390
- }
391
- }
392
- }); // Save initial coordinates on pointer-down
393
-
394
- if (name === 'onPointerDown') {
395
- internal.initialClick = [event.offsetX, event.offsetY];
396
- internal.initialHits = hits.map(hit => hit.eventObject);
397
- } // If a click yields no results, pass it back to the user as a miss
398
-
399
-
400
- if ((name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick') && !hits.length) {
401
- if (calculateDistance(event) <= 2) {
402
- pointerMissed(event, internal.interaction);
403
- if (onPointerMissed) onPointerMissed(event);
404
- }
405
- }
406
- };
407
- };
408
-
409
- function pointerMissed(event, objects) {
410
- objects.forEach(object => {
411
- var _r3f$handlers$onPoin, _r3f$handlers;
412
-
413
- return (_r3f$handlers$onPoin = (_r3f$handlers = object.__r3f.handlers).onPointerMissed) == null ? void 0 : _r3f$handlers$onPoin.call(_r3f$handlers, event);
414
- });
415
- }
416
-
417
- return {
418
- handlePointer
419
- };
420
- }
421
-
422
- const isDiffSet = def => def && !!def.memoized && !!def.changes;
423
-
424
- // Type guard to tell a store from a portal
425
- const isStore = def => def && !!def.getState;
426
-
427
- const getContainer = (container, child) => {
428
- var _container$__r3f$root, _container$__r3f;
429
-
430
- return {
431
- // If the container is not a root-store then it must be a THREE.Object3D into which part of the
432
- // scene is portalled into. Now there can be two variants of this, either that object is part of
433
- // the regular jsx tree, in which case it already has __r3f with a valid root attached, or it lies
434
- // outside react, in which case we must take the root of the child that is about to be attached to it.
435
- root: isStore(container) ? container : (_container$__r3f$root = (_container$__r3f = container.__r3f) == null ? void 0 : _container$__r3f.root) != null ? _container$__r3f$root : child.__r3f.root,
436
- // The container is the eventual target into which objects are mounted, it has to be a THREE.Object3D
437
- container: isStore(container) ? container.getState().scene : container
438
- };
439
- };
440
-
441
- const DEFAULT = '__default';
442
- const EMPTY = {};
443
- let catalogue = {};
444
-
445
- let extend = objects => void (catalogue = { ...catalogue,
446
- ...objects
447
- }); // Shallow check arrays, but check objects atomically
448
-
449
-
450
- function checkShallow(a, b) {
451
- if (is.arr(a) && is.equ(a, b)) return true;
452
- if (a === b) return true;
453
- return false;
454
- } // Each object in the scene carries a small LocalState descriptor
455
-
456
-
457
- function prepare(object, state) {
458
- const instance = object;
459
-
460
- if (state != null && state.primitive || !instance.__r3f) {
461
- instance.__r3f = {
462
- root: null,
463
- memoizedProps: {},
464
- handlers: {
465
- count: 0
466
- },
467
- objects: [],
468
- ...state
469
- };
470
- }
471
-
472
- return object;
473
- }
474
-
475
- function createRenderer(roots) {
476
- // This function prepares a set of changes to be applied to the instance
477
- function diffProps(instance, {
478
- children: cN,
479
- key: kN,
480
- ref: rN,
481
- ...props
482
- }, {
483
- children: cP,
484
- key: kP,
485
- ref: rP,
486
- ...previous
487
- } = {}, accumulative = false) {
488
- var _instance$__r3f;
489
-
490
- const localState = (_instance$__r3f = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f : {};
491
- const entries = Object.entries(props);
492
- const changes = []; // Catch removed props, prepend them so they can be reset or removed
493
-
494
- if (accumulative) {
495
- const previousKeys = Object.keys(previous);
496
-
497
- for (let i = 0; i < previousKeys.length; i++) if (!props.hasOwnProperty(previousKeys[i])) entries.unshift([previousKeys[i], DEFAULT + 'remove']);
498
- }
499
-
500
- entries.forEach(([key, value]) => {
501
- var _instance$__r3f2;
502
-
503
- // Bail out on primitive object
504
- if ((_instance$__r3f2 = instance.__r3f) != null && _instance$__r3f2.primitive && key === 'object') return; // When props match bail out
505
-
506
- if (checkShallow(value, previous[key])) return;
507
- let currentInstance = instance;
508
- let targetProp = currentInstance[key]; // Collect handlers and bail out
509
-
510
- if (/^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(key)) return changes.push([key, value, true, currentInstance, targetProp]); // Revolve dashed props
511
-
512
- if (key.includes('-')) {
513
- const entries = key.split('-');
514
- targetProp = entries.reduce((acc, key) => acc[key], instance); // If the target is atomic, it forces us to switch the root
515
-
516
- if (!(targetProp && targetProp.set)) {
517
- const [name, ...reverseEntries] = entries.reverse();
518
- currentInstance = reverseEntries.reverse().reduce((acc, key) => acc[key], instance);
519
- key = name;
520
- }
521
- }
522
-
523
- changes.push([key, value, false, currentInstance, targetProp]);
524
- });
525
- const memoized = { ...props
526
- };
527
- if (localState.memoizedProps && localState.memoizedProps.args) memoized.args = localState.memoizedProps.args;
528
- if (localState.memoizedProps && localState.memoizedProps.attach) memoized.attach = localState.memoizedProps.attach;
529
- return {
530
- accumulative,
531
- memoized,
532
- changes
533
- };
534
- }
535
-
536
- function applyProps(instance, data) {
537
- var _instance$__r3f3, _root$getState, _localState$handlers, _localState$handlers2;
538
-
539
- // Filter equals, events and reserved props
540
- const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
541
- const root = localState.root;
542
- const rootState = (_root$getState = root == null ? void 0 : root.getState == null ? void 0 : root.getState()) != null ? _root$getState : {};
543
- const {
544
- memoized,
545
- changes
546
- } = isDiffSet(data) ? data : diffProps(instance, data);
547
- const prevHandlers = (_localState$handlers = localState.handlers) == null ? void 0 : _localState$handlers.count; // Prepare memoized props
548
-
549
- if (instance.__r3f) instance.__r3f.memoizedProps = memoized;
550
- changes.forEach(([key, value, isEvent, currentInstance, targetProp]) => {
551
- // https://github.com/mrdoob/three.js/issues/21209
552
- // HMR/fast-refresh relies on the ability to cancel out props, but threejs
553
- // has no means to do this. Hence we curate a small collection of value-classes
554
- // with their respective constructor/set arguments
555
- // For removed props, try to set default values, if possible
556
- if (value === DEFAULT + 'remove') {
557
- if (targetProp && targetProp.constructor) {
558
- // use the prop constructor to find the default it should be
559
- value = new targetProp.constructor(memoized.args);
560
- } else if (currentInstance.constructor) {
561
- // create a blank slate of the instance and copy the particular parameter.
562
- // @ts-ignore
563
- const defaultClassCall = new currentInstance.constructor(currentInstance.__r3f.memoizedProps.args);
564
- value = defaultClassCall[targetProp]; // destory the instance
565
-
566
- if (defaultClassCall.dispose) defaultClassCall.dispose(); // instance does not have constructor, just set it to 0
567
- } else value = 0;
568
- } // Deal with pointer events ...
569
-
570
-
571
- if (isEvent) {
572
- if (value) localState.handlers[key] = value;else delete localState.handlers[key];
573
- localState.handlers.count = Object.keys(localState.handlers).length;
574
- } // Special treatment for objects with support for set/copy, and layers
575
- else if (targetProp && targetProp.set && (targetProp.copy || targetProp instanceof THREE__namespace.Layers)) {
576
- // If value is an array
577
- if (Array.isArray(value)) {
578
- if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
579
- } // Test again target.copy(class) next ...
580
- else if (targetProp.copy && value && value.constructor && targetProp.constructor.name === value.constructor.name) targetProp.copy(value); // If nothing else fits, just set the single value, ignore undefined
581
- // https://github.com/react-spring/react-three-fiber/issues/274
582
- else if (value !== undefined) {
583
- const isColor = targetProp instanceof THREE__namespace.Color; // Allow setting array scalars
584
-
585
- if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
586
- else if (targetProp instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) targetProp.mask = value.mask; // Otherwise just set ...
587
- else targetProp.set(value); // Auto-convert sRGB colors, for now ...
588
- // https://github.com/react-spring/react-three-fiber/issues/344
589
-
590
- if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
591
- } // Else, just overwrite the value
592
-
593
- } else {
594
- currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
595
- // https://github.com/react-spring/react-three-fiber/issues/344
596
-
597
- if (!rootState.linear && currentInstance[key] instanceof THREE__namespace.Texture) currentInstance[key].encoding = THREE__namespace.sRGBEncoding;
598
- }
599
-
600
- invalidateInstance(instance);
601
- });
602
-
603
- if (rootState.internal && instance.raycast && prevHandlers !== ((_localState$handlers2 = localState.handlers) == null ? void 0 : _localState$handlers2.count)) {
604
- // Pre-emptively remove the instance from the interaction manager
605
- const index = rootState.internal.interaction.indexOf(instance);
606
- if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
607
-
608
- if (localState.handlers.count) rootState.internal.interaction.push(instance);
609
- } // Call the update lifecycle when it is being updated, but only when it is part of the scene
610
-
611
-
612
- if (changes.length && instance.parent) updateInstance(instance);
613
- }
614
-
615
- function invalidateInstance(instance) {
616
- var _instance$__r3f4, _instance$__r3f4$root;
617
-
618
- const state = (_instance$__r3f4 = instance.__r3f) == null ? void 0 : (_instance$__r3f4$root = _instance$__r3f4.root) == null ? void 0 : _instance$__r3f4$root.getState == null ? void 0 : _instance$__r3f4$root.getState();
619
- if (state && state.internal.frames === 0) state.invalidate();
620
- }
621
-
622
- function updateInstance(instance) {
623
- instance.onUpdate == null ? void 0 : instance.onUpdate(instance);
624
- }
625
-
626
- function createInstance(type, {
627
- args = [],
628
- ...props
629
- }, root, hostContext, internalInstanceHandle) {
630
- let name = `${type[0].toUpperCase()}${type.slice(1)}`;
631
- let instance; // https://github.com/facebook/react/issues/17147
632
- // Portals do not give us a root, they are themselves treated as a root by the reconciler
633
- // In order to figure out the actual root we have to climb through fiber internals :(
634
-
635
- if (!isStore(root) && internalInstanceHandle) {
636
- const fn = node => {
637
- if (!node.return) return node.stateNode && node.stateNode.containerInfo;else return fn(node.return);
638
- };
639
-
640
- root = fn(internalInstanceHandle);
641
- } // Assert that by now we have a valid root
642
-
643
-
644
- if (!root || !isStore(root)) throw `No valid root for ${name}!`;
645
-
646
- if (type === 'primitive') {
647
- if (props.object === undefined) throw `Primitives without 'object' are invalid!`;
648
- const object = props.object;
649
- instance = prepare(object, {
650
- root,
651
- primitive: true
652
- });
653
- } else {
654
- const target = catalogue[name] || THREE__namespace[name];
655
- if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`;
656
- const isArgsArr = is.arr(args); // Instanciate new object, link it to the root
657
-
658
- instance = prepare(isArgsArr ? new target(...args) : new target(args), {
659
- root,
660
- // append memoized props with args so it's not forgotten
661
- memoizedProps: {
662
- args: isArgsArr && args.length === 0 ? null : args
663
- }
664
- });
665
- } // Auto-attach geometries and materials
666
-
667
-
668
- if (!('attachFns' in props)) {
669
- if (name.endsWith('Geometry')) {
670
- props = {
671
- attach: 'geometry',
672
- ...props
673
- };
674
- } else if (name.endsWith('Material')) {
675
- props = {
676
- attach: 'material',
677
- ...props
678
- };
679
- }
680
- } // It should NOT call onUpdate on object instanciation, because it hasn't been added to the
681
- // view yet. If the callback relies on references for instance, they won't be ready yet, this is
682
- // why it passes "true" here
683
-
684
-
685
- applyProps(instance, props);
686
- return instance;
687
- }
688
-
689
- function appendChild(parentInstance, child) {
690
- let addedAsChild = false;
691
-
692
- if (child) {
693
- // The attach attribute implies that the object attaches itself on the parent
694
- if (child.attachArray) {
695
- if (!is.arr(parentInstance[child.attachArray])) parentInstance[child.attachArray] = [];
696
- parentInstance[child.attachArray].push(child);
697
- } else if (child.attachObject) {
698
- if (!is.obj(parentInstance[child.attachObject[0]])) parentInstance[child.attachObject[0]] = {};
699
- parentInstance[child.attachObject[0]][child.attachObject[1]] = child;
700
- } else if (child.attach && !is.fun(child.attach)) {
701
- parentInstance[child.attach] = child;
702
- } else if (is.arr(child.attachFns)) {
703
- const [attachFn] = child.attachFns;
704
-
705
- if (is.str(attachFn) && is.fun(parentInstance[attachFn])) {
706
- parentInstance[attachFn](child);
707
- } else if (is.fun(attachFn)) {
708
- attachFn(child, parentInstance);
709
- }
710
- } else if (child.isObject3D) {
711
- // add in the usual parent-child way
712
- parentInstance.add(child);
713
- addedAsChild = true;
714
- }
715
-
716
- if (!addedAsChild) {
717
- // This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
718
- // that is, anything that's a child in React but not a child in the scenegraph.
719
- parentInstance.__r3f.objects.push(child);
720
-
721
- child.parent = parentInstance;
722
- }
723
-
724
- updateInstance(child);
725
- invalidateInstance(child);
726
- }
727
- }
728
-
729
- function insertBefore(parentInstance, child, beforeChild) {
730
- let added = false;
731
-
732
- if (child) {
733
- if (child.attachArray) {
734
- const array = parentInstance[child.attachArray];
735
- if (!is.arr(array)) parentInstance[child.attachArray] = [];
736
- array.splice(array.indexOf(beforeChild), 0, child);
737
- } else if (child.attachObject || child.attach && !is.fun(child.attach)) {
738
- // attach and attachObject don't have an order anyway, so just append
739
- return appendChild(parentInstance, child);
740
- } else if (child.isObject3D) {
741
- child.parent = parentInstance;
742
- child.dispatchEvent({
743
- type: 'added'
744
- });
745
- const restSiblings = parentInstance.children.filter(sibling => sibling !== child);
746
- const index = restSiblings.indexOf(beforeChild);
747
- parentInstance.children = [...restSiblings.slice(0, index), child, ...restSiblings.slice(index)];
748
- added = true;
749
- }
750
-
751
- if (!added) {
752
- parentInstance.__r3f.objects.push(child);
753
-
754
- child.parent = parentInstance;
755
- }
756
-
757
- updateInstance(child);
758
- invalidateInstance(child);
759
- }
760
- }
761
-
762
- function removeRecursive(array, parent, dispose = false) {
763
- if (array) [...array].forEach(child => removeChild(parent, child, dispose));
764
- }
765
-
766
- function removeChild(parentInstance, child, dispose) {
767
- if (child) {
768
- var _child$__r3f2;
769
-
770
- if (parentInstance.__r3f.objects) {
771
- const oldLength = parentInstance.__r3f.objects.length;
772
- parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child);
773
- const newLength = parentInstance.__r3f.objects.length; // was it in the list?
774
-
775
- if (newLength < oldLength) {
776
- // we had also set this, so we must clear it now
777
- child.parent = null;
778
- }
779
- } // Remove attachment
780
-
781
-
782
- if (child.attachArray) {
783
- parentInstance[child.attachArray] = parentInstance[child.attachArray].filter(x => x !== child);
784
- } else if (child.attachObject) {
785
- delete parentInstance[child.attachObject[0]][child.attachObject[1]];
786
- } else if (child.attach && !is.fun(child.attach)) {
787
- parentInstance[child.attach] = null;
788
- } else if (is.arr(child.attachFns)) {
789
- const [, detachFn] = child.attachFns;
790
-
791
- if (is.str(detachFn) && is.fun(parentInstance[detachFn])) {
792
- parentInstance[detachFn](child);
793
- } else if (is.fun(detachFn)) {
794
- detachFn(child, parentInstance);
795
- }
796
- } else if (child.isObject3D) {
797
- var _child$__r3f;
798
-
799
- parentInstance.remove(child); // Remove interactivity
800
-
801
- if ((_child$__r3f = child.__r3f) != null && _child$__r3f.root) {
802
- removeInteractivity(child.__r3f.root, child);
803
- }
804
- } // Allow objects to bail out of recursive dispose alltogether by passing dispose={null}
805
- // Never dispose of primitives because their state may be kept outside of React!
806
- // In order for an object to be able to dispose it has to have
807
- // - a dispose method,
808
- // - it cannot be a <primitive object={...} />
809
- // - it cannot be a THREE.Scene, because three has broken it's own api
810
- //
811
- // Since disposal is recursive, we can check the optional dispose arg, which will be undefined
812
- // when the reconciler calls it, but then carry our own check recursively
813
-
814
-
815
- const isPrimitive = (_child$__r3f2 = child.__r3f) == null ? void 0 : _child$__r3f2.primitive;
816
- const shouldDispose = dispose === undefined ? child.dispose !== null && !isPrimitive : dispose; // Remove nested child objects. Primitives should not have objects and children that are
817
- // attached to them declaratively ...
818
-
819
- if (!isPrimitive) {
820
- var _child$__r3f3;
821
-
822
- removeRecursive((_child$__r3f3 = child.__r3f) == null ? void 0 : _child$__r3f3.objects, child, shouldDispose);
823
- removeRecursive(child.children, child, shouldDispose);
824
- } // Remove references
825
-
826
-
827
- if (child.__r3f) {
828
- delete child.__r3f.root;
829
- delete child.__r3f.objects;
830
- delete child.__r3f.handlers;
831
- delete child.__r3f.memoizedProps;
832
- if (!isPrimitive) delete child.__r3f;
833
- } // Dispose item whenever the reconciler feels like it
834
-
835
-
836
- if (shouldDispose && child.dispose && child.type !== 'Scene') {
837
- scheduler.unstable_runWithPriority(scheduler.unstable_IdlePriority, () => {
838
- try {
839
- child.dispose();
840
- } catch (e) {
841
- /* ... */
842
- }
843
- });
844
- }
845
-
846
- invalidateInstance(parentInstance);
847
- }
848
- }
849
-
850
- function switchInstance(instance, type, newProps, fiber) {
851
- const parent = instance.parent;
852
- if (!parent) return;
853
- const newInstance = createInstance(type, newProps, instance.__r3f.root); // https://github.com/pmndrs/react-three-fiber/issues/1348
854
- // When args change the instance has to be re-constructed, which then
855
- // forces r3f to re-parent the children and non-scene objects
856
-
857
- if (instance.children) {
858
- instance.children.forEach(child => appendChild(newInstance, child));
859
- instance.children = [];
860
- }
861
-
862
- instance.__r3f.objects.forEach(child => appendChild(newInstance, child));
863
-
864
- instance.__r3f.objects = [];
865
- removeChild(parent, instance);
866
- appendChild(parent, newInstance) // This evil hack switches the react-internal fiber node
867
- // https://github.com/facebook/react/issues/14983
868
- // https://github.com/facebook/react/pull/15021
869
- ;
870
- [fiber, fiber.alternate].forEach(fiber => {
871
- if (fiber !== null) {
872
- fiber.stateNode = newInstance;
873
-
874
- if (fiber.ref) {
875
- if (typeof fiber.ref === 'function') fiber.ref(newInstance);else fiber.ref.current = newInstance;
876
- }
877
- }
878
- });
879
- }
880
-
881
- const reconciler = Reconciler__default['default']({
882
- now: scheduler.unstable_now,
883
- createInstance,
884
- removeChild,
885
- appendChild,
886
- appendInitialChild: appendChild,
887
- insertBefore,
888
- warnsIfNotActing: true,
889
- supportsMutation: true,
890
- isPrimaryRenderer: false,
891
- getCurrentEventPriority: () => constants.DefaultEventPriority,
892
- // @ts-ignore
893
- scheduleTimeout: is.fun(setTimeout) ? setTimeout : undefined,
894
- // @ts-ignore
895
- cancelTimeout: is.fun(clearTimeout) ? clearTimeout : undefined,
896
- // @ts-ignore
897
- setTimeout: is.fun(setTimeout) ? setTimeout : undefined,
898
- // @ts-ignore
899
- clearTimeout: is.fun(clearTimeout) ? clearTimeout : undefined,
900
- noTimeout: -1,
901
- appendChildToContainer: (parentInstance, child) => {
902
- const {
903
- container,
904
- root
905
- } = getContainer(parentInstance, child); // Link current root to the default scene
906
-
907
- container.__r3f.root = root;
908
- appendChild(container, child);
909
- },
910
- removeChildFromContainer: (parentInstance, child) => removeChild(getContainer(parentInstance, child).container, child),
911
- insertInContainerBefore: (parentInstance, child, beforeChild) => insertBefore(getContainer(parentInstance, child).container, child, beforeChild),
912
-
913
- prepareUpdate(instance, type, oldProps, newProps) {
914
- if (instance.__r3f.primitive && newProps.object && newProps.object !== instance) return [true];else {
915
- // This is a data object, let's extract critical information about it
916
- const {
917
- args: argsNew = [],
918
- children: cN,
919
- ...restNew
920
- } = newProps;
921
- const {
922
- args: argsOld = [],
923
- children: cO,
924
- ...restOld
925
- } = oldProps; // If it has new props or arguments, then it needs to be re-instanciated
926
-
927
- if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
928
-
929
- const diff = diffProps(instance, restNew, restOld, true);
930
- if (diff.changes.length) return [false, diff]; // Otherwise do not touch the instance
931
-
932
- return null;
933
- }
934
- },
935
-
936
- commitUpdate(instance, [reconstruct, diff], type, oldProps, newProps, fiber) {
937
- //console.log(type)
938
- // Reconstruct when args or <primitive object={...} have changes
939
- if (reconstruct) switchInstance(instance, type, newProps, fiber); // Otherwise just overwrite props
940
- else applyProps(instance, diff);
941
- },
942
-
943
- hideInstance(instance) {
944
- if (instance.isObject3D) {
945
- instance.visible = false;
946
- invalidateInstance(instance);
947
- }
948
- },
949
-
950
- unhideInstance(instance, props) {
951
- if (instance.isObject3D && props.visible == null || props.visible) {
952
- instance.visible = true;
953
- invalidateInstance(instance);
954
- }
955
- },
956
-
957
- hideTextInstance() {
958
- throw new Error('Text is not allowed in the R3F tree.');
959
- },
960
-
961
- getPublicInstance(instance) {
962
- // TODO: might fix switchInstance (?)
963
- return instance;
964
- },
965
-
966
- getRootHostContext(rootContainer) {
967
- return EMPTY;
968
- },
969
-
970
- getChildHostContext(parentHostContext) {
971
- return parentHostContext;
972
- },
973
-
974
- createTextInstance() {},
975
-
976
- finalizeInitialChildren() {
977
- return false;
978
- },
979
-
980
- commitMount() {// noop
981
- },
982
-
983
- shouldDeprioritizeSubtree() {
984
- return false;
985
- },
986
-
987
- prepareForCommit() {
988
- return null;
989
- },
990
-
991
- preparePortalMount(containerInfo) {
992
- prepare(containerInfo);
993
- },
994
-
995
- resetAfterCommit() {// noop
996
- },
997
-
998
- shouldSetTextContent() {
999
- return false;
1000
- },
1001
-
1002
- clearContainer() {
1003
- return false;
1004
- },
1005
-
1006
- detachDeletedInstance() {// noop
1007
- }
1008
-
1009
- });
1010
- return {
1011
- reconciler,
1012
- applyProps
1013
- };
1014
- }
1015
-
1016
- const isRenderer = def => def && !!def.render;
1017
- const isOrthographicCamera = def => def && def.isOrthographicCamera;
1018
- const context = /*#__PURE__*/React__namespace.createContext(null);
1019
-
1020
- const createStore = (applyProps, invalidate, advance, props) => {
1021
- const {
1022
- gl,
1023
- size,
1024
- shadows = false,
1025
- linear = false,
1026
- flat = false,
1027
- vr = false,
1028
- orthographic = false,
1029
- frameloop = 'always',
1030
- dpr = 1,
1031
- performance,
1032
- clock = new THREE__namespace.Clock(),
1033
- raycaster: raycastOptions,
1034
- camera: cameraOptions,
1035
- onPointerMissed
1036
- } = props; // Set shadowmap
1037
-
1038
- if (shadows) {
1039
- gl.shadowMap.enabled = true;
1040
- if (typeof shadows === 'object') Object.assign(gl.shadowMap, shadows);else gl.shadowMap.type = THREE__namespace.PCFSoftShadowMap;
1041
- } // Set color management
1042
-
1043
-
1044
- if (!linear) gl.outputEncoding = THREE__namespace.sRGBEncoding;
1045
- if (!flat) gl.toneMapping = THREE__namespace.ACESFilmicToneMapping; // clock.elapsedTime is updated using advance(timestamp)
1046
-
1047
- if (frameloop === 'never') {
1048
- clock.stop();
1049
- clock.elapsedTime = 0;
1050
- }
1051
-
1052
- const rootState = create__default['default']((set, get) => {
1053
- // Create custom raycaster
1054
- const raycaster = new THREE__namespace.Raycaster();
1055
- const {
1056
- params,
1057
- ...options
1058
- } = raycastOptions || {};
1059
- applyProps(raycaster, {
1060
- enabled: true,
1061
- ...options,
1062
- params: { ...raycaster.params,
1063
- ...params
1064
- }
1065
- }); // Create default camera
1066
-
1067
- const isCamera = cameraOptions instanceof THREE__namespace.Camera;
1068
- 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);
1069
-
1070
- if (!isCamera) {
1071
- camera.position.z = 5;
1072
- if (cameraOptions) applyProps(camera, cameraOptions); // Always look at center by default
1073
-
1074
- camera.lookAt(0, 0, 0);
1075
- }
1076
-
1077
- function setDpr(dpr) {
1078
- return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
1079
- }
1080
-
1081
- const initialDpr = setDpr(dpr);
1082
- const position = new THREE__namespace.Vector3();
1083
- const defaultTarget = new THREE__namespace.Vector3();
1084
-
1085
- function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
1086
- const {
1087
- width,
1088
- height
1089
- } = size;
1090
- const aspect = width / height;
1091
- const distance = camera.getWorldPosition(position).distanceTo(target);
1092
-
1093
- if (isOrthographicCamera(camera)) {
1094
- return {
1095
- width: width / camera.zoom,
1096
- height: height / camera.zoom,
1097
- factor: 1,
1098
- distance,
1099
- aspect
1100
- };
1101
- } else {
1102
- const fov = camera.fov * Math.PI / 180; // convert vertical fov to radians
1103
-
1104
- const h = 2 * Math.tan(fov / 2) * distance; // visible height
1105
-
1106
- const w = h * (width / height);
1107
- return {
1108
- width: w,
1109
- height: h,
1110
- factor: width / w,
1111
- distance,
1112
- aspect
1113
- };
1114
- }
1115
- }
1116
-
1117
- let performanceTimeout = undefined;
1118
-
1119
- const setPerformanceCurrent = current => set(state => ({
1120
- performance: { ...state.performance,
1121
- current
1122
- }
1123
- }));
1124
-
1125
- return {
1126
- gl,
1127
- set,
1128
- get,
1129
- invalidate: () => invalidate(get()),
1130
- advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
1131
- linear,
1132
- flat,
1133
- scene: prepare(new THREE__namespace.Scene()),
1134
- camera,
1135
- controls: null,
1136
- raycaster,
1137
- clock,
1138
- mouse: new THREE__namespace.Vector2(),
1139
- vr,
1140
- frameloop,
1141
- onPointerMissed,
1142
- performance: {
1143
- current: 1,
1144
- min: 0.5,
1145
- max: 1,
1146
- debounce: 200,
1147
- ...performance,
1148
- regress: () => {
1149
- const state = get(); // Clear timeout
1150
-
1151
- if (performanceTimeout) clearTimeout(performanceTimeout); // Set lower bound performance
1152
-
1153
- if (state.performance.current !== state.performance.min) setPerformanceCurrent(state.performance.min); // Go back to upper bound performance after a while unless something regresses meanwhile
1154
-
1155
- performanceTimeout = setTimeout(() => setPerformanceCurrent(get().performance.max), state.performance.debounce);
1156
- }
1157
- },
1158
- size: {
1159
- width: 0,
1160
- height: 0
1161
- },
1162
- viewport: {
1163
- initialDpr,
1164
- dpr: initialDpr,
1165
- width: 0,
1166
- height: 0,
1167
- aspect: 0,
1168
- distance: 0,
1169
- factor: 0,
1170
- getCurrentViewport
1171
- },
1172
- setSize: (width, height) => {
1173
- const size = {
1174
- width,
1175
- height
1176
- };
1177
- set(state => ({
1178
- size,
1179
- viewport: { ...state.viewport,
1180
- ...getCurrentViewport(camera, defaultTarget, size)
1181
- }
1182
- }));
1183
- },
1184
- setDpr: dpr => set(state => ({
1185
- viewport: { ...state.viewport,
1186
- dpr: setDpr(dpr)
1187
- }
1188
- })),
1189
- events: {
1190
- connected: false
1191
- },
1192
- internal: {
1193
- active: false,
1194
- priority: 0,
1195
- frames: 0,
1196
- lastProps: props,
1197
- interaction: [],
1198
- hovered: new Map(),
1199
- subscribers: [],
1200
- initialClick: [0, 0],
1201
- initialHits: [],
1202
- capturedMap: new Map(),
1203
- subscribe: (ref, priority = 0) => {
1204
- set(({
1205
- internal
1206
- }) => ({
1207
- internal: { ...internal,
1208
- // If this subscription was given a priority, it takes rendering into its own hands
1209
- // For that reason we switch off automatic rendering and increase the manual flag
1210
- // As long as this flag is positive there can be no internal rendering at all
1211
- // because there could be multiple render subscriptions
1212
- priority: internal.priority + (priority > 0 ? 1 : 0),
1213
- // Register subscriber and sort layers from lowest to highest, meaning,
1214
- // highest priority renders last (on top of the other frames)
1215
- subscribers: [...internal.subscribers, {
1216
- ref,
1217
- priority
1218
- }].sort((a, b) => a.priority - b.priority)
1219
- }
1220
- }));
1221
- return () => {
1222
- set(({
1223
- internal
1224
- }) => ({
1225
- internal: { ...internal,
1226
- // Decrease manual flag if this subscription had a priority
1227
- priority: internal.priority - (priority > 0 ? 1 : 0),
1228
- // Remove subscriber from list
1229
- subscribers: internal.subscribers.filter(s => s.ref !== ref)
1230
- }
1231
- }));
1232
- };
1233
- }
1234
- }
1235
- };
1236
- }); // Resize camera and renderer on changes to size and pixelratio
1237
-
1238
- rootState.subscribe(() => {
1239
- const {
1240
- camera,
1241
- size,
1242
- viewport,
1243
- internal
1244
- } = rootState.getState(); // https://github.com/pmndrs/react-three-fiber/issues/92
1245
- // Do not mess with the camera if it belongs to the user
1246
-
1247
- if (!(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
1248
- if (isOrthographicCamera(camera)) {
1249
- camera.left = size.width / -2;
1250
- camera.right = size.width / 2;
1251
- camera.top = size.height / 2;
1252
- camera.bottom = size.height / -2;
1253
- } else {
1254
- camera.aspect = size.width / size.height;
1255
- }
1256
-
1257
- camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
1258
- // Update matrix world since the renderer is a frame late
1259
-
1260
- camera.updateMatrixWorld();
1261
- } // Update renderer
1262
-
1263
-
1264
- gl.setPixelRatio(viewport.dpr);
1265
- gl.setSize(size.width, size.height);
1266
- }, state => [state.viewport.dpr, state.size], shallow__default['default']);
1267
- const state = rootState.getState(); // Update size
1268
-
1269
- if (size) state.setSize(size.width, size.height); // Invalidate on any change
1270
-
1271
- rootState.subscribe(state => invalidate(state)); // Return root state
1272
-
1273
- return rootState;
1274
- };
1275
-
1276
- function createSubs(callback, subs) {
1277
- const index = subs.length;
1278
- subs.push(callback);
1279
- return () => void subs.splice(index, 1);
1280
- }
1281
-
1282
- let i;
1283
- let globalEffects = [];
1284
- let globalAfterEffects = [];
1285
- let globalTailEffects = [];
1286
- const addEffect = callback => createSubs(callback, globalEffects);
1287
- const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
1288
- const addTail = callback => createSubs(callback, globalTailEffects);
1289
-
1290
- function run(effects, timestamp) {
1291
- for (i = 0; i < effects.length; i++) effects[i](timestamp);
1292
- }
1293
-
1294
- function render$1(timestamp, state) {
1295
- // Run local effects
1296
- let delta = state.clock.getDelta(); // In frameloop='never' mode, clock times are updated using the provided timestamp
1297
-
1298
- if (state.frameloop === 'never' && typeof timestamp === 'number') {
1299
- delta = timestamp - state.clock.elapsedTime;
1300
- state.clock.oldTime = state.clock.elapsedTime;
1301
- state.clock.elapsedTime = timestamp;
1302
- } // Call subscribers (useFrame)
1303
-
1304
-
1305
- for (i = 0; i < state.internal.subscribers.length; i++) state.internal.subscribers[i].ref.current(state, delta); // Render content
1306
-
1307
-
1308
- if (!state.internal.priority && state.gl.render) state.gl.render(state.scene, state.camera); // Decrease frame count
1309
-
1310
- state.internal.frames = Math.max(0, state.internal.frames - 1);
1311
- return state.frameloop === 'always' ? 1 : state.internal.frames;
1312
- }
1313
-
1314
- function createLoop(roots) {
1315
- let running = false;
1316
- let repeat;
1317
-
1318
- function loop(timestamp) {
1319
- running = true;
1320
- repeat = 0; // Run effects
1321
-
1322
- run(globalEffects, timestamp); // Render all roots
1323
-
1324
- roots.forEach(root => {
1325
- const state = root.store.getState(); // If the frameloop is invalidated, do not run another frame
1326
-
1327
- if (state.internal.active && (state.frameloop === 'always' || state.internal.frames > 0)) repeat += render$1(timestamp, state);
1328
- }); // Run after-effects
1329
-
1330
- run(globalAfterEffects, timestamp); // Keep on looping if anything invalidates the frameloop
1331
-
1332
- if (repeat > 0) return requestAnimationFrame(loop); // Tail call effects, they are called when rendering stops
1333
- else run(globalTailEffects, timestamp); // Flag end of operation
1334
-
1335
- running = false;
1336
- }
1337
-
1338
- function invalidate(state) {
1339
- if (!state) return roots.forEach(root => invalidate(root.store.getState()));
1340
- if (state.vr || !state.internal.active || state.frameloop === 'never') return; // Increase frames, do not go higher than 60
1341
-
1342
- state.internal.frames = Math.min(60, state.internal.frames + 1); // If the render-loop isn't active, start it
1343
-
1344
- if (!running) {
1345
- running = true;
1346
- requestAnimationFrame(loop);
1347
- }
1348
- }
1349
-
1350
- function advance(timestamp, runGlobalEffects = true, state) {
1351
- if (runGlobalEffects) run(globalEffects, timestamp);
1352
- if (!state) roots.forEach(root => render$1(timestamp, root.store.getState()));else render$1(timestamp, state);
1353
- if (runGlobalEffects) run(globalAfterEffects, timestamp);
1354
- }
1355
-
1356
- return {
1357
- loop,
1358
- invalidate,
1359
- advance
1360
- };
1361
- }
1362
-
1363
86
  function createPointerEvents(store) {
1364
87
  const {
1365
88
  handlePointer
1366
- } = createEvents(store);
89
+ } = hooks.createEvents(store);
1367
90
  const names = {
1368
- onClick: ['click', false],
1369
- onContextMenu: ['contextmenu', false],
1370
- onDoubleClick: ['dblclick', false],
1371
- onWheel: ['wheel', true],
1372
- onPointerDown: ['pointerdown', true],
1373
- onPointerUp: ['pointerup', true],
1374
- onPointerLeave: ['pointerleave', true],
1375
- onPointerMove: ['pointermove', true],
1376
- onPointerCancel: ['pointercancel', true],
91
+ onClick: [CLICK, false],
92
+ onContextMenu: [CONTEXTMENU, false],
93
+ onDoubleClick: [DBLCLICK, false],
94
+ onWheel: [WHEEL, true],
95
+ onPointerDown: [POINTERDOWN, true],
96
+ onPointerUp: [POINTERUP, true],
97
+ onPointerLeave: [POINTERLEAVE, true],
98
+ onPointerMove: [POINTERMOVE, true],
99
+ onPointerCancel: [POINTERCANCEL, true],
1377
100
  onLostPointerCapture: ['lostpointercapture', true]
1378
101
  };
1379
102
  return {
@@ -1426,9 +149,10 @@ function createPointerEvents(store) {
1426
149
  };
1427
150
  }
1428
151
 
1429
- // React currently throws a warning when using useLayoutEffect on the server.
152
+ const CANVAS_PROPS = ['gl', 'events', 'size', 'shadows', 'linear', 'flat', 'orthographic', 'frameloop', 'dpr', 'performance', 'clock', 'raycaster', 'camera', 'onPointerMissed', 'onCreated']; // React currently throws a warning when using useLayoutEffect on the server.
1430
153
  // To get around it, we can conditionally useEffect on the server (no-op) and
1431
154
  // useLayoutEffect in the browser.
155
+
1432
156
  const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React__namespace.useLayoutEffect : React__namespace.useEffect;
1433
157
 
1434
158
  function Block({
@@ -1466,15 +190,17 @@ ErrorBoundary.getDerivedStateFromError = () => ({
1466
190
  const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
1467
191
  children,
1468
192
  fallback,
1469
- tabIndex,
1470
193
  resize,
1471
- id,
1472
194
  style,
1473
- className,
1474
195
  events,
1475
196
  ...props
1476
197
  }, forwardedRef) {
1477
- const [containerRef, size] = useMeasure__default['default']({
198
+ const canvasProps = pick__default["default"](props, CANVAS_PROPS);
199
+ const divProps = omit__default["default"](props, CANVAS_PROPS);
200
+ const [containerRef, {
201
+ width,
202
+ height
203
+ }] = useMeasure__default["default"]({
1478
204
  scroll: true,
1479
205
  debounce: {
1480
206
  scroll: 50,
@@ -1491,28 +217,28 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
1491
217
  if (error) throw error; // Execute JSX in the reconciler as a layout-effect
1492
218
 
1493
219
  useIsomorphicLayoutEffect(() => {
1494
- if (size.width > 0 && size.height > 0) {
220
+ if (width > 0 && height > 0) {
1495
221
  render( /*#__PURE__*/React__namespace.createElement(ErrorBoundary, {
1496
222
  set: setError
1497
223
  }, /*#__PURE__*/React__namespace.createElement(React__namespace.Suspense, {
1498
224
  fallback: /*#__PURE__*/React__namespace.createElement(Block, {
1499
225
  set: setBlock
1500
226
  })
1501
- }, children)), canvasRef.current, { ...props,
1502
- size,
227
+ }, children)), canvasRef.current, { ...canvasProps,
228
+ size: {
229
+ width,
230
+ height
231
+ },
1503
232
  events: events || createPointerEvents
1504
233
  });
1505
234
  }
1506
- }, [size, children]);
235
+ }, [width, height, children, canvasProps]);
1507
236
  React__namespace.useEffect(() => {
1508
237
  const container = canvasRef.current;
1509
238
  return () => unmountComponentAtNode(container);
1510
239
  }, []);
1511
- return /*#__PURE__*/React__namespace.createElement("div", {
240
+ return /*#__PURE__*/React__namespace.createElement("div", _extends({
1512
241
  ref: containerRef,
1513
- id: id,
1514
- className: className,
1515
- tabIndex: tabIndex,
1516
242
  style: {
1517
243
  position: 'relative',
1518
244
  width: '100%',
@@ -1520,105 +246,48 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
1520
246
  overflow: 'hidden',
1521
247
  ...style
1522
248
  }
1523
- }, /*#__PURE__*/React__namespace.createElement("canvas", {
1524
- ref: mergeRefs__default['default']([canvasRef, forwardedRef]),
249
+ }, divProps), /*#__PURE__*/React__namespace.createElement("canvas", {
250
+ ref: mergeRefs__default["default"]([canvasRef, forwardedRef]),
1525
251
  style: {
1526
252
  display: 'block'
1527
253
  }
1528
254
  }, fallback));
1529
255
  });
1530
256
 
1531
- function useStore() {
1532
- const store = React__namespace.useContext(context);
1533
- if (!store) throw `R3F hooks can only be used within the Canvas component!`;
1534
- return store;
1535
- }
1536
- function useThree(selector = state => state, equalityFn) {
1537
- return useStore()(selector, equalityFn);
1538
- }
1539
- function useFrame(callback, renderPriority = 0) {
1540
- const subscribe = useStore().getState().internal.subscribe; // Update ref
1541
-
1542
- const ref = React__namespace.useRef(callback);
1543
- React__namespace.useLayoutEffect(() => void (ref.current = callback), [callback]); // Subscribe on mount, unsubscribe on unmount
1544
-
1545
- React__namespace.useLayoutEffect(() => subscribe(ref, renderPriority), [renderPriority, subscribe]);
1546
- return null;
1547
- }
1548
-
1549
- function buildGraph(object) {
1550
- const data = {
1551
- nodes: {},
1552
- materials: {}
1553
- };
1554
-
1555
- if (object) {
1556
- object.traverse(obj => {
1557
- if (obj.name) {
1558
- data.nodes[obj.name] = obj;
1559
- }
1560
-
1561
- if (obj.material && !data.materials[obj.material.name]) {
1562
- data.materials[obj.material.name] = obj.material;
1563
- }
1564
- });
1565
- }
1566
-
1567
- return data;
1568
- }
1569
-
1570
- function useGraph(object) {
1571
- return React__namespace.useMemo(() => buildGraph(object), [object]);
1572
- }
1573
-
1574
- function loadingFn(extensions, onProgress) {
1575
- return function (Proto, ...input) {
1576
- // Construct new loader and run extensions
1577
- const loader = new Proto();
1578
- if (extensions) extensions(loader); // Go through the urls and load them
1579
-
1580
- return Promise.all(input.map(input => new Promise((res, reject) => loader.load(input, data => {
1581
- if (data.scene) Object.assign(data, buildGraph(data.scene));
1582
- res(data);
1583
- }, onProgress, error => reject(`Could not load ${input}: ${error.message}`)))));
1584
- };
1585
- }
1586
-
1587
- function useLoader(Proto, input, extensions, onProgress) {
1588
- // Use suspense to load async assets
1589
- const keys = Array.isArray(input) ? input : [input];
1590
- const results = useAsset.useAsset(loadingFn(extensions, onProgress), Proto, ...keys); // Return the object/s
1591
-
1592
- return Array.isArray(input) ? results : results[0];
1593
- }
1594
-
1595
- useLoader.preload = function (Proto, input, extensions) {
1596
- const keys = Array.isArray(input) ? input : [input];
1597
- return useAsset.useAsset.preload(loadingFn(extensions), Proto, ...keys);
1598
- };
1599
-
1600
- useLoader.clear = function (Proto, input) {
1601
- const keys = Array.isArray(input) ? input : [input];
1602
- return useAsset.useAsset.clear(Proto, ...keys);
1603
- };
1604
-
1605
257
  const roots = new Map();
1606
258
  const {
1607
259
  invalidate,
1608
260
  advance
1609
- } = createLoop(roots);
261
+ } = hooks.createLoop(roots);
1610
262
  const {
1611
263
  reconciler,
1612
264
  applyProps
1613
- } = createRenderer();
265
+ } = hooks.createRenderer(roots, getEventPriority);
266
+
267
+ const createRendererInstance = (gl, canvas) => {
268
+ const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
269
+ if (hooks.isRenderer(customRenderer)) return customRenderer;
270
+ const renderer = new THREE__namespace.WebGLRenderer({
271
+ powerPreference: 'high-performance',
272
+ canvas: canvas,
273
+ antialias: true,
274
+ alpha: true,
275
+ ...gl
276
+ }); // Set color management
277
+
278
+ renderer.outputEncoding = THREE__namespace.sRGBEncoding;
279
+ renderer.toneMapping = THREE__namespace.ACESFilmicToneMapping; // Set gl props
280
+
281
+ if (gl) applyProps(renderer, gl);
282
+ return renderer;
283
+ };
1614
284
 
1615
- const createRendererInstance = (gl, canvas) => isRenderer(gl) ? gl : new THREE__namespace.WebGLRenderer({
1616
- powerPreference: 'high-performance',
1617
- canvas: canvas,
1618
- antialias: true,
1619
- alpha: true,
1620
- ...gl
1621
- });
285
+ function createRoot(canvas, config) {
286
+ return {
287
+ render: element => render(element, canvas, config),
288
+ unmount: () => unmountComponentAtNode(canvas)
289
+ };
290
+ }
1622
291
 
1623
292
  function render(element, canvas, {
1624
293
  gl,
@@ -1645,15 +314,14 @@ function render(element, canvas, {
1645
314
  let state = (_store = store) == null ? void 0 : _store.getState();
1646
315
 
1647
316
  if (fiber && state) {
1648
- const lastProps = state.internal.lastProps; // When a root was found, see if any fundamental props must be changed or exchanged
317
+ // When a root was found, see if any fundamental props must be changed or exchanged
1649
318
  // Check pixelratio
319
+ if (props.dpr !== undefined && state.viewport.dpr !== hooks.calculateDpr(props.dpr)) state.setDpr(props.dpr); // Check size
1650
320
 
1651
- if (props.dpr !== undefined && !is.equ(lastProps.dpr, props.dpr)) state.setDpr(props.dpr); // Check size
1652
-
1653
- if (!is.equ(lastProps.size, size)) state.setSize(size.width, size.height); // For some props we want to reset the entire root
321
+ if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // For some props we want to reset the entire root
1654
322
  // Changes to the color-space
1655
323
 
1656
- const linearChanged = props.linear !== lastProps.linear;
324
+ const linearChanged = props.linear !== state.internal.lastProps.linear;
1657
325
 
1658
326
  if (linearChanged) {
1659
327
  unmountComponentAtNode(canvas);
@@ -1664,15 +332,9 @@ function render(element, canvas, {
1664
332
  if (!fiber) {
1665
333
  // If no root has been found, make one
1666
334
  // Create gl
1667
- const glRenderer = createRendererInstance(gl, canvas); // Enable VR if requested
1668
-
1669
- if (props.vr) {
1670
- glRenderer.xr.enabled = true;
1671
- glRenderer.setAnimationLoop(timestamp => advance(timestamp, true));
1672
- } // Create store
1673
-
335
+ const glRenderer = createRendererInstance(gl, canvas); // Create store
1674
336
 
1675
- store = createStore(applyProps, invalidate, advance, {
337
+ store = hooks.createStore(applyProps, invalidate, advance, {
1676
338
  gl: glRenderer,
1677
339
  size,
1678
340
  ...props
@@ -1721,9 +383,9 @@ function Provider({
1721
383
 
1722
384
  state.events.connect == null ? void 0 : state.events.connect(target); // Notifiy that init is completed, the scene graph exists, but nothing has yet rendered
1723
385
 
1724
- if (onCreated) onCreated(state);
386
+ if (onCreated) onCreated(state); // eslint-disable-next-line react-hooks/exhaustive-deps
1725
387
  }, []);
1726
- return /*#__PURE__*/React__namespace.createElement(context.Provider, {
388
+ return /*#__PURE__*/React__namespace.createElement(hooks.context.Provider, {
1727
389
  value: store
1728
390
  }, element);
1729
391
  }
@@ -1738,30 +400,25 @@ function unmountComponentAtNode(canvas, callback) {
1738
400
  reconciler.updateContainer(null, fiber, null, () => {
1739
401
  if (state) {
1740
402
  setTimeout(() => {
1741
- var _state$gl, _state$gl$renderLists, _state$gl2;
1742
-
1743
- state.events.disconnect == null ? void 0 : state.events.disconnect();
1744
- (_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();
1745
- (_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
1746
- dispose(state);
1747
- roots.delete(canvas);
1748
- if (callback) callback(canvas);
403
+ try {
404
+ var _state$gl, _state$gl$renderLists, _state$gl2, _state$gl3;
405
+
406
+ state.events.disconnect == null ? void 0 : state.events.disconnect();
407
+ (_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();
408
+ (_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
409
+ if ((_state$gl3 = state.gl) != null && _state$gl3.xr) state.internal.xr.disconnect();
410
+ hooks.dispose(state);
411
+ roots.delete(canvas);
412
+ if (callback) callback(canvas);
413
+ } catch (e) {
414
+ /* ... */
415
+ }
1749
416
  }, 500);
1750
417
  }
1751
418
  });
1752
419
  }
1753
420
  }
1754
421
 
1755
- function dispose(obj) {
1756
- if (obj.dispose && obj.type !== 'Scene') obj.dispose();
1757
-
1758
- for (const p in obj) {
1759
- var _dispose, _ref;
1760
- (_dispose = (_ref = p).dispose) == null ? void 0 : _dispose.call(_ref);
1761
- delete obj[p];
1762
- }
1763
- }
1764
-
1765
422
  const act = reconciler.act;
1766
423
 
1767
424
  function createPortal(children, container) {
@@ -1771,29 +428,30 @@ function createPortal(children, container) {
1771
428
  reconciler.injectIntoDevTools({
1772
429
  bundleType: process.env.NODE_ENV === 'production' ? 0 : 1,
1773
430
  rendererPackageName: '@react-three/fiber',
1774
- version: '17.0.2'
431
+ version: '18.0.0'
1775
432
  });
1776
433
 
434
+ exports.ReactThreeFiber = hooks.threeTypes;
435
+ exports.addAfterEffect = hooks.addAfterEffect;
436
+ exports.addEffect = hooks.addEffect;
437
+ exports.addTail = hooks.addTail;
438
+ exports.context = hooks.context;
439
+ exports.dispose = hooks.dispose;
440
+ exports.extend = hooks.extend;
441
+ exports.useFrame = hooks.useFrame;
442
+ exports.useGraph = hooks.useGraph;
443
+ exports.useLoader = hooks.useLoader;
444
+ exports.useStore = hooks.useStore;
445
+ exports.useThree = hooks.useThree;
1777
446
  exports.Canvas = Canvas;
1778
- exports.ReactThreeFiber = threeTypes;
1779
447
  exports._roots = roots;
1780
448
  exports.act = act;
1781
- exports.addAfterEffect = addAfterEffect;
1782
- exports.addEffect = addEffect;
1783
- exports.addTail = addTail;
1784
449
  exports.advance = advance;
1785
450
  exports.applyProps = applyProps;
1786
- exports.context = context;
1787
451
  exports.createPortal = createPortal;
1788
- exports.dispose = dispose;
452
+ exports.createRoot = createRoot;
1789
453
  exports.events = createPointerEvents;
1790
- exports.extend = extend;
1791
454
  exports.invalidate = invalidate;
1792
455
  exports.reconciler = reconciler;
1793
456
  exports.render = render;
1794
457
  exports.unmountComponentAtNode = unmountComponentAtNode;
1795
- exports.useFrame = useFrame;
1796
- exports.useGraph = useGraph;
1797
- exports.useLoader = useLoader;
1798
- exports.useStore = useStore;
1799
- exports.useThree = useThree;