Adapt SectionListExamples

Summary:
# Changelog:
[General][Added] - Added more RNTester examples for FlatList as similar to SectionListExamples.

Reviewed By: kacieb

Differential Revision: D27104601

fbshipit-source-id: 0a2cb24382d42956bacf455fd0a699adb61c7c83
This commit is contained in:
Luna Wei
2021-03-18 11:36:29 -07:00
committed by Facebook GitHub Bot
parent c357cb4bbf
commit bbf571cf11
7 changed files with 438 additions and 6 deletions
@@ -0,0 +1,28 @@
/**
* 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.
*
* @format
* @flow
*/
'use strict';
import {FlatList_onEndReached} from './FlatListExamples';
const React = require('react');
exports.title = 'FlatList onEndReached';
exports.testTitle = 'Test onEndReached callback';
exports.category = 'ListView';
exports.documentationURL = 'https://reactnative.dev/docs/flatlist';
exports.description =
'Scroll to end of list or tap Test button to see `onEndReached` triggered.';
exports.examples = [
{
title: 'FlatList onEndReached',
render: function(): React.Element<typeof FlatList_onEndReached> {
return <FlatList_onEndReached />;
},
},
];
@@ -0,0 +1,38 @@
/**
* 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.
*
* @format
* @flow
*/
'use strict';
import {FlatList_onViewableItemsChanged} from './FlatListExamples';
const React = require('react');
const VIEWABILITY_CONFIG = {
minimumViewTime: 1000,
viewAreaCoveragePercentThreshold: 100,
waitForInteraction: true,
};
exports.title = 'FlatList onViewableItemsChanged';
exports.testTitle = 'Test onViewableItemsChanged callback';
exports.category = 'ListView';
exports.documentationURL = 'https://reactnative.dev/docs/sectionlist';
exports.description =
'Scroll list to see what items are returned in `onViewableItemsChanged` callback.';
exports.examples = [
{
title: 'FlatList onViewableItemsChanged',
render: function(): React.Element<typeof FlatList_onViewableItemsChanged> {
return (
<FlatList_onViewableItemsChanged
viewabilityConfig={VIEWABILITY_CONFIG}
/>
);
},
},
];
@@ -0,0 +1,27 @@
/**
* 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.
*
* @format
* @flow
*/
'use strict';
import {FlatList_withSeparators} from './FlatListExamples';
const React = require('react');
exports.title = 'FlatList with Separators';
exports.testTitle = 'Test custom separator components';
exports.category = 'ListView';
exports.documentationURL = 'https://reactnative.dev/docs/sectionlist';
exports.description = 'Tap to see pressed states for separator components.';
exports.examples = [
{
title: 'FlatList with Separators',
render: function(): React.Element<typeof FlatList_withSeparators> {
return <FlatList_withSeparators />;
},
},
];
@@ -0,0 +1,312 @@
/**
* 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 strict-local
* @format
*/
import {
Pressable,
Button,
FlatList,
StyleSheet,
Text,
View,
} from 'react-native';
import * as React from 'react';
type FlatListProps = React.ElementProps<typeof FlatList>;
type ViewabilityConfig = $PropertyType<FlatListProps, 'viewabilityConfig'>;
const DATA = [
'Pizza',
'Burger',
'Risotto',
'French Fries',
'Onion Rings',
'Fried Shrimps',
'Water',
'Coke',
'Beer',
'Cheesecake',
'Ice Cream',
];
const Item = ({item, separators}) => {
return (
<Pressable
onPressIn={() => {
separators.highlight();
}}
onPress={() => {
separators.updateProps('trailing', {hasBeenHighlighted: true});
separators.updateProps('leading', {hasBeenHighlighted: true});
}}
onPressOut={() => {
separators.unhighlight();
}}
style={({pressed}) => [
styles.item,
{
backgroundColor: pressed ? 'red' : 'pink',
},
]}
testID={item}>
<Text style={styles.title}>{item}</Text>
</Pressable>
);
};
const Separator = (defaultColor, highlightColor) => ({
leadingItem,
trailingItem,
highlighted,
hasBeenHighlighted,
}) => {
const text = `Separator for leading ${leadingItem} and trailing ${trailingItem} has ${
!hasBeenHighlighted ? 'not ' : ''
}been pressed`;
return (
<View
style={[
styles.separator,
{backgroundColor: highlighted ? highlightColor : defaultColor},
]}>
<Text style={styles.separtorText}>{text}</Text>
</View>
);
};
export function FlatList_inverted(): React.Node {
const [output, setOutput] = React.useState('inverted false');
const [exampleProps, setExampleProps] = React.useState({
inverted: false,
});
const onTest = () => {
setExampleProps({
inverted: !exampleProps.inverted,
});
setOutput(`Is inverted: ${(!exampleProps.inverted).toString()}`);
};
return (
<FlatListExampleWithForwardedRef
exampleProps={exampleProps}
testOutput={output}
onTest={onTest}
testLabel={exampleProps.inverted ? 'Toggle false' : 'Toggle true'}
/>
);
}
export function FlatList_contentInset(): React.Node {
const [initialContentInset, toggledContentInset] = [44, 88];
const [output, setOutput] = React.useState(
`contentInset top: ${initialContentInset.toString()}`,
);
const [exampleProps, setExampleProps] = React.useState({
automaticallyAdjustContentInsets: false,
contentInset: {top: initialContentInset},
contentOffset: {y: -initialContentInset, x: 0},
});
const onTest = () => {
const newContentInset =
exampleProps.contentInset.top === initialContentInset
? toggledContentInset
: initialContentInset;
setExampleProps({
automaticallyAdjustContentInsets: false,
contentInset: {top: newContentInset},
contentOffset: {y: -newContentInset, x: 0},
});
setOutput(`contentInset top: ${newContentInset.toString()}`);
};
return (
<>
<View
style={[
styles.titleContainer,
{height: exampleProps.contentInset.top},
]}>
<Text style={styles.titleText}>Menu</Text>
</View>
<FlatListExampleWithForwardedRef
exampleProps={exampleProps}
testOutput={output}
onTest={onTest}
testLabel={'Toggle header size'}
/>
</>
);
}
export function FlatList_onEndReached(): React.Node {
const [output, setOutput] = React.useState('');
const exampleProps = {
onEndReached: info => setOutput('onEndReached'),
onEndReachedThreshold: 0,
};
const ref = React.useRef(null);
const onTest = () => {
const scrollResponder = ref?.current?.getScrollResponder();
if (scrollResponder != null) {
scrollResponder.scrollToEnd();
}
};
return (
<FlatListExampleWithForwardedRef
ref={ref}
exampleProps={exampleProps}
testOutput={output}
onTest={onTest}
/>
);
}
export function FlatList_withSeparators(): React.Node {
const exampleProps = {
ItemSeparatorComponent: Separator('lightgreen', 'green'),
};
const ref = React.useRef(null);
return (
<FlatListExampleWithForwardedRef ref={ref} exampleProps={exampleProps} />
);
}
export function FlatList_onViewableItemsChanged(props: {
viewabilityConfig: ViewabilityConfig,
offScreen?: ?boolean,
horizontal?: ?boolean,
}): React.Node {
const {viewabilityConfig, offScreen, horizontal} = props;
const [output, setOutput] = React.useState('');
const onViewableItemsChanged = React.useCallback(
info =>
setOutput(
info.viewableItems
.filter(viewToken => viewToken.index != null && viewToken.isViewable)
.map(viewToken => viewToken.item)
.join(', '),
),
[setOutput],
);
const exampleProps = {
onViewableItemsChanged,
viewabilityConfig,
horizontal,
};
return (
<FlatListExampleWithForwardedRef
exampleProps={exampleProps}
testOutput={output}>
{offScreen === true ? <View style={styles.offScreen} /> : null}
</FlatListExampleWithForwardedRef>
);
}
type Props = {
exampleProps: $Shape<React.ElementConfig<typeof FlatList>>,
onTest?: ?() => void,
testLabel?: ?string,
testOutput?: ?string,
children?: ?React.Node,
};
const FlatListExampleWithForwardedRef = React.forwardRef(
(props: Props, ref) => {
return (
<View style={styles.container}>
{props.testOutput != null ? (
<View testID="test_container" style={styles.testContainer}>
<Text numberOfLines={1} testID="output">
{props.testOutput}
</Text>
{props.onTest != null ? (
<Button
testID="start_test"
onPress={props.onTest}
title={props.testLabel ?? 'Test'}
/>
) : null}
</View>
) : null}
{props.children}
<FlatList
{...props.exampleProps}
ref={ref}
testID="flat_list"
data={DATA}
keyExtractor={(item, index) => item + index}
style={styles.list}
renderItem={Item}
/>
</View>
);
},
);
const styles = StyleSheet.create({
item: {
backgroundColor: 'pink',
padding: 20,
marginVertical: 8,
},
header: {
fontSize: 32,
backgroundColor: 'white',
},
title: {
fontSize: 24,
},
titleContainer: {
position: 'absolute',
top: 45,
left: 0,
right: 0,
justifyContent: 'flex-end',
alignItems: 'center',
backgroundColor: 'gray',
zIndex: 1,
},
titleText: {
fontSize: 24,
lineHeight: 44,
fontWeight: 'bold',
},
testContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: '#f2f2f7ff',
padding: 4,
height: 40,
},
output: {
fontSize: 12,
},
separator: {
height: 12,
},
separtorText: {
fontSize: 10,
},
list: {
flex: 1,
},
container: {flex: 1},
offScreen: {
height: 1000,
},
});
@@ -191,7 +191,7 @@ export function SectionList_onEndReached(): React.Node {
onEndReached: info => setOutput('onEndReached'),
onEndReachedThreshold: 0,
};
const ref = React.createRef<?React.ElementRef<typeof SectionList>>();
const ref = React.useRef(null);
const onTest = () => {
const scrollResponder = ref?.current?.getScrollResponder();
@@ -215,7 +215,7 @@ export function SectionList_withSeparators(): React.Node {
ItemSeparatorComponent: Separator('lightgreen', 'green', false),
SectionSeparatorComponent: Separator('lightblue', 'blue', true),
};
const ref = React.createRef<?React.ElementRef<typeof SectionList>>();
const ref = React.useRef(null);
return (
<SectionListExampleWithForwardedRef ref={ref} exampleProps={exampleProps} />
@@ -259,10 +259,7 @@ type Props = {
};
const SectionListExampleWithForwardedRef = React.forwardRef(
function SectionListExample(
props: Props,
ref: ?React.ElementRef<typeof SectionListExampleWithForwardedRef>,
): React.Node {
(props: Props, ref): React.Node => {
return (
<View style={styles.container}>
{props.testOutput != null ? (
@@ -28,6 +28,21 @@ const ComponentExamples: Array<RNTesterExample> = [
category: 'ListView',
module: require('../examples/FlatList/FlatListExample'),
},
{
key: 'FlatList-withSeparators',
module: require('../examples/FlatList/FlatList-withSeparators'),
category: 'ListView',
},
{
key: 'FlatList-onViewableItemsChanged',
module: require('../examples/FlatList/FlatList-onViewableItemsChanged'),
category: 'ListView',
},
{
key: 'FlatList-onEndReached',
module: require('../examples/FlatList/FlatList-onEndReached'),
category: 'ListView',
},
{
key: 'ImageExample',
category: 'Basic',
@@ -31,6 +31,21 @@ const ComponentExamples: Array<RNTesterExample> = [
category: 'ListView',
supportsTVOS: true,
},
{
key: 'FlatList-withSeparators',
module: require('../examples/FlatList/FlatList-withSeparators'),
category: 'ListView',
},
{
key: 'FlatList-onViewableItemsChanged',
module: require('../examples/FlatList/FlatList-onViewableItemsChanged'),
category: 'ListView',
},
{
key: 'FlatList-onEndReached',
module: require('../examples/FlatList/FlatList-onEndReached'),
category: 'ListView',
},
{
key: 'ImageExample',
module: require('../examples/Image/ImageExample'),