diff --git a/Libraries/Components/ScrollView/InternalScrollViewType.js b/Libraries/Components/ScrollView/InternalScrollViewType.js index a1d42bb46a6d29..471e25d9a5dab9 100644 --- a/Libraries/Components/ScrollView/InternalScrollViewType.js +++ b/Libraries/Components/ScrollView/InternalScrollViewType.js @@ -22,7 +22,8 @@ class InternalScrollViewType extends ReactNative.NativeComponent { ) {} flashScrollIndicators() {} - scrollToEnd(options?: {animated?: boolean}) {} + propTypes: empty; + scrollToEnd(options?: ?{animated?: boolean}) {} scrollWithoutAnimationTo(y: number = 0, x: number = 0) {} getScrollResponder(): any {} diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index 6ad41c6b7cc36b..7665527f5ad8c4 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -11,20 +11,13 @@ 'use strict'; const AnimatedImplementation = require('AnimatedImplementation'); -const ColorPropType = require('ColorPropType'); -const EdgeInsetsPropType = require('EdgeInsetsPropType'); const Platform = require('Platform'); -const PointPropType = require('PointPropType'); -const PropTypes = require('prop-types'); const React = require('React'); const ReactNative = require('ReactNative'); const ScrollResponder = require('ScrollResponder'); const ScrollViewStickyHeader = require('ScrollViewStickyHeader'); const StyleSheet = require('StyleSheet'); -const StyleSheetPropType = require('StyleSheetPropType'); const View = require('View'); -const ViewPropTypes = require('ViewPropTypes'); -const ViewStylePropTypes = require('ViewStylePropTypes'); const InternalScrollViewType = require('InternalScrollViewType'); const createReactClass = require('create-react-class'); @@ -531,95 +524,6 @@ export type Props = $ReadOnly<{| */ const ScrollView = createReactClass({ displayName: 'ScrollView', - propTypes: { - ...ViewPropTypes, - automaticallyAdjustContentInsets: PropTypes.bool, - contentInset: EdgeInsetsPropType, - contentOffset: PointPropType, - bounces: PropTypes.bool, - bouncesZoom: PropTypes.bool, - alwaysBounceHorizontal: PropTypes.bool, - alwaysBounceVertical: PropTypes.bool, - centerContent: PropTypes.bool, - contentContainerStyle: StyleSheetPropType(ViewStylePropTypes), - decelerationRate: PropTypes.oneOfType([ - PropTypes.oneOf(['fast', 'normal']), - PropTypes.number, - ]), - horizontal: PropTypes.bool, - indicatorStyle: PropTypes.oneOf([ - 'default', // default - 'black', - 'white', - ]), - invertStickyHeaders: PropTypes.bool, - directionalLockEnabled: PropTypes.bool, - canCancelContentTouches: PropTypes.bool, - keyboardDismissMode: PropTypes.oneOf([ - 'none', // default - 'on-drag', // Cross-platform - 'interactive', // iOS-only - ]), - keyboardShouldPersistTaps: PropTypes.oneOf([ - 'always', - 'never', - 'handled', - false, - true, - ]), - maintainVisibleContentPosition: PropTypes.shape({ - minIndexForVisible: PropTypes.number.isRequired, - autoscrollToTopThreshold: PropTypes.number, - }), - maximumZoomScale: PropTypes.number, - minimumZoomScale: PropTypes.number, - nestedScrollEnabled: PropTypes.bool, - onMomentumScrollBegin: PropTypes.func, - onMomentumScrollEnd: PropTypes.func, - onScroll: PropTypes.func, - onScrollBeginDrag: PropTypes.func, - onScrollEndDrag: PropTypes.func, - onContentSizeChange: PropTypes.func, - pagingEnabled: PropTypes.bool, - pinchGestureEnabled: PropTypes.bool, - scrollEnabled: PropTypes.bool, - scrollEventThrottle: PropTypes.number, - scrollIndicatorInsets: EdgeInsetsPropType, - scrollsToTop: PropTypes.bool, - showsHorizontalScrollIndicator: PropTypes.bool, - showsVerticalScrollIndicator: PropTypes.bool, - stickyHeaderIndices: PropTypes.arrayOf(PropTypes.number), - snapToInterval: PropTypes.number, - snapToAlignment: PropTypes.oneOf([ - 'start', // default - 'center', - 'end', - ]), - removeClippedSubviews: PropTypes.bool, - zoomScale: PropTypes.number, - contentInsetAdjustmentBehavior: PropTypes.oneOf([ - 'automatic', - 'scrollableAxes', - 'never', // default - 'always', - ]), - refreshControl: PropTypes.element, - - endFillColor: ColorPropType, - - scrollPerfTag: PropTypes.string, - - overScrollMode: PropTypes.oneOf(['auto', 'always', 'never']), - DEPRECATED_sendUpdatedChildFrames: PropTypes.bool, - scrollBarThumbImage: PropTypes.oneOfType([ - PropTypes.shape({ - uri: PropTypes.string, - }), - // Opaque type returned by import IMAGE from './image.jpg' - PropTypes.number, - ]), - }, - mixins: [ScrollResponder.Mixin], _scrollAnimatedValue: (new AnimatedImplementation.Value( @@ -637,11 +541,9 @@ const ScrollView = createReactClass({ UNSAFE_componentWillMount: function() { this._scrollAnimatedValue = new AnimatedImplementation.Value( - // $FlowFixMe this.props.contentOffset ? this.props.contentOffset.y : 0, ); this._scrollAnimatedValue.setOffset( - // $FlowFixMe this.props.contentInset ? this.props.contentInset.top : 0, ); this._stickyHeaderRefs = new Map(); @@ -784,7 +686,6 @@ const ScrollView = createReactClass({ if (!this.props.stickyHeaderIndices) { return; } - // $FlowFixMe Invalid prop usage const childArray = React.Children.toArray(this.props.children); if (key !== this._getKeyForIndex(index, childArray)) { // ignore stale layout update @@ -794,10 +695,8 @@ const ScrollView = createReactClass({ const layoutY = event.nativeEvent.layout.y; this._headerLayoutYs.set(key, layoutY); - // $FlowFixMe Invalid prop usage const indexOfIndex = this.props.stickyHeaderIndices.indexOf(index); const previousHeaderIndex = this.props.stickyHeaderIndices[ - // $FlowFixMe Invalid prop usage indexOfIndex - 1 ]; if (previousHeaderIndex != null) { @@ -918,16 +817,13 @@ const ScrollView = createReactClass({ const hasStickyHeaders = stickyHeaderIndices && stickyHeaderIndices.length > 0; const childArray = - // $FlowFixMe Invalid prop usage hasStickyHeaders && React.Children.toArray(this.props.children); const children = hasStickyHeaders ? // $FlowFixMe Invalid prop usage childArray.map((child, index) => { - // $FlowFixMe Invalid prop usage const indexOfIndex = child ? stickyHeaderIndices.indexOf(index) : -1; if (indexOfIndex > -1) { const key = child.key; - // $FlowFixMe Invalid prop usage const nextIndex = stickyHeaderIndices[indexOfIndex + 1]; return ( {Platform.isTV ? null : refreshControl} {contentContainer} @@ -1058,7 +952,6 @@ const ScrollView = createReactClass({ {contentContainer} , @@ -1066,7 +959,6 @@ const ScrollView = createReactClass({ } } return ( - // $FlowFixMe Invalid prop usage {contentContainer} diff --git a/Libraries/Components/WebView/WebView.ios.js b/Libraries/Components/WebView/WebView.ios.js index ca91bc3b877edc..56290df97bcf94 100644 --- a/Libraries/Components/WebView/WebView.ios.js +++ b/Libraries/Components/WebView/WebView.ios.js @@ -203,7 +203,10 @@ class WebView extends React.Component { * - fast: 0.99 (the default for iOS web view) * @platform ios */ - decelerationRate: ScrollView.propTypes.decelerationRate, + decelerationRate: PropTypes.oneOfType([ + PropTypes.oneOf(['fast', 'normal']), + PropTypes.number, + ]), /** * Boolean value that determines whether scrolling is enabled in the * `WebView`. The default value is `true`. diff --git a/Libraries/Lists/ListView/ListView.js b/Libraries/Lists/ListView/ListView.js index 10ab9aef3101e9..bed5dbda2e2f93 100644 --- a/Libraries/Lists/ListView/ListView.js +++ b/Libraries/Lists/ListView/ListView.js @@ -13,7 +13,6 @@ const InternalListViewType = require('InternalListViewType'); const ListViewDataSource = require('ListViewDataSource'); const Platform = require('Platform'); const React = require('React'); -const PropTypes = require('prop-types'); const ReactNative = require('ReactNative'); const RCTScrollViewManager = require('NativeModules').ScrollViewManager; const ScrollView = require('ScrollView'); @@ -37,22 +36,124 @@ const DEFAULT_SCROLL_CALLBACK_THROTTLE = 50; type Props = $ReadOnly<{| ...ScrollViewProps, + /** + * An instance of [ListView.DataSource](docs/listviewdatasource.html) to use + */ dataSource: ListViewDataSource, + /** + * (sectionID, rowID, adjacentRowHighlighted) => renderable + * + * If provided, a renderable component to be rendered as the separator + * below each row but not the last row if there is a section header below. + * Take a sectionID and rowID of the row above and whether its adjacent row + * is highlighted. + */ renderSeparator?: ?Function, + /** + * (rowData, sectionID, rowID, highlightRow) => renderable + * + * Takes a data entry from the data source and its ids and should return + * a renderable component to be rendered as the row. By default the data + * is exactly what was put into the data source, but it's also possible to + * provide custom extractors. ListView can be notified when a row is + * being highlighted by calling `highlightRow(sectionID, rowID)`. This + * sets a boolean value of adjacentRowHighlighted in renderSeparator, allowing you + * to control the separators above and below the highlighted row. The highlighted + * state of a row can be reset by calling highlightRow(null). + */ renderRow: Function, + /** + * How many rows to render on initial component mount. Use this to make + * it so that the first screen worth of data appears at one time instead of + * over the course of multiple frames. + */ initialListSize?: ?number, + /** + * Called when all rows have been rendered and the list has been scrolled + * to within onEndReachedThreshold of the bottom. The native scroll + * event is provided. + */ onEndReached?: ?Function, + /** + * Threshold in pixels (virtual, not physical) for calling onEndReached. + */ onEndReachedThreshold?: ?number, + /** + * Number of rows to render per event loop. Note: if your 'rows' are actually + * cells, i.e. they don't span the full width of your view (as in the + * ListViewGridLayoutExample), you should set the pageSize to be a multiple + * of the number of cells per row, otherwise you're likely to see gaps at + * the edge of the ListView as new pages are loaded. + */ pageSize?: ?number, + /** + * () => renderable + * + * The header and footer are always rendered (if these props are provided) + * on every render pass. If they are expensive to re-render, wrap them + * in StaticContainer or other mechanism as appropriate. Footer is always + * at the bottom of the list, and header at the top, on every render pass. + * In a horizontal ListView, the header is rendered on the left and the + * footer on the right. + */ renderFooter?: ?Function, renderHeader?: ?Function, + /** + * (sectionData, sectionID) => renderable + * + * If provided, a header is rendered for this section. + */ renderSectionHeader?: ?Function, + /** + * (props) => renderable + * + * A function that returns the scrollable component in which the list rows + * are rendered. Defaults to returning a ScrollView with the given props. + */ renderScrollComponent?: ?Function, + /** + * How early to start rendering rows before they come on screen, in + * pixels. + */ scrollRenderAheadDistance?: ?number, + /** + * (visibleRows, changedRows) => void + * + * Called when the set of visible rows changes. `visibleRows` maps + * { sectionID: { rowID: true }} for all the visible rows, and + * `changedRows` maps { sectionID: { rowID: true | false }} for the rows + * that have changed their visibility, with true indicating visible, and + * false indicating the view has moved out of view. + */ onChangeVisibleRows?: ?Function, + /** + * A performance optimization for improving scroll perf of + * large lists, used in conjunction with overflow: 'hidden' on the row + * containers. This is enabled by default. + */ removeClippedSubviews?: ?boolean, + /** + * Makes the sections headers sticky. The sticky behavior means that it + * will scroll with the content at the top of the section until it reaches + * the top of the screen, at which point it will stick to the top until it + * is pushed off the screen by the next section header. This property is + * not supported in conjunction with `horizontal={true}`. Only enabled by + * default on iOS because of typical platform standards. + */ stickySectionHeadersEnabled?: ?boolean, + /** + * An array of child indices determining which children get docked to the + * top of the screen when scrolling. For example, passing + * `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the + * top of the scroll view. This property is not supported in conjunction + * with `horizontal={true}`. + */ stickyHeaderIndices?: ?$ReadOnlyArray, + /** + * Flag indicating whether empty section headers should be rendered. In the future release + * empty section headers will be rendered by default, and the flag will be deprecated. + * If empty sections are not desired to be rendered their indices should be excluded from sectionID object. + */ enableEmptySections?: ?boolean, |}>; @@ -128,136 +229,6 @@ const ListView = createReactClass({ DataSource: ListViewDataSource, }, - /** - * You must provide a renderRow function. If you omit any of the other render - * functions, ListView will simply skip rendering them. - * - * - renderRow(rowData, sectionID, rowID, highlightRow); - * - renderSectionHeader(sectionData, sectionID); - */ - propTypes: { - ...ScrollView.propTypes, - /** - * An instance of [ListView.DataSource](docs/listviewdatasource.html) to use - */ - dataSource: PropTypes.instanceOf(ListViewDataSource).isRequired, - /** - * (sectionID, rowID, adjacentRowHighlighted) => renderable - * - * If provided, a renderable component to be rendered as the separator - * below each row but not the last row if there is a section header below. - * Take a sectionID and rowID of the row above and whether its adjacent row - * is highlighted. - */ - renderSeparator: PropTypes.func, - /** - * (rowData, sectionID, rowID, highlightRow) => renderable - * - * Takes a data entry from the data source and its ids and should return - * a renderable component to be rendered as the row. By default the data - * is exactly what was put into the data source, but it's also possible to - * provide custom extractors. ListView can be notified when a row is - * being highlighted by calling `highlightRow(sectionID, rowID)`. This - * sets a boolean value of adjacentRowHighlighted in renderSeparator, allowing you - * to control the separators above and below the highlighted row. The highlighted - * state of a row can be reset by calling highlightRow(null). - */ - renderRow: PropTypes.func.isRequired, - /** - * How many rows to render on initial component mount. Use this to make - * it so that the first screen worth of data appears at one time instead of - * over the course of multiple frames. - */ - initialListSize: PropTypes.number.isRequired, - /** - * Called when all rows have been rendered and the list has been scrolled - * to within onEndReachedThreshold of the bottom. The native scroll - * event is provided. - */ - onEndReached: PropTypes.func, - /** - * Threshold in pixels (virtual, not physical) for calling onEndReached. - */ - onEndReachedThreshold: PropTypes.number.isRequired, - /** - * Number of rows to render per event loop. Note: if your 'rows' are actually - * cells, i.e. they don't span the full width of your view (as in the - * ListViewGridLayoutExample), you should set the pageSize to be a multiple - * of the number of cells per row, otherwise you're likely to see gaps at - * the edge of the ListView as new pages are loaded. - */ - pageSize: PropTypes.number.isRequired, - /** - * () => renderable - * - * The header and footer are always rendered (if these props are provided) - * on every render pass. If they are expensive to re-render, wrap them - * in StaticContainer or other mechanism as appropriate. Footer is always - * at the bottom of the list, and header at the top, on every render pass. - * In a horizontal ListView, the header is rendered on the left and the - * footer on the right. - */ - renderFooter: PropTypes.func, - renderHeader: PropTypes.func, - /** - * (sectionData, sectionID) => renderable - * - * If provided, a header is rendered for this section. - */ - renderSectionHeader: PropTypes.func, - /** - * (props) => renderable - * - * A function that returns the scrollable component in which the list rows - * are rendered. Defaults to returning a ScrollView with the given props. - */ - renderScrollComponent: PropTypes.func.isRequired, - /** - * How early to start rendering rows before they come on screen, in - * pixels. - */ - scrollRenderAheadDistance: PropTypes.number.isRequired, - /** - * (visibleRows, changedRows) => void - * - * Called when the set of visible rows changes. `visibleRows` maps - * { sectionID: { rowID: true }} for all the visible rows, and - * `changedRows` maps { sectionID: { rowID: true | false }} for the rows - * that have changed their visibility, with true indicating visible, and - * false indicating the view has moved out of view. - */ - onChangeVisibleRows: PropTypes.func, - /** - * A performance optimization for improving scroll perf of - * large lists, used in conjunction with overflow: 'hidden' on the row - * containers. This is enabled by default. - */ - removeClippedSubviews: PropTypes.bool, - /** - * Makes the sections headers sticky. The sticky behavior means that it - * will scroll with the content at the top of the section until it reaches - * the top of the screen, at which point it will stick to the top until it - * is pushed off the screen by the next section header. This property is - * not supported in conjunction with `horizontal={true}`. Only enabled by - * default on iOS because of typical platform standards. - */ - stickySectionHeadersEnabled: PropTypes.bool, - /** - * An array of child indices determining which children get docked to the - * top of the screen when scrolling. For example, passing - * `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the - * top of the scroll view. This property is not supported in conjunction - * with `horizontal={true}`. - */ - stickyHeaderIndices: PropTypes.arrayOf(PropTypes.number).isRequired, - /** - * Flag indicating whether empty section headers should be rendered. In the future release - * empty section headers will be rendered by default, and the flag will be deprecated. - * If empty sections are not desired to be rendered their indices should be excluded from sectionID object. - */ - enableEmptySections: PropTypes.bool, - }, - /** * Exports some data, e.g. for perf investigations or analytics. */ @@ -296,7 +267,7 @@ const ListView = createReactClass({ * * See `ScrollView#scrollTo`. */ - scrollTo: function(...args: Array) { + scrollTo: function(...args: any) { if (this._scrollComponent && this._scrollComponent.scrollTo) { this._scrollComponent.scrollTo(...args); } @@ -312,7 +283,7 @@ const ListView = createReactClass({ * * See `ScrollView#scrollToEnd`. */ - scrollToEnd: function(options?: ?{animated?: ?boolean}) { + scrollToEnd: function(options?: ?{animated?: boolean}) { if (this._scrollComponent) { if (this._scrollComponent.scrollToEnd) { this._scrollComponent.scrollToEnd(options); @@ -366,7 +337,7 @@ const ListView = createReactClass({ }, getInnerViewNode: function() { - return this._scrollComponent.getInnerViewNode(); + return this._scrollComponent && this._scrollComponent.getInnerViewNode(); }, UNSAFE_componentWillMount: function() {