123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- /**
- * 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 strict-local
- */
- // This is a controlled component version of RCTPickerIOS.
- 'use strict';
- const React = require('react');
- const StyleSheet = require('../../StyleSheet/StyleSheet');
- const View = require('../View/View');
- const invariant = require('invariant');
- const processColor = require('../../StyleSheet/processColor');
- import RCTPickerNativeComponent, {
- Commands as PickerCommands,
- } from './RCTPickerNativeComponent';
- import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
- import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
- import type {ProcessedColorValue} from '../../StyleSheet/processColor';
- import type {SyntheticEvent} from '../../Types/CoreEventTypes';
- import type {ViewProps} from '../View/ViewPropTypes';
- type PickerIOSChangeEvent = SyntheticEvent<
- $ReadOnly<{|
- newValue: number | string,
- newIndex: number,
- |}>,
- >;
- type RCTPickerIOSItemType = $ReadOnly<{|
- label: ?Label,
- value: ?(number | string),
- textColor: ?ProcessedColorValue,
- |}>;
- type Label = Stringish | number;
- type Props = $ReadOnly<{|
- ...ViewProps,
- children: React.ChildrenArray<React.Element<typeof PickerIOSItem>>,
- itemStyle?: ?TextStyleProp,
- onChange?: ?(event: PickerIOSChangeEvent) => mixed,
- onValueChange?: ?(itemValue: string | number, itemIndex: number) => mixed,
- selectedValue: ?(number | string),
- accessibilityLabel?: ?string,
- |}>;
- type State = {|
- selectedIndex: number,
- items: $ReadOnlyArray<RCTPickerIOSItemType>,
- |};
- type ItemProps = $ReadOnly<{|
- label: ?Label,
- value?: ?(number | string),
- color?: ?ColorValue,
- |}>;
- const PickerIOSItem = (props: ItemProps): null => {
- return null;
- };
- class PickerIOS extends React.Component<Props, State> {
- _picker: ?React.ElementRef<typeof RCTPickerNativeComponent> = null;
- _lastNativeValue: ?number;
- state: State = {
- selectedIndex: 0,
- items: [],
- };
- static Item: (props: ItemProps) => null = PickerIOSItem;
- static getDerivedStateFromProps(props: Props): State {
- let selectedIndex = 0;
- const items = [];
- React.Children.toArray(props.children)
- .filter(child => child !== null)
- .forEach(function(child, index) {
- if (child.props.value === props.selectedValue) {
- selectedIndex = index;
- }
- const processedTextColor = processColor(child.props.color);
- invariant(
- processedTextColor == null || typeof processedTextColor === 'number',
- 'Unexpected color given for PickerIOSItem color',
- );
- items.push({
- value: child.props.value,
- label: child.props.label,
- textColor: processedTextColor,
- });
- });
- return {selectedIndex, items};
- }
- render(): React.Node {
- return (
- <View style={this.props.style}>
- <RCTPickerNativeComponent
- ref={picker => {
- this._picker = picker;
- }}
- testID={this.props.testID}
- style={[styles.pickerIOS, this.props.itemStyle]}
- items={this.state.items}
- selectedIndex={this.state.selectedIndex}
- onChange={this._onChange}
- accessibilityLabel={this.props.accessibilityLabel}
- />
- </View>
- );
- }
- componentDidUpdate() {
- // This is necessary in case native updates the picker and JS decides
- // that the update should be ignored and we should stick with the value
- // that we have in JS.
- if (
- this._picker &&
- this._lastNativeValue !== undefined &&
- this._lastNativeValue !== this.state.selectedIndex
- ) {
- PickerCommands.setNativeSelectedIndex(
- this._picker,
- this.state.selectedIndex,
- );
- }
- }
- _onChange = event => {
- if (this.props.onChange) {
- this.props.onChange(event);
- }
- if (this.props.onValueChange) {
- this.props.onValueChange(
- event.nativeEvent.newValue,
- event.nativeEvent.newIndex,
- );
- }
- this._lastNativeValue = event.nativeEvent.newIndex;
- this.forceUpdate();
- };
- }
- const styles = StyleSheet.create({
- pickerIOS: {
- // The picker will conform to whatever width is given, but we do
- // have to set the component's height explicitly on the
- // surrounding view to ensure it gets rendered.
- height: 216,
- },
- });
- module.exports = PickerIOS;
|