Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding playground to withRepeat subpage #5917

Open
wants to merge 11 commits into
base: @xnameTM/fixing-details
Choose a base branch
from
4 changes: 4 additions & 0 deletions docs/docs/animations/withRepeat.mdx
Expand Up @@ -71,6 +71,10 @@ A function called on animation complete. In case the animation is cancelled, the

A parameter that determines how the animation responds to the device's reduced motion accessibility setting.

import { useRepeatPlayground } from '@site/src/components/InteractivePlayground';

<InteractivePlayground usePlayground={useRepeatPlayground} />

### Returns

`withRepeat` returns an [animation object](/docs/fundamentals/glossary#animation-object) which holds the current state of the animation. It can be either assigned directly to a [shared value](/docs/fundamentals/glossary#shared-value) or can be used as a value for a style object returned from [useAnimatedStyle](docs/core/useAnimatedStyle).
Expand Down
22 changes: 20 additions & 2 deletions docs/src/components/InteractivePlayground/index.tsx
Expand Up @@ -10,6 +10,7 @@ import ReducedMotionWarning from '../ReducedMotionWarning';
import useClampPlayground from './useClampPlayground';
import useSpringPlayground from './useSpringPlayground';
import useTimingPlayground from './useTimingPlayground';
import useRepeatPlayground from './useRepeatPlayground';
import useInterpolateColorPlayground from './useInterpolateColorPlayground';
import useAnimatedSensorPlayground from './useAnimatedSensorPlayground';
import useDecayPlayground from './useDecayPlayground';
Expand All @@ -30,6 +31,7 @@ export {
useClampPlayground,
useSpringPlayground,
useTimingPlayground,
useRepeatPlayground,
useInterpolateColorPlayground,
useAnimatedSensorPlayground,
useDecayPlayground,
Expand Down Expand Up @@ -136,6 +138,7 @@ interface RangeProps {
step?: number;
value: number;
onChange: Dispatch<number>;
disabled?: boolean;
label: string;
}

Expand All @@ -161,6 +164,18 @@ const RangeStyling = {
},
};

const DisabledRangeStyling = {
color: 'var(--swm-interactive-slider)', // color of the main path of slider
'& .MuiSlider-thumb': {
backgroundColor: '#ccc', //color of thumb
transform: 'translate(-50%, -40%)',
},
'& .MuiSlider-rail': {
color: 'var(--swm-interactive-slider-rail)', //color of the rail (remaining area of slider)
opacity: 1,
},
};

const TextFieldStyling = {
minWidth: 88,
'& .MuiInputBase-input': {
Expand All @@ -179,16 +194,18 @@ export function Range({
max,
value,
onChange,
disabled,
label,
step = 1,
}: RangeProps) {
return (
<>
<div className={styles.row}>
<label>{label}</label>
<label style={{ color: disabled ? '#aaa' : 'black' }}>{label}</label>
<TextField
type="number"
hiddenLabel
disabled={disabled}
size="small"
inputProps={{ min: min, max: max, step: step }}
sx={TextFieldStyling}
Expand All @@ -204,7 +221,8 @@ export function Range({
max={max}
step={step}
value={value}
sx={RangeStyling}
disabled={disabled}
sx={disabled ? DisabledRangeStyling : RangeStyling}
onChange={(e: Event & { target: HTMLInputElement }) =>
onChange(parseFloat(e.target.value))
}
Expand Down
@@ -0,0 +1,93 @@
import React, { useEffect } from 'react';
import { StyleSheet, View, Button } from 'react-native';
import Animated, {
useSharedValue,
useAnimatedStyle,
cancelAnimation,
ReduceMotion,
withTiming,
withRepeat,
} from 'react-native-reanimated';

interface Props {
options: {
numberOfReps: number;
reverse: boolean;
reduceMotion: ReduceMotion;
};
}

export default function App({ options }: Props) {
const offset = useSharedValue(0);
const [running, setRunning] = React.useState(false);

const animatedStyles = useAnimatedStyle(() => {
return {
transform: [{ translateX: offset.value }],
};
});

useEffect(() => {
cancelAnimation(offset);
offset.value = 0;
}, [options]);

const handlePress = () => {
if (running) {
cancelAnimation(offset);
setRunning(false);
return;
}

setRunning(true);
offset.value = 0;
offset.value = withRepeat(
withTiming(200, { duration: 1000 }),
options.numberOfReps,
options.reverse,
() => setRunning(false),
options.reduceMotion
);
};

return (
<View style={styles.container}>
<View style={[styles.wrapper]}>
<Animated.View style={[styles.box, animatedStyles]} />
</View>
<View style={styles.buttonWrapper}>
<Button onPress={handlePress} title={running ? 'Stop' : 'Start'} />
</View>
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
height: '100%',
marginTop: 64,
marginBottom: 34,
},
wrapper: {
flex: 1,
width: 300,
},
box: {
height: 100,
width: 100,
backgroundColor: '#b58df1',
borderRadius: 20,
cursor: 'grab',
alignItems: 'center',
justifyContent: 'center',
},
buttonWrapper: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginTop: 16,
},
});
@@ -0,0 +1,77 @@
import React, { useState } from 'react';
import Example from './Example';

import { Range, CheckboxOption, SelectOption, formatReduceMotion } from '..';
import { ReduceMotion } from 'react-native-reanimated';

const defaultConfig = {
numberOfReps: 2,
reverse: false,
reduceMotion: ReduceMotion.System,
};

const TIMING_OFFSET = 200;

export default function useRepeatPlayground() {
const [infinity, setInfinity] = useState(false);
const [numberOfReps, setNumberOfReps] = useState(defaultConfig.numberOfReps);
const [reverse, setReverse] = useState(defaultConfig.reverse);
const [reduceMotion, setReduceMotion] = useState(defaultConfig.reduceMotion);

const resetOptions = () => {
setNumberOfReps(() => defaultConfig.numberOfReps);
setReverse(() => defaultConfig.reverse);
setReduceMotion(() => defaultConfig.reduceMotion);
};

const code = `
withRepeat(
withTiming(${TIMING_OFFSET}, { duration: 1000 }),
${infinity ? -1 : numberOfReps},
${reverse},
() => {},
${formatReduceMotion(reduceMotion)},
)
`;

const controls = (
<>
<CheckboxOption
label="Infinity"
value={infinity}
onChange={setInfinity}
/>
<Range
label="Repetitions"
min={1}
max={10}
step={1}
disabled={infinity}
value={numberOfReps}
onChange={setNumberOfReps}
/>
<CheckboxOption label="Reverse" value={reverse} onChange={setReverse} />
<SelectOption
label="Reduce motion"
value={reduceMotion}
onChange={(option) => setReduceMotion(option as ReduceMotion)}
options={[ReduceMotion.System, ReduceMotion.Always, ReduceMotion.Never]}
/>
</>
);

return {
example: Example,
props: {
options: {
numberOfReps: infinity ? -1 : numberOfReps,
reverse,
reduceMotion,
},
},
controls,
code,
resetOptions,
additionalComponents: {},
};
}
1 change: 0 additions & 1 deletion docs/src/examples/SpringCarousel.tsx
Expand Up @@ -4,7 +4,6 @@ import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
SharedValue,
} from 'react-native-reanimated';

const INITIAL_OFFSET = 110;
Expand Down
1 change: 0 additions & 1 deletion docs/src/examples/SpringMassCompare.tsx
Expand Up @@ -5,7 +5,6 @@ import Animated, {
useAnimatedStyle,
withSpring,
withRepeat,
SharedValue,
} from 'react-native-reanimated';

const duration = 1800;
Expand Down
1 change: 0 additions & 1 deletion docs/src/examples/TimingEasingCompare.tsx
Expand Up @@ -6,7 +6,6 @@ import Animated, {
withTiming,
Easing,
withRepeat,
SharedValue,
} from 'react-native-reanimated';

const duration = 2000;
Expand Down
1 change: 0 additions & 1 deletion docs/src/examples/UseReducedMotion.tsx
@@ -1,7 +1,6 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import Animated, {
SharedValue,
useAnimatedStyle,
useReducedMotion,
useSharedValue,
Expand Down