@react-three/fiber 7.0.18 → 7.0.22

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.
@@ -0,0 +1,590 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var hooks = require('../../dist/hooks-1558bdce.cjs.dev.js');
6
+ var THREE = require('three');
7
+ var React = require('react');
8
+ var constants = require('react-reconciler/constants');
9
+ var Pressability = require('react-native/Libraries/Pressability/Pressability');
10
+ var reactNative = require('react-native');
11
+ var expoAsset = require('expo-asset');
12
+ var expoFileSystem = require('expo-file-system');
13
+ var base64Arraybuffer = require('base64-arraybuffer');
14
+ var suspendReact = require('suspend-react');
15
+ var _extends = require('@babel/runtime/helpers/extends');
16
+ var expoGl = require('expo-gl');
17
+ var pick = require('lodash-es/pick');
18
+ var omit = require('lodash-es/omit');
19
+ require('react-reconciler');
20
+ require('zustand');
21
+
22
+ function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
23
+
24
+ function _interopNamespace(e) {
25
+ if (e && e.__esModule) return e;
26
+ var n = Object.create(null);
27
+ if (e) {
28
+ Object.keys(e).forEach(function (k) {
29
+ if (k !== 'default') {
30
+ var d = Object.getOwnPropertyDescriptor(e, k);
31
+ Object.defineProperty(n, k, d.get ? d : {
32
+ enumerable: true,
33
+ get: function () { return e[k]; }
34
+ });
35
+ }
36
+ });
37
+ }
38
+ n["default"] = e;
39
+ return Object.freeze(n);
40
+ }
41
+
42
+ var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
43
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
44
+ var Pressability__default = /*#__PURE__*/_interopDefault(Pressability);
45
+ var pick__default = /*#__PURE__*/_interopDefault(pick);
46
+ var omit__default = /*#__PURE__*/_interopDefault(omit);
47
+
48
+ // @ts-ignore
49
+ const EVENTS = {
50
+ PRESS: 'onPress',
51
+ PRESSIN: 'onPressIn',
52
+ PRESSOUT: 'onPressOut',
53
+ LONGPRESS: 'onLongPress',
54
+ HOVERIN: 'onHoverIn',
55
+ HOVEROUT: 'onHoverOut',
56
+ PRESSMOVE: 'onPressMove'
57
+ };
58
+ const DOM_EVENTS = {
59
+ [EVENTS.PRESS]: 'onClick',
60
+ [EVENTS.PRESSIN]: 'onPointerDown',
61
+ [EVENTS.PRESSOUT]: 'onPointerUp',
62
+ [EVENTS.LONGPRESS]: 'onDoubleClick',
63
+ [EVENTS.HOVERIN]: 'onPointerOver',
64
+ [EVENTS.HOVEROUT]: 'onPointerOut',
65
+ [EVENTS.PRESSMOVE]: 'onPointerMove'
66
+ }; // https://github.com/facebook/react/tree/main/packages/react-reconciler#getcurrenteventpriority
67
+ // Gives React a clue as to how import the current interaction is
68
+
69
+ function getEventPriority() {
70
+ var _window, _window$event;
71
+
72
+ let name = (_window = window) == null ? void 0 : (_window$event = _window.event) == null ? void 0 : _window$event.type;
73
+
74
+ switch (name) {
75
+ case EVENTS.PRESS:
76
+ case EVENTS.PRESSIN:
77
+ case EVENTS.PRESSOUT:
78
+ case EVENTS.LONGPRESS:
79
+ return constants.DiscreteEventPriority;
80
+
81
+ case EVENTS.HOVERIN:
82
+ case EVENTS.HOVEROUT:
83
+ case EVENTS.PRESSMOVE:
84
+ return constants.ContinuousEventPriority;
85
+
86
+ default:
87
+ return constants.DefaultEventPriority;
88
+ }
89
+ }
90
+ function createTouchEvents(store) {
91
+ const {
92
+ handlePointer
93
+ } = hooks.createEvents(store);
94
+
95
+ const handleTouch = (event, name) => {
96
+ event.persist() // Apply offset
97
+ ;
98
+ event.nativeEvent.offsetX = event.nativeEvent.pageX;
99
+ event.nativeEvent.offsetY = event.nativeEvent.pageY; // Emulate DOM event
100
+
101
+ const callback = handlePointer(DOM_EVENTS[name]);
102
+ return callback(event.nativeEvent);
103
+ };
104
+
105
+ return {
106
+ connected: false,
107
+ handlers: Object.values(EVENTS).reduce((acc, name) => ({ ...acc,
108
+ [name]: event => handleTouch(event, name)
109
+ }), {}),
110
+ connect: () => {
111
+ const {
112
+ set,
113
+ events
114
+ } = store.getState();
115
+ events.disconnect == null ? void 0 : events.disconnect();
116
+ const manager = new Pressability__default["default"](events == null ? void 0 : events.handlers);
117
+ set(state => ({
118
+ events: { ...state.events,
119
+ connected: manager
120
+ }
121
+ }));
122
+ },
123
+ disconnect: () => {
124
+ const {
125
+ set,
126
+ events
127
+ } = store.getState();
128
+
129
+ if (events.connected) {
130
+ events.connected.reset();
131
+ set(state => ({
132
+ events: { ...state.events,
133
+ connected: false
134
+ }
135
+ }));
136
+ }
137
+ }
138
+ };
139
+ }
140
+
141
+ const CANVAS_PROPS = ['gl', 'events', 'size', 'shadows', 'linear', 'flat', 'orthographic', 'frameloop', // 'dpr',
142
+ 'performance', 'clock', 'raycaster', 'camera', 'onPointerMissed', 'onCreated']; // React currently throws a warning when using useLayoutEffect on the server.
143
+ // To get around it, we can conditionally useEffect on the server (no-op) and
144
+ // useLayoutEffect in the browser.
145
+
146
+ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React__namespace.useLayoutEffect : React__namespace.useEffect;
147
+
148
+ function Block({
149
+ set
150
+ }) {
151
+ useIsomorphicLayoutEffect(() => {
152
+ set(new Promise(() => null));
153
+ return () => set(false);
154
+ }, []);
155
+ return null;
156
+ }
157
+
158
+ class ErrorBoundary extends React__namespace.Component {
159
+ constructor(...args) {
160
+ super(...args);
161
+ this.state = {
162
+ error: false
163
+ };
164
+ }
165
+
166
+ componentDidCatch(error) {
167
+ this.props.set(error);
168
+ }
169
+
170
+ render() {
171
+ return this.state.error ? null : this.props.children;
172
+ }
173
+
174
+ }
175
+
176
+ ErrorBoundary.getDerivedStateFromError = () => ({
177
+ error: true
178
+ });
179
+
180
+ const Canvas = /*#__PURE__*/React__namespace.forwardRef(({
181
+ children,
182
+ fallback,
183
+ style,
184
+ events,
185
+ nativeRef_EXPERIMENTAL,
186
+ onContextCreate,
187
+ ...props
188
+ }, forwardedRef) => {
189
+ const canvasProps = pick__default["default"](props, CANVAS_PROPS);
190
+ const viewProps = omit__default["default"](props, CANVAS_PROPS);
191
+ const [context, setContext] = React__namespace.useState(null);
192
+ const [{
193
+ width,
194
+ height
195
+ }, setSize] = React__namespace.useState({
196
+ width: 0,
197
+ height: 0
198
+ });
199
+ const [bind, setBind] = React__namespace.useState();
200
+ const [block, setBlock] = React__namespace.useState(false);
201
+ const [error, setError] = React__namespace.useState(false); // Suspend this component if block is a promise (2nd run)
202
+
203
+ if (block) throw block; // Throw exception outwards if anything within canvas throws
204
+
205
+ if (error) throw error;
206
+ const onLayout = React__namespace.useCallback(e => {
207
+ const {
208
+ width,
209
+ height
210
+ } = e.nativeEvent.layout;
211
+ setSize({
212
+ width,
213
+ height
214
+ });
215
+ }, []); // Execute JSX in the reconciler as a layout-effect
216
+
217
+ useIsomorphicLayoutEffect(() => {
218
+ if (width > 0 && height > 0 && context) {
219
+ const store = render( /*#__PURE__*/React__namespace.createElement(ErrorBoundary, {
220
+ set: setError
221
+ }, /*#__PURE__*/React__namespace.createElement(React__namespace.Suspense, {
222
+ fallback: /*#__PURE__*/React__namespace.createElement(Block, {
223
+ set: setBlock
224
+ })
225
+ }, children)), context, { ...canvasProps,
226
+ size: {
227
+ width,
228
+ height
229
+ },
230
+ events: events || createTouchEvents
231
+ });
232
+ const state = store.getState();
233
+ setBind(state.events.connected.getEventHandlers());
234
+ }
235
+ }, [width, height, children, context, canvasProps]);
236
+ useIsomorphicLayoutEffect(() => {
237
+ return () => {
238
+ if (context) unmountComponentAtNode(context);
239
+ };
240
+ }, []);
241
+ return /*#__PURE__*/React__namespace.createElement(reactNative.View, _extends({}, viewProps, {
242
+ ref: forwardedRef,
243
+ onLayout: onLayout,
244
+ style: {
245
+ flex: 1,
246
+ ...style
247
+ }
248
+ }, bind), width > 0 && /*#__PURE__*/React__namespace.createElement(expoGl.GLView, {
249
+ nativeRef_EXPERIMENTAL: ref => {
250
+ if (nativeRef_EXPERIMENTAL && !nativeRef_EXPERIMENTAL.current) {
251
+ nativeRef_EXPERIMENTAL.current = ref;
252
+ }
253
+ },
254
+ onContextCreate: async gl => {
255
+ await (onContextCreate == null ? void 0 : onContextCreate(gl));
256
+ setContext(gl);
257
+ },
258
+ style: reactNative.StyleSheet.absoluteFill
259
+ }));
260
+ });
261
+
262
+ /**
263
+ * Generates an asset based on input type.
264
+ */
265
+
266
+ const getAsset = input => {
267
+ if (input instanceof expoAsset.Asset) return input;
268
+
269
+ switch (typeof input) {
270
+ case 'string':
271
+ return expoAsset.Asset.fromURI(input);
272
+
273
+ case 'number':
274
+ return expoAsset.Asset.fromModule(input);
275
+
276
+ default:
277
+ throw 'Invalid asset! Must be a URI or module.';
278
+ }
279
+ };
280
+ /**
281
+ * Downloads from a local URI and decodes into an ArrayBuffer.
282
+ */
283
+
284
+
285
+ const toBuffer = async localUri => expoFileSystem.readAsStringAsync(localUri, {
286
+ encoding: 'base64'
287
+ }).then(base64Arraybuffer.decode);
288
+
289
+ function loadingFn(extensions, onProgress) {
290
+ return function (Proto, ...input) {
291
+ // Construct new loader and run extensions
292
+ const loader = new Proto();
293
+ if (extensions) extensions(loader); // Go through the urls and load them
294
+
295
+ return Promise.all(input.map(entry => new Promise(async (res, reject) => {
296
+ var _parse, _ref;
297
+
298
+ // Construct URL
299
+ const url = typeof entry === 'string' ? loader.path + entry : entry; // There's no Image in native, so we create & pass a data texture instead
300
+
301
+ if (loader instanceof THREE__namespace.TextureLoader) {
302
+ const asset = await getAsset(url).downloadAsync();
303
+ const texture = new THREE__namespace.Texture();
304
+ texture.isDataTexture = true;
305
+ texture.image = {
306
+ data: asset,
307
+ width: asset.width,
308
+ height: asset.height
309
+ };
310
+ texture.needsUpdate = true;
311
+ return res(texture);
312
+ } // Do similar for CubeTextures
313
+
314
+
315
+ if (loader instanceof THREE__namespace.CubeTextureLoader) {
316
+ const texture = new THREE__namespace.CubeTexture();
317
+ texture.isDataTexture = true;
318
+ texture.images = await Promise.all(url.map(async src => {
319
+ const asset = await getAsset(src).downloadAsync();
320
+ return {
321
+ data: asset,
322
+ width: asset.width,
323
+ height: asset.height
324
+ };
325
+ }));
326
+ texture.needsUpdate = true;
327
+ return res(texture);
328
+ } // If asset is external and not an Image, load it
329
+
330
+
331
+ if (url.startsWith != null && url.startsWith('http') && Proto.prototype.hasOwnProperty('load')) {
332
+ return loader.load(entry, data => {
333
+ if (data.scene) Object.assign(data, hooks.buildGraph(data.scene));
334
+ res(data);
335
+ }, onProgress, error => reject(`Could not load ${url}: ${error.message}`));
336
+ } // Otherwise, create a localUri and a file buffer
337
+
338
+
339
+ const {
340
+ localUri
341
+ } = await getAsset(url).downloadAsync();
342
+ const arrayBuffer = await toBuffer(localUri); // Parse it
343
+
344
+ const parsed = (_parse = (_ref = loader).parse) == null ? void 0 : _parse.call(_ref, arrayBuffer, undefined, data => {
345
+ if (data.scene) Object.assign(data, hooks.buildGraph(data.scene));
346
+ res(data);
347
+ }, error => reject(`Could not load ${url}: ${error.message}`)); // Respect synchronous parsers which don't have callbacks
348
+
349
+ if (parsed) return res(parsed);
350
+ })));
351
+ };
352
+ }
353
+
354
+ function useLoader(Proto, input, extensions, onProgress) {
355
+ // Use suspense to load async assets
356
+ const keys = Array.isArray(input) ? input : [input];
357
+ const results = suspendReact.suspend(loadingFn(extensions, onProgress), [Proto, ...keys], {
358
+ equal: hooks.is.equ
359
+ }); // Return the object/s
360
+
361
+ return Array.isArray(input) ? results : results[0];
362
+ }
363
+
364
+ useLoader.preload = function (Proto, input, extensions) {
365
+ const keys = Array.isArray(input) ? input : [input];
366
+ return suspendReact.preload(loadingFn(extensions), [Proto, ...keys]);
367
+ };
368
+
369
+ useLoader.clear = function (Proto, input) {
370
+ const keys = Array.isArray(input) ? input : [input];
371
+ return suspendReact.clear([Proto, ...keys]);
372
+ };
373
+
374
+ const roots = new Map();
375
+ const {
376
+ invalidate,
377
+ advance
378
+ } = hooks.createLoop(roots);
379
+ const {
380
+ reconciler,
381
+ applyProps
382
+ } = hooks.createRenderer(roots, getEventPriority);
383
+
384
+ const createRendererInstance = (gl, context) => {
385
+ // Create canvas shim
386
+ const canvas = {
387
+ width: context.drawingBufferWidth,
388
+ height: context.drawingBufferHeight,
389
+ style: {},
390
+ addEventListener: () => {},
391
+ removeEventListener: () => {},
392
+ clientHeight: context.drawingBufferHeight
393
+ }; // If a renderer is specified, return it
394
+
395
+ const customRenderer = typeof gl === 'function' ? gl(canvas, context) : gl;
396
+ if (hooks.isRenderer(customRenderer)) return customRenderer; // Create renderer and pass our canvas and its context
397
+
398
+ const renderer = new THREE__namespace.WebGLRenderer({
399
+ powerPreference: 'high-performance',
400
+ antialias: true,
401
+ alpha: true,
402
+ ...gl,
403
+ canvas,
404
+ context
405
+ }); // Set color management
406
+
407
+ renderer.outputEncoding = THREE__namespace.sRGBEncoding;
408
+ renderer.toneMapping = THREE__namespace.ACESFilmicToneMapping; // Set GL props
409
+
410
+ if (gl) applyProps(renderer, gl); // Bind render to RN bridge
411
+
412
+ if (context.endFrameEXP) {
413
+ const renderFrame = renderer.render.bind(renderer);
414
+
415
+ renderer.render = (scene, camera) => {
416
+ renderFrame(scene, camera);
417
+ context.endFrameEXP();
418
+ };
419
+ }
420
+
421
+ return renderer;
422
+ };
423
+
424
+ function createRoot(context, config) {
425
+ return {
426
+ render: element => render(element, context, config),
427
+ unmount: () => unmountComponentAtNode(context)
428
+ };
429
+ }
430
+
431
+ function render(element, context, {
432
+ gl,
433
+ size = {
434
+ width: 0,
435
+ height: 0
436
+ },
437
+ events,
438
+ onCreated,
439
+ ...props
440
+ } = {}) {
441
+ var _store;
442
+
443
+ let root = roots.get(context);
444
+ let fiber = root == null ? void 0 : root.fiber;
445
+ let store = root == null ? void 0 : root.store;
446
+ let state = (_store = store) == null ? void 0 : _store.getState();
447
+
448
+ if (fiber && state) {
449
+ // When a root was found, see if any fundamental props must be changed or exchanged
450
+ // Check size
451
+ 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
452
+ // Changes to the color-space
453
+
454
+ const linearChanged = props.linear !== state.internal.lastProps.linear;
455
+
456
+ if (linearChanged) {
457
+ unmountComponentAtNode(context);
458
+ fiber = undefined;
459
+ }
460
+ }
461
+
462
+ if (!fiber) {
463
+ // If no root has been found, make one
464
+ // Create gl
465
+ const glRenderer = createRendererInstance(gl, context); // Create store
466
+
467
+ store = hooks.createStore(applyProps, invalidate, advance, {
468
+ gl: glRenderer,
469
+ size,
470
+ ...props,
471
+ // expo-gl can only render at native dpr/resolution
472
+ // https://github.com/expo/expo-three/issues/39
473
+ dpr: reactNative.PixelRatio.get()
474
+ });
475
+ const state = store.getState(); // Create renderer
476
+
477
+ fiber = reconciler.createContainer(store, constants.ConcurrentRoot, false, null); // Map it
478
+
479
+ roots.set(context, {
480
+ fiber,
481
+ store
482
+ }); // Store event manager internally and connect it
483
+
484
+ if (events) {
485
+ var _state$get$events$con, _state$get$events;
486
+
487
+ state.set({
488
+ events: events(store)
489
+ });
490
+ (_state$get$events$con = (_state$get$events = state.get().events).connect) == null ? void 0 : _state$get$events$con.call(_state$get$events, context);
491
+ }
492
+ }
493
+
494
+ if (store && fiber) {
495
+ reconciler.updateContainer( /*#__PURE__*/React__namespace.createElement(Provider, {
496
+ store: store,
497
+ element: element,
498
+ onCreated: onCreated
499
+ }), fiber, null, () => undefined);
500
+ return store;
501
+ } else {
502
+ throw 'Error creating root!';
503
+ }
504
+ }
505
+
506
+ function Provider({
507
+ store,
508
+ element,
509
+ onCreated
510
+ }) {
511
+ React__namespace.useEffect(() => {
512
+ const state = store.getState(); // Flag the canvas active, rendering will now begin
513
+
514
+ state.set(state => ({
515
+ internal: { ...state.internal,
516
+ active: true
517
+ }
518
+ })); // Notifiy that init is completed, the scene graph exists, but nothing has yet rendered
519
+
520
+ if (onCreated) onCreated(state); // eslint-disable-next-line react-hooks/exhaustive-deps
521
+ }, []);
522
+ return /*#__PURE__*/React__namespace.createElement(hooks.context.Provider, {
523
+ value: store
524
+ }, element);
525
+ }
526
+
527
+ function unmountComponentAtNode(context, callback) {
528
+ const root = roots.get(context);
529
+ const fiber = root == null ? void 0 : root.fiber;
530
+
531
+ if (fiber) {
532
+ const state = root == null ? void 0 : root.store.getState();
533
+ if (state) state.internal.active = false;
534
+ reconciler.updateContainer(null, fiber, null, () => {
535
+ if (state) {
536
+ setTimeout(() => {
537
+ try {
538
+ var _state$gl, _state$gl$renderLists, _state$gl2;
539
+
540
+ state.events.disconnect == null ? void 0 : state.events.disconnect();
541
+ (_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();
542
+ (_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
543
+ hooks.dispose(state);
544
+ roots.delete(context);
545
+ if (callback) callback(context);
546
+ } catch (e) {
547
+ /* ... */
548
+ }
549
+ }, 500);
550
+ }
551
+ });
552
+ }
553
+ }
554
+
555
+ const act = reconciler.act;
556
+
557
+ function createPortal(children, container) {
558
+ return reconciler.createPortal(children, container, null, null);
559
+ }
560
+
561
+ reconciler.injectIntoDevTools({
562
+ bundleType: process.env.NODE_ENV === 'production' ? 0 : 1,
563
+ rendererPackageName: '@react-three/fiber',
564
+ version: '18.0.0'
565
+ });
566
+
567
+ exports.ReactThreeFiber = hooks.threeTypes;
568
+ exports.addAfterEffect = hooks.addAfterEffect;
569
+ exports.addEffect = hooks.addEffect;
570
+ exports.addTail = hooks.addTail;
571
+ exports.context = hooks.context;
572
+ exports.dispose = hooks.dispose;
573
+ exports.extend = hooks.extend;
574
+ exports.useFrame = hooks.useFrame;
575
+ exports.useGraph = hooks.useGraph;
576
+ exports.useStore = hooks.useStore;
577
+ exports.useThree = hooks.useThree;
578
+ exports.Canvas = Canvas;
579
+ exports._roots = roots;
580
+ exports.act = act;
581
+ exports.advance = advance;
582
+ exports.applyProps = applyProps;
583
+ exports.createPortal = createPortal;
584
+ exports.createRoot = createRoot;
585
+ exports.events = createTouchEvents;
586
+ exports.invalidate = invalidate;
587
+ exports.reconciler = reconciler;
588
+ exports.render = render;
589
+ exports.unmountComponentAtNode = unmountComponentAtNode;
590
+ exports.useLoader = useLoader;
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ if (process.env.NODE_ENV === "production") {
4
+ module.exports = require("./react-three-fiber-native.cjs.prod.js");
5
+ } else {
6
+ module.exports = require("./react-three-fiber-native.cjs.dev.js");
7
+ }