react-ui-animate 2.0.0 → 3.0.0-rc.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/.vscode/settings.json +3 -3
- package/LICENSE +21 -21
- package/README.md +115 -115
- package/dist/animation/animationType.d.ts +15 -15
- package/dist/animation/core/animation/Animation.d.ts +16 -0
- package/dist/animation/core/animation/FluidValue.d.ts +21 -0
- package/dist/animation/core/animation/RequestAnimationFrame.d.ts +8 -0
- package/dist/animation/core/animation/SpringAnimation.d.ts +41 -0
- package/dist/animation/core/animation/TimingAnimation.d.ts +35 -0
- package/dist/animation/core/animation/TransitionValue.d.ts +21 -0
- package/dist/animation/core/controllers/Animation.d.ts +16 -0
- package/dist/animation/core/controllers/FluidValue.d.ts +32 -0
- package/dist/animation/core/controllers/RequestAnimationFrame.d.ts +8 -0
- package/dist/animation/core/controllers/SpringAnimation.d.ts +41 -0
- package/dist/animation/core/controllers/TimingAnimation.d.ts +35 -0
- package/dist/animation/core/easing/Bezier.d.ts +8 -0
- package/dist/animation/core/easing/Easing.d.ts +40 -0
- package/dist/animation/core/helpers/camelCaseToKebabCase.d.ts +8 -0
- package/dist/animation/core/helpers/camelToDash.d.ts +7 -0
- package/dist/animation/core/helpers/canInterpolate.d.ts +11 -0
- package/dist/animation/core/helpers/getAnimatableObject.d.ts +22 -0
- package/dist/animation/core/helpers/getCleanProps.d.ts +10 -0
- package/dist/animation/core/helpers/getCssValue.d.ts +8 -0
- package/dist/animation/core/helpers/getNonAnimatableStyle.d.ts +6 -0
- package/dist/animation/core/helpers/index.d.ts +5 -0
- package/dist/animation/core/helpers/isDefined.d.ts +12 -0
- package/dist/animation/core/helpers/isFluidValue.d.ts +6 -0
- package/dist/animation/core/index.d.ts +11 -0
- package/dist/animation/core/interpolation/Colors.d.ts +25 -0
- package/dist/animation/core/interpolation/Interpolation.d.ts +80 -0
- package/dist/animation/core/interpolation/__tests__/Colors.test.d.ts +1 -0
- package/dist/animation/core/react/Tags.d.ts +3 -0
- package/dist/animation/core/react/TransformStyles.d.ts +8 -0
- package/dist/animation/core/react/animated.d.ts +29 -0
- package/dist/animation/core/react/combineRefs.d.ts +2 -0
- package/dist/animation/core/react/fluid.d.ts +6 -0
- package/dist/animation/core/react/functions/camelToDash.d.ts +7 -0
- package/dist/animation/core/react/functions/getAnimatableObject.d.ts +22 -0
- package/dist/animation/core/react/functions/getCleanProps.d.ts +4 -0
- package/dist/animation/core/react/functions/getCssValue.d.ts +8 -0
- package/dist/animation/core/react/functions/getNonAnimatableStyle.d.ts +6 -0
- package/dist/animation/core/react/functions/index.d.ts +7 -0
- package/dist/animation/core/react/functions/isDefined.d.ts +6 -0
- package/dist/animation/core/react/functions/isTransitionValue.d.ts +6 -0
- package/dist/animation/core/react/helpers/camelToDash.d.ts +7 -0
- package/dist/animation/core/react/helpers/canInterpolate.d.ts +7 -0
- package/dist/animation/core/react/helpers/getAnimatableObject.d.ts +22 -0
- package/dist/animation/core/react/helpers/getCleanProps.d.ts +4 -0
- package/dist/animation/core/react/helpers/getCssValue.d.ts +8 -0
- package/dist/animation/core/react/helpers/getNonAnimatableStyle.d.ts +6 -0
- package/dist/animation/core/react/helpers/index.d.ts +7 -0
- package/dist/animation/core/react/helpers/isDefined.d.ts +6 -0
- package/dist/animation/core/react/helpers/isFluidValue.d.ts +6 -0
- package/dist/animation/core/react/helpers/isTransitionValue.d.ts +6 -0
- package/dist/animation/core/react/makeFluid.d.ts +30 -0
- package/dist/animation/core/react/transforms.d.ts +6 -0
- package/dist/animation/core/react/useFluidValue.d.ts +9 -0
- package/dist/animation/core/react/useMount.d.ts +20 -0
- package/dist/animation/core/react/useMounts.d.ts +26 -0
- package/dist/animation/core/react/useTransition.d.ts +9 -0
- package/dist/animation/core/react/useTransitions.d.ts +11 -0
- package/dist/animation/core/types/animation.d.ts +54 -0
- package/dist/animation/core/types/common.d.ts +4 -0
- package/dist/animation/core/types/fluid.d.ts +19 -0
- package/dist/animation/core/types/index.d.ts +2 -0
- package/dist/animation/getInitialConfig.d.ts +3 -3
- package/dist/animation/index.d.ts +6 -6
- package/dist/animation/interpolation.d.ts +21 -21
- package/dist/animation/lib/animationType.d.ts +15 -0
- package/dist/animation/lib/getInitialConfig.d.ts +3 -0
- package/dist/animation/lib/index.d.ts +5 -0
- package/dist/animation/lib/interpolation.d.ts +20 -0
- package/dist/animation/lib/modules/AnimatedBlock.d.ts +8 -0
- package/dist/animation/lib/modules/AnimatedImage.d.ts +8 -0
- package/dist/animation/lib/modules/AnimatedInline.d.ts +8 -0
- package/dist/animation/lib/modules/MountedBlock.d.ts +29 -0
- package/dist/animation/lib/modules/ScrollableBlock.d.ts +22 -0
- package/dist/animation/lib/modules/TransitionBlock.d.ts +18 -0
- package/dist/animation/lib/modules/index.d.ts +6 -0
- package/dist/animation/lib/useAnimatedValue.d.ts +17 -0
- package/dist/animation/lib/useMountedValue.d.ts +14 -0
- package/dist/animation/modules/AnimatedBlock.d.ts +8 -8
- package/dist/animation/modules/AnimatedImage.d.ts +8 -8
- package/dist/animation/modules/AnimatedInline.d.ts +8 -8
- package/dist/animation/modules/MountedBlock.d.ts +29 -18
- package/dist/animation/modules/ScrollableBlock.d.ts +21 -21
- package/dist/animation/modules/TransitionBlock.d.ts +17 -17
- package/dist/animation/modules/index.d.ts +6 -6
- package/dist/animation/useAnimatedValue.d.ts +22 -22
- package/dist/animation/useMountedValue.d.ts +15 -15
- package/dist/gestures/controllers/DragGesture.d.ts +17 -17
- package/dist/gestures/controllers/Gesture.d.ts +20 -20
- package/dist/gestures/controllers/MouseMoveGesture.d.ts +13 -13
- package/dist/gestures/controllers/ScrollGesture.d.ts +14 -14
- package/dist/gestures/controllers/WheelGesture.d.ts +15 -15
- package/dist/gestures/controllers/index.d.ts +4 -4
- package/dist/gestures/eventAttacher.d.ts +11 -11
- package/dist/gestures/helpers/eventAttacher.d.ts +11 -0
- package/dist/gestures/helpers/index.d.ts +1 -0
- package/dist/gestures/helpers/math.d.ts +34 -0
- package/dist/gestures/helpers/withDefault.d.ts +4 -0
- package/dist/gestures/hooks/index.d.ts +5 -5
- package/dist/gestures/hooks/useDrag.d.ts +4 -4
- package/dist/gestures/hooks/useGesture.d.ts +9 -9
- package/dist/gestures/hooks/useMouseMove.d.ts +4 -4
- package/dist/gestures/hooks/useRecognizer.d.ts +10 -10
- package/dist/gestures/hooks/useScroll.d.ts +4 -4
- package/dist/gestures/hooks/useWheel.d.ts +4 -4
- package/dist/gestures/index.d.ts +2 -2
- package/dist/gestures/math.d.ts +34 -34
- package/dist/gestures/types.d.ts +51 -51
- package/dist/gestures/withDefault.d.ts +4 -4
- package/dist/hooks/index.d.ts +3 -3
- package/dist/hooks/useMeasure.d.ts +14 -14
- package/dist/hooks/useOutsideClick.d.ts +2 -2
- package/dist/hooks/useWindowDimension.d.ts +9 -9
- package/dist/index.d.ts +9 -5
- package/dist/index.js +2758 -1052
- package/dist/index.js.map +1 -1
- package/dist/utils/delay.d.ts +5 -5
- package/dist/utils/index.d.ts +1 -2
- package/dist/utils/isDefined.d.ts +1 -1
- package/ecosystem.config.js +12 -0
- package/example/README.md +46 -0
- package/example/package-lock.json +19597 -0
- package/example/package.json +45 -0
- package/example/public/favicon.ico +0 -0
- package/example/public/index.html +20 -0
- package/example/public/logo192.png +0 -0
- package/example/public/logo512.png +0 -0
- package/example/public/manifest.json +25 -0
- package/example/public/robots.txt +3 -0
- package/example/src/App.tsx +41 -0
- package/example/src/components/Draggable.tsx +46 -0
- package/example/src/components/Gestures.tsx +151 -0
- package/example/src/components/Interpolation.tsx +21 -0
- package/example/src/components/Loop.tsx +48 -0
- package/example/src/components/MountedBlock.tsx +25 -0
- package/example/src/components/MouseMove.tsx +59 -0
- package/example/src/components/MultistageTransition.tsx +34 -0
- package/example/src/components/Scroll.tsx +39 -0
- package/example/src/components/ScrollableBlock.tsx +27 -0
- package/example/src/components/SnapTo.tsx +55 -0
- package/example/src/components/TransitionBlock.tsx +37 -0
- package/example/src/components/Wheel.tsx +39 -0
- package/example/src/components/index.ts +18 -0
- package/example/src/components/svgLine.tsx +48 -0
- package/example/src/components/useAnimatedValue.tsx +57 -0
- package/example/src/components/useMountedValue.tsx +62 -0
- package/example/src/index.css +8 -0
- package/example/src/index.tsx +16 -0
- package/example/tsconfig.json +26 -0
- package/package.json +48 -48
- package/{rollup.config.js → rollup.config.mjs} +18 -18
- package/src/animation/core/controllers/Animation.ts +27 -0
- package/src/animation/core/controllers/FluidValue.ts +97 -0
- package/src/animation/core/controllers/RequestAnimationFrame.ts +13 -0
- package/src/animation/core/controllers/SpringAnimation.ts +218 -0
- package/src/animation/core/controllers/TimingAnimation.ts +152 -0
- package/src/animation/core/easing/Bezier.ts +146 -0
- package/src/animation/core/easing/Easing.ts +132 -0
- package/src/animation/core/helpers/camelCaseToKebabCase.ts +10 -0
- package/src/animation/core/helpers/getCleanProps.ts +16 -0
- package/src/animation/core/helpers/getCssValue.ts +60 -0
- package/src/animation/core/helpers/index.ts +5 -0
- package/src/animation/core/helpers/isDefined.ts +14 -0
- package/src/animation/core/helpers/isFluidValue.ts +11 -0
- package/src/animation/core/index.ts +16 -0
- package/src/animation/core/interpolation/Colors.ts +232 -0
- package/src/animation/core/interpolation/Interpolation.ts +395 -0
- package/src/animation/core/interpolation/__tests__/Colors.test.tsx +35 -0
- package/src/animation/core/react/fluid.ts +197 -0
- package/src/animation/core/react/makeFluid.ts +294 -0
- package/src/animation/core/react/transforms.ts +90 -0
- package/src/animation/core/react/useFluidValue.ts +43 -0
- package/src/animation/core/react/useMount.ts +58 -0
- package/src/animation/core/types/animation.d.ts +56 -0
- package/src/animation/core/types/common.d.ts +4 -0
- package/src/animation/core/types/fluid.d.ts +38 -0
- package/src/animation/{animationType.ts → lib/animationType.ts} +17 -17
- package/src/animation/{getInitialConfig.ts → lib/getInitialConfig.ts} +61 -61
- package/src/animation/lib/index.ts +12 -0
- package/src/animation/{interpolation.ts → lib/interpolation.ts} +47 -48
- package/src/animation/{modules → lib/modules}/AnimatedBlock.ts +8 -8
- package/src/animation/{modules → lib/modules}/AnimatedImage.ts +8 -8
- package/src/animation/{modules → lib/modules}/AnimatedInline.ts +8 -8
- package/src/animation/lib/modules/MountedBlock.tsx +51 -0
- package/src/animation/{modules → lib/modules}/ScrollableBlock.tsx +68 -69
- package/src/animation/{modules → lib/modules}/TransitionBlock.tsx +28 -29
- package/src/animation/{modules → lib/modules}/index.ts +6 -6
- package/src/animation/{useAnimatedValue.ts → lib/useAnimatedValue.ts} +60 -71
- package/src/animation/{useMountedValue.ts → lib/useMountedValue.ts} +18 -19
- package/src/gestures/controllers/DragGesture.ts +178 -177
- package/src/gestures/controllers/Gesture.ts +54 -54
- package/src/gestures/controllers/MouseMoveGesture.ts +111 -111
- package/src/gestures/controllers/ScrollGesture.ts +107 -107
- package/src/gestures/controllers/WheelGesture.ts +123 -123
- package/src/gestures/controllers/index.ts +4 -4
- package/src/gestures/{eventAttacher.ts → helpers/eventAttacher.ts} +67 -67
- package/src/gestures/helpers/index.ts +1 -0
- package/src/gestures/{math.ts → helpers/math.ts} +120 -120
- package/src/gestures/{withDefault.ts → helpers/withDefault.ts} +3 -3
- package/src/gestures/hooks/index.ts +5 -5
- package/src/gestures/hooks/useDrag.ts +14 -14
- package/src/gestures/hooks/useGesture.ts +38 -38
- package/src/gestures/hooks/useMouseMove.ts +11 -11
- package/src/gestures/hooks/useRecognizer.ts +59 -59
- package/src/gestures/hooks/useScroll.ts +11 -11
- package/src/gestures/hooks/useWheel.ts +11 -11
- package/src/gestures/{types.ts → types/index.d.ts} +49 -49
- package/src/hooks/index.ts +3 -3
- package/src/hooks/useMeasure.ts +132 -133
- package/src/hooks/useOutsideClick.ts +36 -36
- package/src/hooks/useWindowDimension.ts +58 -59
- package/src/index.ts +42 -5
- package/src/utils/delay.ts +9 -9
- package/src/utils/index.ts +1 -2
- package/tsconfig.json +24 -25
- package/src/animation/index.ts +0 -10
- package/src/animation/modules/MountedBlock.tsx +0 -25
- package/src/gestures/index.ts +0 -2
- package/src/utils/isDefined.ts +0 -4
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useRef,
|
|
3
|
+
useMemo,
|
|
4
|
+
useLayoutEffect,
|
|
5
|
+
createElement,
|
|
6
|
+
forwardRef,
|
|
7
|
+
RefObject,
|
|
8
|
+
} from 'react';
|
|
9
|
+
|
|
10
|
+
import { SpringAnimation } from '../controllers/SpringAnimation';
|
|
11
|
+
import { TimingAnimation } from '../controllers/TimingAnimation';
|
|
12
|
+
import {
|
|
13
|
+
ExtrapolateConfig,
|
|
14
|
+
canInterpolate,
|
|
15
|
+
interpolateNumbers,
|
|
16
|
+
} from '../interpolation/Interpolation';
|
|
17
|
+
import { getTransform, isTransformKey } from './transforms';
|
|
18
|
+
import {
|
|
19
|
+
isDefined,
|
|
20
|
+
getCleanProps,
|
|
21
|
+
getCssValue,
|
|
22
|
+
camelCaseToKebabCase,
|
|
23
|
+
isFluidValue,
|
|
24
|
+
} from '../helpers';
|
|
25
|
+
import { FluidValue } from '../controllers/FluidValue';
|
|
26
|
+
|
|
27
|
+
import type { ResultType, FluidValueConfig, Length } from '../types/animation';
|
|
28
|
+
import type { FluidProps, WrappedComponentOrTag } from '../types/fluid';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Higher-order component to make any component animatable.
|
|
32
|
+
*
|
|
33
|
+
* This function takes a React component or an HTML tag and returns a new component
|
|
34
|
+
* that can smoothly transition between states using fluid animations. It enhances
|
|
35
|
+
* the user experience by adding dynamic and engaging animations to the wrapped component.
|
|
36
|
+
*
|
|
37
|
+
* @param WrapperComponent - The React component or HTML tag to be wrapped with animation functionality.
|
|
38
|
+
* @returns - A new component with added animation capabilities.
|
|
39
|
+
*
|
|
40
|
+
* The returned component uses fluid animations to smoothly transition between different
|
|
41
|
+
* states. It supports both style and prop animations, handling transforms and other
|
|
42
|
+
* properties seamlessly. The component ensures that animations are efficiently applied
|
|
43
|
+
* and updated based on the current state and configuration of fluid values.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* const AnimatedDiv = makeFluid('div');
|
|
47
|
+
*
|
|
48
|
+
* const MyComponent = () => {
|
|
49
|
+
* const opacity = useAnimatedValue(1)
|
|
50
|
+
* return (
|
|
51
|
+
* <AnimatedDiv style={{ opacity: opacity.value }}>
|
|
52
|
+
* Hello, world!
|
|
53
|
+
* </AnimatedDiv>
|
|
54
|
+
* )};
|
|
55
|
+
*/
|
|
56
|
+
export function makeFluid<C extends WrappedComponentOrTag>(
|
|
57
|
+
WrapperComponent: C
|
|
58
|
+
) {
|
|
59
|
+
return forwardRef((givenProps: FluidProps<C>, givenRef: any) => {
|
|
60
|
+
const instanceRef = useRef<any>(null);
|
|
61
|
+
|
|
62
|
+
const transformStyleRef = useRef<Record<string, Length>>({});
|
|
63
|
+
|
|
64
|
+
const { fluids, nonFluids } = useMemo(() => {
|
|
65
|
+
const { style, ...props } = givenProps;
|
|
66
|
+
const fluidStyle = getFluids('style', style);
|
|
67
|
+
const fluidProps = getFluids('props', props);
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
fluids: [...fluidStyle.fluids, ...fluidProps.fluids],
|
|
71
|
+
nonFluids: [...fluidStyle.nonFluids, ...fluidProps.nonFluids],
|
|
72
|
+
};
|
|
73
|
+
}, [givenProps]);
|
|
74
|
+
|
|
75
|
+
const applyAnimationValues = ({
|
|
76
|
+
isTransform,
|
|
77
|
+
propertyType,
|
|
78
|
+
property,
|
|
79
|
+
value,
|
|
80
|
+
}: {
|
|
81
|
+
isTransform: boolean;
|
|
82
|
+
propertyType: 'style' | 'props';
|
|
83
|
+
property: string;
|
|
84
|
+
value: Length;
|
|
85
|
+
}) => {
|
|
86
|
+
if (!instanceRef.current) return;
|
|
87
|
+
|
|
88
|
+
if (propertyType === 'style') {
|
|
89
|
+
if (isTransform) {
|
|
90
|
+
transformStyleRef.current[property] = value;
|
|
91
|
+
instanceRef.current.style.transform = getTransform(
|
|
92
|
+
transformStyleRef.current
|
|
93
|
+
);
|
|
94
|
+
} else {
|
|
95
|
+
instanceRef.current.style[property] = getCssValue(property, value);
|
|
96
|
+
}
|
|
97
|
+
} else if (propertyType === 'props') {
|
|
98
|
+
instanceRef.current.setAttribute(camelCaseToKebabCase(property), value);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
useLayoutEffect(() => {
|
|
103
|
+
nonFluids.forEach(({ isTransform, property, propertyType, value }) =>
|
|
104
|
+
applyAnimationValues({
|
|
105
|
+
isTransform,
|
|
106
|
+
property,
|
|
107
|
+
propertyType,
|
|
108
|
+
value: value as number,
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
}, [nonFluids]);
|
|
112
|
+
|
|
113
|
+
useLayoutEffect(() => {
|
|
114
|
+
const subscribers: any = [];
|
|
115
|
+
|
|
116
|
+
fluids.forEach((f) => {
|
|
117
|
+
const { value: fluidValue, propertyType, property, isTransform } = f;
|
|
118
|
+
const { _subscribe, _value, _currentValue, _config } = fluidValue;
|
|
119
|
+
|
|
120
|
+
const interpolationOutputRange: string[] = [];
|
|
121
|
+
const generateAnimation = animationObjectGenerator(_config);
|
|
122
|
+
let animation: any = null;
|
|
123
|
+
|
|
124
|
+
const onFrame = (value: number) => {
|
|
125
|
+
_currentValue.current = value;
|
|
126
|
+
|
|
127
|
+
const updatedValue: number = fluidValue.isInterpolation
|
|
128
|
+
? interpolateNumbers(
|
|
129
|
+
value,
|
|
130
|
+
fluidValue.interpolationConfig.inputRange,
|
|
131
|
+
fluidValue.interpolationConfig.outputRange,
|
|
132
|
+
fluidValue.interpolationConfig.extrapolateConfig
|
|
133
|
+
)
|
|
134
|
+
: value;
|
|
135
|
+
|
|
136
|
+
applyAnimationValues({
|
|
137
|
+
isTransform,
|
|
138
|
+
propertyType,
|
|
139
|
+
property,
|
|
140
|
+
value: updatedValue,
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const onUpdate = (
|
|
145
|
+
value: Length,
|
|
146
|
+
config?: FluidValueConfig,
|
|
147
|
+
callback?: (value: ResultType) => void
|
|
148
|
+
) => {
|
|
149
|
+
if (canInterpolate(_value, value)) {
|
|
150
|
+
const previousAnimation = animation;
|
|
151
|
+
|
|
152
|
+
if (previousAnimation._value !== value) {
|
|
153
|
+
animation.stop();
|
|
154
|
+
|
|
155
|
+
animation = generateAnimation(
|
|
156
|
+
previousAnimation._position,
|
|
157
|
+
config
|
|
158
|
+
);
|
|
159
|
+
config?.onStart && config.onStart(previousAnimation._position);
|
|
160
|
+
|
|
161
|
+
if (typeof value === 'string') {
|
|
162
|
+
if (!interpolationOutputRange.includes(_value as string)) {
|
|
163
|
+
interpolationOutputRange.push(_value as string);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (!interpolationOutputRange.includes(value)) {
|
|
167
|
+
interpolationOutputRange.push(value);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
fluidValue.isInterpolation = true;
|
|
171
|
+
fluidValue.interpolationConfig = {
|
|
172
|
+
inputRange: interpolationOutputRange.map((_, i) => i),
|
|
173
|
+
outputRange: interpolationOutputRange,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
animation.start({
|
|
178
|
+
toValue:
|
|
179
|
+
typeof value === 'string'
|
|
180
|
+
? interpolationOutputRange.indexOf(value)
|
|
181
|
+
: value,
|
|
182
|
+
onFrame,
|
|
183
|
+
previousAnimation,
|
|
184
|
+
onEnd: callback,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
if (typeof value !== typeof _value) {
|
|
189
|
+
throw new Error(
|
|
190
|
+
`Cannot assign ${typeof value} to animated ${typeof _value}`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
applyAnimationValues({
|
|
195
|
+
isTransform,
|
|
196
|
+
propertyType,
|
|
197
|
+
property,
|
|
198
|
+
value,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
animation = generateAnimation(typeof _value === 'string' ? 0 : _value);
|
|
204
|
+
applyAnimationValues({
|
|
205
|
+
isTransform,
|
|
206
|
+
propertyType,
|
|
207
|
+
property,
|
|
208
|
+
value: _value,
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const subscribe = _subscribe(onUpdate, property, Date.now());
|
|
212
|
+
subscribers.push(subscribe);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
return () => {
|
|
216
|
+
subscribers.forEach((subscriber: () => void) => subscriber());
|
|
217
|
+
};
|
|
218
|
+
}, []);
|
|
219
|
+
|
|
220
|
+
return createElement(WrapperComponent, {
|
|
221
|
+
...getCleanProps(givenProps),
|
|
222
|
+
ref: combineRefs(instanceRef, givenRef),
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function combineRefs(
|
|
228
|
+
...refs: Array<RefObject<any> | ((element: HTMLElement) => void)>
|
|
229
|
+
) {
|
|
230
|
+
return function applyRef(element: HTMLElement) {
|
|
231
|
+
refs.forEach((ref) => {
|
|
232
|
+
if (!ref) return;
|
|
233
|
+
if (typeof ref === 'function') {
|
|
234
|
+
ref(element);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if ('current' in ref) (ref.current as HTMLElement) = element;
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function animationObjectGenerator(defaultConfig?: FluidValueConfig) {
|
|
243
|
+
return (value: number, config?: FluidValueConfig) => {
|
|
244
|
+
const animationConfig = { ...defaultConfig, ...config };
|
|
245
|
+
|
|
246
|
+
const Animation =
|
|
247
|
+
isDefined(animationConfig?.duration) || animationConfig?.immediate
|
|
248
|
+
? TimingAnimation
|
|
249
|
+
: SpringAnimation;
|
|
250
|
+
|
|
251
|
+
return new Animation({
|
|
252
|
+
initialPosition: value,
|
|
253
|
+
config: animationConfig,
|
|
254
|
+
});
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
type InterpolationValue = {
|
|
259
|
+
isInterpolation: boolean;
|
|
260
|
+
interpolationConfig: {
|
|
261
|
+
inputRange: Array<number>;
|
|
262
|
+
outputRange: Array<number | string>;
|
|
263
|
+
extrapolateConfig?: ExtrapolateConfig;
|
|
264
|
+
};
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
type Fluid = {
|
|
268
|
+
isTransform: boolean;
|
|
269
|
+
property: string;
|
|
270
|
+
propertyType: 'style' | 'props';
|
|
271
|
+
value: FluidValue & InterpolationValue;
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
type NonFluid = Omit<Fluid, 'value'> & { value: unknown };
|
|
275
|
+
|
|
276
|
+
function getFluids(
|
|
277
|
+
propertyType: Fluid['propertyType'],
|
|
278
|
+
props: Record<string, any> = {}
|
|
279
|
+
) {
|
|
280
|
+
return Object.entries(props).reduce(
|
|
281
|
+
(res, [property, value]) => {
|
|
282
|
+
const isTransform = propertyType === 'style' && isTransformKey(property);
|
|
283
|
+
|
|
284
|
+
if (isFluidValue(value)) {
|
|
285
|
+
res.fluids.push({ isTransform, property, propertyType, value });
|
|
286
|
+
} else {
|
|
287
|
+
res.nonFluids.push({ isTransform, property, propertyType, value });
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return res;
|
|
291
|
+
},
|
|
292
|
+
{ fluids: [], nonFluids: [] } as { fluids: Fluid[]; nonFluids: NonFluid[] }
|
|
293
|
+
);
|
|
294
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export const styleTrasformKeys = [
|
|
2
|
+
'translate',
|
|
3
|
+
'translateX',
|
|
4
|
+
'translateY',
|
|
5
|
+
'translateZ',
|
|
6
|
+
'scale',
|
|
7
|
+
'scaleX',
|
|
8
|
+
'scaleY',
|
|
9
|
+
'scaleZ',
|
|
10
|
+
'rotate',
|
|
11
|
+
'rotateX',
|
|
12
|
+
'rotateY',
|
|
13
|
+
'rotateZ',
|
|
14
|
+
'skew',
|
|
15
|
+
'skewX',
|
|
16
|
+
'skewY',
|
|
17
|
+
] as const;
|
|
18
|
+
|
|
19
|
+
function splitCSSValueAndUnit(value: string) {
|
|
20
|
+
const valueMatch = value.match(/(-)?(\d+.)?\d+/g);
|
|
21
|
+
const unitMatch = value.match(
|
|
22
|
+
/px|rem|em|ex|%|cm|mm|in|pt|pc|ch|vh|vw|vmin|vmax/
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
value: Number(valueMatch),
|
|
27
|
+
unit: unitMatch && unitMatch[0],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// get unit of transform style property
|
|
32
|
+
function getValueUnit(property: string, value: string) {
|
|
33
|
+
let unit;
|
|
34
|
+
|
|
35
|
+
const splitValue = splitCSSValueAndUnit(String(value)).value;
|
|
36
|
+
const splitUnit = splitCSSValueAndUnit(String(value)).unit;
|
|
37
|
+
|
|
38
|
+
// if string value is passed with unit then split it
|
|
39
|
+
if (splitUnit) {
|
|
40
|
+
return { value: splitValue, unit: splitUnit };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (property.includes('translate') || property.includes('perspective')) {
|
|
44
|
+
unit = 'px';
|
|
45
|
+
} else if (property.includes('scale')) {
|
|
46
|
+
unit = '';
|
|
47
|
+
} else if (property.includes('rotate') || property.includes('skew')) {
|
|
48
|
+
unit = 'deg';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { value, unit };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getTransformValueWithUnits(property: string, value: string) {
|
|
55
|
+
const valueUnit = getValueUnit(property, value);
|
|
56
|
+
|
|
57
|
+
if (
|
|
58
|
+
property.includes('X') ||
|
|
59
|
+
property.includes('Y') ||
|
|
60
|
+
property.includes('Z') ||
|
|
61
|
+
property.includes('perspective') ||
|
|
62
|
+
property.includes('rotate') ||
|
|
63
|
+
property.includes('skew')
|
|
64
|
+
) {
|
|
65
|
+
// axis value
|
|
66
|
+
return `${property}(${valueUnit.value}${valueUnit.unit})`;
|
|
67
|
+
} else if (property.includes('translate') || property.indexOf('scale')) {
|
|
68
|
+
// two parameter value
|
|
69
|
+
return `${property}(${valueUnit.value}${valueUnit.unit}, ${valueUnit.value}${valueUnit.unit})`;
|
|
70
|
+
} else {
|
|
71
|
+
throw new Error(`Error! Property '${property}' cannot be transformed`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* getTransform function returns transform string from style object
|
|
77
|
+
*/
|
|
78
|
+
export function getTransform(style: Record<string, any>) {
|
|
79
|
+
return Object.entries(style)
|
|
80
|
+
.map(([prop, value]) => getTransformValueWithUnits(prop, value))
|
|
81
|
+
.reduce(
|
|
82
|
+
(transform: string, value: string) => (transform += ` ${value}`),
|
|
83
|
+
''
|
|
84
|
+
)
|
|
85
|
+
.trim();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function isTransformKey(key: string) {
|
|
89
|
+
return (styleTrasformKeys as readonly string[]).includes(key);
|
|
90
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useMemo, useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
import { FluidValue } from '../controllers/FluidValue';
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
FluidValueConfig,
|
|
7
|
+
Length,
|
|
8
|
+
AssignValue,
|
|
9
|
+
OnUpdateCallback,
|
|
10
|
+
} from '../types/animation';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* useFluidValue
|
|
14
|
+
*
|
|
15
|
+
* @param value - initial value
|
|
16
|
+
* @param config - the config object for `FluidValue`
|
|
17
|
+
*/
|
|
18
|
+
export const useFluidValue = (
|
|
19
|
+
value: Length,
|
|
20
|
+
config?: FluidValueConfig
|
|
21
|
+
): [
|
|
22
|
+
FluidValue,
|
|
23
|
+
(
|
|
24
|
+
updateValue: AssignValue,
|
|
25
|
+
config?: FluidValueConfig,
|
|
26
|
+
callback?: OnUpdateCallback
|
|
27
|
+
) => void
|
|
28
|
+
] => {
|
|
29
|
+
const fluid = useMemo(() => new FluidValue(value, config), []);
|
|
30
|
+
|
|
31
|
+
const setFluid = useCallback(
|
|
32
|
+
(
|
|
33
|
+
updateValue: AssignValue,
|
|
34
|
+
config?: FluidValueConfig,
|
|
35
|
+
callback?: OnUpdateCallback
|
|
36
|
+
) => {
|
|
37
|
+
fluid.setValue(updateValue, config, callback);
|
|
38
|
+
},
|
|
39
|
+
[]
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
return [fluid, setFluid];
|
|
43
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useState, useRef, useLayoutEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import { useFluidValue } from './useFluidValue';
|
|
4
|
+
import { FluidValue } from '../controllers/FluidValue';
|
|
5
|
+
|
|
6
|
+
import type { AssignValue, FluidValueConfig } from '../types/animation';
|
|
7
|
+
|
|
8
|
+
export interface UseMountConfig {
|
|
9
|
+
from: number;
|
|
10
|
+
enter: number | AssignValue;
|
|
11
|
+
exit: number | AssignValue;
|
|
12
|
+
enterConfig?: FluidValueConfig;
|
|
13
|
+
exitConfig?: FluidValueConfig;
|
|
14
|
+
config?: FluidValueConfig;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* `useMount`
|
|
19
|
+
*
|
|
20
|
+
* applies mounting and unmounting of a component according to state change
|
|
21
|
+
* applying transitions
|
|
22
|
+
*
|
|
23
|
+
* @param state - boolean indicating mount state of a component
|
|
24
|
+
* @param config - the config object `UseMountConfig`
|
|
25
|
+
*/
|
|
26
|
+
export const useMount = (state: boolean, config: UseMountConfig) => {
|
|
27
|
+
const [mounted, setMounted] = useState(false);
|
|
28
|
+
const {
|
|
29
|
+
from,
|
|
30
|
+
enter,
|
|
31
|
+
exit,
|
|
32
|
+
config: innerConfig,
|
|
33
|
+
enterConfig,
|
|
34
|
+
exitConfig,
|
|
35
|
+
} = useRef(config).current;
|
|
36
|
+
const [animation, setAnimation] = useFluidValue(from, innerConfig);
|
|
37
|
+
|
|
38
|
+
useLayoutEffect(() => {
|
|
39
|
+
if (state) {
|
|
40
|
+
setMounted(true);
|
|
41
|
+
queueMicrotask(() => setAnimation(enter, enterConfig));
|
|
42
|
+
} else {
|
|
43
|
+
setAnimation(
|
|
44
|
+
exit,
|
|
45
|
+
exitConfig,
|
|
46
|
+
function ({ finished }: { finished: boolean }) {
|
|
47
|
+
if (finished) {
|
|
48
|
+
setMounted(false);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}, [state]);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
callback: (animation: FluidValue, mounted: boolean) => React.ReactNode
|
|
57
|
+
) => callback(animation, mounted);
|
|
58
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Fn } from './common';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base unit which is accepted by `FluidValue`
|
|
5
|
+
*/
|
|
6
|
+
export type Length = number | string;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Object passed as an argument on `onRest` function
|
|
10
|
+
*/
|
|
11
|
+
export type ResultType = { finished: boolean; value: number };
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Function read by `animated` hoc to determine whether it
|
|
15
|
+
* can be animated or not
|
|
16
|
+
*/
|
|
17
|
+
export type SubscribeFn = (
|
|
18
|
+
onUpdate: OnUpdateFn,
|
|
19
|
+
property: string,
|
|
20
|
+
uuid: number
|
|
21
|
+
) => void;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Configuration object for `FluidValue`
|
|
25
|
+
*/
|
|
26
|
+
export interface FluidValueConfig {
|
|
27
|
+
mass?: number;
|
|
28
|
+
tension?: number;
|
|
29
|
+
friction?: number;
|
|
30
|
+
duration?: number;
|
|
31
|
+
easing?: Fn<number, number>;
|
|
32
|
+
immediate?: boolean;
|
|
33
|
+
delay?: number;
|
|
34
|
+
restDistance?: number;
|
|
35
|
+
onChange?: Fn<number, void>;
|
|
36
|
+
onRest?: Fn<ResultType, void>;
|
|
37
|
+
onStart?: Fn<number, void>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Object which can be assigned to animate
|
|
42
|
+
*/
|
|
43
|
+
export type AssignValue =
|
|
44
|
+
| Length
|
|
45
|
+
| Fn<(next: Length, config?: FluidValueConfig) => Promise<any>, void>;
|
|
46
|
+
|
|
47
|
+
export type OnUpdateCallback = Fn<ResultType, void>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Function to start the animation (it starts the already subscribed animation)
|
|
51
|
+
*/
|
|
52
|
+
export type OnUpdateFn = (
|
|
53
|
+
updatedValue: AssignValue,
|
|
54
|
+
config?: FluidValueConfig,
|
|
55
|
+
callback?: OnUpdateCallback
|
|
56
|
+
) => void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CSSProperties,
|
|
3
|
+
HTMLAttributes,
|
|
4
|
+
SVGAttributes,
|
|
5
|
+
ComponentType,
|
|
6
|
+
} from 'react';
|
|
7
|
+
|
|
8
|
+
import { FluidValue } from '../controllers/FluidValue';
|
|
9
|
+
import { styleTrasformKeys } from '../react/transforms';
|
|
10
|
+
|
|
11
|
+
export type FluidTypes = 'spring' | 'timing';
|
|
12
|
+
|
|
13
|
+
export type FluidCSSProperties = {
|
|
14
|
+
[key in keyof CSSProperties]: CSSProperties[key];
|
|
15
|
+
} & {
|
|
16
|
+
[key in (typeof styleTrasformKeys)[number]]?: number | string | FluidValue;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type FluidHTMLAttributes<T> = {
|
|
20
|
+
[property in keyof HTMLAttributes<T>]:
|
|
21
|
+
| HTMLAttributes<T>[property]
|
|
22
|
+
| FluidValue;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type FluidSVGAttributes<T> = {
|
|
26
|
+
[property in keyof SVGAttributes<T>]: SVGAttributes<T>[property] | FluidValue;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type FluidProps<T> = Omit<
|
|
30
|
+
FluidHTMLAttributes<T> & FluidSVGAttributes<T>,
|
|
31
|
+
'style'
|
|
32
|
+
> & {
|
|
33
|
+
style?: FluidCSSProperties;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type WrappedComponentOrTag =
|
|
37
|
+
| ComponentType<HTMLAttributes<HTMLElement>>
|
|
38
|
+
| keyof JSX.IntrinsicElements;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { getInitialConfig } from './getInitialConfig';
|
|
2
|
-
|
|
3
|
-
export const AnimationConfigUtils = {
|
|
4
|
-
ELASTIC: getInitialConfig('elastic'),
|
|
5
|
-
BOUNCE: getInitialConfig('bounce'),
|
|
6
|
-
EASE: getInitialConfig('ease'),
|
|
7
|
-
STIFF: getInitialConfig('stiff'),
|
|
8
|
-
WOOBLE: getInitialConfig('wooble'),
|
|
9
|
-
EASE_IN: getInitialConfig('easein'),
|
|
10
|
-
EASE_OUT: getInitialConfig('easeout'),
|
|
11
|
-
EASE_IN_OUT: getInitialConfig('easeinout'),
|
|
12
|
-
POWER1: getInitialConfig('power1'),
|
|
13
|
-
POWER2: getInitialConfig('power2'),
|
|
14
|
-
POWER3: getInitialConfig('power3'),
|
|
15
|
-
POWER4: getInitialConfig('power4'),
|
|
16
|
-
LINEAR: getInitialConfig('linear'),
|
|
17
|
-
};
|
|
1
|
+
import { getInitialConfig } from './getInitialConfig';
|
|
2
|
+
|
|
3
|
+
export const AnimationConfigUtils = {
|
|
4
|
+
ELASTIC: getInitialConfig('elastic'),
|
|
5
|
+
BOUNCE: getInitialConfig('bounce'),
|
|
6
|
+
EASE: getInitialConfig('ease'),
|
|
7
|
+
STIFF: getInitialConfig('stiff'),
|
|
8
|
+
WOOBLE: getInitialConfig('wooble'),
|
|
9
|
+
EASE_IN: getInitialConfig('easein'),
|
|
10
|
+
EASE_OUT: getInitialConfig('easeout'),
|
|
11
|
+
EASE_IN_OUT: getInitialConfig('easeinout'),
|
|
12
|
+
POWER1: getInitialConfig('power1'),
|
|
13
|
+
POWER2: getInitialConfig('power2'),
|
|
14
|
+
POWER3: getInitialConfig('power3'),
|
|
15
|
+
POWER4: getInitialConfig('power4'),
|
|
16
|
+
LINEAR: getInitialConfig('linear'),
|
|
17
|
+
};
|