mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-06-12 05:53:56 +00:00
[change] Remove SwipeableListView
Ref #1352 Ref https://github.com/facebook/react-native/issues/23313
This commit is contained in:
@@ -142,7 +142,6 @@ React Native v0.55
|
||||
| SectionList | ✓ | |
|
||||
| StatusBar | (✓) | Mock. No equivalent web APIs. |
|
||||
| SwipeableFlatList | ✓ | |
|
||||
| SwipeableListView | ✓ | |
|
||||
| Switch | ✓ | |
|
||||
| Text | ✓ | Missing `onLongPress` ([#1011](https://github.com/necolas/react-native-web/issues/1011)) support. |
|
||||
| TextInput | ✓ | Missing rich text features ([#1023](https://github.com/necolas/react-native-web/issues/1023)), and auto-expanding behaviour ([#795](https://github.com/necolas/react-native-web/issues/795)). |
|
||||
|
||||
@@ -46,7 +46,6 @@ module.exports = {
|
||||
StatusBar: true,
|
||||
StyleSheet: true,
|
||||
SwipeableFlatList: true,
|
||||
SwipeableListView: true,
|
||||
Switch: true,
|
||||
Systrace: true,
|
||||
TVEventHandler: true,
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Nicolas Gallagher.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import SwipeableListView from '../../vendor/react-native/SwipeableListView';
|
||||
export default SwipeableListView;
|
||||
-2
@@ -49,7 +49,6 @@ import ScrollView from './exports/ScrollView';
|
||||
import SectionList from './exports/SectionList';
|
||||
import StatusBar from './exports/StatusBar';
|
||||
import SwipeableFlatList from './exports/SwipeableFlatList';
|
||||
import SwipeableListView from './exports/SwipeableListView';
|
||||
import Switch from './exports/Switch';
|
||||
import Text from './exports/Text';
|
||||
import TextInput from './exports/TextInput';
|
||||
@@ -138,7 +137,6 @@ export {
|
||||
SectionList,
|
||||
StatusBar,
|
||||
SwipeableFlatList,
|
||||
SwipeableListView,
|
||||
Switch,
|
||||
Text,
|
||||
TextInput,
|
||||
|
||||
Vendored
-113
@@ -1,113 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule SwipeableListViewDataSource
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
import ListViewDataSource from '../ListView/ListViewDataSource';
|
||||
|
||||
/**
|
||||
* Data source wrapper around ListViewDataSource to allow for tracking of
|
||||
* which row is swiped open and close opened row(s) when another row is swiped
|
||||
* open.
|
||||
*
|
||||
* See https://github.com/facebook/react-native/pull/5602 for why
|
||||
* ListViewDataSource is not subclassed.
|
||||
*/
|
||||
class SwipeableListViewDataSource {
|
||||
_previousOpenRowID: string;
|
||||
_openRowID: string;
|
||||
|
||||
_dataBlob: any;
|
||||
_dataSource: ListViewDataSource;
|
||||
|
||||
rowIdentities: Array<Array<string>>;
|
||||
sectionIdentities: Array<string>;
|
||||
|
||||
constructor(params: Object) {
|
||||
this._dataSource = new ListViewDataSource({
|
||||
getRowData: params.getRowData,
|
||||
getSectionHeaderData: params.getSectionHeaderData,
|
||||
rowHasChanged: (row1, row2) => {
|
||||
/**
|
||||
* Row needs to be re-rendered if its swiped open/close status is
|
||||
* changed, or its data blob changed.
|
||||
*/
|
||||
return (
|
||||
(row1.id !== this._previousOpenRowID && row2.id === this._openRowID) ||
|
||||
(row1.id === this._previousOpenRowID && row2.id !== this._openRowID) ||
|
||||
params.rowHasChanged(row1, row2)
|
||||
);
|
||||
},
|
||||
sectionHeaderHasChanged: params.sectionHeaderHasChanged,
|
||||
});
|
||||
}
|
||||
|
||||
cloneWithRowsAndSections(
|
||||
dataBlob: any,
|
||||
sectionIdentities: ?Array<string>,
|
||||
rowIdentities: ?Array<Array<string>>
|
||||
): SwipeableListViewDataSource {
|
||||
this._dataSource = this._dataSource.cloneWithRowsAndSections(
|
||||
dataBlob,
|
||||
sectionIdentities,
|
||||
rowIdentities
|
||||
);
|
||||
|
||||
this._dataBlob = dataBlob;
|
||||
this.rowIdentities = this._dataSource.rowIdentities;
|
||||
this.sectionIdentities = this._dataSource.sectionIdentities;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// For the actual ListView to use
|
||||
getDataSource(): ListViewDataSource {
|
||||
return this._dataSource;
|
||||
}
|
||||
|
||||
getOpenRowID(): ?string {
|
||||
return this._openRowID;
|
||||
}
|
||||
|
||||
getFirstRowID(): ?string {
|
||||
/**
|
||||
* If rowIdentities is specified, find the first data row from there since
|
||||
* we don't want to attempt to bounce section headers. If unspecified, find
|
||||
* the first data row from _dataBlob.
|
||||
*/
|
||||
if (this.rowIdentities) {
|
||||
return this.rowIdentities[0] && this.rowIdentities[0][0];
|
||||
}
|
||||
return Object.keys(this._dataBlob)[0];
|
||||
}
|
||||
|
||||
getLastRowID(): ?string {
|
||||
if (this.rowIdentities && this.rowIdentities.length) {
|
||||
const lastSection = this.rowIdentities[this.rowIdentities.length - 1];
|
||||
if (lastSection && lastSection.length) {
|
||||
return lastSection[lastSection.length - 1];
|
||||
}
|
||||
}
|
||||
return Object.keys(this._dataBlob)[this._dataBlob.length - 1];
|
||||
}
|
||||
|
||||
setOpenRowID(rowID: string): SwipeableListViewDataSource {
|
||||
this._previousOpenRowID = this._openRowID;
|
||||
this._openRowID = rowID;
|
||||
|
||||
this._dataSource = this._dataSource.cloneWithRowsAndSections(
|
||||
this._dataBlob,
|
||||
this.sectionIdentities,
|
||||
this.rowIdentities
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export default SwipeableListViewDataSource;
|
||||
-211
@@ -1,211 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule SwipeableListView
|
||||
* @noflow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
import ListView from '../ListView';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import SwipeableListViewDataSource from './SwipeableListViewDataSource';
|
||||
import SwipeableRow from '../SwipeableRow';
|
||||
|
||||
type DefaultProps = {
|
||||
bounceFirstRowOnMount: boolean,
|
||||
renderQuickActions: Function,
|
||||
};
|
||||
|
||||
type Props = {
|
||||
bounceFirstRowOnMount: boolean,
|
||||
dataSource: SwipeableListViewDataSource,
|
||||
maxSwipeDistance: number | (rowData: any, sectionID: string, rowID: string) => number,
|
||||
onScroll?: ?Function,
|
||||
renderRow: Function,
|
||||
renderQuickActions: Function,
|
||||
};
|
||||
|
||||
type State = {
|
||||
dataSource: Object,
|
||||
};
|
||||
|
||||
/**
|
||||
* A container component that renders multiple SwipeableRow's in a ListView
|
||||
* implementation. This is designed to be a drop-in replacement for the
|
||||
* standard React Native `ListView`, so use it as if it were a ListView, but
|
||||
* with extra props, i.e.
|
||||
*
|
||||
* let ds = SwipeableListView.getNewDataSource();
|
||||
* ds.cloneWithRowsAndSections(dataBlob, ?sectionIDs, ?rowIDs);
|
||||
* // ..
|
||||
* <SwipeableListView renderRow={..} renderQuickActions={..} {..ListView props} />
|
||||
*
|
||||
* SwipeableRow can be used independently of this component, but the main
|
||||
* benefit of using this component is
|
||||
*
|
||||
* - It ensures that at most 1 row is swiped open (auto closes others)
|
||||
* - It can bounce the 1st row of the list so users know it's swipeable
|
||||
* - More to come
|
||||
*/
|
||||
class SwipeableListView extends React.Component<Props, State> {
|
||||
props: Props;
|
||||
state: State;
|
||||
|
||||
_listViewRef: ?React.Element<any> = null;
|
||||
_shouldBounceFirstRowOnMount: boolean = false;
|
||||
|
||||
static getNewDataSource(): Object {
|
||||
return new SwipeableListViewDataSource({
|
||||
getRowData: (data, sectionID, rowID) => data[sectionID][rowID],
|
||||
getSectionHeaderData: (data, sectionID) => data[sectionID],
|
||||
rowHasChanged: (row1, row2) => row1 !== row2,
|
||||
sectionHeaderHasChanged: (s1, s2) => s1 !== s2,
|
||||
});
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
/**
|
||||
* To alert the user that swiping is possible, the first row can bounce
|
||||
* on component mount.
|
||||
*/
|
||||
bounceFirstRowOnMount: PropTypes.bool.isRequired,
|
||||
/**
|
||||
* Use `SwipeableListView.getNewDataSource()` to get a data source to use,
|
||||
* then use it just like you would a normal ListView data source
|
||||
*/
|
||||
dataSource: PropTypes.instanceOf(SwipeableListViewDataSource).isRequired,
|
||||
// Maximum distance to open to after a swipe
|
||||
maxSwipeDistance: PropTypes.oneOfType([
|
||||
PropTypes.number,
|
||||
PropTypes.func,
|
||||
]).isRequired,
|
||||
// Callback method to render the swipeable view
|
||||
renderRow: PropTypes.func.isRequired,
|
||||
// Callback method to render the view that will be unveiled on swipe
|
||||
renderQuickActions: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
bounceFirstRowOnMount: false,
|
||||
renderQuickActions: () => null,
|
||||
};
|
||||
|
||||
constructor(props: Props, context: any): void {
|
||||
super(props, context);
|
||||
|
||||
this._shouldBounceFirstRowOnMount = this.props.bounceFirstRowOnMount;
|
||||
this.state = {
|
||||
dataSource: this.props.dataSource,
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps: Props): void {
|
||||
if (this.state.dataSource.getDataSource() !== nextProps.dataSource.getDataSource()) {
|
||||
this.setState({
|
||||
dataSource: nextProps.dataSource,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render(): React.Node {
|
||||
return (
|
||||
<ListView
|
||||
{...this.props}
|
||||
ref={(ref) => {
|
||||
this._listViewRef = ref;
|
||||
}}
|
||||
dataSource={this.state.dataSource.getDataSource()}
|
||||
onScroll={this._onScroll}
|
||||
renderRow={this._renderRow}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
_onScroll = (e): void => {
|
||||
// Close any opens rows on ListView scroll
|
||||
if (this.props.dataSource.getOpenRowID()) {
|
||||
this.setState({
|
||||
dataSource: this.state.dataSource.setOpenRowID(null),
|
||||
});
|
||||
}
|
||||
this.props.onScroll && this.props.onScroll(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a work-around to lock vertical `ListView` scrolling on iOS and
|
||||
* mimic Android behaviour. Locking vertical scrolling when horizontal
|
||||
* scrolling is active allows us to significantly improve framerates
|
||||
* (from high 20s to almost consistently 60 fps)
|
||||
*/
|
||||
_setListViewScrollable(value: boolean): void {
|
||||
if (this._listViewRef && typeof this._listViewRef.setNativeProps === 'function') {
|
||||
this._listViewRef.setNativeProps({
|
||||
scrollEnabled: value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Passing through ListView's getScrollResponder() function
|
||||
getScrollResponder(): ?Object {
|
||||
if (this._listViewRef && typeof this._listViewRef.getScrollResponder === 'function') {
|
||||
return this._listViewRef.getScrollResponder();
|
||||
}
|
||||
}
|
||||
|
||||
// This enables rows having variable width slideoutView.
|
||||
_getMaxSwipeDistance(rowData: Object, sectionID: string, rowID: string): number {
|
||||
if (typeof this.props.maxSwipeDistance === 'function') {
|
||||
return this.props.maxSwipeDistance(rowData, sectionID, rowID);
|
||||
}
|
||||
|
||||
return this.props.maxSwipeDistance;
|
||||
}
|
||||
|
||||
_renderRow = (rowData: Object, sectionID: string, rowID: string): React.Element<any> => {
|
||||
const slideoutView = this.props.renderQuickActions(rowData, sectionID, rowID);
|
||||
|
||||
// If renderQuickActions is unspecified or returns falsey, don't allow swipe
|
||||
if (!slideoutView) {
|
||||
return this.props.renderRow(rowData, sectionID, rowID);
|
||||
}
|
||||
|
||||
let shouldBounceOnMount = false;
|
||||
if (this._shouldBounceFirstRowOnMount) {
|
||||
this._shouldBounceFirstRowOnMount = false;
|
||||
shouldBounceOnMount = rowID === this.props.dataSource.getFirstRowID();
|
||||
}
|
||||
|
||||
return (
|
||||
<SwipeableRow
|
||||
slideoutView={slideoutView}
|
||||
isOpen={rowData.id === this.props.dataSource.getOpenRowID()}
|
||||
maxSwipeDistance={this._getMaxSwipeDistance(rowData, sectionID, rowID)}
|
||||
key={rowID}
|
||||
onOpen={() => this._onOpen(rowData.id)}
|
||||
onClose={() => this._onClose(rowData.id)}
|
||||
onSwipeEnd={() => this._setListViewScrollable(true)}
|
||||
onSwipeStart={() => this._setListViewScrollable(false)}
|
||||
shouldBounceOnMount={shouldBounceOnMount}>
|
||||
{this.props.renderRow(rowData, sectionID, rowID)}
|
||||
</SwipeableRow>
|
||||
);
|
||||
};
|
||||
|
||||
_onOpen(rowID: string): void {
|
||||
this.setState({
|
||||
dataSource: this.state.dataSource.setOpenRowID(rowID),
|
||||
});
|
||||
}
|
||||
|
||||
_onClose(rowID: string): void {
|
||||
this.setState({
|
||||
dataSource: this.state.dataSource.setOpenRowID(null),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default SwipeableListView;
|
||||
Reference in New Issue
Block a user