diff --git a/cspell.json b/cspell.json index d9a0e979c9c..67d8fabce97 100644 --- a/cspell.json +++ b/cspell.json @@ -32,7 +32,12 @@ "pressable", "inout", "workletizes", - "worklets" + "worklets", + "runtimes", + "overdamped", + "automagically", + "threejs", + "nomalized" ], "ignorePaths": ["node_modules", "docs/src/components/Testimonials"], "useGitignore": true diff --git a/docs/docs/advanced/measure.mdx b/docs/docs/advanced/measure.mdx index e53d7b40ecd..4eb8b7ca35b 100644 --- a/docs/docs/advanced/measure.mdx +++ b/docs/docs/advanced/measure.mdx @@ -73,7 +73,7 @@ or returns `null` when the measurement couldn't be performed. import MeasureBasic from '@site/src/examples/MeasureBasic'; import MeasureBasicSrc from '!!raw-loader!@site/src/examples/MeasureBasic'; -} /> + ## Remarks diff --git a/docs/docs/advanced/setNativeProps.mdx b/docs/docs/advanced/setNativeProps.mdx index f54b8cf1510..e9869317554 100644 --- a/docs/docs/advanced/setNativeProps.mdx +++ b/docs/docs/advanced/setNativeProps.mdx @@ -63,7 +63,7 @@ An object with properties you want to update. These could be both style props (e import SetNativeProps from '@site/src/examples/SetNativeProps'; import SetNativePropsSrc from '!!raw-loader!@site/src/examples/SetNativeProps'; -} /> + ## Remarks diff --git a/docs/docs/advanced/useAnimatedReaction.mdx b/docs/docs/advanced/useAnimatedReaction.mdx index b1b0e0553c2..5fd02d7eb42 100644 --- a/docs/docs/advanced/useAnimatedReaction.mdx +++ b/docs/docs/advanced/useAnimatedReaction.mdx @@ -99,7 +99,7 @@ import AnimatedReactionMeasureSrc from '!!raw-loader!@site/src/examples/Animated } + component={AnimatedReactionMeasure} /> ## Remarks diff --git a/docs/docs/advanced/useFrameCallback.mdx b/docs/docs/advanced/useFrameCallback.mdx index 51b5eab8e65..c397205037f 100644 --- a/docs/docs/advanced/useFrameCallback.mdx +++ b/docs/docs/advanced/useFrameCallback.mdx @@ -11,7 +11,7 @@ import FrameCallbackSimpleSrc from '!!raw-loader!@site/src/examples/FrameCallbac } + component={FrameCallbackSimple} /> ## Reference @@ -87,7 +87,7 @@ import FrameCallbackDinoSrc from '!!raw-loader!@site/src/examples/FrameCallbackD } + component={FrameCallbackDino} label="Tap to jump" /> diff --git a/docs/docs/animations/withDecay.mdx b/docs/docs/animations/withDecay.mdx index 489a66ee0ea..277177cd8d0 100644 --- a/docs/docs/animations/withDecay.mdx +++ b/docs/docs/animations/withDecay.mdx @@ -11,7 +11,7 @@ import DecayBasicSrc from '!!raw-loader!@site/src/examples/DecayBasic'; } + component={DecayBasic} label="Grab and drag the square" /> @@ -62,6 +62,10 @@ enum ReduceMotion { The decay animation configuration. +import { useDecayPlayground } from '@site/src/components/InteractivePlayground'; + + + Available properties: | Name | Type | Default | Description | @@ -89,7 +93,7 @@ import DecayTrainSrc from '!!raw-loader!@site/src/examples/DecayTrain'; } + component={DecayTrain} label="Grab and drag the train" /> diff --git a/docs/docs/animations/withDelay.mdx b/docs/docs/animations/withDelay.mdx index 830b332c727..59cc3e8cfe7 100644 --- a/docs/docs/animations/withDelay.mdx +++ b/docs/docs/animations/withDelay.mdx @@ -61,7 +61,7 @@ A parameter that determines how the animation responds to the device's reduced m import DelayText from '@site/src/examples/DelayText'; import DelayTextSrc from '!!raw-loader!@site/src/examples/DelayText'; -} /> + ## Platform compatibility diff --git a/docs/docs/animations/withRepeat.mdx b/docs/docs/animations/withRepeat.mdx index 9801770bee9..105734e0f36 100644 --- a/docs/docs/animations/withRepeat.mdx +++ b/docs/docs/animations/withRepeat.mdx @@ -9,7 +9,7 @@ sidebar_position: 5 import RepeatBasic from '@site/src/examples/RepeatBasic'; import RepeatBasicSrc from '!!raw-loader!@site/src/examples/RepeatBasic'; -} /> + ## Reference @@ -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'; + + + ### 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). @@ -80,7 +84,7 @@ A parameter that determines how the animation responds to the device's reduced m import SequenceWobble from '@site/src/examples/SequenceWobble'; import SequenceWobbleSrc from '!!raw-loader!@site/src/examples/SequenceWobble'; -} /> + ## Remarks diff --git a/docs/docs/animations/withSequence.mdx b/docs/docs/animations/withSequence.mdx index 70dfa6ac6db..d0f12ac3a2d 100644 --- a/docs/docs/animations/withSequence.mdx +++ b/docs/docs/animations/withSequence.mdx @@ -9,7 +9,7 @@ sidebar_position: 4 import SequenceBasic from '@site/src/examples/SequenceBasic'; import SequenceBasicSrc from '!!raw-loader!@site/src/examples/SequenceBasic'; -} /> + ## Reference @@ -61,7 +61,7 @@ Any number of [animation objects](docs/fundamentals/glossary#animation-object) t import SequenceWobble from '@site/src/examples/SequenceWobble'; import SequenceWobbleSrc from '!!raw-loader!@site/src/examples/SequenceWobble'; -} /> + ## Platform compatibility diff --git a/docs/docs/animations/withSpring.mdx b/docs/docs/animations/withSpring.mdx index 176da1d1e3d..df37905e524 100644 --- a/docs/docs/animations/withSpring.mdx +++ b/docs/docs/animations/withSpring.mdx @@ -9,7 +9,7 @@ sidebar_position: 2 import SpringBasic from '@site/src/examples/SpringBasic'; import SpringBasicSrc from '!!raw-loader!@site/src/examples/SpringBasic'; -} /> + ## Reference @@ -116,7 +116,7 @@ A function called upon animation completion. If the animation is cancelled, the import SpringCarousel from '@site/src/examples/SpringCarousel'; import SpringCarouselSrc from '!!raw-loader!@site/src/examples/SpringCarousel'; -} /> + ## Remarks diff --git a/docs/docs/animations/withTiming.mdx b/docs/docs/animations/withTiming.mdx index d4f2626a8d6..90a932e7a1a 100644 --- a/docs/docs/animations/withTiming.mdx +++ b/docs/docs/animations/withTiming.mdx @@ -9,7 +9,7 @@ sidebar_position: 1 import TimingBasic from '@site/src/examples/TimingBasic'; import TimingBasicSrc from '!!raw-loader!@site/src/examples/TimingBasic'; -} /> + ## Reference @@ -84,7 +84,7 @@ import TimingEasingCompareSrc from '!!raw-loader!@site/src/examples/TimingEasing } + component={TimingEasingCompare} /> Reanimated provides a selection of ready-to-use easing functions in the `Easing` module. You can find a visualization of some common easing functions at [http://easings.net/](http://easings.net/). @@ -133,7 +133,7 @@ A function called upon animation completion. If the animation is cancelled, the import TimingTabs from '@site/src/examples/TimingTabs'; import TimingTabsSrc from '!!raw-loader!@site/src/examples/TimingTabs'; -} /> + ## Remarks diff --git a/docs/docs/core/cancelAnimation.mdx b/docs/docs/core/cancelAnimation.mdx index 697105c4f62..7e7dbfc16ea 100644 --- a/docs/docs/core/cancelAnimation.mdx +++ b/docs/docs/core/cancelAnimation.mdx @@ -47,7 +47,7 @@ The shared value of a running animation that you want to cancel. If no animation import CancelAnimation from '@site/src/examples/CancelAnimation'; import CancelAnimationSrc from '!!raw-loader!@site/src/examples/CancelAnimation'; -} /> + ## Remarks diff --git a/docs/docs/core/createAnimatedComponent.mdx b/docs/docs/core/createAnimatedComponent.mdx index 0e65504e940..e73232a6ea4 100644 --- a/docs/docs/core/createAnimatedComponent.mdx +++ b/docs/docs/core/createAnimatedComponent.mdx @@ -57,7 +57,7 @@ import CreateAnimatedComponentSrc from '!!raw-loader!@site/src/examples/CreateAn } + component={CreateAnimatedComponent} showCode /> diff --git a/docs/docs/core/useAnimatedProps.mdx b/docs/docs/core/useAnimatedProps.mdx index b6973c32f83..5d9d1380dfa 100644 --- a/docs/docs/core/useAnimatedProps.mdx +++ b/docs/docs/core/useAnimatedProps.mdx @@ -80,7 +80,7 @@ import AnimatedPropAdapterSrc from '!!raw-loader!@site/src/examples/AnimatedProp import AnimatingProps from '@site/src/examples/AnimatingProps'; import AnimatingPropsSrc from '!!raw-loader!@site/src/examples/AnimatingProps'; -} /> + ## Remarks diff --git a/docs/docs/core/useAnimatedStyle.mdx b/docs/docs/core/useAnimatedStyle.mdx index 291d607c8d9..0cecb52874f 100644 --- a/docs/docs/core/useAnimatedStyle.mdx +++ b/docs/docs/core/useAnimatedStyle.mdx @@ -71,7 +71,7 @@ import AnimatingStylesSrc from '!!raw-loader!@site/src/examples/AnimatingStyles' } + component={AnimatingStyles} showCode /> diff --git a/docs/docs/core/useDerivedValue.mdx b/docs/docs/core/useDerivedValue.mdx index 9e075635a0c..d20452a8273 100644 --- a/docs/docs/core/useDerivedValue.mdx +++ b/docs/docs/core/useDerivedValue.mdx @@ -54,7 +54,7 @@ Only relevant when using Reanimated [without the Babel plugin on the Web](https: import DerivedValue from '@site/src/examples/DerivedValue'; import DerivedValueSrc from '!!raw-loader!@site/src/examples/DerivedValue'; -} /> + ## Remarks diff --git a/docs/docs/core/useSharedValue.mdx b/docs/docs/core/useSharedValue.mdx index 32f3eff87ca..70d2b7ec82d 100644 --- a/docs/docs/core/useSharedValue.mdx +++ b/docs/docs/core/useSharedValue.mdx @@ -61,7 +61,7 @@ Values stored in shared values can be accessed and modified by their `.value` pr import SharedValue from '@site/src/examples/SharedValue'; import SharedValueSrc from '!!raw-loader!@site/src/examples/SharedValue'; -} showCode /> + ## Remarks diff --git a/docs/docs/device/useReducedMotion.mdx b/docs/docs/device/useReducedMotion.mdx index f5700087d2c..6d0beb9a63e 100644 --- a/docs/docs/device/useReducedMotion.mdx +++ b/docs/docs/device/useReducedMotion.mdx @@ -34,10 +34,7 @@ function App() { import UseReducedMotion from '@site/src/examples/UseReducedMotion'; import UseReducedMotionSrc from '!!raw-loader!@site/src/examples/UseReducedMotion'; -} -/> + ## Remarks diff --git a/docs/docs/fundamentals/animating-styles-and-props.mdx b/docs/docs/fundamentals/animating-styles-and-props.mdx index ccfd333ed56..971b6df277f 100644 --- a/docs/docs/fundamentals/animating-styles-and-props.mdx +++ b/docs/docs/fundamentals/animating-styles-and-props.mdx @@ -65,7 +65,7 @@ import AnimatingStylesSrc from '!!raw-loader!@site/src/examples/AnimatingStyles' You can see it in action in the example below: -} /> + ## Animating props @@ -119,7 +119,7 @@ In a function which `useAnimatedProps` takes as an argument, we return an object Check out the full example below: -} /> + ## Summary diff --git a/docs/docs/fundamentals/applying-modifiers.mdx b/docs/docs/fundamentals/applying-modifiers.mdx index 758987a4252..101c1d0fdfd 100644 --- a/docs/docs/fundamentals/applying-modifiers.mdx +++ b/docs/docs/fundamentals/applying-modifiers.mdx @@ -21,7 +21,7 @@ import TimingSrc from '!!raw-loader!@site/src/examples/ApplyingModifiers/Timing' -} /> + ## Repeating an animation @@ -49,7 +49,7 @@ import RepeatSrc from '!!raw-loader!@site/src/examples/ApplyingModifiers/Repeat' When we run this code we can see that the box jiggles left to right between the set offset and a starting position. After the animation finishes the box doesn't come back to its initial place. It's not really how we imagined a shake animation but we'll get there in a second! -} /> + ## Running animations in a sequence @@ -75,7 +75,7 @@ import SequenceSrc from '!!raw-loader!@site/src/examples/ApplyingModifiers/Seque -} /> + ## Starting the animation with delay @@ -100,7 +100,7 @@ import DelaySrc from '!!raw-loader!@site/src/examples/ApplyingModifiers/Delay'; import Delay from '@site/src/examples/ApplyingModifiers/Delay'; -} /> + ## Summary diff --git a/docs/docs/fundamentals/customizing-animation.mdx b/docs/docs/fundamentals/customizing-animation.mdx index 591f4a84858..b9f5a4a7e99 100644 --- a/docs/docs/fundamentals/customizing-animation.mdx +++ b/docs/docs/fundamentals/customizing-animation.mdx @@ -34,7 +34,7 @@ import TimingEasingCompareSrc from '!!raw-loader!@site/src/examples/TimingEasing } + component={TimingEasingCompare} /> Reanimated comes with a handful of predefined easing functions. You can play around with them in the interactive playground below or check the full [`withTiming` API reference](/docs/animations/withTiming). @@ -69,10 +69,7 @@ The mass of a spring influences how hard is it to make an object move and to bri import SpringMassCompare from '@site/src/examples/SpringMassCompare'; import SpringMassCompareSrc from '!!raw-loader!@site/src/examples/SpringMassCompare'; -} -/> + Stiffness affects how bouncy the spring is. As an example, think about the difference between a steel spring (with very high stiffness) and a spring made out of soft plastic (with low stiffness). diff --git a/docs/docs/fundamentals/handling-gestures.mdx b/docs/docs/fundamentals/handling-gestures.mdx index c1751294769..05eba4efaaa 100644 --- a/docs/docs/fundamentals/handling-gestures.mdx +++ b/docs/docs/fundamentals/handling-gestures.mdx @@ -51,7 +51,7 @@ And that's it! Pretty straightforward, isn't it? Let's see it in the full glory } + component={TapGesture} label="Tap the circle" /> @@ -78,7 +78,7 @@ You can play around with the example below and see how the circle changes and re } + component={PanGesture} label="Grab and drag the circle" /> @@ -101,7 +101,7 @@ Play around and see how the square decelerates when let go with some speed! } + component={DecayBasic} label="Grab and release the square" /> diff --git a/docs/docs/fundamentals/your-first-animation.mdx b/docs/docs/fundamentals/your-first-animation.mdx index 4ba34f7c0dd..3f27d71dfd0 100644 --- a/docs/docs/fundamentals/your-first-animation.mdx +++ b/docs/docs/fundamentals/your-first-animation.mdx @@ -149,7 +149,7 @@ And voilĂ , we've made our first animation using Reanimated! You can see how it import FirstAnimation from '@site/src/examples/FirstAnimation'; import FirstAnimationSrc from '!!raw-loader!@site/src/examples/FirstAnimation'; -} /> + ## Summary diff --git a/docs/docs/scroll/scrollTo.mdx b/docs/docs/scroll/scrollTo.mdx index f88eda0516a..75dda7a7c68 100644 --- a/docs/docs/scroll/scrollTo.mdx +++ b/docs/docs/scroll/scrollTo.mdx @@ -67,7 +67,7 @@ Whether the scroll should be smooth (`true`) or instant (`false`). import ScrollTo from '@site/src/examples/ScrollTo'; import ScrollToSrc from '!!raw-loader!@site/src/examples/ScrollTo'; -} /> + ## Remarks diff --git a/docs/docs/scroll/useScrollViewOffset.mdx b/docs/docs/scroll/useScrollViewOffset.mdx index afba120c577..27ad7b7f7ee 100644 --- a/docs/docs/scroll/useScrollViewOffset.mdx +++ b/docs/docs/scroll/useScrollViewOffset.mdx @@ -55,7 +55,7 @@ import ScrollViewOffsetSrc from '!!raw-loader!@site/src/examples/ScrollViewOffse } + component={ScrollViewOffset} showCode /> diff --git a/docs/docs/threading/runOnJS.mdx b/docs/docs/threading/runOnJS.mdx index d5dc9ca829a..4993dee92b4 100644 --- a/docs/docs/threading/runOnJS.mdx +++ b/docs/docs/threading/runOnJS.mdx @@ -49,7 +49,7 @@ Don't forget to call the function returned from `runOnJS`. import RunOnJS from '@site/src/examples/RunOnJS'; import RunOnJSSrc from '!!raw-loader!@site/src/examples/RunOnJS'; -} /> + ## Remarks diff --git a/docs/docs/threading/runOnUI.mdx b/docs/docs/threading/runOnUI.mdx index ac165d4015a..c4c55cb4d7a 100644 --- a/docs/docs/threading/runOnUI.mdx +++ b/docs/docs/threading/runOnUI.mdx @@ -57,7 +57,7 @@ import RunOnUISrc from '!!raw-loader!@site/src/examples/RunOnUI'; } + component={RunOnUI} label="Tap each word" /> diff --git a/docs/docs/utilities/clamp.mdx b/docs/docs/utilities/clamp.mdx index 57e04651a75..3d19b9cca27 100644 --- a/docs/docs/utilities/clamp.mdx +++ b/docs/docs/utilities/clamp.mdx @@ -50,7 +50,7 @@ import ClampSrc from '!!raw-loader!@site/src/examples/Clamp'; } + component={Clamp} label="Grab and drag the square" /> diff --git a/docs/docs/utilities/interpolate.mdx b/docs/docs/utilities/interpolate.mdx index 173bc4ca692..6399a7ff093 100644 --- a/docs/docs/utilities/interpolate.mdx +++ b/docs/docs/utilities/interpolate.mdx @@ -9,7 +9,7 @@ sidebar_position: 1 import Interpolate from '@site/src/examples/Interpolate'; import InterpolateSrc from '!!raw-loader!@site/src/examples/Interpolate'; -} /> + ## Reference @@ -124,7 +124,7 @@ import InterpolateRotationSrc from '!!raw-loader!@site/src/examples/InterpolateR } + component={InterpolateRotation} label="Grab and drag any of the squares. The dashed lines indicate the range of the interpolation." /> diff --git a/docs/src/components/Hero/SelectedLabel/SelectionBox/index.tsx b/docs/src/components/Hero/SelectedLabel/SelectionBox/index.tsx index 96ee1b18548..15df95448d0 100644 --- a/docs/src/components/Hero/SelectedLabel/SelectionBox/index.tsx +++ b/docs/src/components/Hero/SelectedLabel/SelectionBox/index.tsx @@ -53,6 +53,8 @@ const SelectionBox: React.FC<{ children, isInteractive, }) => { + const touchPosition = { x: 0, y: 0 }; + const classList = getClassListByIdentifier( draggableIdentifier, isInteractive @@ -60,11 +62,33 @@ const SelectionBox: React.FC<{ return ( { + if ( + typeof event.movementX === 'number' && + typeof event.movementY === 'number' + ) + return; + + touchPosition.x = event.touches[0].clientX; + touchPosition.y = event.touches[0].clientY; + }} onDrag={(event: any) => { propagationFunction( - { x: event.movementX, y: event.movementY }, + { + x: event.movementX ?? event.touches[0].clientX - touchPosition.x, + y: event.movementY ?? event.touches[0].clientY - touchPosition.y, + }, draggableIdentifier ); + + if ( + typeof event.movementX === 'number' && + typeof event.movementY === 'number' + ) + return; + + touchPosition.x = event.touches[0].clientX; + touchPosition.y = event.touches[0].clientY; }} allowAnyClick={false} axis={'none'}> diff --git a/docs/src/components/Hero/StartScreen/styles.module.css b/docs/src/components/Hero/StartScreen/styles.module.css index 43c293112b6..0f3f025235f 100644 --- a/docs/src/components/Hero/StartScreen/styles.module.css +++ b/docs/src/components/Hero/StartScreen/styles.module.css @@ -43,6 +43,12 @@ color: var(--swm-landing-heading); } +@media (max-width: 996px) { + .subheadingLabel { + margin-top: 52px; + } +} + .buttonContainer { display: flex; justify-content: flex-start; diff --git a/docs/src/components/InteractiveExample/index.tsx b/docs/src/components/InteractiveExample/index.tsx index 2b7c991c3c0..14687ba89f3 100644 --- a/docs/src/components/InteractiveExample/index.tsx +++ b/docs/src/components/InteractiveExample/index.tsx @@ -69,7 +69,7 @@ function compileTSXtoJSX(tsxCode: string) { interface Props { src: string; - component: React.ReactNode; + component: React.FC<{ width?: number }>; label?: string; showCode?: boolean; // whether to show code by default larger?: boolean; // should the view be enlarged? @@ -83,7 +83,7 @@ enum Tab { export default function InteractiveExample({ src: tsxCode, - component, + component: Component, label, showCode = false, larger = false, @@ -92,17 +92,31 @@ export default function InteractiveExample({ const [key, setKey] = React.useState(0); const [tab, setTab] = React.useState(Tab.PREVIEW); const [jsxCode, setJsxCode] = React.useState(() => compileTSXtoJSX(tsxCode)); + const [width, setWidth] = React.useState(null); + const [showPreview, setShowPreview] = React.useState(!showCode); + + const interactiveExampleRef = React.useRef(null); const resetExample = () => { + if (interactiveExampleRef.current) { + setWidth(interactiveExampleRef.current.offsetWidth); + } setKey(key + 1); }; + React.useEffect(() => { + if (interactiveExampleRef.current) { + setWidth(interactiveExampleRef.current.offsetWidth); + } + }, [interactiveExampleRef.current]); + const prefersReducedMotion = useReducedMotion(); return ( Loading...}> {() => (
@@ -155,7 +169,9 @@ export default function InteractiveExample({
{tab === Tab.PREVIEW ? ( <> - {component} + + {width !== null && } +
{ - example: JSX.Element; + example: React.FC<{ width?: number }>; + props?: Record; code: string; controls: string; resetOptions: () => {}; @@ -47,21 +52,39 @@ export default function InteractivePlayground( props: InteractivePlaygroundProps ) { const [key, setKey] = React.useState(0); + const [width, setWidth] = React.useState(null); - const { example, code, controls, resetOptions, additionalComponents } = - props.usePlayground(); + const interactiveExampleRef = React.useRef(null); + + const { + example: Example, + props: exampleProps, + code, + controls, + resetOptions, + additionalComponents, + } = props.usePlayground(); const resetExample = () => { + if (interactiveExampleRef.current) { + setWidth(interactiveExampleRef.current.offsetWidth); + } setKey(key + 1); resetOptions(); }; const prefersReducedMotion = useReducedMotion(); + React.useEffect(() => { + if (interactiveExampleRef.current) { + setWidth(interactiveExampleRef.current.offsetWidth); + } + }, [interactiveExampleRef.current]); + return ( Loading...
}> {() => ( -
+
{prefersReducedMotion && }
- {example} + + +
{additionalComponents?.section}
@@ -103,6 +128,7 @@ interface RangeProps { step?: number; value: number; onChange: Dispatch; + disabled?: boolean; label: string; } @@ -120,6 +146,19 @@ const RangeStyling = { color: 'var(--swm-interactive-slider)', // color of the main path of slider '& .MuiSlider-thumb': { backgroundColor: 'var(--swm-interactive-slider)', //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 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) @@ -145,16 +184,18 @@ export function Range({ max, value, onChange, + disabled, label, step = 1, }: RangeProps) { return ( <>
- + onChange(parseFloat(e.target.value)) } diff --git a/docs/src/components/InteractivePlayground/useAnimatedSensorPlayground/index.tsx b/docs/src/components/InteractivePlayground/useAnimatedSensorPlayground/index.tsx index dc976b43b04..d5c8aba22c1 100644 --- a/docs/src/components/InteractivePlayground/useAnimatedSensorPlayground/index.tsx +++ b/docs/src/components/InteractivePlayground/useAnimatedSensorPlayground/index.tsx @@ -224,12 +224,11 @@ export default function useAnimatedSensorPlayground() { GYROSCOPE: gyroscopeCode, }[sensorType]; - const example = useMemo(() => , [x, y, z]); - return { code, controls, - example, + example: Example, + props: { values: { x, y, z } }, resetOptions, }; } diff --git a/docs/src/components/InteractivePlayground/useClampPlayground/Example.tsx b/docs/src/components/InteractivePlayground/useClampPlayground/Example.tsx index 8a8be363e82..0b2cd42e188 100644 --- a/docs/src/components/InteractivePlayground/useClampPlayground/Example.tsx +++ b/docs/src/components/InteractivePlayground/useClampPlayground/Example.tsx @@ -11,10 +11,8 @@ import Animated, { } from 'react-native-reanimated'; const BOX_START = 0; -const BOX_STOP = 200; const BOX_SIZE = 80; -const FRAME_WIDTH = 400; const FRAME_HEIGHT = 100; const CLAMP_MARKER_HEIGHT = 40; @@ -25,8 +23,11 @@ interface ClampPlaygroundOptions { interface Props { options: ClampPlaygroundOptions; + width: number; } -export default function App({ options }: Props) { +export default function App({ width: FRAME_WIDTH, options }: Props) { + FRAME_WIDTH = FRAME_WIDTH - 50; + const config = { damping: 3, }; @@ -36,10 +37,16 @@ export default function App({ options }: Props) { transform: [ { translateX: withClamp( - { min: options.lowerBound, max: options.upperBound }, + { + min: (options.lowerBound / 400) * FRAME_WIDTH, + max: (options.upperBound / 400) * FRAME_WIDTH - BOX_SIZE, + }, withRepeat( withSequence( - withDelay(2000, withSpring(BOX_STOP, config)), + withDelay( + 2000, + withSpring((options.upperBound / 600) * FRAME_WIDTH, config) + ), withTiming(BOX_START, { duration: 0 }) ), -1, @@ -56,7 +63,10 @@ export default function App({ options }: Props) { { translateX: withRepeat( withSequence( - withDelay(2000, withSpring(200, config)), + withDelay( + 2000, + withSpring((options.upperBound / 600) * FRAME_WIDTH, config) + ), withTiming(0, { duration: 0 }) ), -1, @@ -90,7 +100,7 @@ export default function App({ options }: Props) { { marginTop: (BOX_SIZE - FRAME_HEIGHT) / 2, borderRightWidth: 2, - width: options.lowerBound, + width: (options.lowerBound / 400) * FRAME_WIDTH, }, ]} /> @@ -107,7 +117,7 @@ export default function App({ options }: Props) { { borderLeftWidth: 2, marginTop: -(BOX_SIZE + FRAME_HEIGHT) / 2, - width: FRAME_WIDTH - options.upperBound - BOX_SIZE, + width: FRAME_WIDTH - (options.upperBound / 400) * FRAME_WIDTH, alignSelf: 'flex-end', }, ]} @@ -141,6 +151,8 @@ const styles = StyleSheet.create({ alignItems: 'center', justifyContent: 'center', padding: CLAMP_MARKER_HEIGHT, + paddingLeft: '2rem', + paddingRight: '2rem', paddingBottom: 0, }, clampMarker: { diff --git a/docs/src/components/InteractivePlayground/useClampPlayground/index.tsx b/docs/src/components/InteractivePlayground/useClampPlayground/index.tsx index 137a8f2bbd9..271d60b597d 100644 --- a/docs/src/components/InteractivePlayground/useClampPlayground/index.tsx +++ b/docs/src/components/InteractivePlayground/useClampPlayground/index.tsx @@ -11,15 +11,6 @@ export default function useClampPlayground() { const [lowerBound, setLowerBound] = useState(initialState.lowerBound); const [upperBound, setUpperBound] = useState(initialState.upperBound); - const example = ( - - ); - const controls = ( & { + rubberBandFactor: number; + }; +} + +export default function App({ options }: Props) { + const offset = useSharedValue(0); + + const animatedStyles = useAnimatedStyle(() => { + return { + transform: [{ translateX: offset.value }], + }; + }); + + useEffect(() => { + cancelAnimation(offset); + offset.value = 0; + }, [options]); + + const pan = Gesture.Pan() + .onChange((event) => { + offset.value += event.changeX; + }) + .onFinalize((event) => { + offset.value = withDecay({ + velocity: event.velocityX, + ...(options as WithDecayConfig), + }); + }); + + return ( + + + + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + height: '100%', + marginTop: 64, + marginBottom: 34, + }, + wrapper: { + flex: 1, + width: '100%', + alignItems: 'center', + justifyContent: 'center', + }, + box: { + height: 100, + width: 100, + backgroundColor: '#b58df1', + borderRadius: 20, + cursor: 'grab', + alignItems: 'center', + justifyContent: 'center', + }, +}); diff --git a/docs/src/components/InteractivePlayground/useDecayPlayground/index.tsx b/docs/src/components/InteractivePlayground/useDecayPlayground/index.tsx new file mode 100644 index 00000000000..7752bf15eaf --- /dev/null +++ b/docs/src/components/InteractivePlayground/useDecayPlayground/index.tsx @@ -0,0 +1,126 @@ +import React, { useState } from 'react'; +import Example from './Example'; + +import { + Range, + CheckboxOption, + SelectOption, + formatReduceMotion, + DoubleRange, +} from '..'; +import { ReduceMotion, WithDecayConfig } from 'react-native-reanimated'; + +const defaultConfig: Omit & { + rubberBandFactor: number; +} = { + deceleration: 0.998, + clamp: [-300, 300], + velocityFactor: 1, + rubberBandEffect: true, + rubberBandFactor: 0.6, + reduceMotion: ReduceMotion.System, +}; + +export default function useDecayPlayground() { + const [deceleration, setDeceleration] = useState(defaultConfig.deceleration); + const [clampMin, setClampMin] = useState(defaultConfig.clamp[0]); + const [clampMax, setClampMax] = useState(defaultConfig.clamp[1]); + const [velocityFactor, setVelocityFactor] = useState( + defaultConfig.velocityFactor + ); + const [rubberBandEffect, setRubberBandEffect] = useState( + defaultConfig.rubberBandEffect + ); + const [rubberBandFactor, setRubberBandFactor] = useState( + defaultConfig.rubberBandFactor + ); + const [reduceMotion, setReduceMotion] = useState(defaultConfig.reduceMotion); + + const resetOptions = () => { + setDeceleration(() => defaultConfig.deceleration); + setClampMin(() => defaultConfig.clamp[0]); + setClampMax(() => defaultConfig.clamp[1]); + setVelocityFactor(() => defaultConfig.velocityFactor); + setRubberBandEffect(() => defaultConfig.rubberBandEffect); + setReduceMotion(() => defaultConfig.reduceMotion); + }; + + const code = ` + withDecay({ + velocity: event.velocityX, + deceleration: ${deceleration}, + clamp: [${clampMin}, ${clampMax}], + velocityFactor: ${velocityFactor}, + rubberBandEffect: ${rubberBandEffect}, + ${rubberBandEffect ? '' : '// '}rubberBandFactor: ${rubberBandFactor}, + reduceMotion: ${formatReduceMotion(reduceMotion)}, + }) + `; + + const controls = ( + <> + {/* Needed state-controlled Tabs and `TabItem` components from "@theme/Tabs" so I hacked them around with classes ;) */} + + + + + + setReduceMotion(option as ReduceMotion)} + options={[ReduceMotion.System, ReduceMotion.Always, ReduceMotion.Never]} + /> + + ); + + return { + example: Example, + props: { + options: { + deceleration, + clamp: [clampMin, clampMax], + velocityFactor, + rubberBandEffect, + rubberBandFactor, + reduceMotion, + }, + }, + controls, + code, + resetOptions, + additionalComponents: {}, + }; +} diff --git a/docs/src/components/InteractivePlayground/useInterpolateColorPlayground/ColorPicker/index.tsx b/docs/src/components/InteractivePlayground/useInterpolateColorPlayground/ColorPicker/index.tsx index 81b12ed78ba..f24426aec5c 100644 --- a/docs/src/components/InteractivePlayground/useInterpolateColorPlayground/ColorPicker/index.tsx +++ b/docs/src/components/InteractivePlayground/useInterpolateColorPlayground/ColorPicker/index.tsx @@ -19,7 +19,13 @@ const TextFieldStyling = { }, }; -const ColorPicker = ({ color, setColor, defaultValue, refreshKey }) => { +const ColorPicker = ({ + color, + setColor, + defaultValue, + refreshKey, + prevKeyRef, +}) => { const [inputColor, setInputColor] = useState(color); const resetOptionsHandler = () => { @@ -28,7 +34,10 @@ const ColorPicker = ({ color, setColor, defaultValue, refreshKey }) => { }; useEffect(() => { - resetOptionsHandler(); + if (prevKeyRef.current !== refreshKey) { + prevKeyRef.current = refreshKey; + resetOptionsHandler(); + } }, [refreshKey]); return ( diff --git a/docs/src/components/InteractivePlayground/useInterpolateColorPlayground/index.tsx b/docs/src/components/InteractivePlayground/useInterpolateColorPlayground/index.tsx index 7ed0c1ea32a..47a532db265 100644 --- a/docs/src/components/InteractivePlayground/useInterpolateColorPlayground/index.tsx +++ b/docs/src/components/InteractivePlayground/useInterpolateColorPlayground/index.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useRef, useEffect } from 'react'; import { CheckboxOption, Range, SelectOption } from '../'; import Example from './Example'; import styles from './styles.module.css'; @@ -32,6 +32,8 @@ export default function useInterpolateColorPlayground() { const isMobile = windowWidth < 600; const [key, setKey] = useState(0); + const prevRefreshKeyLeft = useRef(key); + const prevRefreshKeyRight = useRef(key); const [colorBarsSectionCollapsed, setColorBarsSectionCollapsed] = useState(true); @@ -112,25 +114,6 @@ export default function useInterpolateColorPlayground() { /> ); - const example = ( -
- - {!isMobile && colorBox} - - {isMobile && colorBox} -
- ); - const section = ( <> ); + function ExampleFC() { + return ( +
+ + {!isMobile && colorBox} + + {isMobile && colorBox} +
+ ); + } + return { - example, + example: ExampleFC, controls, code, resetOptions, diff --git a/docs/src/components/InteractivePlayground/useRepeatPlayground/Example.tsx b/docs/src/components/InteractivePlayground/useRepeatPlayground/Example.tsx new file mode 100644 index 00000000000..83782aafe2c --- /dev/null +++ b/docs/src/components/InteractivePlayground/useRepeatPlayground/Example.tsx @@ -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 ( + + + + + +