ActivityIndicator ES6 Class
Reviewed By: yungsters Differential Revision: D8219463 fbshipit-source-id: 7d252d15bb4a7345d156b1659b09be2a4a69ba6c
This commit is contained in:
parent
a35a238317
commit
edd7acbb1e
|
@ -10,19 +10,15 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const ColorPropType = require('ColorPropType');
|
||||
const NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
const Platform = require('Platform');
|
||||
const ProgressBarAndroid = require('ProgressBarAndroid');
|
||||
const PropTypes = require('prop-types');
|
||||
const React = require('React');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const View = require('View');
|
||||
const ViewPropTypes = require('ViewPropTypes');
|
||||
|
||||
const createReactClass = require('create-react-class');
|
||||
const requireNativeComponent = require('requireNativeComponent');
|
||||
|
||||
import type {NativeComponent} from 'ReactNative';
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
let RCTActivityIndicator;
|
||||
|
@ -31,113 +27,103 @@ const GRAY = '#999999';
|
|||
|
||||
type IndicatorSize = number | 'small' | 'large';
|
||||
|
||||
type IOSProps = $ReadOnly<{|
|
||||
/**
|
||||
* Whether the indicator should hide when not animating (true by default).
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/activityindicator.html#hideswhenstopped
|
||||
*/
|
||||
hidesWhenStopped?: ?boolean,
|
||||
|}>;
|
||||
type Props = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
...IOSProps,
|
||||
|
||||
/**
|
||||
* Whether to show the indicator (true, the default) or hide it (false).
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/activityindicator.html#animating
|
||||
*/
|
||||
animating?: ?boolean,
|
||||
|
||||
/**
|
||||
* The foreground color of the spinner (default is gray).
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/activityindicator.html#color
|
||||
*/
|
||||
color?: ?string,
|
||||
hidesWhenStopped?: ?boolean,
|
||||
|
||||
/**
|
||||
* Size of the indicator (default is 'small').
|
||||
* Passing a number to the size prop is only supported on Android.
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/activityindicator.html#size
|
||||
*/
|
||||
size?: ?IndicatorSize,
|
||||
|}>;
|
||||
|
||||
type DefaultProps = {
|
||||
animating: boolean,
|
||||
color: ?string,
|
||||
hidesWhenStopped: boolean,
|
||||
size: IndicatorSize,
|
||||
};
|
||||
|
||||
/**
|
||||
* Displays a circular loading indicator.
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/activityindicator.html
|
||||
*/
|
||||
const ActivityIndicator = ((createReactClass({
|
||||
displayName: 'ActivityIndicator',
|
||||
mixins: [NativeMethodsMixin],
|
||||
const ActivityIndicator = (
|
||||
props: $ReadOnly<{|
|
||||
...Props,
|
||||
forwardedRef?: ?React.Ref<'RCTActivityIndicatorView'>,
|
||||
|}>,
|
||||
) => {
|
||||
const {onLayout, style, forwardedRef, ...restProps} = props;
|
||||
let sizeStyle;
|
||||
|
||||
propTypes: {
|
||||
...ViewPropTypes,
|
||||
/**
|
||||
* Whether to show the indicator (true, the default) or hide it (false).
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/activityindicator.html#animating
|
||||
*/
|
||||
animating: PropTypes.bool,
|
||||
/**
|
||||
* The foreground color of the spinner (default is gray).
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/activityindicator.html#color
|
||||
*/
|
||||
color: ColorPropType,
|
||||
/**
|
||||
* Size of the indicator (default is 'small').
|
||||
* Passing a number to the size prop is only supported on Android.
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/activityindicator.html#size
|
||||
*/
|
||||
size: PropTypes.oneOfType([
|
||||
PropTypes.oneOf(['small', 'large']),
|
||||
PropTypes.number,
|
||||
]),
|
||||
/**
|
||||
* Whether the indicator should hide when not animating (true by default).
|
||||
*
|
||||
* @platform ios
|
||||
*
|
||||
* See http://facebook.github.io/react-native/docs/activityindicator.html#hideswhenstopped
|
||||
*/
|
||||
hidesWhenStopped: PropTypes.bool,
|
||||
},
|
||||
switch (props.size) {
|
||||
case 'small':
|
||||
sizeStyle = styles.sizeSmall;
|
||||
break;
|
||||
case 'large':
|
||||
sizeStyle = styles.sizeLarge;
|
||||
break;
|
||||
default:
|
||||
sizeStyle = {height: props.size, width: props.size};
|
||||
break;
|
||||
}
|
||||
|
||||
getDefaultProps(): DefaultProps {
|
||||
return {
|
||||
animating: true,
|
||||
color: Platform.OS === 'ios' ? GRAY : null,
|
||||
hidesWhenStopped: true,
|
||||
size: 'small',
|
||||
};
|
||||
},
|
||||
const nativeProps = {
|
||||
...restProps,
|
||||
ref: forwardedRef,
|
||||
style: sizeStyle,
|
||||
styleAttr: 'Normal',
|
||||
indeterminate: true,
|
||||
};
|
||||
|
||||
render() {
|
||||
const {onLayout, style, ...props} = this.props;
|
||||
let sizeStyle;
|
||||
return (
|
||||
<View onLayout={onLayout} style={[styles.container, style]}>
|
||||
{Platform.OS === 'ios' ? (
|
||||
<RCTActivityIndicator {...nativeProps} />
|
||||
) : (
|
||||
<ProgressBarAndroid {...nativeProps} />
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
switch (props.size) {
|
||||
case 'small':
|
||||
sizeStyle = styles.sizeSmall;
|
||||
break;
|
||||
case 'large':
|
||||
sizeStyle = styles.sizeLarge;
|
||||
break;
|
||||
default:
|
||||
sizeStyle = {height: props.size, width: props.size};
|
||||
break;
|
||||
}
|
||||
// $FlowFixMe - TODO T29156721 `React.forwardRef` is not defined in Flow, yet.
|
||||
const ActivityIndicatorWithRef = React.forwardRef((props: Props, ref) => {
|
||||
return <ActivityIndicator {...props} forwardedRef={ref} />;
|
||||
});
|
||||
|
||||
const nativeProps = {
|
||||
...props,
|
||||
style: sizeStyle,
|
||||
styleAttr: 'Normal',
|
||||
indeterminate: true,
|
||||
};
|
||||
|
||||
return (
|
||||
<View onLayout={onLayout} style={[styles.container, style]}>
|
||||
{Platform.OS === 'ios' ? (
|
||||
<RCTActivityIndicator {...nativeProps} />
|
||||
) : (
|
||||
<ProgressBarAndroid {...nativeProps} />
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}): any): React.ComponentType<Props>);
|
||||
ActivityIndicatorWithRef.defaultProps = {
|
||||
animating: true,
|
||||
color: Platform.OS === 'ios' ? GRAY : null,
|
||||
hidesWhenStopped: true,
|
||||
size: 'small',
|
||||
};
|
||||
ActivityIndicatorWithRef.displayName = 'ActivityIndicator';
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
RCTActivityIndicator = requireNativeComponent(
|
||||
'RCTActivityIndicatorView',
|
||||
ActivityIndicator,
|
||||
null,
|
||||
{nativeOnly: {activityIndicatorViewStyle: true}},
|
||||
);
|
||||
}
|
||||
|
@ -157,4 +143,4 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
module.exports = ActivityIndicator;
|
||||
module.exports = (ActivityIndicatorWithRef: Class<NativeComponent<Props>>);
|
||||
|
|
|
@ -20,9 +20,24 @@ module.exports = (moduleName, instanceMethods) => {
|
|||
render() {
|
||||
const name = RealComponent.displayName || RealComponent.name;
|
||||
|
||||
const props = Object.assign({}, RealComponent.defaultProps);
|
||||
|
||||
if (this.props) {
|
||||
Object.keys(this.props).forEach(prop => {
|
||||
// We can't just assign props on top of defaultProps
|
||||
// because React treats undefined as special and different from null.
|
||||
// If a prop is specified but set to undefined it is ignored and the
|
||||
// default prop is used instead. If it is set to null, then the
|
||||
// null value overwrites the default value.
|
||||
if (this.props[prop] !== undefined) {
|
||||
props[prop] = this.props[prop];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return React.createElement(
|
||||
name.replace(/^(RCT|RK)/, ''),
|
||||
this.props,
|
||||
props,
|
||||
this.props.children,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue