mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Move SectionList examples together
Summary: Changelog: [Internal] - Move SectionList examples together. An interim state for next diff to add a 3rd level of navigation so each example is rendered in separate surface. Reviewed By: kacieb Differential Revision: D29480143 fbshipit-source-id: f7f10920bd4ab938665f17f0a80debaff55b9788
This commit is contained in:
committed by
Facebook GitHub Bot
parent
fd08255b0b
commit
9fb2659f56
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* 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 SectionListBaseExample from './SectionListBaseExample';
|
||||
import * as React from 'react';
|
||||
import {View, Text, StyleSheet} from 'react-native';
|
||||
|
||||
export function SectionList_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>
|
||||
<SectionListBaseExample
|
||||
exampleProps={exampleProps}
|
||||
testOutput={output}
|
||||
onTest={onTest}
|
||||
testLabel={'Toggle header size'}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
const styles = StyleSheet.create({
|
||||
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',
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
title: 'SectionList Content Inset',
|
||||
name: 'SectionList-contentInset',
|
||||
render: function(): React.Element<typeof SectionList_contentInset> {
|
||||
return <SectionList_contentInset />;
|
||||
},
|
||||
};
|
||||
@@ -9,19 +9,36 @@
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import {SectionList_inverted} from './SectionListExamples';
|
||||
const React = require('react');
|
||||
import SectionListBaseExample from './SectionListBaseExample';
|
||||
import * as React from 'react';
|
||||
|
||||
exports.title = 'SectionList inverted';
|
||||
exports.testTitle = 'Test inverted prop';
|
||||
exports.category = 'ListView';
|
||||
exports.documentationURL = 'https://reactnative.dev/docs/sectionlist';
|
||||
exports.description = 'Toggle inverted to see list inverted.';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'SectionList inverted',
|
||||
render: function(): React.Element<typeof SectionList_inverted> {
|
||||
return <SectionList_inverted />;
|
||||
},
|
||||
export function SectionList_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 (
|
||||
<SectionListBaseExample
|
||||
exampleProps={exampleProps}
|
||||
testOutput={output}
|
||||
onTest={onTest}
|
||||
testLabel={exampleProps.inverted ? 'Toggle false' : 'Toggle true'}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default {
|
||||
title: 'SectionList Inverted',
|
||||
name: 'SectionList-inverted',
|
||||
render: function(): React.Element<typeof SectionList_inverted> {
|
||||
return <SectionList_inverted />;
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
@@ -8,21 +8,38 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import {SectionList_onEndReached} from './SectionListExamples';
|
||||
const React = require('react');
|
||||
import SectionListBaseExample from './SectionListBaseExample';
|
||||
import * as React from 'react';
|
||||
|
||||
exports.title = 'SectionList onEndReached';
|
||||
exports.testTitle = 'Test onEndReached callback';
|
||||
exports.category = 'ListView';
|
||||
exports.documentationURL = 'https://reactnative.dev/docs/sectionlist';
|
||||
exports.description =
|
||||
'Scroll to end of list or tap Test button to see `onEndReached` triggered.';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'SectionList onEndReached',
|
||||
render: function(): React.Element<typeof SectionList_onEndReached> {
|
||||
return <SectionList_onEndReached />;
|
||||
},
|
||||
export function SectionList_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 (
|
||||
<SectionListBaseExample
|
||||
ref={ref}
|
||||
exampleProps={exampleProps}
|
||||
testOutput={output}
|
||||
onTest={onTest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default {
|
||||
title: 'SectionList Inverted',
|
||||
name: 'SectionList-onEndReached',
|
||||
render: function(): React.Element<typeof SectionList_onEndReached> {
|
||||
return <SectionList_onEndReached />;
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import {SectionList_onViewableItemsChanged} from './SectionListExamples';
|
||||
const React = require('react');
|
||||
import SectionListBaseExample from './SectionListBaseExample';
|
||||
import {View, StyleSheet, SectionList} from 'react-native';
|
||||
import * as React from 'react';
|
||||
|
||||
const VIEWABILITY_CONFIG = {
|
||||
minimumViewTime: 1000,
|
||||
@@ -18,23 +18,60 @@ const VIEWABILITY_CONFIG = {
|
||||
waitForInteraction: true,
|
||||
};
|
||||
|
||||
exports.title = 'SectionList 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: 'SectionList onViewableItemsChanged',
|
||||
render: function(): React.Element<
|
||||
typeof SectionList_onViewableItemsChanged,
|
||||
> {
|
||||
return (
|
||||
<SectionList_onViewableItemsChanged
|
||||
viewabilityConfig={VIEWABILITY_CONFIG}
|
||||
/>
|
||||
);
|
||||
},
|
||||
type SectionListProps = React.ElementProps<typeof SectionList>;
|
||||
type ViewabilityConfig = $PropertyType<SectionListProps, 'viewabilityConfig'>;
|
||||
|
||||
export function SectionList_onViewableItemsChanged(props: {
|
||||
viewabilityConfig: ViewabilityConfig,
|
||||
offScreen?: ?boolean,
|
||||
horizontal?: ?boolean,
|
||||
useScrollRefScroll?: ?boolean,
|
||||
}): React.Node {
|
||||
const {viewabilityConfig, offScreen, horizontal, useScrollRefScroll} = props;
|
||||
const [output, setOutput] = React.useState('');
|
||||
const exampleProps = {
|
||||
onViewableItemsChanged: info =>
|
||||
setOutput(
|
||||
info.viewableItems
|
||||
.filter(viewToken => viewToken.index != null && viewToken.isViewable)
|
||||
.map(viewToken => viewToken.item)
|
||||
.join(', '),
|
||||
),
|
||||
viewabilityConfig,
|
||||
horizontal,
|
||||
};
|
||||
const ref = React.useRef(null);
|
||||
const onTest =
|
||||
useScrollRefScroll === true
|
||||
? () => {
|
||||
ref?.current?.getScrollResponder()?.scrollToEnd();
|
||||
}
|
||||
: null;
|
||||
|
||||
return (
|
||||
<SectionListBaseExample
|
||||
ref={ref}
|
||||
exampleProps={exampleProps}
|
||||
onTest={onTest}
|
||||
testOutput={output}>
|
||||
{offScreen === true ? <View style={styles.offScreen} /> : null}
|
||||
</SectionListBaseExample>
|
||||
);
|
||||
}
|
||||
const styles = StyleSheet.create({
|
||||
offScreen: {
|
||||
height: 1000,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
export default {
|
||||
title: 'SectionList On Viewable Items Changed',
|
||||
name: 'SectionList_onViewableItemsChanged',
|
||||
render: function(): React.Element<typeof SectionList_onViewableItemsChanged> {
|
||||
return (
|
||||
<SectionList_onViewableItemsChanged
|
||||
viewabilityConfig={VIEWABILITY_CONFIG}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -9,22 +9,44 @@
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import {SectionList_stickySectionHeadersEnabled} from './SectionListExamples';
|
||||
const React = require('react');
|
||||
import SectionListBaseExample from './SectionListBaseExample';
|
||||
import * as React from 'react';
|
||||
|
||||
exports.title = 'SectionList stickySectionHeadersEnabled';
|
||||
exports.testTitle = 'Test stickySectionHeadersEnabled prop';
|
||||
exports.category = 'ListView';
|
||||
exports.documentationURL = 'https://reactnative.dev/docs/sectionlist';
|
||||
exports.description =
|
||||
'Toggle stickySectionHeadersEnabled to see section headers stick.';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'SectionList stickySectionHeadersEnabled',
|
||||
render: function(): React.Element<
|
||||
typeof SectionList_stickySectionHeadersEnabled,
|
||||
> {
|
||||
return <SectionList_stickySectionHeadersEnabled />;
|
||||
},
|
||||
export function SectionList_stickySectionHeadersEnabled(): React.Node {
|
||||
const [output, setOutput] = React.useState(
|
||||
'stickySectionHeadersEnabled false',
|
||||
);
|
||||
const [exampleProps, setExampleProps] = React.useState({
|
||||
stickySectionHeadersEnabled: false,
|
||||
});
|
||||
|
||||
const onTest = () => {
|
||||
setExampleProps({
|
||||
stickySectionHeadersEnabled: !exampleProps.stickySectionHeadersEnabled,
|
||||
});
|
||||
setOutput(
|
||||
`stickySectionHeadersEnabled ${(!exampleProps.stickySectionHeadersEnabled).toString()}`,
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<SectionListBaseExample
|
||||
exampleProps={exampleProps}
|
||||
testOutput={output}
|
||||
onTest={onTest}
|
||||
testLabel={
|
||||
exampleProps.stickySectionHeadersEnabled ? 'Sticky Off' : 'Sticky On'
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default {
|
||||
title: 'SectionList Sticky Headers Enabled',
|
||||
name: 'SectionList-stickyHeadersEnabled',
|
||||
render: function(): React.Element<
|
||||
typeof SectionList_stickySectionHeadersEnabled,
|
||||
> {
|
||||
return <SectionList_stickySectionHeadersEnabled />;
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
@@ -8,20 +8,56 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import {SectionList_withSeparators} from './SectionListExamples';
|
||||
const React = require('react');
|
||||
import SectionListBaseExample from './SectionListBaseExample';
|
||||
import {View, Text, StyleSheet} from 'react-native';
|
||||
import * as React from 'react';
|
||||
|
||||
exports.title = 'SectionList 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: 'SectionList with Separators',
|
||||
render: function(): React.Element<typeof SectionList_withSeparators> {
|
||||
return <SectionList_withSeparators />;
|
||||
},
|
||||
const Separator = (defaultColor, highlightColor, isSectionSeparator) => ({
|
||||
leadingItem,
|
||||
trailingItem,
|
||||
highlighted,
|
||||
hasBeenHighlighted,
|
||||
}) => {
|
||||
const text = `${
|
||||
isSectionSeparator ? 'Section ' : ''
|
||||
}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 SectionList_withSeparators(): React.Node {
|
||||
const exampleProps = {
|
||||
ItemSeparatorComponent: Separator('lightgreen', 'green', false),
|
||||
SectionSeparatorComponent: Separator('lightblue', 'blue', true),
|
||||
};
|
||||
const ref = React.useRef(null);
|
||||
|
||||
return <SectionListBaseExample ref={ref} exampleProps={exampleProps} />;
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
separator: {
|
||||
height: 12,
|
||||
},
|
||||
];
|
||||
separtorText: {
|
||||
fontSize: 10,
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
title: 'SectionList With Separators',
|
||||
name: 'SectionList-withSeparators',
|
||||
render: function(): React.Element<typeof SectionList_withSeparators> {
|
||||
return <SectionList_withSeparators />;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* 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,
|
||||
SectionList,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
const DATA = [
|
||||
{
|
||||
title: 'Main dishes',
|
||||
data: ['Pizza', 'Burger', 'Risotto'],
|
||||
},
|
||||
{
|
||||
title: 'Sides',
|
||||
data: ['French Fries', 'Onion Rings', 'Fried Shrimps'],
|
||||
},
|
||||
{
|
||||
title: 'Drinks',
|
||||
data: ['Water', 'Coke', 'Beer'],
|
||||
},
|
||||
{
|
||||
title: 'Desserts',
|
||||
data: ['Cheesecake', 'Ice Cream'],
|
||||
},
|
||||
];
|
||||
|
||||
const Item = ({item, section, 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>
|
||||
);
|
||||
};
|
||||
|
||||
type Props = {
|
||||
exampleProps: $Shape<React.ElementConfig<typeof SectionList>>,
|
||||
onTest?: ?() => void,
|
||||
testLabel?: ?string,
|
||||
testOutput?: ?string,
|
||||
children?: ?React.Node,
|
||||
};
|
||||
|
||||
const SectionListBaseExample: React.AbstractComponent<
|
||||
Props,
|
||||
React.ElementRef<typeof SectionList>,
|
||||
> = React.forwardRef((props: Props, ref): React.Node => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{props.testOutput != null ? (
|
||||
<View testID="test_container" style={styles.testContainer}>
|
||||
<Text style={styles.output} 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}
|
||||
<SectionList
|
||||
ref={ref}
|
||||
testID="section_list"
|
||||
sections={DATA}
|
||||
keyExtractor={(item, index) => item + index}
|
||||
style={styles.list}
|
||||
renderItem={Item}
|
||||
renderSectionHeader={({section: {title}}) => (
|
||||
<Text style={styles.header}>{title}</Text>
|
||||
)}
|
||||
{...props.exampleProps}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
item: {
|
||||
backgroundColor: 'pink',
|
||||
padding: 20,
|
||||
marginVertical: 8,
|
||||
},
|
||||
header: {
|
||||
fontSize: 32,
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
title: {
|
||||
fontSize: 24,
|
||||
},
|
||||
testContainer: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#f2f2f7ff',
|
||||
height: 40,
|
||||
},
|
||||
output: {
|
||||
width: '80%',
|
||||
fontSize: 12,
|
||||
},
|
||||
list: {
|
||||
flex: 1,
|
||||
},
|
||||
container: {flex: 1},
|
||||
});
|
||||
|
||||
export default SectionListBaseExample;
|
||||
@@ -1,359 +0,0 @@
|
||||
/**
|
||||
* 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,
|
||||
SectionList,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
|
||||
import * as React from 'react';
|
||||
type SectionListProps = React.ElementProps<typeof SectionList>;
|
||||
|
||||
type ViewabilityConfig = $PropertyType<SectionListProps, 'viewabilityConfig'>;
|
||||
|
||||
const DATA = [
|
||||
{
|
||||
title: 'Main dishes',
|
||||
data: ['Pizza', 'Burger', 'Risotto'],
|
||||
},
|
||||
{
|
||||
title: 'Sides',
|
||||
data: ['French Fries', 'Onion Rings', 'Fried Shrimps'],
|
||||
},
|
||||
{
|
||||
title: 'Drinks',
|
||||
data: ['Water', 'Coke', 'Beer'],
|
||||
},
|
||||
{
|
||||
title: 'Desserts',
|
||||
data: ['Cheesecake', 'Ice Cream'],
|
||||
},
|
||||
];
|
||||
|
||||
const Item = ({item, section, 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, isSectionSeparator) => ({
|
||||
leadingItem,
|
||||
trailingItem,
|
||||
highlighted,
|
||||
hasBeenHighlighted,
|
||||
}) => {
|
||||
const text = `${
|
||||
isSectionSeparator ? 'Section ' : ''
|
||||
}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 SectionList_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 (
|
||||
<SectionListExampleWithForwardedRef
|
||||
exampleProps={exampleProps}
|
||||
testOutput={output}
|
||||
onTest={onTest}
|
||||
testLabel={exampleProps.inverted ? 'Toggle false' : 'Toggle true'}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function SectionList_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>
|
||||
<SectionListExampleWithForwardedRef
|
||||
exampleProps={exampleProps}
|
||||
testOutput={output}
|
||||
onTest={onTest}
|
||||
testLabel={'Toggle header size'}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function SectionList_stickySectionHeadersEnabled(): React.Node {
|
||||
const [output, setOutput] = React.useState(
|
||||
'stickySectionHeadersEnabled false',
|
||||
);
|
||||
const [exampleProps, setExampleProps] = React.useState({
|
||||
stickySectionHeadersEnabled: false,
|
||||
});
|
||||
|
||||
const onTest = () => {
|
||||
setExampleProps({
|
||||
stickySectionHeadersEnabled: !exampleProps.stickySectionHeadersEnabled,
|
||||
});
|
||||
setOutput(
|
||||
`stickySectionHeadersEnabled ${(!exampleProps.stickySectionHeadersEnabled).toString()}`,
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<SectionListExampleWithForwardedRef
|
||||
exampleProps={exampleProps}
|
||||
testOutput={output}
|
||||
onTest={onTest}
|
||||
testLabel={
|
||||
exampleProps.stickySectionHeadersEnabled ? 'Sticky Off' : 'Sticky On'
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function SectionList_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 (
|
||||
<SectionListExampleWithForwardedRef
|
||||
ref={ref}
|
||||
exampleProps={exampleProps}
|
||||
testOutput={output}
|
||||
onTest={onTest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function SectionList_withSeparators(): React.Node {
|
||||
const exampleProps = {
|
||||
ItemSeparatorComponent: Separator('lightgreen', 'green', false),
|
||||
SectionSeparatorComponent: Separator('lightblue', 'blue', true),
|
||||
};
|
||||
const ref = React.useRef(null);
|
||||
|
||||
return (
|
||||
<SectionListExampleWithForwardedRef ref={ref} exampleProps={exampleProps} />
|
||||
);
|
||||
}
|
||||
|
||||
export function SectionList_onViewableItemsChanged(props: {
|
||||
viewabilityConfig: ViewabilityConfig,
|
||||
offScreen?: ?boolean,
|
||||
horizontal?: ?boolean,
|
||||
useScrollRefScroll?: ?boolean,
|
||||
}): React.Node {
|
||||
const {viewabilityConfig, offScreen, horizontal, useScrollRefScroll} = props;
|
||||
const [output, setOutput] = React.useState('');
|
||||
const exampleProps = {
|
||||
onViewableItemsChanged: info =>
|
||||
setOutput(
|
||||
info.viewableItems
|
||||
.filter(viewToken => viewToken.index != null && viewToken.isViewable)
|
||||
.map(viewToken => viewToken.item)
|
||||
.join(', '),
|
||||
),
|
||||
viewabilityConfig,
|
||||
horizontal,
|
||||
};
|
||||
const ref = React.useRef(null);
|
||||
const onTest =
|
||||
useScrollRefScroll === true
|
||||
? () => {
|
||||
ref?.current?.getScrollResponder()?.scrollToEnd();
|
||||
}
|
||||
: null;
|
||||
|
||||
return (
|
||||
<SectionListExampleWithForwardedRef
|
||||
ref={ref}
|
||||
exampleProps={exampleProps}
|
||||
onTest={onTest}
|
||||
testOutput={output}>
|
||||
{offScreen === true ? <View style={styles.offScreen} /> : null}
|
||||
</SectionListExampleWithForwardedRef>
|
||||
);
|
||||
}
|
||||
|
||||
type Props = {
|
||||
exampleProps: $Shape<React.ElementConfig<typeof SectionList>>,
|
||||
onTest?: ?() => void,
|
||||
testLabel?: ?string,
|
||||
testOutput?: ?string,
|
||||
children?: ?React.Node,
|
||||
};
|
||||
|
||||
const SectionListExampleWithForwardedRef = React.forwardRef(
|
||||
(props: Props, ref): React.Node => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{props.testOutput != null ? (
|
||||
<View testID="test_container" style={styles.testContainer}>
|
||||
<Text style={styles.output} 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}
|
||||
<SectionList
|
||||
ref={ref}
|
||||
testID="section_list"
|
||||
sections={DATA}
|
||||
keyExtractor={(item, index) => item + index}
|
||||
style={styles.list}
|
||||
renderItem={Item}
|
||||
renderSectionHeader={({section: {title}}) => (
|
||||
<Text style={styles.header}>{title}</Text>
|
||||
)}
|
||||
{...props.exampleProps}
|
||||
/>
|
||||
</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',
|
||||
height: 40,
|
||||
},
|
||||
output: {
|
||||
width: '80%',
|
||||
fontSize: 12,
|
||||
},
|
||||
separator: {
|
||||
height: 12,
|
||||
},
|
||||
separtorText: {
|
||||
fontSize: 10,
|
||||
},
|
||||
list: {
|
||||
flex: 1,
|
||||
},
|
||||
container: {flex: 1},
|
||||
offScreen: {
|
||||
height: 1000,
|
||||
},
|
||||
});
|
||||
@@ -10,10 +10,24 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import SectionList_Scrollable from './SectionList-scrollable';
|
||||
import Scrollable from './SectionList-scrollable';
|
||||
import ContentInset from './SectionList-contentInset';
|
||||
import onEndReached from './SectionList-onEndReached';
|
||||
import onViewableItemsChanged from './SectionList-onViewableItemsChanged';
|
||||
import withSeparators from './SectionList-withSeparators';
|
||||
import stickyHeadersEnabled from './SectionList-stickyHeadersEnabled';
|
||||
import inverted from './SectionList-inverted';
|
||||
|
||||
exports.title = 'SectionList';
|
||||
exports.category = 'ListView';
|
||||
exports.documentationURL = 'https://reactnative.dev/docs/sectionlist';
|
||||
exports.description = 'Performant, scrollable list of data.';
|
||||
exports.examples = [SectionList_Scrollable];
|
||||
exports.examples = [
|
||||
ContentInset,
|
||||
onEndReached,
|
||||
onViewableItemsChanged,
|
||||
withSeparators,
|
||||
stickyHeadersEnabled,
|
||||
inverted,
|
||||
Scrollable,
|
||||
];
|
||||
|
||||
@@ -94,31 +94,6 @@ const Components: Array<RNTesterModuleInfo> = [
|
||||
category: 'Basic',
|
||||
module: require('../examples/ScrollView/ScrollViewAnimatedExample'),
|
||||
},
|
||||
{
|
||||
key: 'SectionList-onEndReached',
|
||||
module: require('../examples/SectionList/SectionList-onEndReached'),
|
||||
category: 'ListView',
|
||||
},
|
||||
{
|
||||
key: 'SectionList-inverted',
|
||||
module: require('../examples/SectionList/SectionList-inverted'),
|
||||
category: 'ListView',
|
||||
},
|
||||
{
|
||||
key: 'SectionList-onViewableItemsChanged',
|
||||
module: require('../examples/SectionList/SectionList-onViewableItemsChanged'),
|
||||
category: 'ListView',
|
||||
},
|
||||
{
|
||||
key: 'SectionList-stickyHeadersEnabled',
|
||||
module: require('../examples/SectionList/SectionList-stickyHeadersEnabled'),
|
||||
category: 'ListView',
|
||||
},
|
||||
{
|
||||
key: 'SectionList-withSeparators',
|
||||
module: require('../examples/SectionList/SectionList-withSeparators'),
|
||||
category: 'ListView',
|
||||
},
|
||||
{
|
||||
key: 'SectionListExample',
|
||||
category: 'ListView',
|
||||
|
||||
@@ -118,31 +118,6 @@ const Components: Array<RNTesterModuleInfo> = [
|
||||
module: require('../examples/ScrollView/ScrollViewAnimatedExample'),
|
||||
supportsTVOS: true,
|
||||
},
|
||||
{
|
||||
key: 'SectionList-inverted',
|
||||
module: require('../examples/SectionList/SectionList-inverted'),
|
||||
category: 'ListView',
|
||||
},
|
||||
{
|
||||
key: 'SectionList-stickyHeadersEnabled',
|
||||
module: require('../examples/SectionList/SectionList-stickyHeadersEnabled'),
|
||||
category: 'ListView',
|
||||
},
|
||||
{
|
||||
key: 'SectionList-withSeparators',
|
||||
module: require('../examples/SectionList/SectionList-withSeparators'),
|
||||
category: 'ListView',
|
||||
},
|
||||
{
|
||||
key: 'SectionList-onEndReached',
|
||||
module: require('../examples/SectionList/SectionList-onEndReached'),
|
||||
category: 'ListView',
|
||||
},
|
||||
{
|
||||
key: 'SectionList-onViewableItemsChanged',
|
||||
module: require('../examples/SectionList/SectionList-onViewableItemsChanged'),
|
||||
category: 'ListView',
|
||||
},
|
||||
{
|
||||
key: 'SectionListExample',
|
||||
module: require('../examples/SectionList/SectionListIndex'),
|
||||
|
||||
Reference in New Issue
Block a user