framer-motion 9.0.2 → 9.0.3
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 +3344 -3260
- package/dist/es/animation/hooks/use-animated-state.mjs +3 -3
- package/dist/es/animation/index.mjs +3 -5
- package/dist/es/animation/legacy-popmotion/index.mjs +6 -2
- package/dist/es/animation/legacy-popmotion/inertia.mjs +4 -5
- package/dist/es/components/AnimatePresence/use-presence.mjs +0 -1
- package/dist/es/events/add-dom-event.mjs +6 -0
- package/dist/es/events/add-pointer-event.mjs +8 -0
- package/dist/es/events/use-dom-event.mjs +2 -5
- package/dist/es/gestures/drag/VisualElementDragControls.mjs +31 -30
- package/dist/es/gestures/drag/index.mjs +27 -0
- package/dist/es/gestures/focus.mjs +42 -0
- package/dist/es/gestures/hover.mjs +32 -0
- package/dist/es/gestures/{PanSession.mjs → pan/PanSession.mjs} +8 -8
- package/dist/es/gestures/pan/index.mjs +38 -0
- package/dist/es/gestures/press.mjs +109 -0
- package/dist/es/index.mjs +1 -1
- package/dist/es/motion/features/Feature.mjs +9 -0
- package/dist/es/motion/features/animation/exit.mjs +32 -0
- package/dist/es/motion/features/animation/index.mjs +38 -0
- package/dist/es/motion/features/animations.mjs +8 -37
- package/dist/es/motion/features/definitions.mjs +17 -23
- package/dist/es/motion/features/drag.mjs +12 -5
- package/dist/es/motion/features/gestures.mjs +16 -9
- package/dist/es/motion/features/layout/MeasureLayout.mjs +5 -5
- package/dist/es/motion/features/layout.mjs +11 -0
- package/dist/es/motion/features/load-features.mjs +4 -6
- package/dist/es/motion/features/viewport/index.mjs +96 -0
- package/dist/es/motion/index.mjs +12 -13
- package/dist/es/motion/utils/use-visual-element.mjs +8 -2
- package/dist/es/projection/geometry/delta-apply.mjs +9 -2
- package/dist/es/projection/geometry/delta-calc.mjs +2 -2
- package/dist/es/projection/geometry/delta-remove.mjs +2 -2
- package/dist/es/projection/node/DocumentProjectionNode.mjs +1 -1
- package/dist/es/projection/node/create-projection-node.mjs +65 -57
- package/dist/es/projection/node/group.mjs +5 -3
- package/dist/es/projection/shared/stack.mjs +7 -5
- package/dist/es/render/VisualElement.mjs +68 -47
- package/dist/es/render/dom/DOMVisualElement.mjs +1 -2
- package/dist/es/render/dom/features-max.mjs +2 -4
- package/dist/es/render/dom/motion.mjs +5 -6
- package/dist/es/render/dom/utils/create-config.mjs +1 -2
- package/dist/es/render/dom/value-types/animatable-none.mjs +3 -2
- package/dist/es/render/svg/SVGVisualElement.mjs +2 -2
- package/dist/es/render/utils/animation-state.mjs +6 -2
- package/dist/es/render/utils/animation.mjs +4 -4
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/render/utils/setters.mjs +14 -9
- package/dist/es/value/index.mjs +1 -1
- package/dist/es/value/utils/is-motion-value.mjs +1 -1
- package/dist/framer-motion.dev.js +3341 -3257
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +85 -77
- package/dist/projection.dev.js +217 -177
- package/dist/size-rollup-dom-animation-assets.js +1 -1
- package/dist/size-rollup-dom-animation-m.js +1 -1
- package/dist/size-rollup-dom-animation.js +1 -1
- package/dist/size-rollup-dom-max-assets.js +1 -1
- package/dist/size-rollup-dom-max.js +1 -1
- package/dist/size-rollup-m.js +1 -1
- package/dist/size-rollup-motion.js +1 -1
- package/dist/size-webpack-dom-animation.js +1 -1
- package/dist/size-webpack-dom-max.js +1 -1
- package/dist/size-webpack-m.js +1 -1
- package/dist/three-entry.d.ts +74 -38
- package/package.json +8 -8
- package/dist/es/events/use-pointer-event.mjs +0 -11
- package/dist/es/gestures/drag/use-drag.mjs +0 -20
- package/dist/es/gestures/use-focus-gesture.mjs +0 -37
- package/dist/es/gestures/use-hover-gesture.mjs +0 -32
- package/dist/es/gestures/use-pan-gesture.mjs +0 -46
- package/dist/es/gestures/use-tap-gesture.mjs +0 -115
- package/dist/es/motion/features/layout/index.mjs +0 -7
- package/dist/es/motion/features/viewport/use-viewport.mjs +0 -97
- package/dist/es/motion/utils/VisualElementHandler.mjs +0 -19
- package/dist/es/motion/utils/make-renderless-component.mjs +0 -6
package/dist/three-entry.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import * as
|
|
2
|
+
import * as react from 'react';
|
|
3
3
|
import { SVGAttributes, CSSProperties, RefObject, useEffect } from 'react';
|
|
4
4
|
|
|
5
5
|
declare type EasingFunction = (v: number) => number;
|
|
@@ -919,7 +919,7 @@ interface MotionConfigContext {
|
|
|
919
919
|
/**
|
|
920
920
|
* @public
|
|
921
921
|
*/
|
|
922
|
-
declare const MotionConfigContext:
|
|
922
|
+
declare const MotionConfigContext: react.Context<MotionConfigContext>;
|
|
923
923
|
|
|
924
924
|
declare class NodeStack {
|
|
925
925
|
lead?: IProjectionNode;
|
|
@@ -1102,7 +1102,7 @@ declare type SwitchLayoutGroupContext = SwitchLayoutGroup & InitialPromotionConf
|
|
|
1102
1102
|
/**
|
|
1103
1103
|
* Internal, exported only for usage in Framer
|
|
1104
1104
|
*/
|
|
1105
|
-
declare const SwitchLayoutGroupContext:
|
|
1105
|
+
declare const SwitchLayoutGroupContext: react.Context<SwitchLayoutGroupContext>;
|
|
1106
1106
|
|
|
1107
1107
|
interface VisualState<Instance, RenderState> {
|
|
1108
1108
|
renderState: RenderState;
|
|
@@ -1117,27 +1117,46 @@ interface UseVisualStateConfig<Instance, RenderState> {
|
|
|
1117
1117
|
}
|
|
1118
1118
|
declare const makeUseVisualState: <I, RS>(config: UseVisualStateConfig<I, RS>) => UseVisualState<I, RS>;
|
|
1119
1119
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1120
|
+
declare abstract class Feature<T> {
|
|
1121
|
+
isMounted: boolean;
|
|
1122
|
+
node: VisualElement<T>;
|
|
1123
|
+
constructor(node: VisualElement<T>);
|
|
1124
|
+
abstract mount(): void;
|
|
1125
|
+
abstract unmount(): void;
|
|
1126
|
+
update(): void;
|
|
1125
1127
|
}
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1128
|
+
|
|
1129
|
+
declare function MeasureLayout(props: MotionProps & {
|
|
1130
|
+
visualElement: VisualElement;
|
|
1131
|
+
}): JSX.Element;
|
|
1132
|
+
|
|
1133
|
+
declare type HydratedFeatureDefinition = {
|
|
1134
|
+
isEnabled: (props: MotionProps) => boolean;
|
|
1135
|
+
Feature: typeof Feature<any>;
|
|
1136
|
+
ProjectionNode?: any;
|
|
1137
|
+
MeasureLayout?: typeof MeasureLayout;
|
|
1138
|
+
};
|
|
1139
|
+
interface HydratedFeatureDefinitions {
|
|
1140
|
+
animation?: HydratedFeatureDefinition;
|
|
1141
|
+
exit?: HydratedFeatureDefinition;
|
|
1142
|
+
drag?: HydratedFeatureDefinition;
|
|
1143
|
+
tap?: HydratedFeatureDefinition;
|
|
1144
|
+
focus?: HydratedFeatureDefinition;
|
|
1145
|
+
hover?: HydratedFeatureDefinition;
|
|
1146
|
+
pan?: HydratedFeatureDefinition;
|
|
1147
|
+
inView?: HydratedFeatureDefinition;
|
|
1148
|
+
layout?: HydratedFeatureDefinition;
|
|
1137
1149
|
}
|
|
1138
|
-
|
|
1150
|
+
declare type FeaturePackage = {
|
|
1151
|
+
Feature?: HydratedFeatureDefinition["Feature"];
|
|
1152
|
+
ProjectionNode?: HydratedFeatureDefinition["ProjectionNode"];
|
|
1153
|
+
MeasureLayout?: HydratedFeatureDefinition["MeasureLayout"];
|
|
1154
|
+
};
|
|
1155
|
+
declare type FeaturePackages = {
|
|
1156
|
+
[K in keyof HydratedFeatureDefinitions]: FeaturePackage;
|
|
1157
|
+
};
|
|
1158
|
+
interface FeatureBundle extends FeaturePackages {
|
|
1139
1159
|
renderer: CreateVisualElement<any>;
|
|
1140
|
-
projectionNodeConstructor?: any;
|
|
1141
1160
|
}
|
|
1142
1161
|
|
|
1143
1162
|
declare enum AnimationType {
|
|
@@ -1180,6 +1199,18 @@ interface AnimationTypeState {
|
|
|
1180
1199
|
prevProp?: VariantLabels | TargetAndTransition;
|
|
1181
1200
|
}
|
|
1182
1201
|
|
|
1202
|
+
/**
|
|
1203
|
+
* @public
|
|
1204
|
+
*/
|
|
1205
|
+
interface PresenceContextProps {
|
|
1206
|
+
id: string;
|
|
1207
|
+
isPresent: boolean;
|
|
1208
|
+
register: (id: string | number) => () => void;
|
|
1209
|
+
onExitComplete?: (id: string | number) => void;
|
|
1210
|
+
initial?: false | VariantLabels;
|
|
1211
|
+
custom?: any;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1183
1214
|
/**
|
|
1184
1215
|
* A VisualElement is an imperative abstraction around UI elements such as
|
|
1185
1216
|
* HTMLElement, SVGElement, Three.Object3D etc.
|
|
@@ -1318,11 +1349,6 @@ declare abstract class VisualElement<Instance = unknown, RenderState = unknown,
|
|
|
1318
1349
|
* value might be provided externally by the component via props.
|
|
1319
1350
|
*/
|
|
1320
1351
|
values: Map<string, MotionValue<any>>;
|
|
1321
|
-
/**
|
|
1322
|
-
* Tracks whether this VisualElement's React component is currently present
|
|
1323
|
-
* within the defined React tree.
|
|
1324
|
-
*/
|
|
1325
|
-
isPresent: boolean;
|
|
1326
1352
|
/**
|
|
1327
1353
|
* The AnimationState, this is hydrated by the animation Feature.
|
|
1328
1354
|
*/
|
|
@@ -1335,7 +1361,14 @@ declare abstract class VisualElement<Instance = unknown, RenderState = unknown,
|
|
|
1335
1361
|
/**
|
|
1336
1362
|
* A reference to the latest props provided to the VisualElement's host React component.
|
|
1337
1363
|
*/
|
|
1338
|
-
|
|
1364
|
+
props: MotionProps;
|
|
1365
|
+
prevProps?: MotionProps;
|
|
1366
|
+
presenceContext: PresenceContextProps | null;
|
|
1367
|
+
prevPresenceContext?: PresenceContextProps | null;
|
|
1368
|
+
/**
|
|
1369
|
+
* Cleanup functions for active features (hover/tap/exit etc)
|
|
1370
|
+
*/
|
|
1371
|
+
private features;
|
|
1339
1372
|
/**
|
|
1340
1373
|
* A map of every subscription that binds the provided or generated
|
|
1341
1374
|
* motion values onChange listeners to this visual element.
|
|
@@ -1375,12 +1408,13 @@ declare abstract class VisualElement<Instance = unknown, RenderState = unknown,
|
|
|
1375
1408
|
* VisualElement.on(), but only one of those can be defined via the onUpdate prop.
|
|
1376
1409
|
*/
|
|
1377
1410
|
private propEventSubscriptions;
|
|
1378
|
-
constructor({ parent, props, reducedMotionConfig, visualState, }: VisualElementOptions<Instance, RenderState>, options?: Options);
|
|
1411
|
+
constructor({ parent, props, presenceContext, reducedMotionConfig, visualState, }: VisualElementOptions<Instance, RenderState>, options?: Options);
|
|
1379
1412
|
mount(instance: Instance): void;
|
|
1380
1413
|
unmount(): void;
|
|
1381
1414
|
private bindToMotionValue;
|
|
1382
1415
|
sortNodePosition(other: VisualElement<Instance>): number;
|
|
1383
|
-
loadFeatures({ children, ...renderedProps }: MotionProps, isStrict: boolean, preloadedFeatures?: FeatureBundle, projectionId?: number,
|
|
1416
|
+
loadFeatures({ children, ...renderedProps }: MotionProps, isStrict: boolean, preloadedFeatures?: FeatureBundle, projectionId?: number, initialLayoutGroupConfig?: SwitchLayoutGroupContext): react.ComponentType<MotionProps> | undefined;
|
|
1417
|
+
updateFeatures(): void;
|
|
1384
1418
|
notifyUpdate: () => void;
|
|
1385
1419
|
triggerBuild(): void;
|
|
1386
1420
|
render: () => void;
|
|
@@ -1405,7 +1439,7 @@ declare abstract class VisualElement<Instance = unknown, RenderState = unknown,
|
|
|
1405
1439
|
* Update the provided props. Ensure any newly-added motion values are
|
|
1406
1440
|
* added to our map, old ones removed, and listeners updated.
|
|
1407
1441
|
*/
|
|
1408
|
-
|
|
1442
|
+
update(props: MotionProps, presenceContext: PresenceContextProps | null): void;
|
|
1409
1443
|
getProps(): MotionProps;
|
|
1410
1444
|
/**
|
|
1411
1445
|
* Returns the variant definition with a given name.
|
|
@@ -1784,7 +1818,7 @@ declare class DragControls {
|
|
|
1784
1818
|
*
|
|
1785
1819
|
* @public
|
|
1786
1820
|
*/
|
|
1787
|
-
start(event:
|
|
1821
|
+
start(event: react.PointerEvent | PointerEvent, options?: DragControlOptions): void;
|
|
1788
1822
|
}
|
|
1789
1823
|
|
|
1790
1824
|
declare type DragElastic = boolean | number | Partial<BoundingBox>;
|
|
@@ -2285,7 +2319,7 @@ interface PanHandlers {
|
|
|
2285
2319
|
* - `offset`: Offset from the original pan event.
|
|
2286
2320
|
* - `velocity`: Current velocity of the pointer.
|
|
2287
2321
|
*/
|
|
2288
|
-
onPan?(event:
|
|
2322
|
+
onPan?(event: PointerEvent, info: PanInfo): void;
|
|
2289
2323
|
/**
|
|
2290
2324
|
* Callback function that fires when the pan gesture begins on this element.
|
|
2291
2325
|
*
|
|
@@ -2305,7 +2339,7 @@ interface PanHandlers {
|
|
|
2305
2339
|
* - `offset`: Offset from the original pan event.
|
|
2306
2340
|
* - `velocity`: Current velocity of the pointer.
|
|
2307
2341
|
*/
|
|
2308
|
-
onPanStart?(event:
|
|
2342
|
+
onPanStart?(event: PointerEvent, info: PanInfo): void;
|
|
2309
2343
|
/**
|
|
2310
2344
|
* Callback function that fires when we begin detecting a pan gesture. This
|
|
2311
2345
|
* is analogous to `onMouseStart` or `onTouchStart`.
|
|
@@ -2323,7 +2357,7 @@ interface PanHandlers {
|
|
|
2323
2357
|
*
|
|
2324
2358
|
* - `point`: Relative to the device or page.
|
|
2325
2359
|
*/
|
|
2326
|
-
onPanSessionStart?(event:
|
|
2360
|
+
onPanSessionStart?(event: PointerEvent, info: EventInfo): void;
|
|
2327
2361
|
/**
|
|
2328
2362
|
* Callback function that fires when the pan gesture ends on this element.
|
|
2329
2363
|
*
|
|
@@ -2343,7 +2377,7 @@ interface PanHandlers {
|
|
|
2343
2377
|
* - `offset`: Offset from the original pan event.
|
|
2344
2378
|
* - `velocity`: Current velocity of the pointer.
|
|
2345
2379
|
*/
|
|
2346
|
-
onPanEnd?(event:
|
|
2380
|
+
onPanEnd?(event: PointerEvent, info: PanInfo): void;
|
|
2347
2381
|
}
|
|
2348
2382
|
/**
|
|
2349
2383
|
* @public
|
|
@@ -2381,6 +2415,9 @@ interface ViewportOptions {
|
|
|
2381
2415
|
once?: boolean;
|
|
2382
2416
|
margin?: string;
|
|
2383
2417
|
amount?: "some" | "all" | number;
|
|
2418
|
+
/**
|
|
2419
|
+
* @deprecated IntersectionObserver fallback will always be disabled from 10.0. Prefer polyfill for older browser support.
|
|
2420
|
+
*/
|
|
2384
2421
|
fallback?: boolean;
|
|
2385
2422
|
}
|
|
2386
2423
|
interface ViewportProps {
|
|
@@ -2664,7 +2701,7 @@ declare type VisualElementOptions<Instance, RenderState = any> = {
|
|
|
2664
2701
|
visualState: VisualState<Instance, RenderState>;
|
|
2665
2702
|
parent?: VisualElement<unknown>;
|
|
2666
2703
|
variantParent?: VisualElement<unknown>;
|
|
2667
|
-
|
|
2704
|
+
presenceContext: PresenceContextProps | null;
|
|
2668
2705
|
props: MotionProps;
|
|
2669
2706
|
blockInitialAnimation?: boolean;
|
|
2670
2707
|
reducedMotionConfig?: ReducedMotionConfig;
|
|
@@ -2680,7 +2717,6 @@ interface VisualElementEventCallbacks {
|
|
|
2680
2717
|
LayoutMeasure: (layout: Box, prevLayout?: Box) => void;
|
|
2681
2718
|
LayoutUpdate: (layout: Axis, prevLayout: Axis) => void;
|
|
2682
2719
|
Update: (latest: ResolvedValues) => void;
|
|
2683
|
-
Render: () => void;
|
|
2684
2720
|
AnimationStart: (definition: AnimationDefinition) => void;
|
|
2685
2721
|
AnimationComplete: (definition: AnimationDefinition) => void;
|
|
2686
2722
|
LayoutAnimationStart: () => void;
|
|
@@ -2750,7 +2786,7 @@ interface AnimationLifecycles {
|
|
|
2750
2786
|
declare type EventProps = LayoutLifecycles & AnimationLifecycles;
|
|
2751
2787
|
declare type CreateVisualElement<Instance> = (Component: string | React.ComponentType<React.PropsWithChildren<unknown>>, options: VisualElementOptions<Instance>) => VisualElement<Instance>;
|
|
2752
2788
|
|
|
2753
|
-
declare const animations:
|
|
2789
|
+
declare const animations: FeaturePackages;
|
|
2754
2790
|
|
|
2755
2791
|
declare function useVisualElementContext(): VisualElement<unknown, unknown, {}> | undefined;
|
|
2756
2792
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "framer-motion",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.3",
|
|
4
4
|
"description": "A simple and powerful React animation library",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/es/index.mjs",
|
|
@@ -76,28 +76,28 @@
|
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
"path": "./dist/size-rollup-m.js",
|
|
79
|
-
"maxSize": "4.
|
|
79
|
+
"maxSize": "4.68 kB"
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
82
|
"path": "./dist/size-rollup-dom-animation.js",
|
|
83
|
-
"maxSize": "14.
|
|
83
|
+
"maxSize": "14.88 kB"
|
|
84
84
|
},
|
|
85
85
|
{
|
|
86
86
|
"path": "./dist/size-rollup-dom-max.js",
|
|
87
|
-
"maxSize": "25.
|
|
87
|
+
"maxSize": "25.56 kB"
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
90
|
"path": "./dist/size-webpack-m.js",
|
|
91
|
-
"maxSize": "4.
|
|
91
|
+
"maxSize": "4.8 kB"
|
|
92
92
|
},
|
|
93
93
|
{
|
|
94
94
|
"path": "./dist/size-webpack-dom-animation.js",
|
|
95
|
-
"maxSize": "
|
|
95
|
+
"maxSize": "18.91 kB"
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
98
|
"path": "./dist/size-webpack-dom-max.js",
|
|
99
|
-
"maxSize": "30.
|
|
99
|
+
"maxSize": "30.43 kB"
|
|
100
100
|
}
|
|
101
101
|
],
|
|
102
|
-
"gitHead": "
|
|
102
|
+
"gitHead": "80400267dedc1e899949428217cd496a1ba687c3"
|
|
103
103
|
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { addDomEvent, useDomEvent } from './use-dom-event.mjs';
|
|
2
|
-
import { addPointerInfo } from './event-info.mjs';
|
|
3
|
-
|
|
4
|
-
function addPointerEvent(target, eventName, handler, options) {
|
|
5
|
-
return addDomEvent(target, eventName, addPointerInfo(handler), options);
|
|
6
|
-
}
|
|
7
|
-
function usePointerEvent(ref, eventName, handler, options) {
|
|
8
|
-
return useDomEvent(ref, eventName, handler && addPointerInfo(handler), options);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export { addPointerEvent, usePointerEvent };
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
2
|
-
import { VisualElementDragControls } from './VisualElementDragControls.mjs';
|
|
3
|
-
import { useConstant } from '../../utils/use-constant.mjs';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* A hook that allows an element to be dragged.
|
|
7
|
-
*
|
|
8
|
-
* @internal
|
|
9
|
-
*/
|
|
10
|
-
function useDrag(props) {
|
|
11
|
-
const { dragControls: groupDragControls, visualElement } = props;
|
|
12
|
-
const dragControls = useConstant(() => new VisualElementDragControls(visualElement));
|
|
13
|
-
// If we've been provided a DragControls for manual control over the drag gesture,
|
|
14
|
-
// subscribe this component to it on mount.
|
|
15
|
-
useEffect(() => groupDragControls && groupDragControls.subscribe(dragControls), [dragControls, groupDragControls]);
|
|
16
|
-
// Apply the event listeners to the element
|
|
17
|
-
useEffect(() => dragControls.addListeners(), [dragControls]);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export { useDrag };
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { AnimationType } from '../render/utils/types.mjs';
|
|
2
|
-
import { useDomEvent } from '../events/use-dom-event.mjs';
|
|
3
|
-
import { useRef, useCallback } from 'react';
|
|
4
|
-
|
|
5
|
-
function useFocusGesture({ whileFocus, visualElement, }) {
|
|
6
|
-
const isFocusActive = useRef(false);
|
|
7
|
-
const { animationState } = visualElement;
|
|
8
|
-
const onFocus = useCallback(() => {
|
|
9
|
-
let isFocusVisible = false;
|
|
10
|
-
/**
|
|
11
|
-
* If this element doesn't match focus-visible then don't
|
|
12
|
-
* apply whileHover. But, if matches throws that focus-visible
|
|
13
|
-
* is not a valid selector then in that browser outline styles will be applied
|
|
14
|
-
* to the element by default and we want to match that behaviour with whileFocus.
|
|
15
|
-
*/
|
|
16
|
-
try {
|
|
17
|
-
isFocusVisible = visualElement.current.matches(":focus-visible");
|
|
18
|
-
}
|
|
19
|
-
catch (e) {
|
|
20
|
-
isFocusVisible = true;
|
|
21
|
-
}
|
|
22
|
-
if (!isFocusVisible || !animationState)
|
|
23
|
-
return;
|
|
24
|
-
animationState.setActive(AnimationType.Focus, true);
|
|
25
|
-
isFocusActive.current = true;
|
|
26
|
-
}, [animationState]);
|
|
27
|
-
const onBlur = useCallback(() => {
|
|
28
|
-
if (!isFocusActive.current || !animationState)
|
|
29
|
-
return;
|
|
30
|
-
animationState.setActive(AnimationType.Focus, false);
|
|
31
|
-
isFocusActive.current = false;
|
|
32
|
-
}, [animationState]);
|
|
33
|
-
useDomEvent(visualElement, "focus", whileFocus ? onFocus : undefined);
|
|
34
|
-
useDomEvent(visualElement, "blur", whileFocus ? onBlur : undefined);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export { useFocusGesture };
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { AnimationType } from '../render/utils/types.mjs';
|
|
2
|
-
import { usePointerEvent } from '../events/use-pointer-event.mjs';
|
|
3
|
-
import { isDragActive } from './drag/utils/lock.mjs';
|
|
4
|
-
import { useMemo } from 'react';
|
|
5
|
-
|
|
6
|
-
function createHoverEvent(visualElement, isActive, applyVariants, callback) {
|
|
7
|
-
return (event, info) => {
|
|
8
|
-
if (event.type === "touch" || isDragActive())
|
|
9
|
-
return;
|
|
10
|
-
/**
|
|
11
|
-
* Ensure we trigger animations before firing event callback
|
|
12
|
-
*/
|
|
13
|
-
if (applyVariants && visualElement.animationState) {
|
|
14
|
-
visualElement.animationState.setActive(AnimationType.Hover, isActive);
|
|
15
|
-
}
|
|
16
|
-
callback && callback(event, info);
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
function useHoverGesture({ onHoverStart, onHoverEnd, whileHover, visualElement, }) {
|
|
20
|
-
usePointerEvent(visualElement, "pointerenter", useMemo(() => {
|
|
21
|
-
return onHoverStart || whileHover
|
|
22
|
-
? createHoverEvent(visualElement, true, Boolean(whileHover), onHoverStart)
|
|
23
|
-
: undefined;
|
|
24
|
-
}, [onHoverStart, Boolean(whileHover), visualElement]), { passive: !onHoverStart });
|
|
25
|
-
usePointerEvent(visualElement, "pointerleave", useMemo(() => {
|
|
26
|
-
return onHoverEnd || whileHover
|
|
27
|
-
? createHoverEvent(visualElement, false, Boolean(whileHover), onHoverEnd)
|
|
28
|
-
: undefined;
|
|
29
|
-
}, [onHoverStart, Boolean(whileHover), visualElement]), { passive: !onHoverEnd });
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export { useHoverGesture };
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { useRef, useContext, useEffect } from 'react';
|
|
2
|
-
import { MotionConfigContext } from '../context/MotionConfigContext.mjs';
|
|
3
|
-
import { useUnmountEffect } from '../utils/use-unmount-effect.mjs';
|
|
4
|
-
import { usePointerEvent } from '../events/use-pointer-event.mjs';
|
|
5
|
-
import { PanSession } from './PanSession.mjs';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
* @param handlers -
|
|
10
|
-
* @param ref -
|
|
11
|
-
*
|
|
12
|
-
* @privateRemarks
|
|
13
|
-
* Currently this sets new pan gesture functions every render. The memo route has been explored
|
|
14
|
-
* in the past but ultimately we're still creating new functions every render. An optimisation
|
|
15
|
-
* to explore is creating the pan gestures and loading them into a `ref`.
|
|
16
|
-
*
|
|
17
|
-
* @internal
|
|
18
|
-
*/
|
|
19
|
-
function usePanGesture({ onPan, onPanStart, onPanEnd, onPanSessionStart, visualElement, }) {
|
|
20
|
-
const hasPanEvents = onPan || onPanStart || onPanEnd || onPanSessionStart;
|
|
21
|
-
const panSession = useRef(null);
|
|
22
|
-
const { transformPagePoint } = useContext(MotionConfigContext);
|
|
23
|
-
const handlers = {
|
|
24
|
-
onSessionStart: onPanSessionStart,
|
|
25
|
-
onStart: onPanStart,
|
|
26
|
-
onMove: onPan,
|
|
27
|
-
onEnd: (event, info) => {
|
|
28
|
-
panSession.current = null;
|
|
29
|
-
onPanEnd && onPanEnd(event, info);
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
if (panSession.current !== null) {
|
|
34
|
-
panSession.current.updateHandlers(handlers);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
function onPointerDown(event) {
|
|
38
|
-
panSession.current = new PanSession(event, handlers, {
|
|
39
|
-
transformPagePoint,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
usePointerEvent(visualElement, "pointerdown", hasPanEvents && onPointerDown);
|
|
43
|
-
useUnmountEffect(() => panSession.current && panSession.current.end());
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export { usePanGesture };
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { useRef, useCallback } from 'react';
|
|
2
|
-
import { isNodeOrChild } from './utils/is-node-or-child.mjs';
|
|
3
|
-
import { addPointerEvent, usePointerEvent } from '../events/use-pointer-event.mjs';
|
|
4
|
-
import { useUnmountEffect } from '../utils/use-unmount-effect.mjs';
|
|
5
|
-
import { AnimationType } from '../render/utils/types.mjs';
|
|
6
|
-
import { isDragActive } from './drag/utils/lock.mjs';
|
|
7
|
-
import { pipe } from '../utils/pipe.mjs';
|
|
8
|
-
import { addDomEvent, useDomEvent } from '../events/use-dom-event.mjs';
|
|
9
|
-
import { extractEventInfo } from '../events/event-info.mjs';
|
|
10
|
-
|
|
11
|
-
function fireSyntheticPointerEvent(name, handler) {
|
|
12
|
-
if (!handler)
|
|
13
|
-
return;
|
|
14
|
-
const syntheticPointerEvent = new PointerEvent("pointer" + name);
|
|
15
|
-
handler(syntheticPointerEvent, extractEventInfo(syntheticPointerEvent));
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* @param handlers -
|
|
19
|
-
* @internal
|
|
20
|
-
*/
|
|
21
|
-
function useTapGesture({ onTap, onTapStart, onTapCancel, whileTap, visualElement, ...props }) {
|
|
22
|
-
const hasPressListeners = onTap || onTapStart || onTapCancel || whileTap;
|
|
23
|
-
const isPressing = useRef(false);
|
|
24
|
-
const cancelPointerEndListeners = useRef(null);
|
|
25
|
-
/**
|
|
26
|
-
* Only set listener to passive if there are no external listeners.
|
|
27
|
-
*/
|
|
28
|
-
const eventOptions = {
|
|
29
|
-
passive: !(onTapStart ||
|
|
30
|
-
onTap ||
|
|
31
|
-
onTapCancel ||
|
|
32
|
-
props["onPointerDown"]),
|
|
33
|
-
};
|
|
34
|
-
function removePointerEndListener() {
|
|
35
|
-
cancelPointerEndListeners.current && cancelPointerEndListeners.current();
|
|
36
|
-
cancelPointerEndListeners.current = null;
|
|
37
|
-
}
|
|
38
|
-
function checkPointerEnd() {
|
|
39
|
-
removePointerEndListener();
|
|
40
|
-
isPressing.current = false;
|
|
41
|
-
const latestProps = visualElement.getProps();
|
|
42
|
-
if (latestProps.whileTap && visualElement.animationState) {
|
|
43
|
-
visualElement.animationState.setActive(AnimationType.Tap, false);
|
|
44
|
-
}
|
|
45
|
-
return !isDragActive();
|
|
46
|
-
}
|
|
47
|
-
function onPointerUp(event, info) {
|
|
48
|
-
var _a, _b, _c, _d;
|
|
49
|
-
if (!checkPointerEnd())
|
|
50
|
-
return;
|
|
51
|
-
/**
|
|
52
|
-
* We only count this as a tap gesture if the event.target is the same
|
|
53
|
-
* as, or a child of, this component's element
|
|
54
|
-
*/
|
|
55
|
-
!isNodeOrChild(visualElement.current, event.target)
|
|
56
|
-
? (_b = (_a = visualElement.getProps()).onTapCancel) === null || _b === void 0 ? void 0 : _b.call(_a, event, info)
|
|
57
|
-
: (_d = (_c = visualElement.getProps()).onTap) === null || _d === void 0 ? void 0 : _d.call(_c, event, info);
|
|
58
|
-
}
|
|
59
|
-
function onPointerCancel(event, info) {
|
|
60
|
-
var _a, _b;
|
|
61
|
-
if (!checkPointerEnd())
|
|
62
|
-
return;
|
|
63
|
-
(_b = (_a = visualElement.getProps()).onTapCancel) === null || _b === void 0 ? void 0 : _b.call(_a, event, info);
|
|
64
|
-
}
|
|
65
|
-
function onPointerStart(event, info) {
|
|
66
|
-
var _a;
|
|
67
|
-
const latestProps = visualElement.getProps();
|
|
68
|
-
/**
|
|
69
|
-
* Ensure we trigger animations before firing event callback
|
|
70
|
-
*/
|
|
71
|
-
if (latestProps.whileTap && visualElement.animationState) {
|
|
72
|
-
visualElement.animationState.setActive(AnimationType.Tap, true);
|
|
73
|
-
}
|
|
74
|
-
(_a = latestProps.onTapStart) === null || _a === void 0 ? void 0 : _a.call(latestProps, event, info);
|
|
75
|
-
}
|
|
76
|
-
const callbackDependencies = [
|
|
77
|
-
Boolean(onTapStart),
|
|
78
|
-
Boolean(onTap),
|
|
79
|
-
Boolean(whileTap),
|
|
80
|
-
visualElement,
|
|
81
|
-
];
|
|
82
|
-
const startPress = useCallback((event, info) => {
|
|
83
|
-
removePointerEndListener();
|
|
84
|
-
if (isPressing.current)
|
|
85
|
-
return;
|
|
86
|
-
isPressing.current = true;
|
|
87
|
-
cancelPointerEndListeners.current = pipe(addPointerEvent(window, "pointerup", onPointerUp, eventOptions), addPointerEvent(window, "pointercancel", onPointerCancel, eventOptions));
|
|
88
|
-
onPointerStart(event, info);
|
|
89
|
-
}, callbackDependencies);
|
|
90
|
-
usePointerEvent(visualElement, "pointerdown", hasPressListeners ? startPress : undefined, eventOptions);
|
|
91
|
-
const startAccessiblePress = useCallback(() => {
|
|
92
|
-
const stopKeydownListener = addDomEvent(visualElement.current, "keydown", (event) => {
|
|
93
|
-
if (event.key !== "Enter" || isPressing.current)
|
|
94
|
-
return;
|
|
95
|
-
isPressing.current = true;
|
|
96
|
-
cancelPointerEndListeners.current = addDomEvent(visualElement.current, "keyup", () => {
|
|
97
|
-
if (event.key !== "Enter" || !checkPointerEnd())
|
|
98
|
-
return;
|
|
99
|
-
fireSyntheticPointerEvent("up", visualElement.getProps().onTap);
|
|
100
|
-
}, eventOptions);
|
|
101
|
-
fireSyntheticPointerEvent("down", onPointerStart);
|
|
102
|
-
});
|
|
103
|
-
const stopBlurListener = addDomEvent(visualElement.current, "blur", () => {
|
|
104
|
-
stopKeydownListener();
|
|
105
|
-
stopBlurListener();
|
|
106
|
-
if (isPressing.current) {
|
|
107
|
-
fireSyntheticPointerEvent("cancel", onPointerCancel);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}, callbackDependencies);
|
|
111
|
-
useDomEvent(visualElement, "focus", hasPressListeners ? startAccessiblePress : undefined);
|
|
112
|
-
useUnmountEffect(removePointerEndListener);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export { useTapGesture };
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { useRef, useEffect } from 'react';
|
|
2
|
-
import { AnimationType } from '../../../render/utils/types.mjs';
|
|
3
|
-
import { warnOnce } from '../../../utils/warn-once.mjs';
|
|
4
|
-
import { observeIntersection } from './observers.mjs';
|
|
5
|
-
|
|
6
|
-
function useViewport({ visualElement, whileInView, onViewportEnter, onViewportLeave, viewport = {}, }) {
|
|
7
|
-
const state = useRef({
|
|
8
|
-
hasEnteredView: false,
|
|
9
|
-
isInView: false,
|
|
10
|
-
});
|
|
11
|
-
let shouldObserve = Boolean(whileInView || onViewportEnter || onViewportLeave);
|
|
12
|
-
if (viewport.once && state.current.hasEnteredView)
|
|
13
|
-
shouldObserve = false;
|
|
14
|
-
const useObserver = typeof IntersectionObserver === "undefined"
|
|
15
|
-
? useMissingIntersectionObserver
|
|
16
|
-
: useIntersectionObserver;
|
|
17
|
-
useObserver(shouldObserve, state.current, visualElement, viewport);
|
|
18
|
-
}
|
|
19
|
-
const thresholdNames = {
|
|
20
|
-
some: 0,
|
|
21
|
-
all: 1,
|
|
22
|
-
};
|
|
23
|
-
function useIntersectionObserver(shouldObserve, state, visualElement, { root, margin: rootMargin, amount = "some", once }) {
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
if (!shouldObserve || !visualElement.current)
|
|
26
|
-
return;
|
|
27
|
-
const options = {
|
|
28
|
-
root: root === null || root === void 0 ? void 0 : root.current,
|
|
29
|
-
rootMargin,
|
|
30
|
-
threshold: typeof amount === "number" ? amount : thresholdNames[amount],
|
|
31
|
-
};
|
|
32
|
-
const intersectionCallback = (entry) => {
|
|
33
|
-
const { isIntersecting } = entry;
|
|
34
|
-
/**
|
|
35
|
-
* If there's been no change in the viewport state, early return.
|
|
36
|
-
*/
|
|
37
|
-
if (state.isInView === isIntersecting)
|
|
38
|
-
return;
|
|
39
|
-
state.isInView = isIntersecting;
|
|
40
|
-
/**
|
|
41
|
-
* Handle hasEnteredView. If this is only meant to run once, and
|
|
42
|
-
* element isn't visible, early return. Otherwise set hasEnteredView to true.
|
|
43
|
-
*/
|
|
44
|
-
if (once && !isIntersecting && state.hasEnteredView) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
else if (isIntersecting) {
|
|
48
|
-
state.hasEnteredView = true;
|
|
49
|
-
}
|
|
50
|
-
if (visualElement.animationState) {
|
|
51
|
-
visualElement.animationState.setActive(AnimationType.InView, isIntersecting);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Use the latest committed props rather than the ones in scope
|
|
55
|
-
* when this observer is created
|
|
56
|
-
*/
|
|
57
|
-
const props = visualElement.getProps();
|
|
58
|
-
const callback = isIntersecting
|
|
59
|
-
? props.onViewportEnter
|
|
60
|
-
: props.onViewportLeave;
|
|
61
|
-
callback && callback(entry);
|
|
62
|
-
};
|
|
63
|
-
return observeIntersection(visualElement.current, options, intersectionCallback);
|
|
64
|
-
}, [shouldObserve, root, rootMargin, amount]);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* If IntersectionObserver is missing, we activate inView and fire onViewportEnter
|
|
68
|
-
* on mount. This way, the page will be in the state the author expects users
|
|
69
|
-
* to see it in for everyone.
|
|
70
|
-
*/
|
|
71
|
-
function useMissingIntersectionObserver(shouldObserve, state, visualElement, { fallback = true }) {
|
|
72
|
-
useEffect(() => {
|
|
73
|
-
if (!shouldObserve || !fallback)
|
|
74
|
-
return;
|
|
75
|
-
if (process.env.NODE_ENV !== "production") {
|
|
76
|
-
warnOnce(false, "IntersectionObserver not available on this device. whileInView animations will trigger on mount.");
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Fire this in an rAF because, at this point, the animation state
|
|
80
|
-
* won't have flushed for the first time and there's certain logic in
|
|
81
|
-
* there that behaves differently on the initial animation.
|
|
82
|
-
*
|
|
83
|
-
* This hook should be quite rarely called so setting this in an rAF
|
|
84
|
-
* is preferred to changing the behaviour of the animation state.
|
|
85
|
-
*/
|
|
86
|
-
requestAnimationFrame(() => {
|
|
87
|
-
state.hasEnteredView = true;
|
|
88
|
-
const { onViewportEnter } = visualElement.getProps();
|
|
89
|
-
onViewportEnter && onViewportEnter(null);
|
|
90
|
-
if (visualElement.animationState) {
|
|
91
|
-
visualElement.animationState.setActive(AnimationType.InView, true);
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
}, [shouldObserve]);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export { useViewport };
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React__default from 'react';
|
|
2
|
-
|
|
3
|
-
class VisualElementHandler extends React__default.Component {
|
|
4
|
-
/**
|
|
5
|
-
* Update visual element props as soon as we know this update is going to be commited.
|
|
6
|
-
*/
|
|
7
|
-
getSnapshotBeforeUpdate() {
|
|
8
|
-
const { visualElement, props } = this.props;
|
|
9
|
-
if (visualElement)
|
|
10
|
-
visualElement.setProps(props);
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
componentDidUpdate() { }
|
|
14
|
-
render() {
|
|
15
|
-
return this.props.children;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export { VisualElementHandler };
|