Add simultaneous handlers support to make the component usable within a ScrollView (#273)
* Set react-native-gesture-handler dependency to ^1.10.0 * Ignore JetBrains IDE settings * Add simultaneousHandlers and onGestureHandlerRef props * Remove onGestureHandlerRef as it turned out it is not necessary * Add simultaneousHandler prop to README
This commit is contained in:
parent
0567117b2b
commit
1c0da9a29a
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
node_modules/**/*
|
||||
/lib
|
||||
coverage/
|
||||
.idea
|
||||
|
||||
74
README.md
74
README.md
@ -31,39 +31,41 @@ yarn add react-native-draggable-flatlist
|
||||
|
||||
All props are spread onto underlying [FlatList](https://facebook.github.io/react-native/docs/flatlist)
|
||||
|
||||
| Name | Type | Description |
|
||||
| :------------------------- | :---------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `data` | `T[]` | Items to be rendered. |
|
||||
| `horizontal` | `boolean` | Orientation of list. |
|
||||
| `renderItem` | `(params: { item: T, index: number, drag: () => void, isActive: boolean}) => JSX.Element` | Call `drag` when the row should become active (i.e. in an `onLongPress` or `onPressIn`). |
|
||||
| `renderPlaceholder` | `(params: { item: T, index: number }) => React.ReactNode` | Component to be rendered underneath the hovering component |
|
||||
| `keyExtractor` | `(item: T, index: number) => string` | Unique key for each item |
|
||||
| `onDragBegin` | `(index: number) => void` | Called when row becomes active. |
|
||||
| `onRelease` | `(index: number) => void` | Called when active row touch ends. |
|
||||
| `onDragEnd` | `(params: { data: T[], from: number, to: number }) => void` | Called after animation has completed. Returns updated ordering of `data` |
|
||||
| `autoscrollThreshold` | `number` | Distance from edge of container where list begins to autoscroll when dragging. |
|
||||
| `autoscrollSpeed` | `number` | Determines how fast the list autoscrolls. |
|
||||
| `onRef` | `(ref: React.RefObject<DraggableFlatList<T>>) => void` | Returns underlying Animated FlatList ref. |
|
||||
| `animationConfig` | `Partial<Animated.SpringConfig>` | Configure list animations. See [reanimated spring config](https://github.com/software-mansion/react-native-reanimated/blob/master/react-native-reanimated.d.ts#L112-L120) |
|
||||
| `activationDistance` | `number` | Distance a finger must travel before the gesture handler activates. Useful when using a draggable list within a TabNavigator so that the list does not capture navigator gestures. |
|
||||
| `layoutInvalidationKey` | `string` | Changing this value forces a remeasure of all item layouts. Useful if item size/ordering updates after initial mount. |
|
||||
| `onScrollOffsetChange` | `(offset: number) => void` | Called with scroll offset. Stand-in for `onScroll`. |
|
||||
| `onPlaceholderIndexChange` | `(index: number) => void` | Called when the index of the placeholder changes |
|
||||
| `dragItemOverflow` | `boolean` | If true, dragged item follows finger beyond list boundary. |
|
||||
| `dragHitSlop` | `object: {top: number, left: number, bottom: number, right: number}` | Enables control over what part of the connected view area can be used to begin recognizing the gesture. Numbers need to be non-positive (only possible to reduce responsive area). |
|
||||
| `debug` | `boolean` | Enables debug logging and animation debugger. |
|
||||
| `containerStyle` | `StyleProp<ViewStyle>` | Style of the main component. |
|
||||
| Name | Type | Description |
|
||||
| :------------------------- | :---------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `data` | `T[]` | Items to be rendered. |
|
||||
| `horizontal` | `boolean` | Orientation of list. |
|
||||
| `renderItem` | `(params: { item: T, index: number, drag: () => void, isActive: boolean}) => JSX.Element` | Call `drag` when the row should become active (i.e. in an `onLongPress` or `onPressIn`). |
|
||||
| `renderPlaceholder` | `(params: { item: T, index: number }) => React.ReactNode` | Component to be rendered underneath the hovering component |
|
||||
| `keyExtractor` | `(item: T, index: number) => string` | Unique key for each item |
|
||||
| `onDragBegin` | `(index: number) => void` | Called when row becomes active. |
|
||||
| `onRelease` | `(index: number) => void` | Called when active row touch ends. |
|
||||
| `onDragEnd` | `(params: { data: T[], from: number, to: number }) => void` | Called after animation has completed. Returns updated ordering of `data` |
|
||||
| `autoscrollThreshold` | `number` | Distance from edge of container where list begins to autoscroll when dragging. |
|
||||
| `autoscrollSpeed` | `number` | Determines how fast the list autoscrolls. |
|
||||
| `onRef` | `(ref: React.RefObject<DraggableFlatList<T>>) => void` | Returns underlying Animated FlatList ref. |
|
||||
| `animationConfig` | `Partial<Animated.SpringConfig>` | Configure list animations. See [reanimated spring config](https://github.com/software-mansion/react-native-reanimated/blob/master/react-native-reanimated.d.ts#L112-L120) |
|
||||
| `activationDistance` | `number` | Distance a finger must travel before the gesture handler activates. Useful when using a draggable list within a TabNavigator so that the list does not capture navigator gestures. |
|
||||
| `layoutInvalidationKey` | `string` | Changing this value forces a remeasure of all item layouts. Useful if item size/ordering updates after initial mount. |
|
||||
| `onScrollOffsetChange` | `(offset: number) => void` | Called with scroll offset. Stand-in for `onScroll`. |
|
||||
| `onPlaceholderIndexChange` | `(index: number) => void` | Called when the index of the placeholder changes |
|
||||
| `dragItemOverflow` | `boolean` | If true, dragged item follows finger beyond list boundary. |
|
||||
| `dragHitSlop` | `object: {top: number, left: number, bottom: number, right: number}` | Enables control over what part of the connected view area can be used to begin recognizing the gesture. Numbers need to be non-positive (only possible to reduce responsive area). |
|
||||
| `debug` | `boolean` | Enables debug logging and animation debugger. |
|
||||
| `containerStyle` | `StyleProp<ViewStyle>` | Style of the main component. |
|
||||
| `simultaneousHandlers` | `React.Ref<any>` or `React.Ref<any>[]` | References to other gesture handlers, mainly useful when using this component within a `ScrollView`. See [Cross handler interactions](https://docs.swmansion.com/react-native-gesture-handler/docs/interactions/). |
|
||||
|
||||
## Example
|
||||
|
||||
Example snack: https://snack.expo.io/@computerjazz/rndfl-example <br />
|
||||
Example snack with scale effect on hover: https://snack.expo.io/@computerjazz/rndfl-dragwithhovereffect
|
||||
|
||||
```typescript
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { View, TouchableOpacity, Text } from 'react-native';
|
||||
import React, { useState, useCallback } from "react";
|
||||
import { View, TouchableOpacity, Text } from "react-native";
|
||||
import DraggableFlatList, {
|
||||
RenderItemParams,
|
||||
} from 'react-native-draggable-flatlist';
|
||||
RenderItemParams
|
||||
} from "react-native-draggable-flatlist";
|
||||
|
||||
const NUM_ITEMS = 10;
|
||||
|
||||
@ -78,7 +80,7 @@ const exampleData: Item[] = [...Array(20)].map((d, index) => {
|
||||
return {
|
||||
key: `item-${backgroundColor}`,
|
||||
label: String(index),
|
||||
backgroundColor,
|
||||
backgroundColor
|
||||
};
|
||||
});
|
||||
|
||||
@ -97,17 +99,19 @@ function Example() {
|
||||
<TouchableOpacity
|
||||
style={{
|
||||
height: 100,
|
||||
backgroundColor: isActive ? 'red' : item.backgroundColor,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: isActive ? "red" : item.backgroundColor,
|
||||
alignItems: "center",
|
||||
justifyContent: "center"
|
||||
}}
|
||||
onLongPress={drag}>
|
||||
onLongPress={drag}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
color: 'white',
|
||||
fontSize: 32,
|
||||
}}>
|
||||
fontWeight: "bold",
|
||||
color: "white",
|
||||
fontSize: 32
|
||||
}}
|
||||
>
|
||||
{item.label}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
@ -58,7 +58,7 @@
|
||||
"pretty-quick": "^2.0.1",
|
||||
"react": "^16.13.1",
|
||||
"react-native": "^0.61.5",
|
||||
"react-native-gesture-handler": "^1.5.3",
|
||||
"react-native-gesture-handler": "^1.10.0",
|
||||
"react-native-reanimated": "^1.13.0",
|
||||
"react-test-renderer": "~16.11.0",
|
||||
"typescript": "^3.7.3"
|
||||
|
||||
@ -113,6 +113,7 @@ export type DraggableFlatListProps<T> = Modify<
|
||||
onPlaceholderIndexChange?: (placeholderIndex: number) => void;
|
||||
containerStyle?: StyleProp<ViewStyle>;
|
||||
dragItemOverflow?: boolean;
|
||||
simultaneousHandlers?: React.Ref<any> | React.Ref<any>[];
|
||||
} & Partial<DefaultProps>
|
||||
>;
|
||||
|
||||
@ -1002,7 +1003,8 @@ class DraggableFlatList<T> extends React.Component<
|
||||
onScrollOffsetChange,
|
||||
renderPlaceholder,
|
||||
onPlaceholderIndexChange,
|
||||
containerStyle
|
||||
containerStyle,
|
||||
simultaneousHandlers
|
||||
} = this.props;
|
||||
|
||||
const { hoverComponent } = this.state;
|
||||
@ -1019,6 +1021,7 @@ class DraggableFlatList<T> extends React.Component<
|
||||
hitSlop={dragHitSlop}
|
||||
onGestureEvent={this.onPanGestureEvent}
|
||||
onHandlerStateChange={this.onPanStateChange}
|
||||
simultaneousHandlers={simultaneousHandlers}
|
||||
{...dynamicProps}
|
||||
>
|
||||
<Animated.View
|
||||
@ -1040,6 +1043,7 @@ class DraggableFlatList<T> extends React.Component<
|
||||
keyExtractor={this.keyExtractor}
|
||||
onScroll={this.onScroll}
|
||||
scrollEventThrottle={1}
|
||||
simultaneousHandlers={simultaneousHandlers}
|
||||
/>
|
||||
{!!hoverComponent && this.renderHoverComponent()}
|
||||
<Animated.Code dependencies={[]}>
|
||||
|
||||
34
yarn.lock
34
yarn.lock
@ -2331,6 +2331,13 @@ create-react-class@^15.6.3:
|
||||
loose-envify "^1.3.1"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
cross-fetch@^3.0.4:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.6.tgz#3a4040bc8941e653e0e9cf17f29ebcd177d3365c"
|
||||
integrity sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ==
|
||||
dependencies:
|
||||
node-fetch "2.6.1"
|
||||
|
||||
cross-spawn@^5.0.1, cross-spawn@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
|
||||
@ -2877,6 +2884,19 @@ fbjs@^1.0.0:
|
||||
setimmediate "^1.0.5"
|
||||
ua-parser-js "^0.7.18"
|
||||
|
||||
fbjs@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.0.tgz#0907067fb3f57a78f45d95f1eacffcacd623c165"
|
||||
integrity sha512-dJd4PiDOFuhe7vk4F80Mba83Vr2QuK86FoxtgPmzBqEJahncp+13YCmfoa53KHCo6OnlXLG7eeMWPfB5CrpVKg==
|
||||
dependencies:
|
||||
cross-fetch "^3.0.4"
|
||||
fbjs-css-vars "^1.0.0"
|
||||
loose-envify "^1.0.0"
|
||||
object-assign "^4.1.0"
|
||||
promise "^7.1.1"
|
||||
setimmediate "^1.0.5"
|
||||
ua-parser-js "^0.7.18"
|
||||
|
||||
figures@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
|
||||
@ -4848,6 +4868,11 @@ nice-try@^1.0.4:
|
||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||
|
||||
node-fetch@2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
|
||||
|
||||
node-fetch@^1.0.1:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
|
||||
@ -5471,12 +5496,13 @@ react-is@^17.0.1:
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339"
|
||||
integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==
|
||||
|
||||
react-native-gesture-handler@^1.5.3:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.8.0.tgz#18f61f51da50320f938957b0ee79bc58f47449dc"
|
||||
integrity sha512-E2FZa0qZ5Bi0Z8Jg4n9DaFomHvedSjwbO2DPmUUHYRy1lH2yxXUpSrqJd6yymu+Efzmjg2+JZzsjFYA2Iq8VEQ==
|
||||
react-native-gesture-handler@^1.10.0:
|
||||
version "1.10.3"
|
||||
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.10.3.tgz#942bbf2963bbf49fa79593600ee9d7b5dab3cfc0"
|
||||
integrity sha512-cBGMi1IEsIVMgoox4RvMx7V2r6bNKw0uR1Mu1o7NbuHS6BRSVLq0dP34l2ecnPlC+jpWd3le6Yg1nrdCjby2Mw==
|
||||
dependencies:
|
||||
"@egjs/hammerjs" "^2.0.17"
|
||||
fbjs "^3.0.0"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
invariant "^2.2.4"
|
||||
prop-types "^15.7.2"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user