UNPKG

create-expo-cljs-app

Version:

Create a react native application with Expo and Shadow-CLJS!

587 lines (550 loc) 19.6 kB
/** * 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 * @format */ import type { ViewProps } from '../../../exports/View'; import type { ViewabilityConfig, ViewToken, ViewabilityConfigCallbackPair } from '../ViewabilityHelper'; import Batchinator from '../Batchinator'; import FillRateHelper from '../FillRateHelper'; import PropTypes from 'prop-types'; import * as React from 'react'; import RefreshControl from '../../../exports/RefreshControl'; import ScrollView from '../../../exports/ScrollView'; import StyleSheet from '../../../exports/StyleSheet'; import UIManager from '../../../exports/UIManager'; import View from '../../../exports/View'; import ViewabilityHelper from '../ViewabilityHelper'; import findNodeHandle from '../../../exports/findNodeHandle'; const flattenStyle = StyleSheet.flatten; import infoLog from '../infoLog'; import invariant from 'fbjs/lib/invariant'; import warning from 'fbjs/lib/warning'; import { computeWindowedRenderLimits } from '../VirtualizeUtils'; import { VirtualizedListCellContextProvider, VirtualizedListContext, VirtualizedListContextProvider, type ChildListState, type ListDebugInfo } from './VirtualizedListContext.js'; type Item = any; type ViewStyleProp = $PropertyType<ViewProps, 'style'>; export type renderItemType = (info: any) => ?React.Element<any>; const __DEV__ = process.env.NODE_ENV !== 'production'; export type Separators = { highlight: () => void, unhighlight: () => void, updateProps: (select: 'leading' | 'trailing', newProps: Object) => void, ... }; export type RenderItemProps<ItemT> = { item: ItemT, index: number, separators: Separators, ... }; export type RenderItemType<ItemT> = (info: RenderItemProps<ItemT>) => React.Node; type ViewabilityHelperCallbackTuple = { viewabilityHelper: ViewabilityHelper, onViewableItemsChanged: (info: { viewableItems: Array<ViewToken>, changed: Array<ViewToken>, ... }) => void, ... }; type RequiredProps = {| /** * The default accessor functions assume this is an Array<{key: string} | {id: string}> but you can override * getItem, getItemCount, and keyExtractor to handle any type of index-based data. */ data?: any, /** * A generic accessor for extracting an item from any sort of data blob. */ getItem: (data: any, index: number) => ?Item, /** * Determines how many items are in the data blob. */ getItemCount: (data: any) => number, |}; type OptionalProps = {| renderItem?: ?RenderItemType<Item>, /** * `debug` will turn on extra logging and visual overlays to aid with debugging both usage and * implementation, but with a significant perf hit. */ debug?: ?boolean, /** * DEPRECATED: Virtualization provides significant performance and memory optimizations, but fully * unmounts react instances that are outside of the render window. You should only need to disable * this for debugging purposes. */ disableVirtualization?: ?boolean, /** * A marker property for telling the list to re-render (since it implements `PureComponent`). If * any of your `renderItem`, Header, Footer, etc. functions depend on anything outside of the * `data` prop, stick it here and treat it immutably. */ extraData?: any, // e.g. height, y getItemLayout?: (data: any, index: number) => { length: number, offset: number, index: number, ... }, horizontal?: ?boolean, /** * How many items to render in the initial batch. This should be enough to fill the screen but not * much more. Note these items will never be unmounted as part of the windowed rendering in order * to improve perceived performance of scroll-to-top actions. */ initialNumToRender: number, /** * Instead of starting at the top with the first item, start at `initialScrollIndex`. This * disables the "scroll to top" optimization that keeps the first `initialNumToRender` items * always rendered and immediately renders the items starting at this initial index. Requires * `getItemLayout` to be implemented. */ initialScrollIndex?: ?number, /** * Reverses the direction of scroll. Uses scale transforms of -1. */ inverted?: ?boolean, keyExtractor: (item: Item, index: number) => string, /** * Each cell is rendered using this element. Can be a React Component Class, * or a render function. Defaults to using View. */ CellRendererComponent?: ?React.ComponentType<any>, /** * Rendered in between each item, but not at the top or bottom. By default, `highlighted` and * `leadingItem` props are provided. `renderItem` provides `separators.highlight`/`unhighlight` * which will update the `highlighted` prop, but you can also add custom props with * `separators.updateProps`. */ ItemSeparatorComponent?: ?React.ComponentType<any>, /** * Takes an item from `data` and renders it into the list. Example usage: * * <FlatList * ItemSeparatorComponent={Platform.OS !== 'android' && ({highlighted}) => ( * <View style={[style.separator, highlighted && {marginLeft: 0}]} /> * )} * data={[{title: 'Title Text', key: 'item1'}]} * ListItemComponent={({item, separators}) => ( * <TouchableHighlight * onPress={() => this._onPress(item)} * onShowUnderlay={separators.highlight} * onHideUnderlay={separators.unhighlight}> * <View style={{backgroundColor: 'white'}}> * <Text>{item.title}</Text> * </View> * </TouchableHighlight> * )} * /> * * Provides additional metadata like `index` if you need it, as well as a more generic * `separators.updateProps` function which let's you set whatever props you want to change the * rendering of either the leading separator or trailing separator in case the more common * `highlight` and `unhighlight` (which set the `highlighted: boolean` prop) are insufficient for * your use-case. */ ListItemComponent?: ?(React.ComponentType<any> | React.Element<any>), /** * Rendered when the list is empty. Can be a React Component Class, a render function, or * a rendered element. */ ListEmptyComponent?: ?(React.ComponentType<any> | React.Element<any>), /** * Rendered at the bottom of all the items. Can be a React Component Class, a render function, or * a rendered element. */ ListFooterComponent?: ?(React.ComponentType<any> | React.Element<any>), /** * Styling for internal View for ListFooterComponent */ ListFooterComponentStyle?: ViewStyleProp, /** * Rendered at the top of all the items. Can be a React Component Class, a render function, or * a rendered element. */ ListHeaderComponent?: ?(React.ComponentType<any> | React.Element<any>), /** * Styling for internal View for ListHeaderComponent */ ListHeaderComponentStyle?: ViewStyleProp, /** * A unique identifier for this list. If there are multiple VirtualizedLists at the same level of * nesting within another VirtualizedList, this key is necessary for virtualization to * work properly. */ listKey?: string, /** * The maximum number of items to render in each incremental render batch. The more rendered at * once, the better the fill rate, but responsiveness may suffer because rendering content may * interfere with responding to button taps or other interactions. */ maxToRenderPerBatch: number, /** * Called once when the scroll position gets within `onEndReachedThreshold` of the rendered * content. */ onEndReached?: ?(info: { distanceFromEnd: number, ... }) => void, /** * How far from the end (in units of visible length of the list) the bottom edge of the * list must be from the end of the content to trigger the `onEndReached` callback. * Thus a value of 0.5 will trigger `onEndReached` when the end of the content is * within half the visible length of the list. */ onEndReachedThreshold?: ?number, /** * If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make * sure to also set the `refreshing` prop correctly. */ onRefresh?: ?() => void, /** * Used to handle failures when scrolling to an index that has not been measured yet. Recommended * action is to either compute your own offset and `scrollTo` it, or scroll as far as possible and * then try again after more items have been rendered. */ onScrollToIndexFailed?: ?(info: { index: number, highestMeasuredFrameIndex: number, averageItemLength: number, ... }) => void, /** * Called when the viewability of rows changes, as defined by the * `viewabilityConfig` prop. */ onViewableItemsChanged?: ?(info: { viewableItems: Array<ViewToken>, changed: Array<ViewToken>, ... }) => void, persistentScrollbar?: ?boolean, /** * Set this when offset is needed for the loading indicator to show correctly. * @platform android */ progressViewOffset?: number, /** * A custom refresh control element. When set, it overrides the default * <RefreshControl> component built internally. The onRefresh and refreshing * props are also ignored. Only works for vertical VirtualizedList. */ refreshControl?: ?React.Element<any>, /** * Set this true while waiting for new data from a refresh. */ refreshing?: ?boolean, /** * Note: may have bugs (missing content) in some circumstances - use at your own risk. * * This may improve scroll performance for large lists. */ removeClippedSubviews?: boolean, /** * Render a custom scroll component, e.g. with a differently styled `RefreshControl`. */ renderScrollComponent?: (props: Object) => React.Element<any>, /** * Amount of time between low-pri item render batches, e.g. for rendering items quite a ways off * screen. Similar fill rate/responsiveness tradeoff as `maxToRenderPerBatch`. */ updateCellsBatchingPeriod: number, /** * See `ViewabilityHelper` for flow type and further documentation. */ viewabilityConfig?: ViewabilityConfig, /** * List of ViewabilityConfig/onViewableItemsChanged pairs. A specific onViewableItemsChanged * will be called when its corresponding ViewabilityConfig's conditions are met. */ viewabilityConfigCallbackPairs?: Array<ViewabilityConfigCallbackPair>, /** * Determines the maximum number of items rendered outside of the visible area, in units of * visible lengths. So if your list fills the screen, then `windowSize={21}` (the default) will * render the visible screen area plus up to 10 screens above and 10 below the viewport. Reducing * this number will reduce memory consumption and may improve performance, but will increase the * chance that fast scrolling may reveal momentary blank areas of unrendered content. */ windowSize: number, /** * The legacy implementation is no longer supported. */ legacyImplementation?: empty, |}; type Props = {| // $FlowFixMe: View should be changed to an exact type in the future ...React.ElementConfig<typeof ScrollView>, ...RequiredProps, ...OptionalProps, |}; type DefaultProps = {| disableVirtualization: boolean, horizontal: boolean, initialNumToRender: number, keyExtractor: (item: Item, index: number) => string, maxToRenderPerBatch: number, onEndReachedThreshold: number, scrollEventThrottle: number, updateCellsBatchingPeriod: number, windowSize: number, |}; let _usedIndexForKey = false; let _keylessItemComponentName: string = ''; type State = { first: number, last: number, }; /** * Base implementation for the more convenient [`<FlatList>`](https://reactnative.dev/docs/flatlist.html) * and [`<SectionList>`](https://reactnative.dev/docs/sectionlist.html) components, which are also better * documented. In general, this should only really be used if you need more flexibility than * `FlatList` provides, e.g. for use with immutable data instead of plain arrays. * * Virtualization massively improves memory consumption and performance of large lists by * maintaining a finite render window of active items and replacing all items outside of the render * window with appropriately sized blank space. The window adapts to scrolling behavior, and items * are rendered incrementally with low-pri (after any running interactions) if they are far from the * visible area, or with hi-pri otherwise to minimize the potential of seeing blank space. * * Some caveats: * * - Internal state is not preserved when content scrolls out of the render window. Make sure all * your data is captured in the item data or external stores like Flux, Redux, or Relay. * - This is a `PureComponent` which means that it will not re-render if `props` remain shallow- * equal. Make sure that everything your `renderItem` function depends on is passed as a prop * (e.g. `extraData`) that is not `===` after updates, otherwise your UI may not update on * changes. This includes the `data` prop and parent component state. * - In order to constrain memory and enable smooth scrolling, content is rendered asynchronously * offscreen. This means it's possible to scroll faster than the fill rate ands momentarily see * blank content. This is a tradeoff that can be adjusted to suit the needs of each application, * and we are working on improving it behind the scenes. * - By default, the list looks for a `key` or `id` prop on each item and uses that for the React key. * Alternatively, you can provide a custom `keyExtractor` prop. * */ declare class VirtualizedList extends React.PureComponent<Props, State> { static contextType: typeof VirtualizedListContext, scrollToEnd(params?: ?{ animated?: ?boolean, ... }): any, scrollToIndex(params: { animated?: ?boolean, index: number, viewOffset?: number, viewPosition?: number, ... }): any, scrollToItem(params: { animated?: ?boolean, item: Item, viewPosition?: number, ... }): any, scrollToOffset(params: { animated?: ?boolean, offset: number, ... }): any, recordInteraction(): any, flashScrollIndicators(): any, getScrollResponder(): ?typeof ScrollView, getScrollableNode(): ?number, getScrollRef(): ?React.ElementRef<typeof ScrollView> | ?React.ElementRef<typeof View>, setNativeProps(props: Object): any, static defaultProps: DefaultProps, _getCellKey(): string, _getListKey(): string, _getDebugInfo(): ListDebugInfo, _getScrollMetrics: any, hasMore(): boolean, _getOutermostParentListRef: any, _getNestedChildState: any, _registerAsNestedChild: any, _unregisterAsNestedChild: any, state: State, constructor(props: Props): any, componentDidMount(): any, componentWillUnmount(): any, static getDerivedStateFromProps(newProps: Props, prevState: State): State, _pushCells(cells: Array<Object>, stickyHeaderIndices: Array<number>, stickyIndicesFromProps: Set<number>, first: number, last: number, inversionStyle: ViewStyleProp): any, _onUpdateSeparators: any, _isVirtualizationDisabled(): boolean, _isNestedWithSameOrientation(): boolean, render(): React.Node, componentDidUpdate(prevProps: Props): any, _averageCellLength: any, _cellKeysToChildListKeys: Map<string, Set<string>>, _cellRefs: any, _fillRateHelper: FillRateHelper, _frames: any, _footerLength: any, _hasDoneInitialScroll: any, _hasInteracted: any, _hasMore: any, _hasWarned: any, _headerLength: any, _hiPriInProgress: boolean, _highestMeasuredFrameIndex: any, _indicesToKeys: Map<number, string>, _nestedChildLists: Map<string, { ref: ?VirtualizedList, state: ?ChildListState, ... }>, _offsetFromParentVirtualizedList: number, _prevParentOffset: number, _scrollMetrics: any, _scrollRef: ?React.ElementRef<any>, _sentEndForContentLength: any, _totalCellLength: any, _totalCellsMeasured: any, _updateCellsToRenderBatcher: Batchinator, _viewabilityTuples: Array<ViewabilityHelperCallbackTuple>, _captureScrollRef: any, _computeBlankness(): any, _defaultRenderScrollComponent: any, _onCellLayout(e: any, cellKey: any, index: any): any, _onCellUnmount: any, _triggerRemeasureForChildListsInCell(cellKey: string): void, measureLayoutRelativeToContainingList(): void, _onLayout: any, _onLayoutEmpty: any, _getFooterCellKey(): string, _onLayoutFooter: any, _onLayoutHeader: any, _renderDebugOverlay(): any, _selectLength(metrics: $ReadOnly<{ height: number, width: number, ... }>): number, _selectOffset(metrics: $ReadOnly<{ x: number, y: number, ... }>): number, _maybeCallOnEndReached(): any, _onContentSizeChange: any, _convertParentScrollMetrics: any, _onScroll: any, _scheduleCellsToRenderUpdate(): any, _onScrollBeginDrag: any, _onScrollEndDrag: any, _onMomentumScrollBegin: any, _onMomentumScrollEnd: any, _updateCellsToRender: any, _createViewToken: any, _getFrameMetricsApprox: any, _getFrameMetrics: any, _updateViewableItems(data: any): any, } type CellRendererProps = { CellRendererComponent?: ?React.ComponentType<any>, ItemSeparatorComponent: ?React.ComponentType<*>, cellKey: string, fillRateHelper: FillRateHelper, horizontal: ?boolean, index: number, inversionStyle: ViewStyleProp, item: Item, // This is extracted by ScrollViewStickyHeader onLayout: (event: Object) => void, onUnmount: (cellKey: string) => void, onUpdateSeparators: (cellKeys: Array<?string>, props: Object) => void, parentProps: { // e.g. height, y, getItemLayout?: (data: any, index: number) => { length: number, offset: number, index: number, ... }, renderItem?: ?RenderItemType<Item>, ListItemComponent?: ?(React.ComponentType<any> | React.Element<any>), ... }, prevCellKey: ?string, ... }; type CellRendererState = { separatorProps: $ReadOnly<{| highlighted: boolean, leadingItem: ?Item, |}>, ... }; declare class CellRenderer extends React.Component<CellRendererProps, CellRendererState> { state: any, static getDerivedStateFromProps(props: CellRendererProps, prevState: CellRendererState): ?CellRendererState, _separators: any, updateSeparatorProps(newProps: Object): any, componentWillUnmount(): any, _renderElement(renderItem: any, ListItemComponent: any, item: any, index: any): any, render(): any, } declare function describeNestedLists(childList: { +cellKey: string, +key: string, +ref: VirtualizedList, +parentDebugInfo: ListDebugInfo, +horizontal: boolean, ... }): any; const styles = StyleSheet.create({ verticallyInverted: { transform: [{ scaleY: -1 }] }, horizontallyInverted: { transform: [{ scaleX: -1 }] }, row: { flexDirection: 'row' }, rowReverse: { flexDirection: 'row-reverse' }, columnReverse: { flexDirection: 'column-reverse' }, debug: { flex: 1 }, debugOverlayBase: { position: 'absolute', top: 0, right: 0 }, debugOverlay: { bottom: 0, width: 20, borderColor: 'blue', borderWidth: 1 }, debugOverlayFrame: { left: 0, backgroundColor: 'orange' }, debugOverlayFrameLast: { left: 0, borderColor: 'green', borderWidth: 2 }, debugOverlayFrameVis: { left: 0, borderColor: 'red', borderWidth: 2 } }); export default VirtualizedList;