diff --git a/packages/rn-tester/js/examples/SectionList/SectionList-contentInset.js b/packages/rn-tester/js/examples/SectionList/SectionList-contentInset.js new file mode 100644 index 00000000000..4cd05f4c402 --- /dev/null +++ b/packages/rn-tester/js/examples/SectionList/SectionList-contentInset.js @@ -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 ( + <> + + Menu + + + + ); +} +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 { + return ; + }, +}; diff --git a/packages/rn-tester/js/examples/SectionList/SectionList-inverted.js b/packages/rn-tester/js/examples/SectionList/SectionList-inverted.js index 98d9f45787a..926faf026a8 100644 --- a/packages/rn-tester/js/examples/SectionList/SectionList-inverted.js +++ b/packages/rn-tester/js/examples/SectionList/SectionList-inverted.js @@ -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 { - return ; - }, +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 ( + + ); +} + +export default { + title: 'SectionList Inverted', + name: 'SectionList-inverted', + render: function(): React.Element { + return ; }, -]; +}; diff --git a/packages/rn-tester/js/examples/SectionList/SectionList-onEndReached.js b/packages/rn-tester/js/examples/SectionList/SectionList-onEndReached.js index 80abda2f911..a8ba9549473 100644 --- a/packages/rn-tester/js/examples/SectionList/SectionList-onEndReached.js +++ b/packages/rn-tester/js/examples/SectionList/SectionList-onEndReached.js @@ -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 { - return ; - }, +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 ( + + ); +} + +export default { + title: 'SectionList Inverted', + name: 'SectionList-onEndReached', + render: function(): React.Element { + return ; }, -]; +}; diff --git a/packages/rn-tester/js/examples/SectionList/SectionList-onViewableItemsChanged.js b/packages/rn-tester/js/examples/SectionList/SectionList-onViewableItemsChanged.js index 872e8b6831a..92a5f35e3c0 100644 --- a/packages/rn-tester/js/examples/SectionList/SectionList-onViewableItemsChanged.js +++ b/packages/rn-tester/js/examples/SectionList/SectionList-onViewableItemsChanged.js @@ -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 ( - - ); - }, +type SectionListProps = React.ElementProps; +type ViewabilityConfig = $PropertyType; + +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 ( + + {offScreen === true ? : null} + + ); +} +const styles = StyleSheet.create({ + offScreen: { + height: 1000, }, -]; +}); + +export default { + title: 'SectionList On Viewable Items Changed', + name: 'SectionList_onViewableItemsChanged', + render: function(): React.Element { + return ( + + ); + }, +}; diff --git a/packages/rn-tester/js/examples/SectionList/SectionList-stickyHeadersEnabled.js b/packages/rn-tester/js/examples/SectionList/SectionList-stickyHeadersEnabled.js index 7edc4589561..a7e602b5557 100644 --- a/packages/rn-tester/js/examples/SectionList/SectionList-stickyHeadersEnabled.js +++ b/packages/rn-tester/js/examples/SectionList/SectionList-stickyHeadersEnabled.js @@ -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 ; - }, +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 ( + + ); +} + +export default { + title: 'SectionList Sticky Headers Enabled', + name: 'SectionList-stickyHeadersEnabled', + render: function(): React.Element< + typeof SectionList_stickySectionHeadersEnabled, + > { + return ; }, -]; +}; diff --git a/packages/rn-tester/js/examples/SectionList/SectionList-withSeparators.js b/packages/rn-tester/js/examples/SectionList/SectionList-withSeparators.js index bd0fcfd0ba5..106c172e760 100644 --- a/packages/rn-tester/js/examples/SectionList/SectionList-withSeparators.js +++ b/packages/rn-tester/js/examples/SectionList/SectionList-withSeparators.js @@ -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 { - return ; - }, +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 ( + + {text} + + ); +}; + +export function SectionList_withSeparators(): React.Node { + const exampleProps = { + ItemSeparatorComponent: Separator('lightgreen', 'green', false), + SectionSeparatorComponent: Separator('lightblue', 'blue', true), + }; + const ref = React.useRef(null); + + return ; +} + +const styles = StyleSheet.create({ + separator: { + height: 12, }, -]; + separtorText: { + fontSize: 10, + }, +}); + +export default { + title: 'SectionList With Separators', + name: 'SectionList-withSeparators', + render: function(): React.Element { + return ; + }, +}; diff --git a/packages/rn-tester/js/examples/SectionList/SectionListBaseExample.js b/packages/rn-tester/js/examples/SectionList/SectionListBaseExample.js new file mode 100644 index 00000000000..4f50a5393ee --- /dev/null +++ b/packages/rn-tester/js/examples/SectionList/SectionListBaseExample.js @@ -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 ( + { + 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}> + {item} + + ); +}; + +type Props = { + exampleProps: $Shape>, + onTest?: ?() => void, + testLabel?: ?string, + testOutput?: ?string, + children?: ?React.Node, +}; + +const SectionListBaseExample: React.AbstractComponent< + Props, + React.ElementRef, +> = React.forwardRef((props: Props, ref): React.Node => { + return ( + + {props.testOutput != null ? ( + + + {props.testOutput} + + {props.onTest != null ? ( +