2015-03-11 02:11:28 +00:00
|
|
|
/**
|
2015-03-23 22:07:33 +00:00
|
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
|
|
*
|
2018-02-17 02:24:55 +00:00
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
2015-03-11 02:11:28 +00:00
|
|
|
*
|
|
|
|
*
|
2015-03-17 20:42:44 +00:00
|
|
|
* This is a controlled component version of RCTPickerIOS
|
2018-05-11 02:06:46 +00:00
|
|
|
*
|
|
|
|
* @format
|
2018-06-10 01:05:12 +00:00
|
|
|
* @flow
|
2015-03-11 02:11:28 +00:00
|
|
|
*/
|
2018-05-11 02:06:46 +00:00
|
|
|
|
2015-03-11 02:11:28 +00:00
|
|
|
'use strict';
|
|
|
|
|
2018-03-03 23:04:46 +00:00
|
|
|
const React = require('React');
|
2018-05-14 07:09:23 +00:00
|
|
|
const ReactNative = require('ReactNative');
|
2018-03-03 23:04:46 +00:00
|
|
|
const StyleSheet = require('StyleSheet');
|
|
|
|
const View = require('View');
|
|
|
|
const processColor = require('processColor');
|
|
|
|
const requireNativeComponent = require('requireNativeComponent');
|
2015-03-11 02:11:28 +00:00
|
|
|
|
2018-06-10 01:05:12 +00:00
|
|
|
import type {SyntheticEvent} from 'CoreEventTypes';
|
2018-05-14 07:09:23 +00:00
|
|
|
import type {ColorValue} from 'StyleSheetTypes';
|
|
|
|
import type {ViewProps} from 'ViewPropTypes';
|
2018-06-10 01:05:12 +00:00
|
|
|
import type {TextStyleProp} from 'StyleSheet';
|
|
|
|
|
|
|
|
type PickerIOSChangeEvent = SyntheticEvent<
|
|
|
|
$ReadOnly<{|
|
|
|
|
newValue: any,
|
|
|
|
newIndex: number,
|
|
|
|
|}>,
|
|
|
|
>;
|
|
|
|
|
|
|
|
type RCTPickerIOSItemType = $ReadOnly<{|
|
|
|
|
label: ?Label,
|
|
|
|
value: ?any,
|
|
|
|
textColor: ?number,
|
|
|
|
|}>;
|
|
|
|
|
|
|
|
type RCTPickerIOSType = Class<
|
|
|
|
ReactNative.NativeComponent<
|
|
|
|
$ReadOnly<{|
|
|
|
|
items: $ReadOnlyArray<RCTPickerIOSItemType>,
|
|
|
|
onChange: (event: PickerIOSChangeEvent) => void,
|
|
|
|
onResponderTerminationRequest: () => boolean,
|
|
|
|
onStartShouldSetResponder: () => boolean,
|
|
|
|
selectedIndex: number,
|
|
|
|
style?: ?TextStyleProp,
|
|
|
|
|}>,
|
|
|
|
>,
|
|
|
|
>;
|
|
|
|
|
|
|
|
const RCTPickerIOS: RCTPickerIOSType = (requireNativeComponent(
|
|
|
|
'RCTPicker',
|
|
|
|
): any);
|
|
|
|
|
|
|
|
type Label = Stringish | number;
|
2018-05-14 07:09:23 +00:00
|
|
|
|
|
|
|
type Props = $ReadOnly<{|
|
|
|
|
...ViewProps,
|
2018-06-10 01:05:12 +00:00
|
|
|
children: React.ChildrenArray<React.Element<typeof PickerIOSItem>>,
|
|
|
|
itemStyle?: ?TextStyleProp,
|
|
|
|
onChange?: ?(event: PickerIOSChangeEvent) => mixed,
|
|
|
|
onValueChange?: ?(newValue: any, newIndex: number) => mixed,
|
|
|
|
selectedValue: any,
|
|
|
|
|}>;
|
|
|
|
|
|
|
|
type State = {|
|
|
|
|
selectedIndex: number,
|
|
|
|
items: $ReadOnlyArray<RCTPickerIOSItemType>,
|
|
|
|
|};
|
|
|
|
|
|
|
|
type ItemProps = $ReadOnly<{|
|
|
|
|
label: ?Label,
|
2018-05-14 07:09:23 +00:00
|
|
|
value?: ?any,
|
2018-06-10 01:05:12 +00:00
|
|
|
color?: ?ColorValue,
|
2018-05-14 07:09:23 +00:00
|
|
|
|}>;
|
|
|
|
|
2018-06-10 01:05:12 +00:00
|
|
|
const PickerIOSItem = (props: ItemProps) => {
|
|
|
|
return null;
|
|
|
|
};
|
2015-03-11 02:11:28 +00:00
|
|
|
|
2018-06-10 01:05:12 +00:00
|
|
|
class PickerIOS extends React.Component<Props, State> {
|
|
|
|
_picker: ?React.ElementRef<RCTPickerIOSType> = null;
|
2015-03-11 02:11:28 +00:00
|
|
|
|
2018-06-10 01:05:12 +00:00
|
|
|
state = {
|
|
|
|
selectedIndex: 0,
|
|
|
|
items: [],
|
|
|
|
};
|
2015-03-11 02:11:28 +00:00
|
|
|
|
2018-06-10 01:05:12 +00:00
|
|
|
static Item = PickerIOSItem;
|
2015-03-11 02:11:28 +00:00
|
|
|
|
2018-06-10 01:05:12 +00:00
|
|
|
static getDerivedStateFromProps(props: Props): State {
|
2018-03-03 23:04:46 +00:00
|
|
|
let selectedIndex = 0;
|
|
|
|
const items = [];
|
2018-05-11 02:06:46 +00:00
|
|
|
React.Children.toArray(props.children).forEach(function(child, index) {
|
2015-03-11 02:11:28 +00:00
|
|
|
if (child.props.value === props.selectedValue) {
|
|
|
|
selectedIndex = index;
|
|
|
|
}
|
2016-12-04 02:46:20 +00:00
|
|
|
items.push({
|
|
|
|
value: child.props.value,
|
|
|
|
label: child.props.label,
|
|
|
|
textColor: processColor(child.props.color),
|
|
|
|
});
|
2015-03-11 02:11:28 +00:00
|
|
|
});
|
|
|
|
return {selectedIndex, items};
|
2018-06-10 01:05:12 +00:00
|
|
|
}
|
2016-02-19 14:49:41 +00:00
|
|
|
|
2018-06-10 01:05:12 +00:00
|
|
|
render() {
|
2015-03-11 02:11:28 +00:00
|
|
|
return (
|
|
|
|
<View style={this.props.style}>
|
2015-03-17 20:42:44 +00:00
|
|
|
<RCTPickerIOS
|
2018-06-10 01:05:12 +00:00
|
|
|
ref={picker => {
|
|
|
|
this._picker = picker;
|
|
|
|
}}
|
2015-12-08 15:44:56 +00:00
|
|
|
style={[styles.pickerIOS, this.props.itemStyle]}
|
2015-03-11 02:11:28 +00:00
|
|
|
items={this.state.items}
|
|
|
|
selectedIndex={this.state.selectedIndex}
|
|
|
|
onChange={this._onChange}
|
2016-11-08 02:01:09 +00:00
|
|
|
onStartShouldSetResponder={() => true}
|
|
|
|
onResponderTerminationRequest={() => false}
|
2015-03-11 02:11:28 +00:00
|
|
|
/>
|
|
|
|
</View>
|
|
|
|
);
|
2018-06-10 01:05:12 +00:00
|
|
|
}
|
2015-03-11 02:11:28 +00:00
|
|
|
|
2018-06-10 01:05:12 +00:00
|
|
|
_onChange = event => {
|
2015-03-11 02:11:28 +00:00
|
|
|
if (this.props.onChange) {
|
|
|
|
this.props.onChange(event);
|
|
|
|
}
|
|
|
|
if (this.props.onValueChange) {
|
2018-05-11 02:06:46 +00:00
|
|
|
this.props.onValueChange(
|
|
|
|
event.nativeEvent.newValue,
|
|
|
|
event.nativeEvent.newIndex,
|
|
|
|
);
|
2015-03-11 02:11:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// The picker is a controlled component. This means we expect the
|
|
|
|
// on*Change handlers to be in charge of updating our
|
|
|
|
// `selectedValue` prop. That way they can also
|
|
|
|
// disallow/undo/mutate the selection of certain values. In other
|
|
|
|
// words, the embedder of this component should be the source of
|
|
|
|
// truth, not the native component.
|
2018-05-11 02:06:46 +00:00
|
|
|
if (
|
|
|
|
this._picker &&
|
|
|
|
this.state.selectedIndex !== event.nativeEvent.newIndex
|
|
|
|
) {
|
2015-12-04 14:56:41 +00:00
|
|
|
this._picker.setNativeProps({
|
2018-05-11 02:06:46 +00:00
|
|
|
selectedIndex: this.state.selectedIndex,
|
2015-03-11 02:11:28 +00:00
|
|
|
});
|
|
|
|
}
|
2016-07-26 08:00:02 +00:00
|
|
|
};
|
2018-05-14 07:09:23 +00:00
|
|
|
}
|
|
|
|
|
2018-03-03 23:04:46 +00:00
|
|
|
const styles = StyleSheet.create({
|
2015-06-05 15:46:17 +00:00
|
|
|
pickerIOS: {
|
2015-03-11 02:11:28 +00:00
|
|
|
// 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.
|
2016-04-26 11:20:56 +00:00
|
|
|
height: 216,
|
2015-03-11 02:11:28 +00:00
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2018-06-10 01:05:12 +00:00
|
|
|
module.exports = PickerIOS;
|