Compare commits
14 Commits
improve-pe
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4e44a01a9 | ||
|
|
46e39a30ae | ||
|
|
0c08b861ae | ||
|
|
60336ebe26 | ||
|
|
20b1208da3 | ||
|
|
cd3b89c4d0 | ||
|
|
a1ec06e9ae | ||
|
|
8b3b9ef625 | ||
|
|
d706ec915e | ||
|
|
575abd8383 | ||
|
|
f49f45228e | ||
|
|
477c767e01 | ||
|
|
759a2eac3e | ||
|
|
d494d2f76a |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
.DS_Store
|
||||
*.log
|
||||
node_modules
|
||||
*.idea
|
||||
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Tim Gibadullin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
11
README.md
11
README.md
@ -31,8 +31,15 @@ npm i react-native-sortable-list --save
|
||||
- **contentContainerStyle?** (Object, Array) these styles will be applied to the inner scroll view content container
|
||||
- **innerContainerStyle?** (Object, Array) these styles will be applied to the inner scroll view content container, excluding the header and footer
|
||||
- **horizontal?** (boolean) when true, the SortableList's children are arranged horizontally in a row instead of vertically in a column. The default value is false.
|
||||
- **showsVerticalScrollIndicator** (boolean) when false, the vertical scroll indicator will not be visible. The default value is true.
|
||||
- **showsHorizontalScrollIndicator** (boolean) when false, the horizontal scroll indicator will not be visible. The default value is true.
|
||||
- **sortingEnabled?** (boolean) when false, rows are not sortable. The default value is true.
|
||||
- **scrollEnabled?** (boolean) when false, the content does not scrollable. The default value is true.
|
||||
- **keyboardShouldPersistTaps** (string)<br />
|
||||
Determines when the keyboard should stay visible after a tap.
|
||||
- 'never' (the default), tapping outside of the focused text input when the keyboard is up dismisses the keyboard. When this happens, children won't receive the tap.
|
||||
- 'always', the keyboard will not dismiss automatically, and the scroll view will not catch taps, but children of the scroll view can catch taps.
|
||||
- 'handled', the keyboard will not dismiss automatically when the tap was handled by a children, (or captured by an ancestor.<br/>
|
||||
- **manuallyActivateRows?** (bool) whether you intend to use the `toggleRowActive` method to activate a row or use the out of box solution.
|
||||
- **autoscrollAreaSize?** (number) determines the height for vertical list and the width for horizontal list of the area at the begining and the end of the list that will trigger autoscrolling. Defaults to 60.<br />
|
||||
- **rowActivationTime?** (number) determines time delay in ms before pressed row becomes active. Defaults to 200 ms.<br />
|
||||
@ -54,8 +61,8 @@ Called when rows were reordered, takes an array of rows keys of the next rows or
|
||||
`(key) => void`<br />
|
||||
Called when a row was activated (user long tapped).
|
||||
- **onReleaseRow?** (function)<br />
|
||||
`(key) => void`<br />
|
||||
Called when the active row was released.
|
||||
`(key, currentOrder) => void`<br />
|
||||
Called when the active row was released. Returns the key and the new list order.
|
||||
- **onPressRow?** (function)<br />
|
||||
`(key) => void`<br />
|
||||
Called when a row was pressed.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-sortable-list",
|
||||
"version": "0.0.21",
|
||||
"version": "0.0.24",
|
||||
"description": "React Native Sortable List component",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
|
||||
14
src/Row.js
14
src/Row.js
@ -1,6 +1,6 @@
|
||||
import React, {Component, cloneElement} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Animated, PanResponder, StyleSheet} from 'react-native';
|
||||
import {Animated, PanResponder, StyleSheet, ViewPropTypes} from 'react-native';
|
||||
import {shallowEqual} from './utils';
|
||||
|
||||
export default class Row extends Component {
|
||||
@ -9,7 +9,7 @@ export default class Row extends Component {
|
||||
animated: PropTypes.bool,
|
||||
disabled: PropTypes.bool,
|
||||
horizontal: PropTypes.bool,
|
||||
style: Animated.View.propTypes.style,
|
||||
style: ViewPropTypes.style,
|
||||
location: PropTypes.shape({
|
||||
x: PropTypes.number,
|
||||
y: PropTypes.number,
|
||||
@ -142,10 +142,11 @@ export default class Row extends Component {
|
||||
},
|
||||
});
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (!this._active && !shallowEqual(this._location, nextProps.location)) {
|
||||
const animated = !this._active && nextProps.animated;
|
||||
this._relocate(nextProps.location, animated);
|
||||
componentDidUpdate() {
|
||||
const {animated, location} = this.props;
|
||||
|
||||
if (!this._active && !shallowEqual(this._location, location)) {
|
||||
this._relocate(location, !this._active && animated);
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,6 +198,7 @@ export default class Row extends Component {
|
||||
Animated.timing(this._animatedLocation, {
|
||||
toValue: nextLocation,
|
||||
duration: 300,
|
||||
useNativeDriver: false,
|
||||
}).start(() => {
|
||||
this._isAnimationRunning = false;
|
||||
});
|
||||
|
||||
@ -23,10 +23,19 @@ export default class SortableList extends Component {
|
||||
sortingEnabled: PropTypes.bool,
|
||||
scrollEnabled: PropTypes.bool,
|
||||
horizontal: PropTypes.bool,
|
||||
showsVerticalScrollIndicator: PropTypes.bool,
|
||||
showsHorizontalScrollIndicator: PropTypes.bool,
|
||||
refreshControl: PropTypes.element,
|
||||
autoscrollAreaSize: PropTypes.number,
|
||||
snapToAlignment: PropTypes.string,
|
||||
rowActivationTime: PropTypes.number,
|
||||
manuallyActivateRows: PropTypes.bool,
|
||||
keyboardShouldPersistTaps: PropTypes.oneOf(['never', 'always', 'handled']),
|
||||
scrollEventThrottle: PropTypes.number,
|
||||
decelerationRate: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
pagingEnabled: PropTypes.bool,
|
||||
nestedScrollEnabled: PropTypes.bool,
|
||||
disableIntervalMomentum: PropTypes.bool,
|
||||
|
||||
renderRow: PropTypes.func.isRequired,
|
||||
renderHeader: PropTypes.func,
|
||||
@ -35,13 +44,22 @@ export default class SortableList extends Component {
|
||||
onChangeOrder: PropTypes.func,
|
||||
onActivateRow: PropTypes.func,
|
||||
onReleaseRow: PropTypes.func,
|
||||
onScroll: PropTypes.func,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
sortingEnabled: true,
|
||||
scrollEnabled: true,
|
||||
keyboardShouldPersistTaps: 'never',
|
||||
autoscrollAreaSize: 60,
|
||||
manuallyActivateRows: false
|
||||
snapToAlignment: 'start',
|
||||
manuallyActivateRows: false,
|
||||
showsVerticalScrollIndicator: true,
|
||||
showsHorizontalScrollIndicator: true,
|
||||
scrollEventThrottle: 2,
|
||||
decelerationRate: 'normal',
|
||||
pagingEnabled: false,
|
||||
onScroll: () => {}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,7 +88,7 @@ export default class SortableList extends Component {
|
||||
scrollEnabled: this.props.scrollEnabled
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
componentDidMount() {
|
||||
this.state.order.forEach((key) => {
|
||||
this._rowsLayouts[key] = new Promise((resolve) => {
|
||||
this._resolveRowLayout[key] = resolve;
|
||||
@ -82,20 +100,20 @@ export default class SortableList extends Component {
|
||||
this._resolveHeaderLayout = resolve;
|
||||
});
|
||||
}
|
||||
|
||||
if (this.props.renderFooter && !this.props.horizontal) {
|
||||
this._footerLayout = new Promise((resolve) => {
|
||||
this._resolveFooterLayout = resolve;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._onUpdateLayouts();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const {data, order} = this.state;
|
||||
let {data: nextData, order: nextOrder} = nextProps;
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const {data, order, scrollEnabled} = this.state;
|
||||
let {data: nextData, order: nextOrder} = this.props;
|
||||
const {data: prevData} = prevState;
|
||||
|
||||
if (data && nextData && !shallowEqual(data, nextData)) {
|
||||
nextOrder = nextOrder || Object.keys(nextData)
|
||||
@ -106,26 +124,32 @@ export default class SortableList extends Component {
|
||||
this._resolveRowLayout[key] = resolve;
|
||||
});
|
||||
});
|
||||
this.setState({
|
||||
animated: false,
|
||||
data: nextData,
|
||||
containerLayout: null,
|
||||
rowsLayouts: null,
|
||||
order: nextOrder
|
||||
});
|
||||
|
||||
if (Object.keys(nextData).length > Object.keys(data).length) {
|
||||
this.setState({
|
||||
animated: false,
|
||||
data: nextData,
|
||||
containerLayout: null,
|
||||
rowsLayouts: null,
|
||||
order: nextOrder
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
data: nextData,
|
||||
order: nextOrder
|
||||
});
|
||||
}
|
||||
|
||||
} else if (order && nextOrder && !shallowEqual(order, nextOrder)) {
|
||||
this.setState({order: nextOrder});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const {data} = this.state;
|
||||
const {data: prevData} = prevState;
|
||||
|
||||
if (data && prevData && !shallowEqual(data, prevData)) {
|
||||
this._onUpdateLayouts();
|
||||
}
|
||||
if (prevProps.scrollEnabled !== scrollEnabled) {
|
||||
this.setState({scrollEnabled: prevProps.scrollEnabled})
|
||||
}
|
||||
}
|
||||
|
||||
scrollBy({dx = 0, dy = 0, animated = false}) {
|
||||
@ -180,7 +204,21 @@ export default class SortableList extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
let {contentContainerStyle, innerContainerStyle, horizontal, style} = this.props;
|
||||
let {
|
||||
contentContainerStyle,
|
||||
innerContainerStyle,
|
||||
horizontal,
|
||||
style,
|
||||
showsVerticalScrollIndicator,
|
||||
showsHorizontalScrollIndicator,
|
||||
snapToAlignment,
|
||||
scrollEventThrottle,
|
||||
decelerationRate,
|
||||
pagingEnabled,
|
||||
nestedScrollEnabled,
|
||||
disableIntervalMomentum,
|
||||
keyboardShouldPersistTaps,
|
||||
} = this.props;
|
||||
const {animated, contentHeight, contentWidth, scrollEnabled} = this.state;
|
||||
const containerStyle = StyleSheet.flatten([style, {opacity: Number(animated)}])
|
||||
innerContainerStyle = [
|
||||
@ -199,13 +237,22 @@ export default class SortableList extends Component {
|
||||
return (
|
||||
<View style={containerStyle} ref={this._onRefContainer}>
|
||||
<ScrollView
|
||||
nestedScrollEnabled={nestedScrollEnabled}
|
||||
disableIntervalMomentum={disableIntervalMomentum}
|
||||
refreshControl={refreshControl}
|
||||
ref={this._onRefScrollView}
|
||||
horizontal={horizontal}
|
||||
contentContainerStyle={contentContainerStyle}
|
||||
scrollEventThrottle={2}
|
||||
scrollEventThrottle={scrollEventThrottle}
|
||||
pagingEnabled={pagingEnabled}
|
||||
decelerationRate={decelerationRate}
|
||||
scrollEnabled={scrollEnabled}
|
||||
onScroll={this._onScroll}>
|
||||
keyboardShouldPersistTaps={keyboardShouldPersistTaps}
|
||||
showsHorizontalScrollIndicator={showsHorizontalScrollIndicator}
|
||||
showsVerticalScrollIndicator={showsVerticalScrollIndicator}
|
||||
snapToAlignment={snapToAlignment}
|
||||
onScroll={this._onScroll}
|
||||
>
|
||||
{this._renderHeader()}
|
||||
<View style={innerContainerStyle}>
|
||||
{this._renderRows()}
|
||||
@ -585,7 +632,7 @@ export default class SortableList extends Component {
|
||||
}));
|
||||
|
||||
if (this.props.onReleaseRow) {
|
||||
this.props.onReleaseRow(rowKey);
|
||||
this.props.onReleaseRow(rowKey, this.state.order);
|
||||
}
|
||||
};
|
||||
|
||||
@ -607,8 +654,9 @@ export default class SortableList extends Component {
|
||||
}
|
||||
};
|
||||
|
||||
_onScroll = ({nativeEvent: {contentOffset}}) => {
|
||||
this._contentOffset = contentOffset;
|
||||
_onScroll = (e) => {
|
||||
this._contentOffset = e.nativeEvent.contentOffset;
|
||||
this.props.onScroll(e)
|
||||
};
|
||||
|
||||
_onRefContainer = (component) => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user