framer-motion 5.4.3 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/three-entry.js +193 -10
- 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 +82 -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 +8 -5
- package/types/components/three/LayoutCamera.d.ts +26 -0
- package/types/components/three/LayoutOrthographicCamera.d.ts +23 -0
- package/types/components/three/MotionCanvas.d.ts +5 -0
- 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 -14
- package/types/components/MotionCanvas/index.d.ts +0 -4
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,18 @@
|
|
|
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
|
+
var mergeRefs = require('react-merge-refs');
|
|
10
11
|
var fiber = require('@react-three/fiber');
|
|
11
|
-
require('hey-listen');
|
|
12
|
-
require('framesync');
|
|
12
|
+
var heyListen = require('hey-listen');
|
|
13
|
+
var sync = require('framesync');
|
|
13
14
|
require('style-value-types');
|
|
14
15
|
|
|
16
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
17
|
+
|
|
15
18
|
function _interopNamespace(e) {
|
|
16
19
|
if (e && e.__esModule) return e;
|
|
17
20
|
var n = Object.create(null);
|
|
@@ -31,6 +34,7 @@ function _interopNamespace(e) {
|
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
37
|
+
var mergeRefs__default = /*#__PURE__*/_interopDefaultLegacy(mergeRefs);
|
|
34
38
|
|
|
35
39
|
function useHover(isStatic, _a, visualElement) {
|
|
36
40
|
var whileHover = _a.whileHover, onHoverStart = _a.onHoverStart, onHoverEnd = _a.onHoverEnd, onPointerOver = _a.onPointerOver, onPointerOut = _a.onPointerOut;
|
|
@@ -183,9 +187,10 @@ var readers = {
|
|
|
183
187
|
rotateZ: readRotation("z"),
|
|
184
188
|
};
|
|
185
189
|
function readAnimatableValue(value) {
|
|
186
|
-
if (
|
|
190
|
+
if (value === undefined) {
|
|
187
191
|
return;
|
|
188
|
-
|
|
192
|
+
}
|
|
193
|
+
else if (value instanceof three.Color) {
|
|
189
194
|
return value.getStyle();
|
|
190
195
|
}
|
|
191
196
|
else {
|
|
@@ -241,7 +246,8 @@ var threeVisualElement = useMotionValue.visualElement({
|
|
|
241
246
|
sortNodePosition: function (a, b) {
|
|
242
247
|
return a.id - b.id;
|
|
243
248
|
},
|
|
244
|
-
makeTargetAnimatable: function (element,
|
|
249
|
+
makeTargetAnimatable: function (element, _a) {
|
|
250
|
+
_a.transition; var target = tslib.__rest(_a, ["transition"]);
|
|
245
251
|
useMotionValue.checkTargetForNewValues(element, target, {});
|
|
246
252
|
return target;
|
|
247
253
|
},
|
|
@@ -287,12 +293,187 @@ var motion = new Proxy(custom, {
|
|
|
287
293
|
},
|
|
288
294
|
});
|
|
289
295
|
|
|
290
|
-
|
|
291
|
-
|
|
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
|
+
*/
|
|
305
|
+
function Block(_a) {
|
|
306
|
+
var set = _a.set;
|
|
307
|
+
useMotionValue.useIsomorphicLayoutEffect(function () {
|
|
308
|
+
set(new Promise(function () { return null; }));
|
|
309
|
+
return function () { return set(false); };
|
|
310
|
+
}, []);
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
var ErrorBoundary = /** @class */ (function (_super) {
|
|
314
|
+
tslib.__extends(ErrorBoundary, _super);
|
|
315
|
+
function ErrorBoundary() {
|
|
316
|
+
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
317
|
+
_this.state = { error: false };
|
|
318
|
+
return _this;
|
|
319
|
+
}
|
|
320
|
+
ErrorBoundary.prototype.componentDidCatch = function (error) {
|
|
321
|
+
this.props.set(error);
|
|
322
|
+
};
|
|
323
|
+
ErrorBoundary.prototype.render = function () {
|
|
324
|
+
return this.state.error ? null : this.props.children;
|
|
325
|
+
};
|
|
326
|
+
ErrorBoundary.getDerivedStateFromError = function () { return ({ error: true }); };
|
|
327
|
+
return ErrorBoundary;
|
|
328
|
+
}(React__namespace.Component));
|
|
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
|
+
*/
|
|
292
337
|
var motionContext = React.useContext(useMotionValue.MotionContext);
|
|
293
|
-
|
|
294
|
-
|
|
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, []);
|
|
351
|
+
var canvasRef = React__namespace.useRef(null);
|
|
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];
|
|
354
|
+
// Suspend this component if block is a promise (2nd run)
|
|
355
|
+
if (block)
|
|
356
|
+
throw block;
|
|
357
|
+
// Throw exception outwards if anything within canvas throws
|
|
358
|
+
if (error)
|
|
359
|
+
throw error;
|
|
360
|
+
// Only render the R3F tree once we have recorded dimensions for the canvas.
|
|
361
|
+
if (size.width > 0 && size.height > 0) {
|
|
362
|
+
fiber.render(React__namespace.createElement(ErrorBoundary, { set: setError },
|
|
363
|
+
React__namespace.createElement(React__namespace.Suspense, { fallback: React__namespace.createElement(Block, { set: setBlock }) },
|
|
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 }));
|
|
367
|
+
}
|
|
368
|
+
useMotionValue.useIsomorphicLayoutEffect(function () {
|
|
369
|
+
var container = canvasRef.current;
|
|
370
|
+
return function () { return fiber.unmountComponentAtNode(container); };
|
|
371
|
+
}, []);
|
|
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) },
|
|
373
|
+
React__namespace.createElement("canvas", { ref: mergeRefs__default["default"]([canvasRef, forwardedRef]), style: { display: "block" } }, fallback)));
|
|
295
374
|
}
|
|
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
|
+
if (latestLayout.current) {
|
|
407
|
+
var _a = latestLayout.current, x = _a.x, y = _a.y;
|
|
408
|
+
var xRatio = useMotionValue.calcLength(newProjection.x) / useMotionValue.calcLength(x);
|
|
409
|
+
var yRatio = useMotionValue.calcLength(newProjection.y) / useMotionValue.calcLength(y);
|
|
410
|
+
gl.setPixelRatio(Math.max(xRatio, yRatio) * window.devicePixelRatio);
|
|
411
|
+
}
|
|
412
|
+
updateCamera(calcBoxSize(newProjection));
|
|
413
|
+
advance(sync.getFrameData().timestamp);
|
|
414
|
+
});
|
|
415
|
+
/**
|
|
416
|
+
* When the layout of an element changes we want to update the renderer
|
|
417
|
+
* output to match the layout dimensions.
|
|
418
|
+
*/
|
|
419
|
+
var removeLayoutMeasureListener = projection.addEventListener("measure", function (newLayout) {
|
|
420
|
+
latestLayout.current = newLayout;
|
|
421
|
+
var newSize = calcBoxSize(newLayout);
|
|
422
|
+
gl.setSize(newSize.width, newSize.height);
|
|
423
|
+
setSize(newSize);
|
|
424
|
+
});
|
|
425
|
+
/**
|
|
426
|
+
* When a projection animation completes we want to update the camera to
|
|
427
|
+
* match the recorded layout of the element.
|
|
428
|
+
*/
|
|
429
|
+
var removeAnimationCompleteListener = projection.addEventListener("animationComplete", function () {
|
|
430
|
+
var actual = (projection.layout || {}).actual;
|
|
431
|
+
actual && updateCamera(calcBoxSize(actual));
|
|
432
|
+
});
|
|
433
|
+
return function () {
|
|
434
|
+
removeProjectionUpdateListener();
|
|
435
|
+
removeLayoutMeasureListener();
|
|
436
|
+
removeAnimationCompleteListener();
|
|
437
|
+
};
|
|
438
|
+
}, []);
|
|
439
|
+
React.useLayoutEffect(function () {
|
|
440
|
+
var cam = layoutCamera.current;
|
|
441
|
+
if (makeDefault && cam) {
|
|
442
|
+
var oldCam_1 = camera;
|
|
443
|
+
set(function () { return ({ camera: cam }); });
|
|
444
|
+
return function () { return set(function () { return ({ camera: oldCam_1 }); }); };
|
|
445
|
+
}
|
|
446
|
+
}, [camera, layoutCamera, makeDefault, set]);
|
|
447
|
+
return { size: size, camera: camera, cameraRef: layoutCamera };
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Adapted from https://github.com/pmndrs/drei/blob/master/src/core/PerspectiveCamera.tsx
|
|
452
|
+
*/
|
|
453
|
+
var LayoutCamera = React__namespace.forwardRef(function (props, ref) {
|
|
454
|
+
var cameraRef = useLayoutCamera(props, function (size) {
|
|
455
|
+
var cam = cameraRef.current;
|
|
456
|
+
if (cam && !props.manual) {
|
|
457
|
+
cam.aspect = size.width / size.height;
|
|
458
|
+
cam.updateProjectionMatrix();
|
|
459
|
+
}
|
|
460
|
+
}).cameraRef;
|
|
461
|
+
return (React__namespace.createElement(motion.perspectiveCamera, tslib.__assign({ ref: mergeRefs__default["default"]([cameraRef, ref]) }, props)));
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
var LayoutOrthographicCamera = React__namespace.forwardRef(function (props, ref) {
|
|
465
|
+
var _a = useLayoutCamera(props, function (newSize) {
|
|
466
|
+
var cam = cameraRef.current;
|
|
467
|
+
if (cam) {
|
|
468
|
+
cam.left = newSize.width / -2;
|
|
469
|
+
cam.right = newSize.width / 2;
|
|
470
|
+
cam.top = newSize.height / 2;
|
|
471
|
+
cam.bottom = newSize.height / -2;
|
|
472
|
+
cam.updateProjectionMatrix();
|
|
473
|
+
}
|
|
474
|
+
}), size = _a.size, cameraRef = _a.cameraRef;
|
|
475
|
+
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)));
|
|
476
|
+
});
|
|
296
477
|
|
|
297
478
|
function useTime() {
|
|
298
479
|
var time = useMotionValue.useMotionValue(0);
|
|
@@ -300,6 +481,8 @@ function useTime() {
|
|
|
300
481
|
return time;
|
|
301
482
|
}
|
|
302
483
|
|
|
484
|
+
exports.LayoutCamera = LayoutCamera;
|
|
485
|
+
exports.LayoutOrthographicCamera = LayoutOrthographicCamera;
|
|
303
486
|
exports.MotionCanvas = MotionCanvas;
|
|
304
487
|
exports.motion = motion;
|
|
305
488
|
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,82 @@
|
|
|
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
|
+
if (latestLayout.current) {
|
|
39
|
+
var _a = latestLayout.current, x = _a.x, y = _a.y;
|
|
40
|
+
var xRatio = calcLength(newProjection.x) / calcLength(x);
|
|
41
|
+
var yRatio = calcLength(newProjection.y) / calcLength(y);
|
|
42
|
+
gl.setPixelRatio(Math.max(xRatio, yRatio) * window.devicePixelRatio);
|
|
43
|
+
}
|
|
44
|
+
updateCamera(calcBoxSize(newProjection));
|
|
45
|
+
advance(getFrameData().timestamp);
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* When the layout of an element changes we want to update the renderer
|
|
49
|
+
* output to match the layout dimensions.
|
|
50
|
+
*/
|
|
51
|
+
var removeLayoutMeasureListener = projection.addEventListener("measure", function (newLayout) {
|
|
52
|
+
latestLayout.current = newLayout;
|
|
53
|
+
var newSize = calcBoxSize(newLayout);
|
|
54
|
+
gl.setSize(newSize.width, newSize.height);
|
|
55
|
+
setSize(newSize);
|
|
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
|
+
actual && updateCamera(calcBoxSize(actual));
|
|
64
|
+
});
|
|
65
|
+
return function () {
|
|
66
|
+
removeProjectionUpdateListener();
|
|
67
|
+
removeLayoutMeasureListener();
|
|
68
|
+
removeAnimationCompleteListener();
|
|
69
|
+
};
|
|
70
|
+
}, []);
|
|
71
|
+
useLayoutEffect(function () {
|
|
72
|
+
var cam = layoutCamera.current;
|
|
73
|
+
if (makeDefault && cam) {
|
|
74
|
+
var oldCam_1 = camera;
|
|
75
|
+
set(function () { return ({ camera: cam }); });
|
|
76
|
+
return function () { return set(function () { return ({ camera: oldCam_1 }); }); };
|
|
77
|
+
}
|
|
78
|
+
}, [camera, layoutCamera, makeDefault, set]);
|
|
79
|
+
return { size: size, camera: camera, cameraRef: layoutCamera };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
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;
|