framer-motion 5.4.4 → 5.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/three-entry.js +154 -23
- package/dist/cjs/{use-motion-value-73ed7c77.js → use-motion-value-28b1fded.js} +3 -1
- package/dist/es/components/three/LayoutCamera.mjs +21 -0
- package/dist/es/components/three/LayoutOrthographicCamera.mjs +21 -0
- package/dist/es/components/three/MotionCanvas.mjs +90 -0
- package/dist/es/components/three/MotionCanvasContext.mjs +5 -0
- package/dist/es/components/three/use-layout-camera.mjs +87 -0
- package/dist/es/context/MotionContext/index.mjs +1 -1
- package/dist/es/index.mjs +1 -0
- package/dist/es/projection/node/create-projection-node.mjs +3 -1
- package/dist/es/render/three/create-visual-element.mjs +3 -1
- package/dist/es/render/three/utils/read-value.mjs +3 -2
- package/dist/es/three-entry.mjs +3 -1
- package/dist/framer-motion.dev.js +4 -1
- package/dist/framer-motion.js +1 -1
- package/dist/projection.dev.js +3 -1
- package/dist/size-rollup-dom-max.js +1 -1
- package/package.json +6 -5
- package/types/components/three/LayoutCamera.d.ts +26 -0
- package/types/components/three/LayoutOrthographicCamera.d.ts +23 -0
- package/types/components/{MotionCanvas/index.d.ts → three/MotionCanvas.d.ts} +1 -1
- package/types/components/three/MotionCanvasContext.d.ts +11 -0
- package/types/components/three/types.d.ts +6 -0
- package/types/components/three/use-layout-camera.d.ts +10 -0
- package/types/index.d.ts +1 -0
- package/types/projection/node/types.d.ts +2 -2
- package/types/three-entry.d.ts +3 -1
- package/dist/es/components/MotionCanvas/index.mjs +0 -68
package/dist/cjs/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var tslib = require('tslib');
|
|
6
|
-
var useMotionValue = require('./use-motion-value-
|
|
6
|
+
var useMotionValue = require('./use-motion-value-28b1fded.js');
|
|
7
7
|
var React = require('react');
|
|
8
8
|
var styleValueTypes = require('style-value-types');
|
|
9
9
|
var popmotion = require('popmotion');
|
|
@@ -3672,6 +3672,7 @@ function useInvertedScale(scale) {
|
|
|
3672
3672
|
exports.FlatTree = useMotionValue.FlatTree;
|
|
3673
3673
|
exports.LayoutGroupContext = useMotionValue.LayoutGroupContext;
|
|
3674
3674
|
exports.MotionConfigContext = useMotionValue.MotionConfigContext;
|
|
3675
|
+
exports.MotionContext = useMotionValue.MotionContext;
|
|
3675
3676
|
exports.MotionValue = useMotionValue.MotionValue;
|
|
3676
3677
|
exports.PresenceContext = useMotionValue.PresenceContext;
|
|
3677
3678
|
exports.SwitchLayoutGroupContext = useMotionValue.SwitchLayoutGroupContext;
|
package/dist/cjs/three-entry.js
CHANGED
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var tslib = require('tslib');
|
|
6
|
-
var useMotionValue = require('./use-motion-value-
|
|
6
|
+
var useMotionValue = require('./use-motion-value-28b1fded.js');
|
|
7
7
|
var React = require('react');
|
|
8
8
|
var popmotion = require('popmotion');
|
|
9
9
|
var three = require('three');
|
|
10
10
|
var mergeRefs = require('react-merge-refs');
|
|
11
|
-
var useMeasure = require('react-use-measure');
|
|
12
11
|
var fiber = require('@react-three/fiber');
|
|
13
|
-
require('hey-listen');
|
|
14
|
-
require('framesync');
|
|
12
|
+
var heyListen = require('hey-listen');
|
|
13
|
+
var sync = require('framesync');
|
|
15
14
|
require('style-value-types');
|
|
16
15
|
|
|
17
16
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -36,7 +35,6 @@ function _interopNamespace(e) {
|
|
|
36
35
|
|
|
37
36
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
38
37
|
var mergeRefs__default = /*#__PURE__*/_interopDefaultLegacy(mergeRefs);
|
|
39
|
-
var useMeasure__default = /*#__PURE__*/_interopDefaultLegacy(useMeasure);
|
|
40
38
|
|
|
41
39
|
function useHover(isStatic, _a, visualElement) {
|
|
42
40
|
var whileHover = _a.whileHover, onHoverStart = _a.onHoverStart, onHoverEnd = _a.onHoverEnd, onPointerOver = _a.onPointerOver, onPointerOut = _a.onPointerOut;
|
|
@@ -189,9 +187,10 @@ var readers = {
|
|
|
189
187
|
rotateZ: readRotation("z"),
|
|
190
188
|
};
|
|
191
189
|
function readAnimatableValue(value) {
|
|
192
|
-
if (
|
|
190
|
+
if (value === undefined) {
|
|
193
191
|
return;
|
|
194
|
-
|
|
192
|
+
}
|
|
193
|
+
else if (value instanceof three.Color) {
|
|
195
194
|
return value.getStyle();
|
|
196
195
|
}
|
|
197
196
|
else {
|
|
@@ -247,7 +246,8 @@ var threeVisualElement = useMotionValue.visualElement({
|
|
|
247
246
|
sortNodePosition: function (a, b) {
|
|
248
247
|
return a.id - b.id;
|
|
249
248
|
},
|
|
250
|
-
makeTargetAnimatable: function (element,
|
|
249
|
+
makeTargetAnimatable: function (element, _a) {
|
|
250
|
+
_a.transition; var target = tslib.__rest(_a, ["transition"]);
|
|
251
251
|
useMotionValue.checkTargetForNewValues(element, target, {});
|
|
252
252
|
return target;
|
|
253
253
|
},
|
|
@@ -293,6 +293,15 @@ var motion = new Proxy(custom, {
|
|
|
293
293
|
},
|
|
294
294
|
});
|
|
295
295
|
|
|
296
|
+
var MotionCanvasContext = React.createContext(undefined);
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* This file contains a version of R3F's Canvas component that uses our projection
|
|
300
|
+
* system for layout measurements instead of use-react-measure so we can keep the
|
|
301
|
+
* projection and cameras in sync.
|
|
302
|
+
*
|
|
303
|
+
* https://github.com/pmndrs/react-three-fiber/blob/master/packages/fiber/src/web/Canvas.tsx
|
|
304
|
+
*/
|
|
296
305
|
function Block(_a) {
|
|
297
306
|
var set = _a.set;
|
|
298
307
|
useMotionValue.useIsomorphicLayoutEffect(function () {
|
|
@@ -317,30 +326,44 @@ var ErrorBoundary = /** @class */ (function (_super) {
|
|
|
317
326
|
ErrorBoundary.getDerivedStateFromError = function () { return ({ error: true }); };
|
|
318
327
|
return ErrorBoundary;
|
|
319
328
|
}(React__namespace.Component));
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
329
|
+
function CanvasComponent(_a, forwardedRef) {
|
|
330
|
+
var children = _a.children, fallback = _a.fallback, tabIndex = _a.tabIndex, id = _a.id, style = _a.style, className = _a.className, events = _a.events, props = tslib.__rest(_a, ["children", "fallback", "tabIndex", "id", "style", "className", "events"]);
|
|
331
|
+
/**
|
|
332
|
+
* Import existing contexts to pass through variants and MotionConfig from
|
|
333
|
+
* the DOM to the 3D tree. Shared variants aren't officially supported yet
|
|
334
|
+
* because the parent DOM tree fires effects before the 3D tree, whereas
|
|
335
|
+
* variants are expected to run from bottom-up in useEffect.
|
|
336
|
+
*/
|
|
328
337
|
var motionContext = React.useContext(useMotionValue.MotionContext);
|
|
329
|
-
var
|
|
338
|
+
var configContext = React.useContext(useMotionValue.MotionConfigContext);
|
|
339
|
+
var layoutCamera = React.useRef(null);
|
|
340
|
+
var _b = tslib.__read(React.useState({ width: 0, height: 0 }), 2), size = _b[0], setSize = _b[1];
|
|
341
|
+
var containerRef = React.useRef(null);
|
|
342
|
+
var handleResize = function () {
|
|
343
|
+
var container = containerRef.current;
|
|
344
|
+
setSize({
|
|
345
|
+
width: container.offsetWidth,
|
|
346
|
+
height: container.offsetHeight,
|
|
347
|
+
});
|
|
348
|
+
};
|
|
349
|
+
// Set canvas size on mount
|
|
350
|
+
React.useLayoutEffect(handleResize, []);
|
|
330
351
|
var canvasRef = React__namespace.useRef(null);
|
|
331
|
-
var
|
|
332
|
-
var
|
|
352
|
+
var _c = tslib.__read(React__namespace.useState(false), 2), block = _c[0], setBlock = _c[1];
|
|
353
|
+
var _d = tslib.__read(React__namespace.useState(false), 2), error = _d[0], setError = _d[1];
|
|
333
354
|
// Suspend this component if block is a promise (2nd run)
|
|
334
355
|
if (block)
|
|
335
356
|
throw block;
|
|
336
357
|
// Throw exception outwards if anything within canvas throws
|
|
337
358
|
if (error)
|
|
338
359
|
throw error;
|
|
339
|
-
//
|
|
340
|
-
if (width > 0 && height > 0) {
|
|
360
|
+
// Only render the R3F tree once we have recorded dimensions for the canvas.
|
|
361
|
+
if (size.width > 0 && size.height > 0) {
|
|
341
362
|
fiber.render(React__namespace.createElement(ErrorBoundary, { set: setError },
|
|
342
363
|
React__namespace.createElement(React__namespace.Suspense, { fallback: React__namespace.createElement(Block, { set: setBlock }) },
|
|
343
|
-
React__namespace.createElement(
|
|
364
|
+
React__namespace.createElement(MotionCanvasContext.Provider, { value: { setSize: setSize, layoutCamera: layoutCamera } },
|
|
365
|
+
React__namespace.createElement(useMotionValue.MotionConfigContext.Provider, { value: configContext },
|
|
366
|
+
React__namespace.createElement(useMotionValue.MotionContext.Provider, { value: motionContext }, children))))), canvasRef.current, tslib.__assign(tslib.__assign({}, props), { size: size, events: events || fiber.events }));
|
|
344
367
|
}
|
|
345
368
|
useMotionValue.useIsomorphicLayoutEffect(function () {
|
|
346
369
|
var container = canvasRef.current;
|
|
@@ -349,7 +372,113 @@ function SyncCanvasComponent(_a, forwardedRef) {
|
|
|
349
372
|
return (React__namespace.createElement("div", { ref: containerRef, id: id, className: className, tabIndex: tabIndex, style: tslib.__assign({ position: "relative", width: "100%", height: "100%", overflow: "hidden" }, style) },
|
|
350
373
|
React__namespace.createElement("canvas", { ref: mergeRefs__default["default"]([canvasRef, forwardedRef]), style: { display: "block" } }, fallback)));
|
|
351
374
|
}
|
|
352
|
-
var MotionCanvas = React.forwardRef(
|
|
375
|
+
var MotionCanvas = React.forwardRef(CanvasComponent);
|
|
376
|
+
|
|
377
|
+
var calcBoxSize = function (_a) {
|
|
378
|
+
var x = _a.x, y = _a.y;
|
|
379
|
+
return ({
|
|
380
|
+
width: useMotionValue.calcLength(x),
|
|
381
|
+
height: useMotionValue.calcLength(y),
|
|
382
|
+
});
|
|
383
|
+
};
|
|
384
|
+
function useLayoutCamera(_a, updateCamera) {
|
|
385
|
+
var _b = _a.makeDefault, makeDefault = _b === void 0 ? true : _b;
|
|
386
|
+
var context = React.useContext(MotionCanvasContext);
|
|
387
|
+
heyListen.invariant(Boolean(context), "No MotionCanvas detected. Replace Canvas from @react-three/fiber with MotionCanvas from framer-motion.");
|
|
388
|
+
var _c = context, setSize = _c.setSize, layoutCamera = _c.layoutCamera;
|
|
389
|
+
var latestLayout = React.useRef(null);
|
|
390
|
+
var advance = fiber.useThree(function (three) { return three.advance; });
|
|
391
|
+
var set = fiber.useThree(function (three) { return three.set; });
|
|
392
|
+
var camera = fiber.useThree(function (three) { return three.camera; });
|
|
393
|
+
var size = fiber.useThree(function (three) { return three.size; });
|
|
394
|
+
var gl = fiber.useThree(function (three) { return three.gl; });
|
|
395
|
+
var parentVisualElement = useMotionValue.useVisualElementContext();
|
|
396
|
+
React.useLayoutEffect(function () {
|
|
397
|
+
updateCamera(size);
|
|
398
|
+
var projection = parentVisualElement === null || parentVisualElement === void 0 ? void 0 : parentVisualElement.projection;
|
|
399
|
+
if (!projection)
|
|
400
|
+
return;
|
|
401
|
+
/**
|
|
402
|
+
* When the projection of an element changes we want to update the camera
|
|
403
|
+
* with the projected dimensions.
|
|
404
|
+
*/
|
|
405
|
+
var removeProjectionUpdateListener = projection.addEventListener("projectionUpdate", function (newProjection) {
|
|
406
|
+
// TODO: Removed to prevent iOS from crashing.
|
|
407
|
+
// Perhaps a better apporach is to set with setSize
|
|
408
|
+
// and then set to window native on animationComplete.
|
|
409
|
+
// if (latestLayout.current) {
|
|
410
|
+
// const { x, y } = latestLayout.current
|
|
411
|
+
// const xRatio = calcLength(newProjection.x) / calcLength(x)
|
|
412
|
+
// const yRatio = calcLength(newProjection.y) / calcLength(y)
|
|
413
|
+
// gl.setPixelRatio(
|
|
414
|
+
// Math.max(xRatio, yRatio) * window.devicePixelRatio
|
|
415
|
+
// )
|
|
416
|
+
// }
|
|
417
|
+
updateCamera(calcBoxSize(newProjection));
|
|
418
|
+
advance(sync.getFrameData().timestamp);
|
|
419
|
+
});
|
|
420
|
+
/**
|
|
421
|
+
* When the layout of an element changes we want to update the renderer
|
|
422
|
+
* output to match the layout dimensions.
|
|
423
|
+
*/
|
|
424
|
+
var removeLayoutMeasureListener = projection.addEventListener("measure", function (newLayout) {
|
|
425
|
+
latestLayout.current = newLayout;
|
|
426
|
+
var newSize = calcBoxSize(newLayout);
|
|
427
|
+
gl.setSize(newSize.width, newSize.height);
|
|
428
|
+
setSize(newSize);
|
|
429
|
+
});
|
|
430
|
+
/**
|
|
431
|
+
* When a projection animation completes we want to update the camera to
|
|
432
|
+
* match the recorded layout of the element.
|
|
433
|
+
*/
|
|
434
|
+
var removeAnimationCompleteListener = projection.addEventListener("animationComplete", function () {
|
|
435
|
+
var actual = (projection.layout || {}).actual;
|
|
436
|
+
actual && updateCamera(calcBoxSize(actual));
|
|
437
|
+
});
|
|
438
|
+
return function () {
|
|
439
|
+
removeProjectionUpdateListener();
|
|
440
|
+
removeLayoutMeasureListener();
|
|
441
|
+
removeAnimationCompleteListener();
|
|
442
|
+
};
|
|
443
|
+
}, []);
|
|
444
|
+
React.useLayoutEffect(function () {
|
|
445
|
+
var cam = layoutCamera.current;
|
|
446
|
+
if (makeDefault && cam) {
|
|
447
|
+
var oldCam_1 = camera;
|
|
448
|
+
set(function () { return ({ camera: cam }); });
|
|
449
|
+
return function () { return set(function () { return ({ camera: oldCam_1 }); }); };
|
|
450
|
+
}
|
|
451
|
+
}, [camera, layoutCamera, makeDefault, set]);
|
|
452
|
+
return { size: size, camera: camera, cameraRef: layoutCamera };
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Adapted from https://github.com/pmndrs/drei/blob/master/src/core/PerspectiveCamera.tsx
|
|
457
|
+
*/
|
|
458
|
+
var LayoutCamera = React__namespace.forwardRef(function (props, ref) {
|
|
459
|
+
var cameraRef = useLayoutCamera(props, function (size) {
|
|
460
|
+
var cam = cameraRef.current;
|
|
461
|
+
if (cam && !props.manual) {
|
|
462
|
+
cam.aspect = size.width / size.height;
|
|
463
|
+
cam.updateProjectionMatrix();
|
|
464
|
+
}
|
|
465
|
+
}).cameraRef;
|
|
466
|
+
return (React__namespace.createElement(motion.perspectiveCamera, tslib.__assign({ ref: mergeRefs__default["default"]([cameraRef, ref]) }, props)));
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
var LayoutOrthographicCamera = React__namespace.forwardRef(function (props, ref) {
|
|
470
|
+
var _a = useLayoutCamera(props, function (newSize) {
|
|
471
|
+
var cam = cameraRef.current;
|
|
472
|
+
if (cam) {
|
|
473
|
+
cam.left = newSize.width / -2;
|
|
474
|
+
cam.right = newSize.width / 2;
|
|
475
|
+
cam.top = newSize.height / 2;
|
|
476
|
+
cam.bottom = newSize.height / -2;
|
|
477
|
+
cam.updateProjectionMatrix();
|
|
478
|
+
}
|
|
479
|
+
}), size = _a.size, cameraRef = _a.cameraRef;
|
|
480
|
+
return (React__namespace.createElement(motion.orthographicCamera, tslib.__assign({ left: size.width / -2, right: size.width / 2, top: size.height / 2, bottom: size.height / -2, ref: mergeRefs__default["default"]([cameraRef, ref]) }, props)));
|
|
481
|
+
});
|
|
353
482
|
|
|
354
483
|
function useTime() {
|
|
355
484
|
var time = useMotionValue.useMotionValue(0);
|
|
@@ -357,6 +486,8 @@ function useTime() {
|
|
|
357
486
|
return time;
|
|
358
487
|
}
|
|
359
488
|
|
|
489
|
+
exports.LayoutCamera = LayoutCamera;
|
|
490
|
+
exports.LayoutOrthographicCamera = LayoutOrthographicCamera;
|
|
360
491
|
exports.MotionCanvas = MotionCanvas;
|
|
361
492
|
exports.motion = motion;
|
|
362
493
|
exports.useTime = useTime;
|
|
@@ -2119,7 +2119,7 @@ function createProjectionNode(_a) {
|
|
|
2119
2119
|
this.layoutCorrected = createBox();
|
|
2120
2120
|
this.isLayoutDirty = false;
|
|
2121
2121
|
this.projectionDelta = undefined;
|
|
2122
|
-
this.notifyListeners("measure");
|
|
2122
|
+
this.notifyListeners("measure", this.layout.actual);
|
|
2123
2123
|
(_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.notifyLayoutMeasure(this.layout.actual, prevLayout === null || prevLayout === void 0 ? void 0 : prevLayout.actual);
|
|
2124
2124
|
};
|
|
2125
2125
|
ProjectionNode.prototype.updateScroll = function () {
|
|
@@ -2388,6 +2388,7 @@ function createProjectionNode(_a) {
|
|
|
2388
2388
|
this.treeScale.y !== prevTreeScaleY) {
|
|
2389
2389
|
this.hasProjected = true;
|
|
2390
2390
|
this.scheduleRender();
|
|
2391
|
+
this.notifyListeners("projectionUpdate", target);
|
|
2391
2392
|
}
|
|
2392
2393
|
};
|
|
2393
2394
|
ProjectionNode.prototype.hide = function () {
|
|
@@ -2490,6 +2491,7 @@ function createProjectionNode(_a) {
|
|
|
2490
2491
|
this.currentAnimation =
|
|
2491
2492
|
this.animationValues =
|
|
2492
2493
|
undefined;
|
|
2494
|
+
this.notifyListeners("animationComplete");
|
|
2493
2495
|
};
|
|
2494
2496
|
ProjectionNode.prototype.finishAnimation = function () {
|
|
2495
2497
|
var _a;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { __assign } from 'tslib';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import mergeRefs from 'react-merge-refs';
|
|
4
|
+
import { motion } from '../../render/three/motion.mjs';
|
|
5
|
+
import { useLayoutCamera } from './use-layout-camera.mjs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Adapted from https://github.com/pmndrs/drei/blob/master/src/core/PerspectiveCamera.tsx
|
|
9
|
+
*/
|
|
10
|
+
var LayoutCamera = React.forwardRef(function (props, ref) {
|
|
11
|
+
var cameraRef = useLayoutCamera(props, function (size) {
|
|
12
|
+
var cam = cameraRef.current;
|
|
13
|
+
if (cam && !props.manual) {
|
|
14
|
+
cam.aspect = size.width / size.height;
|
|
15
|
+
cam.updateProjectionMatrix();
|
|
16
|
+
}
|
|
17
|
+
}).cameraRef;
|
|
18
|
+
return (React.createElement(motion.perspectiveCamera, __assign({ ref: mergeRefs([cameraRef, ref]) }, props)));
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export { LayoutCamera };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { __assign } from 'tslib';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import mergeRefs from 'react-merge-refs';
|
|
4
|
+
import { motion } from '../../render/three/motion.mjs';
|
|
5
|
+
import { useLayoutCamera } from './use-layout-camera.mjs';
|
|
6
|
+
|
|
7
|
+
var LayoutOrthographicCamera = React.forwardRef(function (props, ref) {
|
|
8
|
+
var _a = useLayoutCamera(props, function (newSize) {
|
|
9
|
+
var cam = cameraRef.current;
|
|
10
|
+
if (cam) {
|
|
11
|
+
cam.left = newSize.width / -2;
|
|
12
|
+
cam.right = newSize.width / 2;
|
|
13
|
+
cam.top = newSize.height / 2;
|
|
14
|
+
cam.bottom = newSize.height / -2;
|
|
15
|
+
cam.updateProjectionMatrix();
|
|
16
|
+
}
|
|
17
|
+
}), size = _a.size, cameraRef = _a.cameraRef;
|
|
18
|
+
return (React.createElement(motion.orthographicCamera, __assign({ left: size.width / -2, right: size.width / 2, top: size.height / 2, bottom: size.height / -2, ref: mergeRefs([cameraRef, ref]) }, props)));
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export { LayoutOrthographicCamera };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { __extends, __rest, __read, __assign } from 'tslib';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { forwardRef, useContext, useRef, useState, useLayoutEffect } from 'react';
|
|
4
|
+
import { MotionContext } from '../../context/MotionContext/index.mjs';
|
|
5
|
+
import mergeRefs from 'react-merge-refs';
|
|
6
|
+
import { render, events, unmountComponentAtNode } from '@react-three/fiber';
|
|
7
|
+
import { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.mjs';
|
|
8
|
+
import { MotionConfigContext } from '../../context/MotionConfigContext.mjs';
|
|
9
|
+
import { MotionCanvasContext } from './MotionCanvasContext.mjs';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* This file contains a version of R3F's Canvas component that uses our projection
|
|
13
|
+
* system for layout measurements instead of use-react-measure so we can keep the
|
|
14
|
+
* projection and cameras in sync.
|
|
15
|
+
*
|
|
16
|
+
* https://github.com/pmndrs/react-three-fiber/blob/master/packages/fiber/src/web/Canvas.tsx
|
|
17
|
+
*/
|
|
18
|
+
function Block(_a) {
|
|
19
|
+
var set = _a.set;
|
|
20
|
+
useIsomorphicLayoutEffect(function () {
|
|
21
|
+
set(new Promise(function () { return null; }));
|
|
22
|
+
return function () { return set(false); };
|
|
23
|
+
}, []);
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
var ErrorBoundary = /** @class */ (function (_super) {
|
|
27
|
+
__extends(ErrorBoundary, _super);
|
|
28
|
+
function ErrorBoundary() {
|
|
29
|
+
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
30
|
+
_this.state = { error: false };
|
|
31
|
+
return _this;
|
|
32
|
+
}
|
|
33
|
+
ErrorBoundary.prototype.componentDidCatch = function (error) {
|
|
34
|
+
this.props.set(error);
|
|
35
|
+
};
|
|
36
|
+
ErrorBoundary.prototype.render = function () {
|
|
37
|
+
return this.state.error ? null : this.props.children;
|
|
38
|
+
};
|
|
39
|
+
ErrorBoundary.getDerivedStateFromError = function () { return ({ error: true }); };
|
|
40
|
+
return ErrorBoundary;
|
|
41
|
+
}(React.Component));
|
|
42
|
+
function CanvasComponent(_a, forwardedRef) {
|
|
43
|
+
var children = _a.children, fallback = _a.fallback, tabIndex = _a.tabIndex, id = _a.id, style = _a.style, className = _a.className, events$1 = _a.events, props = __rest(_a, ["children", "fallback", "tabIndex", "id", "style", "className", "events"]);
|
|
44
|
+
/**
|
|
45
|
+
* Import existing contexts to pass through variants and MotionConfig from
|
|
46
|
+
* the DOM to the 3D tree. Shared variants aren't officially supported yet
|
|
47
|
+
* because the parent DOM tree fires effects before the 3D tree, whereas
|
|
48
|
+
* variants are expected to run from bottom-up in useEffect.
|
|
49
|
+
*/
|
|
50
|
+
var motionContext = useContext(MotionContext);
|
|
51
|
+
var configContext = useContext(MotionConfigContext);
|
|
52
|
+
var layoutCamera = useRef(null);
|
|
53
|
+
var _b = __read(useState({ width: 0, height: 0 }), 2), size = _b[0], setSize = _b[1];
|
|
54
|
+
var containerRef = useRef(null);
|
|
55
|
+
var handleResize = function () {
|
|
56
|
+
var container = containerRef.current;
|
|
57
|
+
setSize({
|
|
58
|
+
width: container.offsetWidth,
|
|
59
|
+
height: container.offsetHeight,
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
// Set canvas size on mount
|
|
63
|
+
useLayoutEffect(handleResize, []);
|
|
64
|
+
var canvasRef = React.useRef(null);
|
|
65
|
+
var _c = __read(React.useState(false), 2), block = _c[0], setBlock = _c[1];
|
|
66
|
+
var _d = __read(React.useState(false), 2), error = _d[0], setError = _d[1];
|
|
67
|
+
// Suspend this component if block is a promise (2nd run)
|
|
68
|
+
if (block)
|
|
69
|
+
throw block;
|
|
70
|
+
// Throw exception outwards if anything within canvas throws
|
|
71
|
+
if (error)
|
|
72
|
+
throw error;
|
|
73
|
+
// Only render the R3F tree once we have recorded dimensions for the canvas.
|
|
74
|
+
if (size.width > 0 && size.height > 0) {
|
|
75
|
+
render(React.createElement(ErrorBoundary, { set: setError },
|
|
76
|
+
React.createElement(React.Suspense, { fallback: React.createElement(Block, { set: setBlock }) },
|
|
77
|
+
React.createElement(MotionCanvasContext.Provider, { value: { setSize: setSize, layoutCamera: layoutCamera } },
|
|
78
|
+
React.createElement(MotionConfigContext.Provider, { value: configContext },
|
|
79
|
+
React.createElement(MotionContext.Provider, { value: motionContext }, children))))), canvasRef.current, __assign(__assign({}, props), { size: size, events: events$1 || events }));
|
|
80
|
+
}
|
|
81
|
+
useIsomorphicLayoutEffect(function () {
|
|
82
|
+
var container = canvasRef.current;
|
|
83
|
+
return function () { return unmountComponentAtNode(container); };
|
|
84
|
+
}, []);
|
|
85
|
+
return (React.createElement("div", { ref: containerRef, id: id, className: className, tabIndex: tabIndex, style: __assign({ position: "relative", width: "100%", height: "100%", overflow: "hidden" }, style) },
|
|
86
|
+
React.createElement("canvas", { ref: mergeRefs([canvasRef, forwardedRef]), style: { display: "block" } }, fallback)));
|
|
87
|
+
}
|
|
88
|
+
var MotionCanvas = forwardRef(CanvasComponent);
|
|
89
|
+
|
|
90
|
+
export { MotionCanvas };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { useContext, useRef, useLayoutEffect } from 'react';
|
|
2
|
+
import { useThree } from '@react-three/fiber';
|
|
3
|
+
import { useVisualElementContext } from '../../context/MotionContext/index.mjs';
|
|
4
|
+
import { MotionCanvasContext } from './MotionCanvasContext.mjs';
|
|
5
|
+
import { invariant } from 'hey-listen';
|
|
6
|
+
import { calcLength } from '../../projection/geometry/delta-calc.mjs';
|
|
7
|
+
import { getFrameData } from 'framesync';
|
|
8
|
+
|
|
9
|
+
var calcBoxSize = function (_a) {
|
|
10
|
+
var x = _a.x, y = _a.y;
|
|
11
|
+
return ({
|
|
12
|
+
width: calcLength(x),
|
|
13
|
+
height: calcLength(y),
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
function useLayoutCamera(_a, updateCamera) {
|
|
17
|
+
var _b = _a.makeDefault, makeDefault = _b === void 0 ? true : _b;
|
|
18
|
+
var context = useContext(MotionCanvasContext);
|
|
19
|
+
invariant(Boolean(context), "No MotionCanvas detected. Replace Canvas from @react-three/fiber with MotionCanvas from framer-motion.");
|
|
20
|
+
var _c = context, setSize = _c.setSize, layoutCamera = _c.layoutCamera;
|
|
21
|
+
var latestLayout = useRef(null);
|
|
22
|
+
var advance = useThree(function (three) { return three.advance; });
|
|
23
|
+
var set = useThree(function (three) { return three.set; });
|
|
24
|
+
var camera = useThree(function (three) { return three.camera; });
|
|
25
|
+
var size = useThree(function (three) { return three.size; });
|
|
26
|
+
var gl = useThree(function (three) { return three.gl; });
|
|
27
|
+
var parentVisualElement = useVisualElementContext();
|
|
28
|
+
useLayoutEffect(function () {
|
|
29
|
+
updateCamera(size);
|
|
30
|
+
var projection = parentVisualElement === null || parentVisualElement === void 0 ? void 0 : parentVisualElement.projection;
|
|
31
|
+
if (!projection)
|
|
32
|
+
return;
|
|
33
|
+
/**
|
|
34
|
+
* When the projection of an element changes we want to update the camera
|
|
35
|
+
* with the projected dimensions.
|
|
36
|
+
*/
|
|
37
|
+
var removeProjectionUpdateListener = projection.addEventListener("projectionUpdate", function (newProjection) {
|
|
38
|
+
// TODO: Removed to prevent iOS from crashing.
|
|
39
|
+
// Perhaps a better apporach is to set with setSize
|
|
40
|
+
// and then set to window native on animationComplete.
|
|
41
|
+
// if (latestLayout.current) {
|
|
42
|
+
// const { x, y } = latestLayout.current
|
|
43
|
+
// const xRatio = calcLength(newProjection.x) / calcLength(x)
|
|
44
|
+
// const yRatio = calcLength(newProjection.y) / calcLength(y)
|
|
45
|
+
// gl.setPixelRatio(
|
|
46
|
+
// Math.max(xRatio, yRatio) * window.devicePixelRatio
|
|
47
|
+
// )
|
|
48
|
+
// }
|
|
49
|
+
updateCamera(calcBoxSize(newProjection));
|
|
50
|
+
advance(getFrameData().timestamp);
|
|
51
|
+
});
|
|
52
|
+
/**
|
|
53
|
+
* When the layout of an element changes we want to update the renderer
|
|
54
|
+
* output to match the layout dimensions.
|
|
55
|
+
*/
|
|
56
|
+
var removeLayoutMeasureListener = projection.addEventListener("measure", function (newLayout) {
|
|
57
|
+
latestLayout.current = newLayout;
|
|
58
|
+
var newSize = calcBoxSize(newLayout);
|
|
59
|
+
gl.setSize(newSize.width, newSize.height);
|
|
60
|
+
setSize(newSize);
|
|
61
|
+
});
|
|
62
|
+
/**
|
|
63
|
+
* When a projection animation completes we want to update the camera to
|
|
64
|
+
* match the recorded layout of the element.
|
|
65
|
+
*/
|
|
66
|
+
var removeAnimationCompleteListener = projection.addEventListener("animationComplete", function () {
|
|
67
|
+
var actual = (projection.layout || {}).actual;
|
|
68
|
+
actual && updateCamera(calcBoxSize(actual));
|
|
69
|
+
});
|
|
70
|
+
return function () {
|
|
71
|
+
removeProjectionUpdateListener();
|
|
72
|
+
removeLayoutMeasureListener();
|
|
73
|
+
removeAnimationCompleteListener();
|
|
74
|
+
};
|
|
75
|
+
}, []);
|
|
76
|
+
useLayoutEffect(function () {
|
|
77
|
+
var cam = layoutCamera.current;
|
|
78
|
+
if (makeDefault && cam) {
|
|
79
|
+
var oldCam_1 = camera;
|
|
80
|
+
set(function () { return ({ camera: cam }); });
|
|
81
|
+
return function () { return set(function () { return ({ camera: oldCam_1 }); }); };
|
|
82
|
+
}
|
|
83
|
+
}, [camera, layoutCamera, makeDefault, set]);
|
|
84
|
+
return { size: size, camera: camera, cameraRef: layoutCamera };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export { useLayoutCamera };
|
package/dist/es/index.mjs
CHANGED
|
@@ -36,6 +36,7 @@ export { addScaleCorrector } from './projection/styles/scale-correction.mjs';
|
|
|
36
36
|
export { useInstantTransition } from './utils/use-instant-transition.mjs';
|
|
37
37
|
export { useInstantLayoutTransition } from './projection/use-instant-layout-transition.mjs';
|
|
38
38
|
export { useResetProjection } from './projection/use-reset-projection.mjs';
|
|
39
|
+
export { MotionContext } from './context/MotionContext/index.mjs';
|
|
39
40
|
export { MotionConfigContext } from './context/MotionConfigContext.mjs';
|
|
40
41
|
export { PresenceContext } from './context/PresenceContext.mjs';
|
|
41
42
|
export { LayoutGroupContext } from './context/LayoutGroupContext.mjs';
|
|
@@ -430,7 +430,7 @@ function createProjectionNode(_a) {
|
|
|
430
430
|
this.layoutCorrected = createBox();
|
|
431
431
|
this.isLayoutDirty = false;
|
|
432
432
|
this.projectionDelta = undefined;
|
|
433
|
-
this.notifyListeners("measure");
|
|
433
|
+
this.notifyListeners("measure", this.layout.actual);
|
|
434
434
|
(_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.notifyLayoutMeasure(this.layout.actual, prevLayout === null || prevLayout === void 0 ? void 0 : prevLayout.actual);
|
|
435
435
|
};
|
|
436
436
|
ProjectionNode.prototype.updateScroll = function () {
|
|
@@ -699,6 +699,7 @@ function createProjectionNode(_a) {
|
|
|
699
699
|
this.treeScale.y !== prevTreeScaleY) {
|
|
700
700
|
this.hasProjected = true;
|
|
701
701
|
this.scheduleRender();
|
|
702
|
+
this.notifyListeners("projectionUpdate", target);
|
|
702
703
|
}
|
|
703
704
|
};
|
|
704
705
|
ProjectionNode.prototype.hide = function () {
|
|
@@ -801,6 +802,7 @@ function createProjectionNode(_a) {
|
|
|
801
802
|
this.currentAnimation =
|
|
802
803
|
this.animationValues =
|
|
803
804
|
undefined;
|
|
805
|
+
this.notifyListeners("animationComplete");
|
|
804
806
|
};
|
|
805
807
|
ProjectionNode.prototype.finishAnimation = function () {
|
|
806
808
|
var _a;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { __rest } from 'tslib';
|
|
1
2
|
import { visualElement } from '../index.mjs';
|
|
2
3
|
import { createBox } from '../../projection/geometry/models.mjs';
|
|
3
4
|
import { checkTargetForNewValues } from '../utils/setters.mjs';
|
|
@@ -15,7 +16,8 @@ var threeVisualElement = visualElement({
|
|
|
15
16
|
sortNodePosition: function (a, b) {
|
|
16
17
|
return a.id - b.id;
|
|
17
18
|
},
|
|
18
|
-
makeTargetAnimatable: function (element,
|
|
19
|
+
makeTargetAnimatable: function (element, _a) {
|
|
20
|
+
_a.transition; var target = __rest(_a, ["transition"]);
|
|
19
21
|
checkTargetForNewValues(element, target, {});
|
|
20
22
|
return target;
|
|
21
23
|
},
|
|
@@ -24,9 +24,10 @@ var readers = {
|
|
|
24
24
|
rotateZ: readRotation("z"),
|
|
25
25
|
};
|
|
26
26
|
function readAnimatableValue(value) {
|
|
27
|
-
if (
|
|
27
|
+
if (value === undefined) {
|
|
28
28
|
return;
|
|
29
|
-
|
|
29
|
+
}
|
|
30
|
+
else if (value instanceof Color) {
|
|
30
31
|
return value.getStyle();
|
|
31
32
|
}
|
|
32
33
|
else {
|
package/dist/es/three-entry.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { motion } from './render/three/motion.mjs';
|
|
2
|
-
export { MotionCanvas } from './components/MotionCanvas
|
|
2
|
+
export { MotionCanvas } from './components/three/MotionCanvas.mjs';
|
|
3
|
+
export { LayoutCamera } from './components/three/LayoutCamera.mjs';
|
|
4
|
+
export { LayoutOrthographicCamera } from './components/three/LayoutOrthographicCamera.mjs';
|
|
3
5
|
export { useTime } from './render/three/utils/use-time.mjs';
|
|
@@ -3354,7 +3354,7 @@
|
|
|
3354
3354
|
this.layoutCorrected = createBox();
|
|
3355
3355
|
this.isLayoutDirty = false;
|
|
3356
3356
|
this.projectionDelta = undefined;
|
|
3357
|
-
this.notifyListeners("measure");
|
|
3357
|
+
this.notifyListeners("measure", this.layout.actual);
|
|
3358
3358
|
(_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.notifyLayoutMeasure(this.layout.actual, prevLayout === null || prevLayout === void 0 ? void 0 : prevLayout.actual);
|
|
3359
3359
|
};
|
|
3360
3360
|
ProjectionNode.prototype.updateScroll = function () {
|
|
@@ -3623,6 +3623,7 @@
|
|
|
3623
3623
|
this.treeScale.y !== prevTreeScaleY) {
|
|
3624
3624
|
this.hasProjected = true;
|
|
3625
3625
|
this.scheduleRender();
|
|
3626
|
+
this.notifyListeners("projectionUpdate", target);
|
|
3626
3627
|
}
|
|
3627
3628
|
};
|
|
3628
3629
|
ProjectionNode.prototype.hide = function () {
|
|
@@ -3725,6 +3726,7 @@
|
|
|
3725
3726
|
this.currentAnimation =
|
|
3726
3727
|
this.animationValues =
|
|
3727
3728
|
undefined;
|
|
3729
|
+
this.notifyListeners("animationComplete");
|
|
3728
3730
|
};
|
|
3729
3731
|
ProjectionNode.prototype.finishAnimation = function () {
|
|
3730
3732
|
var _a;
|
|
@@ -9530,6 +9532,7 @@
|
|
|
9530
9532
|
exports.LazyMotion = LazyMotion;
|
|
9531
9533
|
exports.MotionConfig = MotionConfig;
|
|
9532
9534
|
exports.MotionConfigContext = MotionConfigContext;
|
|
9535
|
+
exports.MotionContext = MotionContext;
|
|
9533
9536
|
exports.MotionValue = MotionValue;
|
|
9534
9537
|
exports.PresenceContext = PresenceContext;
|
|
9535
9538
|
exports.Reorder = Reorder;
|