Remove Picker from OSS
Summary: Changelog: [General][Removed] - Remove Picker/PickerIOS export from react-native and delete JS related code Reviewed By: kacieb Differential Revision: D29122947 fbshipit-source-id: 9f754396d1f221fde57ec4dec8e29af598432102
This commit is contained in:
Родитель
fafd2903f1
Коммит
ad0ccac0d6
|
@ -1,83 +0,0 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
import codegenNativeCommands from '../../Utilities/codegenNativeCommands';
|
||||
|
||||
import type {
|
||||
DirectEventHandler,
|
||||
Int32,
|
||||
WithDefault,
|
||||
} from '../../Types/CodegenTypes';
|
||||
import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry';
|
||||
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
|
||||
import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
|
||||
import type {ColorValue} from '../../StyleSheet/StyleSheet';
|
||||
import type {ProcessedColorValue} from '../../StyleSheet/processColor';
|
||||
import type {ViewProps} from '../../Components/View/ViewPropTypes';
|
||||
|
||||
type PickerItem = $ReadOnly<{|
|
||||
label: string,
|
||||
color?: ?ProcessedColorValue,
|
||||
|}>;
|
||||
|
||||
type PickerItemSelectEvent = $ReadOnly<{|
|
||||
position: Int32,
|
||||
|}>;
|
||||
|
||||
type NativeProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
style?: ?TextStyleProp,
|
||||
|
||||
// Props
|
||||
color?: ?ColorValue,
|
||||
backgroundColor?: ?ColorValue,
|
||||
enabled?: WithDefault<boolean, true>,
|
||||
items: $ReadOnlyArray<PickerItem>,
|
||||
prompt?: WithDefault<string, ''>,
|
||||
selected: Int32,
|
||||
|
||||
// Events
|
||||
onSelect?: DirectEventHandler<PickerItemSelectEvent>,
|
||||
|}>;
|
||||
|
||||
type NativeType = HostComponent<NativeProps>;
|
||||
|
||||
interface NativeCommands {
|
||||
+setNativeSelectedPosition: (
|
||||
viewRef: React.ElementRef<NativeType>,
|
||||
index: number,
|
||||
) => void;
|
||||
}
|
||||
|
||||
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
|
||||
supportedCommands: ['setNativeSelectedPosition'],
|
||||
});
|
||||
|
||||
const AndroidDialogPickerNativeComponent: HostComponent<NativeProps> = NativeComponentRegistry.get<NativeProps>(
|
||||
'AndroidDialogPicker',
|
||||
() => ({
|
||||
uiViewClassName: 'AndroidDialogPicker',
|
||||
bubblingEventTypes: {},
|
||||
directEventTypes: {},
|
||||
validAttributes: {
|
||||
color: {process: require('../../StyleSheet/processColor')},
|
||||
backgroundColor: {process: require('../../StyleSheet/processColor')},
|
||||
enabled: true,
|
||||
items: true,
|
||||
prompt: true,
|
||||
selected: true,
|
||||
onSelect: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export default ((AndroidDialogPickerNativeComponent: any): NativeType);
|
|
@ -1,82 +0,0 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
import codegenNativeCommands from '../../Utilities/codegenNativeCommands';
|
||||
|
||||
import type {
|
||||
DirectEventHandler,
|
||||
Int32,
|
||||
WithDefault,
|
||||
} from '../../Types/CodegenTypes';
|
||||
|
||||
import * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry';
|
||||
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
|
||||
import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
|
||||
import type {ColorValue} from '../../StyleSheet/StyleSheet';
|
||||
import type {ProcessedColorValue} from '../../StyleSheet/processColor';
|
||||
import type {ViewProps} from '../../Components/View/ViewPropTypes';
|
||||
|
||||
type PickerItem = $ReadOnly<{|
|
||||
label: string,
|
||||
color?: ?ProcessedColorValue,
|
||||
|}>;
|
||||
|
||||
type PickerItemSelectEvent = $ReadOnly<{|
|
||||
position: Int32,
|
||||
|}>;
|
||||
|
||||
type NativeProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
style?: ?TextStyleProp,
|
||||
|
||||
// Props
|
||||
color?: ?ColorValue,
|
||||
backgroundColor?: ?ColorValue,
|
||||
enabled?: WithDefault<boolean, true>,
|
||||
items: $ReadOnlyArray<PickerItem>,
|
||||
prompt?: WithDefault<string, ''>,
|
||||
selected: Int32,
|
||||
|
||||
// Events
|
||||
onSelect?: DirectEventHandler<PickerItemSelectEvent>,
|
||||
|}>;
|
||||
|
||||
interface NativeCommands {
|
||||
+setNativeSelectedPosition: (
|
||||
viewRef: React.ElementRef<typeof AndroidDropdownPickerNativeComponent>,
|
||||
index: number,
|
||||
) => void;
|
||||
}
|
||||
|
||||
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
|
||||
supportedCommands: ['setNativeSelectedPosition'],
|
||||
});
|
||||
|
||||
const AndroidDropdownPickerNativeComponent: HostComponent<NativeProps> = NativeComponentRegistry.get<NativeProps>(
|
||||
'AndroidDropdownPicker',
|
||||
() => ({
|
||||
uiViewClassName: 'AndroidDropdownPicker',
|
||||
bubblingEventTypes: {},
|
||||
directEventTypes: {},
|
||||
validAttributes: {
|
||||
color: {process: require('../../StyleSheet/processColor')},
|
||||
backgroundColor: {process: require('../../StyleSheet/processColor')},
|
||||
enabled: true,
|
||||
items: true,
|
||||
prompt: true,
|
||||
selected: true,
|
||||
onSelect: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export default AndroidDropdownPickerNativeComponent;
|
|
@ -1,194 +0,0 @@
|
|||
/**
|
||||
* 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 * as React from 'react';
|
||||
import PickerAndroid from './PickerAndroid';
|
||||
import PickerIOS from './PickerIOS';
|
||||
import Platform from '../../Utilities/Platform';
|
||||
import UnimplementedView from '../UnimplementedViews/UnimplementedView';
|
||||
|
||||
import type {TextStyleProp, ColorValue} from '../../StyleSheet/StyleSheet';
|
||||
|
||||
import type {
|
||||
AccessibilityActionEvent,
|
||||
AccessibilityActionInfo,
|
||||
} from '../View/ViewAccessibility';
|
||||
|
||||
const MODE_DIALOG = 'dialog';
|
||||
const MODE_DROPDOWN = 'dropdown';
|
||||
|
||||
type PickerItemProps = $ReadOnly<{|
|
||||
/**
|
||||
* Text to display for this item.
|
||||
*/
|
||||
label: string,
|
||||
|
||||
/**
|
||||
* The value to be passed to picker's `onValueChange` callback when
|
||||
* this item is selected.
|
||||
*/
|
||||
value?: ?string,
|
||||
|
||||
/**
|
||||
* Color of this item's text.
|
||||
* @platform android
|
||||
*/
|
||||
color?: ColorValue,
|
||||
|
||||
/**
|
||||
* Used to locate the item in end-to-end tests.
|
||||
*/
|
||||
testID?: string,
|
||||
|}>;
|
||||
|
||||
/**
|
||||
* Individual selectable item in a Picker.
|
||||
*/
|
||||
export type {PickerItem};
|
||||
class PickerItem extends React.Component<PickerItemProps> {
|
||||
render() {
|
||||
// The items are not rendered directly
|
||||
throw null;
|
||||
}
|
||||
}
|
||||
|
||||
type PickerProps = $ReadOnly<{|
|
||||
children?: React.Node,
|
||||
style?: ?TextStyleProp,
|
||||
|
||||
/**
|
||||
* Value matching value of one of the items.
|
||||
*/
|
||||
selectedValue?: ?string,
|
||||
|
||||
/**
|
||||
* Callback for when an item is selected. This is called with the following parameters:
|
||||
* - `itemValue`: the `value` prop of the item that was selected
|
||||
* - `itemIndex`: the index of the selected item in this picker
|
||||
*/
|
||||
onValueChange?: ?(itemValue: string | number, itemIndex: number) => mixed,
|
||||
|
||||
/**
|
||||
* If set to false, the picker will be disabled, i.e. the user will not be able to make a
|
||||
* selection.
|
||||
* @platform android
|
||||
*/
|
||||
enabled?: ?boolean,
|
||||
|
||||
/**
|
||||
* On Android, specifies how to display the selection items when the user taps on the picker:
|
||||
*
|
||||
* - 'dialog': Show a modal dialog. This is the default.
|
||||
* - 'dropdown': Shows a dropdown anchored to the picker view
|
||||
*
|
||||
* @platform android
|
||||
*/
|
||||
mode?: ?('dialog' | 'dropdown'),
|
||||
|
||||
/**
|
||||
* Style to apply to each of the item labels.
|
||||
* @platform ios
|
||||
*/
|
||||
itemStyle?: ?TextStyleProp,
|
||||
|
||||
/**
|
||||
* Color of the item background.
|
||||
* @platform android
|
||||
*/
|
||||
backgroundColor?: ColorValue,
|
||||
|
||||
/**
|
||||
* Prompt string for this picker, used on Android in dialog mode as the title of the dialog.
|
||||
* @platform android
|
||||
*/
|
||||
prompt?: ?string,
|
||||
|
||||
/**
|
||||
* Used to locate this view in end-to-end tests.
|
||||
*/
|
||||
testID?: ?string,
|
||||
/**
|
||||
* The string used for the accessibility label. Will be read once focused on the picker but not on change.
|
||||
*/
|
||||
accessibilityLabel?: ?string,
|
||||
|
||||
/**
|
||||
* When `true`, indicates that the view is an accessibility element.
|
||||
* By default, all the touchable elements are accessible.
|
||||
*
|
||||
* See https://reactnative.dev/docs/view.html#accessible
|
||||
*/
|
||||
accessible?: ?boolean,
|
||||
|
||||
/**
|
||||
* Provides an array of custom actions available for accessibility.
|
||||
*
|
||||
*/
|
||||
accessibilityActions?: ?$ReadOnlyArray<AccessibilityActionInfo>,
|
||||
|
||||
/**
|
||||
* When `accessible` is true, the system will try to invoke this function
|
||||
* when the user performs an accessibility custom action.
|
||||
*
|
||||
*/
|
||||
onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed,
|
||||
|}>;
|
||||
|
||||
/**
|
||||
* Renders the native picker component on iOS and Android. Example:
|
||||
*
|
||||
* <Picker
|
||||
* selectedValue={this.state.language}
|
||||
* onValueChange={(itemValue, itemIndex) => this.setState({language: itemValue})}>
|
||||
* <Picker.Item label="Java" value="java" />
|
||||
* <Picker.Item label="JavaScript" value="js" />
|
||||
* </Picker>
|
||||
*/
|
||||
class Picker extends React.Component<PickerProps> {
|
||||
/**
|
||||
* On Android, display the options in a dialog.
|
||||
*/
|
||||
static MODE_DIALOG: $TEMPORARY$string<'dialog'> = MODE_DIALOG;
|
||||
|
||||
/**
|
||||
* On Android, display the options in a dropdown (this is the default).
|
||||
*/
|
||||
static MODE_DROPDOWN: $TEMPORARY$string<'dropdown'> = MODE_DROPDOWN;
|
||||
|
||||
static Item: typeof PickerItem = PickerItem;
|
||||
|
||||
render(): React.Node {
|
||||
const {mode = MODE_DIALOG, children, ...rest} = this.props;
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
/* $FlowFixMe[prop-missing] (>=0.81.0 site=react_native_ios_fb) This
|
||||
* suppression was added when renaming suppression sites. */
|
||||
/* $FlowFixMe[incompatible-type] (>=0.81.0 site=react_native_ios_fb) This
|
||||
* suppression was added when renaming suppression sites. */
|
||||
return <PickerIOS {...rest}>{children}</PickerIOS>;
|
||||
} else if (Platform.OS === 'android') {
|
||||
return (
|
||||
/* $FlowFixMe[incompatible-type] (>=0.81.0 site=react_native_android_fb) This
|
||||
* suppression was added when renaming suppression sites. */
|
||||
/* $FlowFixMe[prop-missing] (>=0.81.0 site=react_native_android_fb) This
|
||||
* suppression was added when renaming suppression sites. */
|
||||
<PickerAndroid mode={mode} {...rest}>
|
||||
{children}
|
||||
</PickerAndroid>
|
||||
);
|
||||
} else {
|
||||
return <UnimplementedView />;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Picker;
|
|
@ -1,154 +0,0 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
import AndroidDropdownPickerNativeComponent, {
|
||||
Commands as AndroidDropdownPickerCommands,
|
||||
} from './AndroidDropdownPickerNativeComponent';
|
||||
import AndroidDialogPickerNativeComponent, {
|
||||
Commands as AndroidDialogPickerCommands,
|
||||
} from './AndroidDialogPickerNativeComponent';
|
||||
import * as React from 'react';
|
||||
import StyleSheet from '../../StyleSheet/StyleSheet';
|
||||
import invariant from 'invariant';
|
||||
import processColor from '../../StyleSheet/processColor';
|
||||
|
||||
import type {
|
||||
AccessibilityActionEvent,
|
||||
AccessibilityActionInfo,
|
||||
} from '../View/ViewAccessibility';
|
||||
|
||||
import type {SyntheticEvent} from '../../Types/CoreEventTypes';
|
||||
import type {ColorValue, TextStyleProp} from '../../StyleSheet/StyleSheet';
|
||||
|
||||
type PickerItemSelectSyntheticEvent = SyntheticEvent<
|
||||
$ReadOnly<{|
|
||||
position: number,
|
||||
|}>,
|
||||
>;
|
||||
|
||||
type PickerItemValue = number | string;
|
||||
|
||||
type Props = $ReadOnly<{|
|
||||
accessible?: ?boolean,
|
||||
accessibilityActions?: ?$ReadOnlyArray<AccessibilityActionInfo>,
|
||||
onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed,
|
||||
accessibilityLabel?: ?Stringish,
|
||||
children?: React.Node,
|
||||
style?: ?TextStyleProp,
|
||||
backgroundColor?: ?ColorValue,
|
||||
selectedValue?: ?PickerItemValue,
|
||||
enabled?: ?boolean,
|
||||
mode?: ?('dialog' | 'dropdown'),
|
||||
onValueChange?: ?(itemValue: ?PickerItemValue, itemIndex: number) => mixed,
|
||||
prompt?: ?string,
|
||||
testID?: string,
|
||||
|}>;
|
||||
|
||||
/**
|
||||
* Not exposed as a public API - use <Picker> instead.
|
||||
*/
|
||||
function PickerAndroid(props: Props): React.Node {
|
||||
const pickerRef = React.useRef(null);
|
||||
|
||||
const [items, selected] = React.useMemo(() => {
|
||||
// eslint-disable-next-line no-shadow
|
||||
let selected = 0;
|
||||
// eslint-disable-next-line no-shadow
|
||||
const items = React.Children.map(props.children, (child, index) => {
|
||||
if (child === null) {
|
||||
return null;
|
||||
}
|
||||
if (child.props.value === props.selectedValue) {
|
||||
selected = index;
|
||||
}
|
||||
const {color, label} = child.props;
|
||||
const processedColor = processColor(color);
|
||||
invariant(
|
||||
processedColor == null || typeof processedColor === 'number',
|
||||
'Unexpected color given for PickerAndroid color prop',
|
||||
);
|
||||
return {
|
||||
color: color == null ? null : processedColor,
|
||||
label,
|
||||
};
|
||||
});
|
||||
return [items, selected];
|
||||
}, [props.children, props.selectedValue]);
|
||||
|
||||
const onSelect = React.useCallback(
|
||||
({nativeEvent}: PickerItemSelectSyntheticEvent) => {
|
||||
const {position} = nativeEvent;
|
||||
const onValueChange = props.onValueChange;
|
||||
|
||||
if (onValueChange != null) {
|
||||
if (position >= 0) {
|
||||
const children = React.Children.toArray(props.children).filter(
|
||||
item => item != null,
|
||||
);
|
||||
const value = children[position].props.value;
|
||||
if (props.selectedValue !== value) {
|
||||
onValueChange(value, position);
|
||||
}
|
||||
} else {
|
||||
onValueChange(null, position);
|
||||
}
|
||||
}
|
||||
const {current} = pickerRef;
|
||||
if (current != null && position !== selected) {
|
||||
const Commands =
|
||||
props.mode === 'dropdown'
|
||||
? AndroidDropdownPickerCommands
|
||||
: AndroidDialogPickerCommands;
|
||||
Commands.setNativeSelectedPosition(current, position);
|
||||
}
|
||||
},
|
||||
[
|
||||
props.children,
|
||||
props.onValueChange,
|
||||
props.selectedValue,
|
||||
props.mode,
|
||||
selected,
|
||||
],
|
||||
);
|
||||
|
||||
const rootProps = {
|
||||
accessible: props.accessible,
|
||||
accessibilityActions: props.accessibilityActions,
|
||||
onAccessibilityAction: props.onAccessibilityAction,
|
||||
accessibilityLabel: props.accessibilityLabel,
|
||||
enabled: props.enabled,
|
||||
items,
|
||||
onSelect,
|
||||
prompt: props.prompt,
|
||||
ref: pickerRef,
|
||||
selected,
|
||||
style: StyleSheet.compose(styles.pickerAndroid, props.style),
|
||||
backgroundColor: props.backgroundColor,
|
||||
testID: props.testID,
|
||||
};
|
||||
return props.mode === 'dropdown' ? (
|
||||
<AndroidDropdownPickerNativeComponent {...rootProps} />
|
||||
) : (
|
||||
<AndroidDialogPickerNativeComponent {...rootProps} />
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
pickerAndroid: {
|
||||
// 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.
|
||||
// TODO would be better to export a native constant for this,
|
||||
// like in iOS the RCTDatePickerManager.m
|
||||
height: 50,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = PickerAndroid;
|
|
@ -1,12 +0,0 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = require('../UnimplementedViews/UnimplementedView');
|
|
@ -1,14 +0,0 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
// This is a controlled component version of RCTPickerIOS.
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = require('../UnimplementedViews/UnimplementedView');
|
|
@ -1,163 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
|
||||
import * as React from 'react';
|
||||
import StyleSheet, {
|
||||
type TextStyleProp,
|
||||
type ColorValue,
|
||||
} from '../../StyleSheet/StyleSheet';
|
||||
import View from '../View/View';
|
||||
import invariant from 'invariant';
|
||||
import processColor, {
|
||||
type ProcessedColorValue,
|
||||
} from '../../StyleSheet/processColor';
|
||||
|
||||
import RCTPickerNativeComponent, {
|
||||
Commands as PickerCommands,
|
||||
} from './RCTPickerNativeComponent';
|
||||
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: ?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: ?string,
|
||||
accessibilityLabel?: ?string,
|
||||
|}>;
|
||||
|
||||
type State = {|
|
||||
selectedIndex: number,
|
||||
items: $ReadOnlyArray<RCTPickerIOSItemType>,
|
||||
|};
|
||||
|
||||
type ItemProps = $ReadOnly<{|
|
||||
label: ?Label,
|
||||
value?: ?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;
|
|
@ -1,86 +0,0 @@
|
|||
/**
|
||||
* 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 * as NativeComponentRegistry from '../../NativeComponent/NativeComponentRegistry';
|
||||
import ReactNativeViewViewConfig from '../../Components/View/ReactNativeViewViewConfig';
|
||||
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
|
||||
import type {SyntheticEvent} from '../../Types/CoreEventTypes';
|
||||
import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
|
||||
import type {ProcessedColorValue} from '../../StyleSheet/processColor';
|
||||
import codegenNativeCommands from '../../Utilities/codegenNativeCommands';
|
||||
import * as React from 'react';
|
||||
|
||||
type PickerIOSChangeEvent = SyntheticEvent<
|
||||
$ReadOnly<{|
|
||||
newValue: number | string,
|
||||
newIndex: number,
|
||||
|}>,
|
||||
>;
|
||||
|
||||
type RCTPickerIOSItemType = $ReadOnly<{|
|
||||
label: ?Label,
|
||||
value: ?string,
|
||||
textColor: ?ProcessedColorValue,
|
||||
|}>;
|
||||
|
||||
type Label = Stringish | number;
|
||||
|
||||
type NativeProps = $ReadOnly<{|
|
||||
items: $ReadOnlyArray<RCTPickerIOSItemType>,
|
||||
onChange: (event: PickerIOSChangeEvent) => void,
|
||||
selectedIndex: number,
|
||||
style?: ?TextStyleProp,
|
||||
testID?: ?string,
|
||||
accessibilityLabel?: ?string,
|
||||
|}>;
|
||||
|
||||
type ComponentType = HostComponent<NativeProps>;
|
||||
|
||||
interface NativeCommands {
|
||||
+setNativeSelectedIndex: (
|
||||
viewRef: React.ElementRef<ComponentType>,
|
||||
index: number,
|
||||
) => void;
|
||||
}
|
||||
|
||||
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
|
||||
supportedCommands: ['setNativeSelectedIndex'],
|
||||
});
|
||||
|
||||
const RCTPickerNativeComponent: HostComponent<NativeProps> = NativeComponentRegistry.get<NativeProps>(
|
||||
'RCTPicker',
|
||||
() => ({
|
||||
uiViewClassName: 'RCTPicker',
|
||||
bubblingEventTypes: {
|
||||
topChange: {
|
||||
phasedRegistrationNames: {
|
||||
bubbled: 'onChange',
|
||||
captured: 'onChangeCapture',
|
||||
},
|
||||
},
|
||||
},
|
||||
directEventTypes: {},
|
||||
validAttributes: {
|
||||
...ReactNativeViewViewConfig.validAttributes,
|
||||
color: {process: require('../../StyleSheet/processColor')},
|
||||
fontFamily: true,
|
||||
fontSize: true,
|
||||
fontStyle: true,
|
||||
fontWeight: true,
|
||||
items: true,
|
||||
onChange: true,
|
||||
selectedIndex: true,
|
||||
textAlign: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// flowlint-next-line unclear-type:off
|
||||
export default ((RCTPickerNativeComponent: any): HostComponent<NativeProps>);
|
|
@ -1,34 +0,0 @@
|
|||
/**
|
||||
* 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
|
||||
* @emails oncall+react_native
|
||||
* @flow strict-local
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const Picker = require('../Picker');
|
||||
|
||||
const ReactNativeTestTools = require('../../../Utilities/ReactNativeTestTools');
|
||||
|
||||
describe('<Picker />', () => {
|
||||
it('should render as expected', () => {
|
||||
ReactNativeTestTools.expectRendersMatchingSnapshot(
|
||||
'Picker',
|
||||
() => (
|
||||
<Picker selectedValue="foo" onValueChange={jest.fn()}>
|
||||
<Picker.Item label="foo" value="foo" />
|
||||
<Picker.Item label="bar" value="bar" />
|
||||
</Picker>
|
||||
),
|
||||
() => {
|
||||
jest.dontMock('../Picker');
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,95 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Picker /> should render as expected: should deep render when mocked (please verify output manually) 1`] = `
|
||||
<View>
|
||||
<RCTPicker
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"label": "foo",
|
||||
"textColor": undefined,
|
||||
"value": "foo",
|
||||
},
|
||||
Object {
|
||||
"label": "bar",
|
||||
"textColor": undefined,
|
||||
"value": "bar",
|
||||
},
|
||||
]
|
||||
}
|
||||
onChange={[Function]}
|
||||
selectedIndex={0}
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
"height": 216,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`<Picker /> should render as expected: should deep render when not mocked (please verify output manually) 1`] = `
|
||||
<View>
|
||||
<RCTPicker
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"label": "foo",
|
||||
"textColor": undefined,
|
||||
"value": "foo",
|
||||
},
|
||||
Object {
|
||||
"label": "bar",
|
||||
"textColor": undefined,
|
||||
"value": "bar",
|
||||
},
|
||||
]
|
||||
}
|
||||
onChange={[Function]}
|
||||
selectedIndex={0}
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
"height": 216,
|
||||
},
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`<Picker /> should render as expected: should shallow render as <Picker /> when mocked 1`] = `
|
||||
<Picker
|
||||
onValueChange={[MockFunction]}
|
||||
selectedValue="foo"
|
||||
>
|
||||
<PickerItem
|
||||
label="foo"
|
||||
value="foo"
|
||||
/>
|
||||
<PickerItem
|
||||
label="bar"
|
||||
value="bar"
|
||||
/>
|
||||
</Picker>
|
||||
`;
|
||||
|
||||
exports[`<Picker /> should render as expected: should shallow render as <Picker /> when not mocked 1`] = `
|
||||
<Picker
|
||||
onValueChange={[MockFunction]}
|
||||
selectedValue="foo"
|
||||
>
|
||||
<PickerItem
|
||||
label="foo"
|
||||
value="foo"
|
||||
/>
|
||||
<PickerItem
|
||||
label="bar"
|
||||
value="bar"
|
||||
/>
|
||||
</Picker>
|
||||
`;
|
53
index.js
53
index.js
|
@ -23,8 +23,6 @@ import typeof InputAccessoryView from './Libraries/Components/TextInput/InputAcc
|
|||
import typeof KeyboardAvoidingView from './Libraries/Components/Keyboard/KeyboardAvoidingView';
|
||||
import typeof MaskedViewIOS from './Libraries/Components/MaskedView/MaskedViewIOS';
|
||||
import typeof Modal from './Libraries/Modal/Modal';
|
||||
import typeof Picker from './Libraries/Components/Picker/Picker';
|
||||
import typeof PickerIOS from './Libraries/Components/Picker/PickerIOS';
|
||||
import typeof Pressable from './Libraries/Components/Pressable/Pressable';
|
||||
import typeof ProgressBarAndroid from './Libraries/Components/ProgressBarAndroid/ProgressBarAndroid';
|
||||
import typeof ProgressViewIOS from './Libraries/Components/ProgressViewIOS/ProgressViewIOS';
|
||||
|
@ -168,25 +166,6 @@ module.exports = {
|
|||
get Modal(): Modal {
|
||||
return require('./Libraries/Modal/Modal');
|
||||
},
|
||||
get Picker(): Picker {
|
||||
warnOnce(
|
||||
'picker-moved',
|
||||
'Picker has been extracted from react-native core and will be removed in a future release. ' +
|
||||
"It can now be installed and imported from '@react-native-picker/picker' instead of 'react-native'. " +
|
||||
'See https://github.com/react-native-picker/picker',
|
||||
);
|
||||
return require('./Libraries/Components/Picker/Picker');
|
||||
},
|
||||
// $FlowFixMe[value-as-type]
|
||||
get PickerIOS(): PickerIOS {
|
||||
warnOnce(
|
||||
'pickerios-moved',
|
||||
'PickerIOS has been extracted from react-native core and will be removed in a future release. ' +
|
||||
"It can now be installed and imported from '@react-native-picker/picker' instead of 'react-native'. " +
|
||||
'See https://github.com/react-native-picker/picker',
|
||||
);
|
||||
return require('./Libraries/Components/Picker/PickerIOS');
|
||||
},
|
||||
get Pressable(): Pressable {
|
||||
return require('./Libraries/Components/Pressable/Pressable').default;
|
||||
},
|
||||
|
@ -698,4 +677,36 @@ if (__DEV__) {
|
|||
);
|
||||
},
|
||||
});
|
||||
|
||||
/* $FlowFixMe[prop-missing] This is intentional: Flow will error when
|
||||
* attempting to access Picker. */
|
||||
/* $FlowFixMe[invalid-export] This is intentional: Flow will error when
|
||||
* attempting to access Picker. */
|
||||
Object.defineProperty(module.exports, 'Picker', {
|
||||
configurable: true,
|
||||
get() {
|
||||
invariant(
|
||||
false,
|
||||
'Picker has been removed from React Native. ' +
|
||||
"It can now be installed and imported from '@react-native-picker/picker' instead of 'react-native'. " +
|
||||
'See https://github.com/react-native-picker/picker',
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
/* $FlowFixMe[prop-missing] This is intentional: Flow will error when
|
||||
* attempting to access PickerIOS. */
|
||||
/* $FlowFixMe[invalid-export] This is intentional: Flow will error when
|
||||
* attempting to access PickerIOS. */
|
||||
Object.defineProperty(module.exports, 'PickerIOS', {
|
||||
configurable: true,
|
||||
get() {
|
||||
invariant(
|
||||
false,
|
||||
'PickerIOS has been removed from React Native. ' +
|
||||
"It can now be installed and imported from '@react-native-picker/picker' instead of 'react-native'. " +
|
||||
'See https://github.com/react-native-picker/picker',
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче