framer-motion 5.4.5 → 5.5.2
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 +157 -24
- 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/{MotionCanvas/index.mjs → three/MotionCanvas.mjs} +42 -18
- package/dist/es/components/three/MotionCanvasContext.mjs +5 -0
- package/dist/es/components/three/use-layout-camera.mjs +86 -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 +13 -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/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,32 +326,49 @@ 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
338
|
var configContext = React.useContext(useMotionValue.MotionConfigContext);
|
|
330
|
-
var
|
|
339
|
+
var layoutCamera = React.useRef(null);
|
|
340
|
+
var _b = tslib.__read(React.useState({
|
|
341
|
+
size: { width: 0, height: 0 },
|
|
342
|
+
}), 2), dimensions = _b[0], setDimensions = _b[1];
|
|
343
|
+
var size = dimensions.size, dpr = dimensions.dpr;
|
|
344
|
+
var containerRef = React.useRef(null);
|
|
345
|
+
var handleResize = function () {
|
|
346
|
+
var container = containerRef.current;
|
|
347
|
+
setDimensions({
|
|
348
|
+
size: {
|
|
349
|
+
width: container.offsetWidth,
|
|
350
|
+
height: container.offsetHeight,
|
|
351
|
+
},
|
|
352
|
+
});
|
|
353
|
+
};
|
|
354
|
+
// Set canvas size on mount
|
|
355
|
+
React.useLayoutEffect(handleResize, []);
|
|
331
356
|
var canvasRef = React__namespace.useRef(null);
|
|
332
|
-
var
|
|
333
|
-
var
|
|
357
|
+
var _c = tslib.__read(React__namespace.useState(false), 2), block = _c[0], setBlock = _c[1];
|
|
358
|
+
var _d = tslib.__read(React__namespace.useState(false), 2), error = _d[0], setError = _d[1];
|
|
334
359
|
// Suspend this component if block is a promise (2nd run)
|
|
335
360
|
if (block)
|
|
336
361
|
throw block;
|
|
337
362
|
// Throw exception outwards if anything within canvas throws
|
|
338
363
|
if (error)
|
|
339
364
|
throw error;
|
|
340
|
-
//
|
|
341
|
-
if (width > 0 && height > 0) {
|
|
365
|
+
// Only render the R3F tree once we have recorded dimensions for the canvas.
|
|
366
|
+
if (size.width > 0 && size.height > 0) {
|
|
342
367
|
fiber.render(React__namespace.createElement(ErrorBoundary, { set: setError },
|
|
343
368
|
React__namespace.createElement(React__namespace.Suspense, { fallback: React__namespace.createElement(Block, { set: setBlock }) },
|
|
344
|
-
React__namespace.createElement(
|
|
345
|
-
React__namespace.createElement(useMotionValue.
|
|
369
|
+
React__namespace.createElement(MotionCanvasContext.Provider, { value: { setDimensions: setDimensions, layoutCamera: layoutCamera } },
|
|
370
|
+
React__namespace.createElement(useMotionValue.MotionConfigContext.Provider, { value: configContext },
|
|
371
|
+
React__namespace.createElement(useMotionValue.MotionContext.Provider, { value: motionContext }, children))))), canvasRef.current, tslib.__assign(tslib.__assign({}, props), { dpr: dpr || props.dpr, size: size, events: events || fiber.events }));
|
|
346
372
|
}
|
|
347
373
|
useMotionValue.useIsomorphicLayoutEffect(function () {
|
|
348
374
|
var container = canvasRef.current;
|
|
@@ -351,7 +377,112 @@ function SyncCanvasComponent(_a, forwardedRef) {
|
|
|
351
377
|
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) },
|
|
352
378
|
React__namespace.createElement("canvas", { ref: mergeRefs__default["default"]([canvasRef, forwardedRef]), style: { display: "block" } }, fallback)));
|
|
353
379
|
}
|
|
354
|
-
var MotionCanvas = React.forwardRef(
|
|
380
|
+
var MotionCanvas = React.forwardRef(CanvasComponent);
|
|
381
|
+
|
|
382
|
+
var calcBoxSize = function (_a) {
|
|
383
|
+
var x = _a.x, y = _a.y;
|
|
384
|
+
return ({
|
|
385
|
+
width: useMotionValue.calcLength(x),
|
|
386
|
+
height: useMotionValue.calcLength(y),
|
|
387
|
+
});
|
|
388
|
+
};
|
|
389
|
+
function useLayoutCamera(_a, updateCamera) {
|
|
390
|
+
var _b = _a.makeDefault, makeDefault = _b === void 0 ? true : _b;
|
|
391
|
+
var context = React.useContext(MotionCanvasContext);
|
|
392
|
+
heyListen.invariant(Boolean(context), "No MotionCanvas detected. Replace Canvas from @react-three/fiber with MotionCanvas from framer-motion.");
|
|
393
|
+
var _c = context, setDimensions = _c.setDimensions, layoutCamera = _c.layoutCamera;
|
|
394
|
+
var advance = fiber.useThree(function (three) { return three.advance; });
|
|
395
|
+
var set = fiber.useThree(function (three) { return three.set; });
|
|
396
|
+
var camera = fiber.useThree(function (three) { return three.camera; });
|
|
397
|
+
var size = fiber.useThree(function (three) { return three.size; });
|
|
398
|
+
var gl = fiber.useThree(function (three) { return three.gl; });
|
|
399
|
+
var parentVisualElement = useMotionValue.useVisualElementContext();
|
|
400
|
+
React.useLayoutEffect(function () {
|
|
401
|
+
updateCamera(size);
|
|
402
|
+
var projection = parentVisualElement === null || parentVisualElement === void 0 ? void 0 : parentVisualElement.projection;
|
|
403
|
+
if (!projection)
|
|
404
|
+
return;
|
|
405
|
+
/**
|
|
406
|
+
* When the projection of an element changes we want to update the camera
|
|
407
|
+
* with the projected dimensions.
|
|
408
|
+
*/
|
|
409
|
+
var removeProjectionUpdateListener = projection.addEventListener("projectionUpdate", function (newProjection) {
|
|
410
|
+
updateCamera(calcBoxSize(newProjection));
|
|
411
|
+
advance(sync.getFrameData().timestamp);
|
|
412
|
+
});
|
|
413
|
+
/**
|
|
414
|
+
* When the layout of an element changes we want to update the renderer
|
|
415
|
+
* output to match the layout dimensions.
|
|
416
|
+
*/
|
|
417
|
+
var removeLayoutMeasureListener = projection.addEventListener("measure", function (newLayout) {
|
|
418
|
+
var newSize = calcBoxSize(newLayout);
|
|
419
|
+
gl.setSize(newSize.width, newSize.height);
|
|
420
|
+
var dpr;
|
|
421
|
+
if (newSize.width < size.width ||
|
|
422
|
+
newSize.height < size.height) {
|
|
423
|
+
var xScale = size.width / newSize.width;
|
|
424
|
+
var yScale = size.height / newSize.height;
|
|
425
|
+
var maxScale = Math.max(xScale, yScale);
|
|
426
|
+
dpr = Math.min(maxScale, 8);
|
|
427
|
+
}
|
|
428
|
+
setDimensions({ size: newSize, dpr: dpr });
|
|
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
|
+
if (actual) {
|
|
437
|
+
var newSize = calcBoxSize(actual);
|
|
438
|
+
updateCamera(newSize);
|
|
439
|
+
setDimensions({ size: newSize });
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
return function () {
|
|
443
|
+
removeProjectionUpdateListener();
|
|
444
|
+
removeLayoutMeasureListener();
|
|
445
|
+
removeAnimationCompleteListener();
|
|
446
|
+
};
|
|
447
|
+
}, [size]);
|
|
448
|
+
React.useLayoutEffect(function () {
|
|
449
|
+
var cam = layoutCamera.current;
|
|
450
|
+
if (makeDefault && cam) {
|
|
451
|
+
var oldCam_1 = camera;
|
|
452
|
+
set(function () { return ({ camera: cam }); });
|
|
453
|
+
return function () { return set(function () { return ({ camera: oldCam_1 }); }); };
|
|
454
|
+
}
|
|
455
|
+
}, [camera, layoutCamera, makeDefault, set]);
|
|
456
|
+
return { size: size, camera: camera, cameraRef: layoutCamera };
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Adapted from https://github.com/pmndrs/drei/blob/master/src/core/PerspectiveCamera.tsx
|
|
461
|
+
*/
|
|
462
|
+
var LayoutCamera = React__namespace.forwardRef(function (props, ref) {
|
|
463
|
+
var cameraRef = useLayoutCamera(props, function (size) {
|
|
464
|
+
var cam = cameraRef.current;
|
|
465
|
+
if (cam && !props.manual) {
|
|
466
|
+
cam.aspect = size.width / size.height;
|
|
467
|
+
cam.updateProjectionMatrix();
|
|
468
|
+
}
|
|
469
|
+
}).cameraRef;
|
|
470
|
+
return (React__namespace.createElement(motion.perspectiveCamera, tslib.__assign({ ref: mergeRefs__default["default"]([cameraRef, ref]) }, props)));
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
var LayoutOrthographicCamera = React__namespace.forwardRef(function (props, ref) {
|
|
474
|
+
var _a = useLayoutCamera(props, function (newSize) {
|
|
475
|
+
var cam = cameraRef.current;
|
|
476
|
+
if (cam) {
|
|
477
|
+
cam.left = newSize.width / -2;
|
|
478
|
+
cam.right = newSize.width / 2;
|
|
479
|
+
cam.top = newSize.height / 2;
|
|
480
|
+
cam.bottom = newSize.height / -2;
|
|
481
|
+
cam.updateProjectionMatrix();
|
|
482
|
+
}
|
|
483
|
+
}), size = _a.size, cameraRef = _a.cameraRef;
|
|
484
|
+
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)));
|
|
485
|
+
});
|
|
355
486
|
|
|
356
487
|
function useTime() {
|
|
357
488
|
var time = useMotionValue.useMotionValue(0);
|
|
@@ -359,6 +490,8 @@ function useTime() {
|
|
|
359
490
|
return time;
|
|
360
491
|
}
|
|
361
492
|
|
|
493
|
+
exports.LayoutCamera = LayoutCamera;
|
|
494
|
+
exports.LayoutOrthographicCamera = LayoutOrthographicCamera;
|
|
362
495
|
exports.MotionCanvas = MotionCanvas;
|
|
363
496
|
exports.motion = motion;
|
|
364
497
|
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 };
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import { __extends, __rest, __read, __assign } from 'tslib';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { forwardRef, useContext } from 'react';
|
|
3
|
+
import { forwardRef, useContext, useRef, useState, useLayoutEffect } from 'react';
|
|
4
4
|
import { MotionContext } from '../../context/MotionContext/index.mjs';
|
|
5
5
|
import mergeRefs from 'react-merge-refs';
|
|
6
|
-
import useMeasure from 'react-use-measure';
|
|
7
6
|
import { render, events, unmountComponentAtNode } from '@react-three/fiber';
|
|
8
7
|
import { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.mjs';
|
|
9
8
|
import { MotionConfigContext } from '../../context/MotionConfigContext.mjs';
|
|
9
|
+
import { MotionCanvasContext } from './MotionCanvasContext.mjs';
|
|
10
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
|
+
*/
|
|
11
18
|
function Block(_a) {
|
|
12
19
|
var set = _a.set;
|
|
13
20
|
useIsomorphicLayoutEffect(function () {
|
|
@@ -32,32 +39,49 @@ var ErrorBoundary = /** @class */ (function (_super) {
|
|
|
32
39
|
ErrorBoundary.getDerivedStateFromError = function () { return ({ error: true }); };
|
|
33
40
|
return ErrorBoundary;
|
|
34
41
|
}(React.Component));
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
+
*/
|
|
43
50
|
var motionContext = useContext(MotionContext);
|
|
44
51
|
var configContext = useContext(MotionConfigContext);
|
|
45
|
-
var
|
|
52
|
+
var layoutCamera = useRef(null);
|
|
53
|
+
var _b = __read(useState({
|
|
54
|
+
size: { width: 0, height: 0 },
|
|
55
|
+
}), 2), dimensions = _b[0], setDimensions = _b[1];
|
|
56
|
+
var size = dimensions.size, dpr = dimensions.dpr;
|
|
57
|
+
var containerRef = useRef(null);
|
|
58
|
+
var handleResize = function () {
|
|
59
|
+
var container = containerRef.current;
|
|
60
|
+
setDimensions({
|
|
61
|
+
size: {
|
|
62
|
+
width: container.offsetWidth,
|
|
63
|
+
height: container.offsetHeight,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
// Set canvas size on mount
|
|
68
|
+
useLayoutEffect(handleResize, []);
|
|
46
69
|
var canvasRef = React.useRef(null);
|
|
47
|
-
var
|
|
48
|
-
var
|
|
70
|
+
var _c = __read(React.useState(false), 2), block = _c[0], setBlock = _c[1];
|
|
71
|
+
var _d = __read(React.useState(false), 2), error = _d[0], setError = _d[1];
|
|
49
72
|
// Suspend this component if block is a promise (2nd run)
|
|
50
73
|
if (block)
|
|
51
74
|
throw block;
|
|
52
75
|
// Throw exception outwards if anything within canvas throws
|
|
53
76
|
if (error)
|
|
54
77
|
throw error;
|
|
55
|
-
//
|
|
56
|
-
if (width > 0 && height > 0) {
|
|
78
|
+
// Only render the R3F tree once we have recorded dimensions for the canvas.
|
|
79
|
+
if (size.width > 0 && size.height > 0) {
|
|
57
80
|
render(React.createElement(ErrorBoundary, { set: setError },
|
|
58
81
|
React.createElement(React.Suspense, { fallback: React.createElement(Block, { set: setBlock }) },
|
|
59
|
-
React.createElement(
|
|
60
|
-
React.createElement(
|
|
82
|
+
React.createElement(MotionCanvasContext.Provider, { value: { setDimensions: setDimensions, layoutCamera: layoutCamera } },
|
|
83
|
+
React.createElement(MotionConfigContext.Provider, { value: configContext },
|
|
84
|
+
React.createElement(MotionContext.Provider, { value: motionContext }, children))))), canvasRef.current, __assign(__assign({}, props), { dpr: dpr || props.dpr, size: size, events: events$1 || events }));
|
|
61
85
|
}
|
|
62
86
|
useIsomorphicLayoutEffect(function () {
|
|
63
87
|
var container = canvasRef.current;
|
|
@@ -66,6 +90,6 @@ function SyncCanvasComponent(_a, forwardedRef) {
|
|
|
66
90
|
return (React.createElement("div", { ref: containerRef, id: id, className: className, tabIndex: tabIndex, style: __assign({ position: "relative", width: "100%", height: "100%", overflow: "hidden" }, style) },
|
|
67
91
|
React.createElement("canvas", { ref: mergeRefs([canvasRef, forwardedRef]), style: { display: "block" } }, fallback)));
|
|
68
92
|
}
|
|
69
|
-
var MotionCanvas = forwardRef(
|
|
93
|
+
var MotionCanvas = forwardRef(CanvasComponent);
|
|
70
94
|
|
|
71
95
|
export { MotionCanvas };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { useContext, 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, setDimensions = _c.setDimensions, layoutCamera = _c.layoutCamera;
|
|
21
|
+
var advance = useThree(function (three) { return three.advance; });
|
|
22
|
+
var set = useThree(function (three) { return three.set; });
|
|
23
|
+
var camera = useThree(function (three) { return three.camera; });
|
|
24
|
+
var size = useThree(function (three) { return three.size; });
|
|
25
|
+
var gl = useThree(function (three) { return three.gl; });
|
|
26
|
+
var parentVisualElement = useVisualElementContext();
|
|
27
|
+
useLayoutEffect(function () {
|
|
28
|
+
updateCamera(size);
|
|
29
|
+
var projection = parentVisualElement === null || parentVisualElement === void 0 ? void 0 : parentVisualElement.projection;
|
|
30
|
+
if (!projection)
|
|
31
|
+
return;
|
|
32
|
+
/**
|
|
33
|
+
* When the projection of an element changes we want to update the camera
|
|
34
|
+
* with the projected dimensions.
|
|
35
|
+
*/
|
|
36
|
+
var removeProjectionUpdateListener = projection.addEventListener("projectionUpdate", function (newProjection) {
|
|
37
|
+
updateCamera(calcBoxSize(newProjection));
|
|
38
|
+
advance(getFrameData().timestamp);
|
|
39
|
+
});
|
|
40
|
+
/**
|
|
41
|
+
* When the layout of an element changes we want to update the renderer
|
|
42
|
+
* output to match the layout dimensions.
|
|
43
|
+
*/
|
|
44
|
+
var removeLayoutMeasureListener = projection.addEventListener("measure", function (newLayout) {
|
|
45
|
+
var newSize = calcBoxSize(newLayout);
|
|
46
|
+
gl.setSize(newSize.width, newSize.height);
|
|
47
|
+
var dpr;
|
|
48
|
+
if (newSize.width < size.width ||
|
|
49
|
+
newSize.height < size.height) {
|
|
50
|
+
var xScale = size.width / newSize.width;
|
|
51
|
+
var yScale = size.height / newSize.height;
|
|
52
|
+
var maxScale = Math.max(xScale, yScale);
|
|
53
|
+
dpr = Math.min(maxScale, 8);
|
|
54
|
+
}
|
|
55
|
+
setDimensions({ size: newSize, dpr: dpr });
|
|
56
|
+
});
|
|
57
|
+
/**
|
|
58
|
+
* When a projection animation completes we want to update the camera to
|
|
59
|
+
* match the recorded layout of the element.
|
|
60
|
+
*/
|
|
61
|
+
var removeAnimationCompleteListener = projection.addEventListener("animationComplete", function () {
|
|
62
|
+
var actual = (projection.layout || {}).actual;
|
|
63
|
+
if (actual) {
|
|
64
|
+
var newSize = calcBoxSize(actual);
|
|
65
|
+
updateCamera(newSize);
|
|
66
|
+
setDimensions({ size: newSize });
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return function () {
|
|
70
|
+
removeProjectionUpdateListener();
|
|
71
|
+
removeLayoutMeasureListener();
|
|
72
|
+
removeAnimationCompleteListener();
|
|
73
|
+
};
|
|
74
|
+
}, [size]);
|
|
75
|
+
useLayoutEffect(function () {
|
|
76
|
+
var cam = layoutCamera.current;
|
|
77
|
+
if (makeDefault && cam) {
|
|
78
|
+
var oldCam_1 = camera;
|
|
79
|
+
set(function () { return ({ camera: cam }); });
|
|
80
|
+
return function () { return set(function () { return ({ camera: oldCam_1 }); }); };
|
|
81
|
+
}
|
|
82
|
+
}, [camera, layoutCamera, makeDefault, set]);
|
|
83
|
+
return { size: size, camera: camera, cameraRef: layoutCamera };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
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;
|