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

Add withClamp documentation #5381

Merged
merged 76 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
4db2024
Create new page
Nov 16, 2023
c1c8c9b
Init interactive playground
Nov 21, 2023
6df2a34
Extract options
Nov 21, 2023
d2e4843
Update example
Nov 21, 2023
7860c95
Add reset options
Nov 21, 2023
f4d330c
More text
Nov 21, 2023
b464940
Apply suggestions from code review
Latropos Nov 27, 2023
62309f2
Update docs/src/theme/DocSidebarItems/index.js
Latropos Nov 27, 2023
15d06b7
Update docs
Nov 27, 2023
d8caa80
run Prettier
Nov 27, 2023
974bf28
change to Capital Letter - commit 1
Nov 29, 2023
340d7f5
change to capital letter - commit 2
Nov 29, 2023
90f5171
Fix NDEBUG macro not present in Release builds (#5366)
tjzel Nov 20, 2023
05c97df
Add type tests for AnimatedRef and fix Animated Components regression…
tjzel Nov 20, 2023
a2f428b
Use install_modules_dependencies (#5334)
piaskowyk Nov 21, 2023
088beab
[ios] Only add HERMES_ENABLE_DEBUGGER flag to debug builds (#5383)
gabrieldonadel Nov 21, 2023
72065eb
Add option to omit `initData` in babel plugin (#5266)
bartlomiejbloniarz Nov 21, 2023
eb84611
add some of the missing mock methods to BaseAnimationMock (#5384)
ugurcanatas Nov 21, 2023
462c4ad
Fix undefined `config` in podspec (#5390)
piaskowyk Nov 21, 2023
1fcd43f
Remove `console.log` (#5393)
bartlomiejbloniarz Nov 22, 2023
14ee12f
Run worklets on separate thread (#5192)
tomekzaw Nov 22, 2023
b796e55
Add pretty layout animation example (#5391)
kacperkapusciak Nov 23, 2023
b5ca98d
Fix `entering` in web LA (#5401)
m-bert Nov 23, 2023
35ae2ff
[Web] Fix hiding component with `entering` on every render (#5278)
tjzel Nov 23, 2023
85dcbbc
Bump react-native-screens (#5397)
Latropos Nov 23, 2023
133c55c
Fix entering flickers in web LA (#5405)
m-bert Nov 24, 2023
96823e6
Allow different flavors JS and App (#5404)
tjzel Nov 24, 2023
5bdf738
Fix clamp with prefixes on android (#5408)
Latropos Nov 24, 2023
25cc859
Remove `hasReducedMotion` (#5407)
m-bert Nov 24, 2023
3f9161e
Change example name to Habits (#5410)
kacperkapusciak Nov 24, 2023
a628b2c
Make forceUpdate optional (#5415)
piaskowyk Nov 27, 2023
3fa67f2
Add setFeatureFlag method (#5422)
piaskowyk Nov 28, 2023
245e5a8
Release 3.6.0 (#5411)
piaskowyk Nov 28, 2023
a6158ca
Update compatibility table for 0.73 (#5418)
tomekzaw Nov 28, 2023
05975d0
Change "Reset cache" to "Reset Metro bundler cache" in docs (#5417)
tomekzaw Nov 28, 2023
c2d8f0a
Rename components in compatibility table (#5427)
tomekzaw Nov 28, 2023
774190c
Remove include guard in REAKeyboardEventObserver.h (#5412)
tomekzaw Nov 28, 2023
292b629
Add TSDoc to public API (#5377)
kacperkapusciak Nov 29, 2023
789e9e6
Extract keyframe key construction to a function (#5376)
marmor157 Nov 29, 2023
63896d4
Deprecate old signature (#5433)
Latropos Nov 30, 2023
79745b4
Fix type of `_log` function (#5436)
tomekzaw Nov 30, 2023
99e3001
Rework `interpolate` documentation (#5398)
kacperkapusciak Nov 30, 2023
c4bdfa0
[docs] Fix web support for layout animations (#5439)
kacperkapusciak Nov 30, 2023
356751e
Update PlatformChecker.ts (#5440)
tomekzaw Nov 30, 2023
4b1269e
Fix ScrollView missing properties (#5437)
tjzel Nov 30, 2023
54cf608
Add check for undefined style in LA Web (#5449)
m-bert Dec 1, 2023
a4bae16
Fix `exiting` on web (#5444)
m-bert Dec 1, 2023
59df751
Fix existing transform on web (#5451)
m-bert Dec 1, 2023
8e137ef
Fix keyframes crash (#5454)
m-bert Dec 1, 2023
4f928ac
Fix "Use of undeclared identifier 'debugger'" (#5450)
tomekzaw Dec 1, 2023
af01791
Fix calling `getBoundingClientRect` on `null` (#5462)
m-bert Dec 4, 2023
a189d62
Update habits example (#5453)
m-bert Dec 4, 2023
18e0564
Add build types to issue template (#5420)
tjzel Dec 4, 2023
00c356e
fix: correct typo in `interpolate.mdx` (#5441)
Code-Victor Dec 4, 2023
c4c2737
[doc] Minor grammar fix (#5467)
wodin Dec 5, 2023
4649f71
Remove dummy element on animation cancel (#5452)
m-bert Dec 6, 2023
d1daac4
Replace useRef with useState for useSharedValue (#5458)
amadeus Dec 6, 2023
08c76cd
Fix keyframe error 'Property '_this' doesn't exist' (#5457)
tjzel Dec 7, 2023
30945e2
Fix TS and ESLint in Examples (#5361)
marmor157 Dec 7, 2023
7b3adaa
Add warning about reduced motion in dev mode (#5479)
bartlomiejbloniarz Dec 8, 2023
d691af8
Fix transform in exiting animation (#5470)
m-bert Dec 11, 2023
65f3e7f
Improve reduced motion warning (#5487)
bartlomiejbloniarz Dec 11, 2023
6c31679
Add missing text and improve example
Dec 12, 2023
a247289
Merge branch 'main' into acynk/clamp-hoa-docs
Dec 14, 2023
4f280f3
Changes
Dec 14, 2023
406be71
Merge branch 'main' into acynk/clamp-hoa-docs
Dec 19, 2023
20952c7
Update docs/docs/animations/withClamp.mdx
Latropos Dec 19, 2023
eca40ff
Update docs/src/components/InteractivePlayground/useClampPlayground/E…
Latropos Dec 19, 2023
2cde97c
Update docs/src/components/InteractivePlayground/useClampPlayground/E…
Latropos Dec 19, 2023
cb1bb7b
[ios] Only add HERMES_ENABLE_DEBUGGER flag to debug builds (#5383)
gabrieldonadel Nov 21, 2023
7acf6b6
Fix undefined `config` in podspec (#5390)
piaskowyk Nov 21, 2023
da10b72
Add pretty layout animation example (#5391)
kacperkapusciak Nov 23, 2023
4dc5583
Merge remote-tracking branch 'refs/remotes/origin/acynk/clamp-hoa-doc…
Dec 19, 2023
735b1e8
Polish code
Dec 19, 2023
fdff34b
Fix `entering` in web LA (#5401)
m-bert Nov 23, 2023
2968895
Fix git issue
Dec 19, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions docs/docs/animations/withClamp.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
sidebar_position: 7
---

# withClamp

`withClamp` is an [animation modifier](/docs/fundamentals/glossary#animation-modifier) that lets you limit the scope of movement of your animation to make it stay within some predefined range.
Use it with [withSpring](/docs/animations/withSpring) animation.

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

<InteractivePlayground usePlayground={useClampPlayground} />

Latropos marked this conversation as resolved.
Show resolved Hide resolved
## Reference

```javascript
import { withClamp } from 'react-native-reanimated';

function App() {
sv.value = withClamp({ min: -1, max: 1 }, withSpring(0));
// ...
}
```

<details>
<summary>Type definitions</summary>

```typescript
type AnimatableValue = number | string | number[];

function withClamp<T extends number | string>(
config: {
min?: T;
max?: T;
},
clampedAnimation: T
): T;

enum ReduceMotion {
System = 'system',
Always = 'always',
Never = 'never',
}
```

</details>

### Arguments

#### `config`

An object with following properties:

| Name | Type Description |
| ---------------- | ---------------- | ------------------------------------------------ |
| min <Optional /> | `number` | The lowest value your animation can ever reach |
| max <Optional /> | `number` | The greatest value your animation can ever reach |

#### `animation`

The spring animation you want to clamp.

Latropos marked this conversation as resolved.
Show resolved Hide resolved
Latropos marked this conversation as resolved.
Show resolved Hide resolved
```typescript
const clampedStyleWithDelay = useAnimatedStyle(() => {
return {
width: withClamp({ min: 0, max: 100 }, withSpring(randomWidth.value)),
};
});
```

### Returns

`withClamp` returns an [animation object](/docs/fundamentals/glossary#animation-object). 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).

<div className="platform-compatibility">

| Android | iOS | Web |
| ------- | --- | --- |
| ✅ | ✅ | ✅ |

</div>
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"react-draggable": "^4.4.5",
"react-native": "^0.71.4",
"react-native-gesture-handler": "^2.13.2",
"react-native-reanimated": "^3.6.0-nightly-20231010-4a507b2c4",
"react-native-reanimated": "^3.6.0-nightly-20231120-1eb2acaa0",
"react-native-svg": "^13.14.0",
"react-native-web": "^0.18.12",
"source-map": "^0.7.4",
Expand Down
64 changes: 64 additions & 0 deletions docs/src/components/InteractivePlayground/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import styles from './styles.module.css';
import BrowserOnly from '@docusaurus/BrowserOnly';
import CodeBlock from '@theme/CodeBlock';

import useClampPlayground from './useClampPlayground';
import useSpringPlayground from './useSpringPlayground';
import useTimingPlayground from './useTimingPlayground';
import useInterpolateColorPlayground from './useInterpolateColorPlayground';
Expand All @@ -23,6 +24,7 @@ import {
} from '@mui/material';

export {
useClampPlayground,
useSpringPlayground,
useTimingPlayground,
useInterpolateColorPlayground,
Expand Down Expand Up @@ -99,6 +101,16 @@ interface RangeProps {
label: string;
}

interface DoubleRangeProps {
min: number;
max: number;
step?: number;
value: [number, number];
onChange: [Dispatch<number>, Dispatch<number>];
label: string;
color?: 'yellow' | 'green';
}

const RangeStyling = {
color: 'var(--swm-interactive-slider)', // color of the main path of slider
'& .MuiSlider-thumb': {
Expand Down Expand Up @@ -162,6 +174,58 @@ export function Range({
);
}

export function DoubleRange({
min,
max,
value,
onChange,
label,
step = 1,
color,
}: DoubleRangeProps) {
return (
<>
<div className={styles.row}>
<label>{label}</label>
{[0, 1].map((idx) => {
return (
<TextField
type="number"
hiddenLabel
size="small"
key={`${label}${idx}`}
inputProps={{ min: min, max: max, step: step }}
sx={TextFieldStyling}
value={value[idx]}
Latropos marked this conversation as resolved.
Show resolved Hide resolved
onChange={(e) => {
const newValue = parseFloat(e.target.value);
onChange[idx](
newValue > max[idx]
? max[idx]
: newValue <= min[idx]
? min[idx]
: newValue
);
}}
/>
);
})}
</div>
<Slider
min={min}
max={max}
step={step}
value={value}
sx={RangeStyling}
onChange={(e: Event & { target: HTMLInputElement }) => {
onChange[0](parseFloat(e.target.value[0]));
onChange[1](parseFloat(e.target.value[1]));
}}
/>
</>
);
}

interface CheckboxProps {
value: boolean;
onChange: Dispatch<boolean>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import React from 'react';
import { StyleSheet, View, Text, ViewStyle } from 'react-native';
import Animated, {
useAnimatedStyle,
withClamp,
withSpring,
withRepeat,
withSequence,
withTiming,
withDelay,
} 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;

interface ClampPlaygroundOptions {
lowerBound: number;
upperBound: number;
}

interface Props {
options: ClampPlaygroundOptions;
}
export default function App({ options }: Props) {
const config = {
damping: 3,
};

const clampedStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateX: withClamp(
{ min: options.lowerBound, max: options.upperBound },
withRepeat(
withSequence(
withDelay(2000, withSpring(BOX_STOP, config)),
withTiming(BOX_START, { duration: 0 })
),
-1,
true
)
),
},
],
};
});
const defaultStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateX: withRepeat(
withSequence(
withDelay(2000, withSpring(200, config)),
withTiming(0, { duration: 0 })
),
-1,
true
),
},
],
};
});

function Example({
testedStyle,
description,
showClampMarkers,
}: {
testedStyle: ViewStyle;
description: string;
showClampMarkers: boolean;
}) {
return (
<View
style={{
width: FRAME_WIDTH,
height: FRAME_HEIGHT,
}}>
<View>
{showClampMarkers && (
<View
style={[
styles.clampMarker,
{
marginTop: (BOX_SIZE - FRAME_HEIGHT) / 2,
borderRightWidth: 2,
width: options.lowerBound,
},
]}
/>
)}
</View>
<Animated.View style={[styles.movingBox, testedStyle]}>
<Text style={styles.text}>{description}</Text>
</Animated.View>
<View>
{showClampMarkers && (
<View
style={[
styles.clampMarker,
{
borderLeftWidth: 2,
marginTop: -(BOX_SIZE + FRAME_HEIGHT) / 2,
width: FRAME_WIDTH - options.upperBound - BOX_SIZE,
alignSelf: 'flex-end',
},
]}
/>
)}
</View>
</View>
);
}

return (
<View style={styles.container}>
<Example
testedStyle={clampedStyle}
description="Clamped spring"
showClampMarkers={true}
/>
<Example
testedStyle={defaultStyle}
description="Default spring"
showClampMarkers={false}
/>
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
padding: CLAMP_MARKER_HEIGHT,
paddingBottom: 0,
},
clampMarker: {
position: 'absolute',
margin: 0,
opacity: 0.5,
height: 100,
borderColor: '#b58df1',
borderStyle: 'dashed',
},
movingBox: {
height: BOX_SIZE,
width: BOX_SIZE,
borderColor: '#b58df1',
borderRadius: 20,
borderWidth: 1,
alignItems: 'center',
justifyContent: 'center',
},
text: {
color: '#b58df1',
textTransform: 'uppercase',
fontWeight: 'bold',
textAlign: 'center',
},
});
Loading