This commit is contained in:
Basil Hosmer 2015-03-25 12:55:10 -07:00
Родитель 18b6d5c20d
Коммит 95deed578c
22 изменённых файлов: 238 добавлений и 99 удалений

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ActivityIndicatorIOS
* @flow
*/
'use strict';
@ -29,6 +30,12 @@ var SpinnerSize = keyMirror({
var GRAY = '#999999';
type DefaultProps = {
animating: boolean;
size: 'small' | 'large';
color: string;
};
var ActivityIndicatorIOS = React.createClass({
mixins: [NativeMethodsMixin],
@ -51,7 +58,7 @@ var ActivityIndicatorIOS = React.createClass({
]),
},
getDefaultProps: function() {
getDefaultProps: function(): DefaultProps {
return {
animating: true,
size: SpinnerSize.small,

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule DatePickerIOS
* @flow
*
* This is a controlled component version of RCTDatePickerIOS
*/
@ -26,6 +27,12 @@ var merge = require('merge');
var DATEPICKER = 'datepicker';
type DefaultProps = {
mode: 'date' | 'time' | 'datetime';
};
type Event = Object;
/**
* Use `DatePickerIOS` to render a date/time picker (selector) on iOS. This is
* a controlled component, so you must hook in to the `onDateChange` callback
@ -85,13 +92,13 @@ var DatePickerIOS = React.createClass({
timeZoneOffsetInMinutes: PropTypes.number,
},
getDefaultProps: function() {
getDefaultProps: function(): DefaultProps {
return {
mode: 'datetime',
};
},
_onChange: function(event) {
_onChange: function(event: Event) {
var nativeTimeStamp = event.nativeEvent.timestamp;
this.props.onDateChange && this.props.onDateChange(
new Date(nativeTimeStamp)

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule MapView
* @flow
*/
'use strict';
@ -21,6 +22,8 @@ var deepDiffer = require('deepDiffer');
var insetsDiffer = require('insetsDiffer');
var merge = require('merge');
type Event = Object;
var MapView = React.createClass({
mixins: [NativeMethodsMixin],
@ -119,7 +122,7 @@ var MapView = React.createClass({
onRegionChangeComplete: React.PropTypes.func,
},
_onChange: function(event) {
_onChange: function(event: Event) {
if (event.nativeEvent.continuous) {
this.props.onRegionChange &&
this.props.onRegionChange(event.nativeEvent.region);

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule NavigatorIOS
* @flow
*/
'use strict';
@ -59,7 +60,7 @@ var RCTNavigatorItem = createReactIOSNativeComponentClass({
var NavigatorTransitionerIOS = React.createClass({
requestSchedulingNavigation: function(cb) {
RCTNavigatorManager.requestSchedulingJavaScriptNavigation(
this.getNodeHandle(),
(this: any).getNodeHandle(),
logError,
cb
);
@ -72,6 +73,29 @@ var NavigatorTransitionerIOS = React.createClass({
},
});
type Route = {
component: Function;
title: string;
passProps: Object;
backButtonTitle: string;
rightButtonTitle: string;
onRightButtonPress: Function;
wrapperStyle: any;
};
type State = {
idStack: Array<number>;
routeStack: Array<Route>;
requestedTopOfStack: number;
observedTopOfStack: number;
progress: number;
fromIndex: number;
toIndex: number;
makingNavigatorRequest: boolean;
updatingAllIndicesAtOrBeyond: number;
}
type Event = Object;
/**
* Think of `<NavigatorIOS>` as simply a component that renders an
@ -224,6 +248,8 @@ var NavigatorIOS = React.createClass({
},
navigator: (undefined: ?Object),
componentWillMount: function() {
// Precompute a pack of callbacks that's frequently generated and passed to
// instances.
@ -240,7 +266,7 @@ var NavigatorIOS = React.createClass({
};
},
getInitialState: function() {
getInitialState: function(): State {
return {
idStack: [getuid()],
routeStack: [this.props.initialRoute],
@ -266,7 +292,9 @@ var NavigatorIOS = React.createClass({
};
},
_handleFocusRequest: function(item) {
_toFocusOnNavigationComplete: (undefined: any),
_handleFocusRequest: function(item: any) {
if (this.state.makingNavigatorRequest) {
this._toFocusOnNavigationComplete = item;
} else {
@ -274,14 +302,22 @@ var NavigatorIOS = React.createClass({
}
},
_getFocusEmitter: function() {
if (!this._focusEmitter) {
this._focusEmitter = new EventEmitter();
_focusEmitter: (undefined: ?EventEmitter),
_getFocusEmitter: function(): EventEmitter {
// Flow not yet tracking assignments to instance fields.
var focusEmitter = this._focusEmitter;
if (!focusEmitter) {
focusEmitter = new EventEmitter();
this._focusEmitter = focusEmitter;
}
return this._focusEmitter;
return focusEmitter;
},
getChildContext: function() {
getChildContext: function(): {
onFocusRequested: Function;
focusEmitter: EventEmitter;
} {
return {
onFocusRequested: this._handleFocusRequest,
focusEmitter: this._getFocusEmitter(),
@ -293,13 +329,13 @@ var NavigatorIOS = React.createClass({
focusEmitter: React.PropTypes.instanceOf(EventEmitter),
},
_tryLockNavigator: function(cb) {
_tryLockNavigator: function(cb: () => void) {
this.refs[TRANSITIONER_REF].requestSchedulingNavigation(
(acquiredLock) => acquiredLock && cb()
);
},
_handleNavigatorStackChanged: function(e) {
_handleNavigatorStackChanged: function(e: Event) {
var newObservedTopOfStack = e.nativeEvent.stackLength - 1;
invariant(
newObservedTopOfStack <= this.state.requestedTopOfStack,
@ -352,7 +388,7 @@ var NavigatorIOS = React.createClass({
});
},
push: function(route) {
push: function(route: Route) {
invariant(!!route, 'Must supply route to push');
// Make sure all previous requests are caught up first. Otherwise reject.
if (this.state.requestedTopOfStack === this.state.observedTopOfStack) {
@ -372,7 +408,7 @@ var NavigatorIOS = React.createClass({
}
},
popN: function(n) {
popN: function(n: number) {
if (n === 0) {
return;
}
@ -406,7 +442,7 @@ var NavigatorIOS = React.createClass({
* `index` specifies the route in the stack that should be replaced.
* If it's negative, it counts from the back.
*/
replaceAtIndex: function(route, index) {
replaceAtIndex: function(route: Route, index: number) {
invariant(!!route, 'Must supply route to replace');
if (index < 0) {
index += this.state.routeStack.length;
@ -434,14 +470,14 @@ var NavigatorIOS = React.createClass({
/**
* Replaces the top of the navigation stack.
*/
replace: function(route) {
replace: function(route: Route) {
this.replaceAtIndex(route, -1);
},
/**
* Replace the current route's parent.
*/
replacePrevious: function(route) {
replacePrevious: function(route: Route) {
this.replaceAtIndex(route, -2);
},
@ -449,7 +485,7 @@ var NavigatorIOS = React.createClass({
this.popToRoute(this.state.routeStack[0]);
},
popToRoute: function(route) {
popToRoute: function(route: Route) {
var indexOfRoute = this.state.routeStack.indexOf(route);
invariant(
indexOfRoute !== -1,
@ -459,7 +495,7 @@ var NavigatorIOS = React.createClass({
this.popN(numToPop);
},
replacePreviousAndPop: function(route) {
replacePreviousAndPop: function(route: Route) {
// Make sure all previous requests are caught up first. Otherwise reject.
if (this.state.requestedTopOfStack !== this.state.observedTopOfStack) {
return;
@ -476,7 +512,7 @@ var NavigatorIOS = React.createClass({
});
},
resetTo: function(route) {
resetTo: function(route: Route) {
invariant(!!route, 'Must supply route to push');
// Make sure all previous requests are caught up first. Otherwise reject.
if (this.state.requestedTopOfStack !== this.state.observedTopOfStack) {
@ -486,7 +522,7 @@ var NavigatorIOS = React.createClass({
this.popToRoute(route);
},
handleNavigationComplete: function(e) {
handleNavigationComplete: function(e: Event) {
if (this._toFocusOnNavigationComplete) {
this._getFocusEmitter().emit('focus', this._toFocusOnNavigationComplete);
this._toFocusOnNavigationComplete = null;
@ -494,7 +530,7 @@ var NavigatorIOS = React.createClass({
this._handleNavigatorStackChanged(e);
},
_routeToStackItem: function(route, i) {
_routeToStackItem: function(route: Route, i: number) {
var Component = route.component;
var shouldUpdateChild = this.state.updatingAllIndicesAtOrBeyond !== null &&
this.state.updatingAllIndicesAtOrBeyond >= i;

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ScrollResponder
* @flow
*/
'use strict';
@ -102,10 +103,19 @@ var warning = require('warning');
var IS_ANIMATING_TOUCH_START_THRESHOLD_MS = 16;
type State = {
isTouching: boolean;
lastMomentumScrollBeginTime: number;
lastMomentumScrollEndTime: number;
observedScrollSinceBecomingResponder: boolean;
becameResponderWhileAnimating: boolean;
};
type Event = Object;
var ScrollResponderMixin = {
mixins: [Subscribable.Mixin],
statics: RCTScrollViewConsts,
scrollResponderMixinGetInitialState: function() {
scrollResponderMixinGetInitialState: function(): State {
return {
isTouching: false,
lastMomentumScrollBeginTime: 0,
@ -124,7 +134,7 @@ var ScrollResponderMixin = {
/**
* Invoke this from an `onScroll` event.
*/
scrollResponderHandleScrollShouldSetResponder: function() {
scrollResponderHandleScrollShouldSetResponder: function(): boolean {
return this.state.isTouching;
},
@ -153,7 +163,7 @@ var ScrollResponderMixin = {
* true.
*
*/
scrollResponderHandleStartShouldSetResponder: function() {
scrollResponderHandleStartShouldSetResponder: function(): boolean {
return false;
},
@ -168,7 +178,7 @@ var ScrollResponderMixin = {
*
* Invoke this from an `onStartShouldSetResponderCapture` event.
*/
scrollResponderHandleStartShouldSetResponderCapture: function(e) {
scrollResponderHandleStartShouldSetResponderCapture: function(e: Event): boolean {
// First see if we want to eat taps while the keyboard is up
var currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
if (!this.props.keyboardShouldPersistTaps &&
@ -208,7 +218,7 @@ var ScrollResponderMixin = {
* navigation of a swipe gesture higher in the view hierarchy, should be
* rejected.
*/
scrollResponderHandleTerminationRequest: function() {
scrollResponderHandleTerminationRequest: function(): boolean {
return !this.state.observedScrollSinceBecomingResponder;
},
@ -217,7 +227,7 @@ var ScrollResponderMixin = {
*
* @param {SyntheticEvent} e Event.
*/
scrollResponderHandleTouchEnd: function(e) {
scrollResponderHandleTouchEnd: function(e: Event) {
var nativeEvent = e.nativeEvent;
this.state.isTouching = nativeEvent.touches.length !== 0;
this.props.onTouchEnd && this.props.onTouchEnd(e);
@ -226,7 +236,7 @@ var ScrollResponderMixin = {
/**
* Invoke this from an `onResponderRelease` event.
*/
scrollResponderHandleResponderRelease: function(e) {
scrollResponderHandleResponderRelease: function(e: Event) {
this.props.onResponderRelease && this.props.onResponderRelease(e);
// By default scroll views will unfocus a textField
@ -243,7 +253,7 @@ var ScrollResponderMixin = {
}
},
scrollResponderHandleScroll: function(e) {
scrollResponderHandleScroll: function(e: Event) {
this.state.observedScrollSinceBecomingResponder = true;
this.props.onScroll && this.props.onScroll(e);
},
@ -251,7 +261,7 @@ var ScrollResponderMixin = {
/**
* Invoke this from an `onResponderGrant` event.
*/
scrollResponderHandleResponderGrant: function(e) {
scrollResponderHandleResponderGrant: function(e: Event) {
this.state.observedScrollSinceBecomingResponder = false;
this.props.onResponderGrant && this.props.onResponderGrant(e);
this.state.becameResponderWhileAnimating = this.scrollResponderIsAnimating();
@ -264,21 +274,21 @@ var ScrollResponderMixin = {
*
* Invoke this from an `onScrollBeginDrag` event.
*/
scrollResponderHandleScrollBeginDrag: function(e) {
scrollResponderHandleScrollBeginDrag: function(e: Event) {
this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e);
},
/**
* Invoke this from an `onScrollEndDrag` event.
*/
scrollResponderHandleScrollEndDrag: function(e) {
scrollResponderHandleScrollEndDrag: function(e: Event) {
this.props.onScrollEndDrag && this.props.onScrollEndDrag(e);
},
/**
* Invoke this from an `onMomentumScrollBegin` event.
*/
scrollResponderHandleMomentumScrollBegin: function(e) {
scrollResponderHandleMomentumScrollBegin: function(e: Event) {
this.state.lastMomentumScrollBeginTime = Date.now();
this.props.onMomentumScrollBegin && this.props.onMomentumScrollBegin(e);
},
@ -286,7 +296,7 @@ var ScrollResponderMixin = {
/**
* Invoke this from an `onMomentumScrollEnd` event.
*/
scrollResponderHandleMomentumScrollEnd: function(e) {
scrollResponderHandleMomentumScrollEnd: function(e: Event) {
this.state.lastMomentumScrollEndTime = Date.now();
this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e);
},
@ -302,7 +312,7 @@ var ScrollResponderMixin = {
*
* @param {SyntheticEvent} e Touch Start event.
*/
scrollResponderHandleTouchStart: function(e) {
scrollResponderHandleTouchStart: function(e: Event) {
this.state.isTouching = true;
this.props.onTouchStart && this.props.onTouchStart(e);
},
@ -318,7 +328,7 @@ var ScrollResponderMixin = {
*
* @param {SyntheticEvent} e Touch Start event.
*/
scrollResponderHandleTouchMove: function(e) {
scrollResponderHandleTouchMove: function(e: Event) {
this.props.onTouchMove && this.props.onTouchMove(e);
},
@ -327,7 +337,7 @@ var ScrollResponderMixin = {
* view is currently animating. This is particularly useful to know when
* a touch has just started or ended.
*/
scrollResponderIsAnimating: function() {
scrollResponderIsAnimating: function(): boolean {
var now = Date.now();
var timeSinceLastMomentumScrollEnd = now - this.state.lastMomentumScrollEndTime;
var isAnimating = timeSinceLastMomentumScrollEnd < IS_ANIMATING_TOUCH_START_THRESHOLD_MS ||
@ -340,7 +350,7 @@ var ScrollResponderMixin = {
* This is currently used to help focus on child textview's, but this
* can also be used to quickly scroll to any element we want to focus
*/
scrollResponderScrollTo: function(offsetX, offsetY) {
scrollResponderScrollTo: function(offsetX: number, offsetY: number) {
RCTUIManagerDeprecated.scrollTo(this.getNodeHandle(), offsetX, offsetY);
},
@ -348,7 +358,7 @@ var ScrollResponderMixin = {
* A helper function to zoom to a specific rect in the scrollview.
* @param {object} rect Should have shape {x, y, w, h}
*/
scrollResponderZoomTo: function(rect) {
scrollResponderZoomTo: function(rect: { x: number; y: number; w: number; h: number; }) {
RCTUIManagerDeprecated.zoomToRect(this.getNodeHandle(), rect);
},
@ -357,7 +367,7 @@ var ScrollResponderMixin = {
* parent view. Note that any module using this mixin needs to return
* the parent view's ref in getScrollViewRef() in order to use this method
*/
scrollResponderScrollNativeHandleToKeyboard: function(nodeHandle, additionalOffset) {
scrollResponderScrollNativeHandleToKeyboard: function(nodeHandle: any, additionalOffset?: number) {
this.additionalScrollOffset = additionalOffset || 0;
RCTUIManager.measureLayout(
nodeHandle,
@ -377,7 +387,7 @@ var ScrollResponderMixin = {
* @param {number} width Width of the text input.
* @param {number} height Height of the text input.
*/
scrollResponderInputMeasureAndScrollToKeyboard: function(left, top, width, height) {
scrollResponderInputMeasureAndScrollToKeyboard: function(left: number, top: number, width: number, height: number) {
if (this.keyboardWillOpenTo) {
var scrollOffsetY =
top - this.keyboardWillOpenTo.endCoordinates.screenY + height +
@ -387,7 +397,7 @@ var ScrollResponderMixin = {
this.additionalOffset = 0;
},
scrollResponderTextInputFocusError: function(e) {
scrollResponderTextInputFocusError: function(e: Event) {
console.error('Error measuring text field: ', e);
},
@ -434,12 +444,12 @@ var ScrollResponderMixin = {
* relevant to you. (For example, only if you receive these callbacks after
* you had explicitly focused a node etc).
*/
scrollResponderKeyboardWillShow: function(e) {
scrollResponderKeyboardWillShow: function(e: Event) {
this.keyboardWillOpenTo = e;
this.props.onKeyboardWillShow && this.props.onKeyboardWillShow(e);
},
scrollResponderKeyboardWillHide: function(e) {
scrollResponderKeyboardWillHide: function(e: Event) {
this.keyboardWillOpenTo = null;
this.props.onKeyboardWillHide && this.props.onKeyboardWillHide(e);
},

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ScrollView
* @flow
*/
'use strict';
@ -178,15 +179,15 @@ var ScrollView = React.createClass({
return this.scrollResponderMixinGetInitialState();
},
setNativeProps: function(props) {
setNativeProps: function(props: Object) {
this.refs[SCROLLVIEW].setNativeProps(props);
},
getInnerViewNode: function() {
getInnerViewNode: function(): any {
return this.refs[INNERVIEW].getNodeHandle();
},
scrollTo: function(destY, destX) {
scrollTo: function(destY?: number, destX?: number) {
RCTUIManager.scrollTo(
this.getNodeHandle(),
destX || 0,
@ -202,7 +203,7 @@ var ScrollView = React.createClass({
if (__DEV__ && this.props.style) {
var style = flattenStyle(this.props.style);
var childLayoutProps = ['alignItems', 'justifyContent']
.filter((prop) => style[prop] !== undefined);
.filter((prop) => style && style[prop] !== undefined);
invariant(
childLayoutProps.length === 0,
'ScrollView child layout (' + JSON.stringify(childLayoutProps) +
@ -250,7 +251,7 @@ var ScrollView = React.createClass({
keyboardDismissMode: this.props.keyboardDismissMode ?
keyboardDismissModeConstants[this.props.keyboardDismissMode] :
undefined,
style: [styles.base, this.props.style],
style: ([styles.base, this.props.style]: ?Array<any>),
onTouchStart: this.scrollResponderHandleTouchStart,
onTouchMove: this.scrollResponderHandleTouchMove,
onTouchEnd: this.scrollResponderHandleTouchEnd,
@ -279,6 +280,10 @@ var ScrollView = React.createClass({
ScrollViewClass = AndroidScrollView;
}
}
invariant(
ScrollViewClass !== undefined,
'ScrollViewClass must not be undefined'
);
return (
<ScrollViewClass {...props} ref={SCROLLVIEW}>

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule SliderIOS
* @flow
*/
'use strict';
@ -21,6 +22,8 @@ var createReactIOSNativeComponentClass =
require('createReactIOSNativeComponentClass');
var merge = require('merge');
type Event = Object;
var SliderIOS = React.createClass({
mixins: [NativeMethodsMixin],
@ -52,7 +55,7 @@ var SliderIOS = React.createClass({
onSlidingComplete: PropTypes.func,
},
_onValueChange: function(event) {
_onValueChange: function(event: Event) {
this.props.onChange && this.props.onChange(event);
if (event.nativeEvent.continuous) {
this.props.onValueChange &&

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @provides StaticRenderer
* @flow
*/
'use strict';
@ -18,11 +19,11 @@ var StaticRenderer = React.createClass({
render: React.PropTypes.func.isRequired,
},
shouldComponentUpdate: function(nextProps) {
shouldComponentUpdate: function(nextProps: { shouldUpdate: boolean }): boolean {
return nextProps.shouldUpdate;
},
render: function() {
render: function(): ReactElement {
return this.props.render();
},
});

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule Subscribable
* @flow
*/
'use strict';
@ -73,8 +74,13 @@ var logError = require('logError');
var SUBSCRIBABLE_INTERNAL_EVENT = 'subscriptionEvent';
type Data = Object;
type EventMapping = (_: Data) => Data;
class Subscribable {
_eventMapping: EventMapping;
_lastData: Data;
/**
* Creates a new Subscribable object
*
@ -88,7 +94,7 @@ class Subscribable {
* The resolved data will be transformed with the eventMapping before it
* gets emitted.
*/
constructor(eventEmitter, eventName, eventMapping, getInitData) {
constructor(eventEmitter: EventEmitter, eventName: string, eventMapping?: EventMapping, getInitData?: Function) {
this._internalEmitter = new EventEmitter();
this._eventMapping = eventMapping || (data => data);
@ -106,7 +112,7 @@ class Subscribable {
/**
* Returns the last data emitted from the Subscribable, or undefined
*/
get() {
get(): Data {
return this._lastData;
}
@ -138,7 +144,7 @@ class Subscribable {
* }
* Call `remove` to terminate the subscription before unmounting
*/
subscribe(lifespan, callback, context) {
subscribe(lifespan: { addUnmountCallback: Function }, callback: Function, context: Object) {
invariant(
typeof lifespan.addUnmountCallback === 'function',
'Must provide a valid lifespan, which provides a way to add a ' +
@ -169,7 +175,7 @@ class Subscribable {
* Callback for the initial data resolution. Currently behaves the same as
* `_handleEmit`, but we may eventually want to keep track of the difference
*/
_handleInitData(dataInput) {
_handleInitData(dataInput: Data) {
var emitData = this._eventMapping(dataInput);
this._lastData = emitData;
this._internalEmitter.emit(SUBSCRIBABLE_INTERNAL_EVENT, emitData);
@ -179,7 +185,7 @@ class Subscribable {
* Handle new data emissions. Pass the data through our eventMapping
* transformation, store it for later `get()`ing, and emit it for subscribers
*/
_handleEmit(dataInput) {
_handleEmit(dataInput: Data) {
var emitData = this._eventMapping(dataInput);
this._lastData = emitData;
this._internalEmitter.emit(SUBSCRIBABLE_INTERNAL_EVENT, emitData);
@ -280,12 +286,13 @@ Subscribable.Mixin = {
if (!this._localSubscribables) {
return;
}
var emitterSubscribables;
Object.keys(this._localSubscribables).forEach((eventEmitter) => {
emitterSubscribables = this._localSubscribables[eventEmitter];
Object.keys(emitterSubscribables).forEach((eventName) => {
emitterSubscribables[eventName].cleanup();
});
var emitterSubscribables = this._localSubscribables[eventEmitter];
if (emitterSubscribables) {
Object.keys(emitterSubscribables).forEach((eventName) => {
emitterSubscribables[eventName].cleanup();
});
}
});
this._localSubscribables = null;
},

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule SwitchIOS
* @flow
*
* This is a controlled component version of RCTSwitch.
*/
@ -23,6 +24,13 @@ var merge = require('merge');
var SWITCH = 'switch';
type DefaultProps = {
value: boolean;
disabled: boolean;
};
type Event = Object;
/**
* Use `SwitchIOS` to render a boolean input on iOS. This is
* a controlled component, so you must hook in to the `onValueChange` callback
@ -67,14 +75,14 @@ var SwitchIOS = React.createClass({
tintColor: PropTypes.string,
},
getDefaultProps: function() {
getDefaultProps: function(): DefaultProps {
return {
value: false,
disabled: false,
};
},
_onChange: function(event) {
_onChange: function(event: Event) {
this.props.onChange && this.props.onChange(event);
this.props.onValueChange && this.props.onValueChange(event.nativeEvent.value);

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule TabBarIOS
* @flow
*/
'use strict';

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule TabBarItemIOS
* @flow
*/
'use strict';
@ -43,7 +44,7 @@ var TabBarItemIOS = React.createClass({
}
},
componentWillReceiveProps: function(nextProps) {
componentWillReceiveProps: function(nextProps: { selected: boolean }) {
if (this.state.hasBeenSelected || nextProps.selected) {
this.setState({hasBeenSelected: true});
}

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule TextInput
* @flow
*/
'use strict';
@ -63,6 +64,12 @@ var notMultiline = {
onSubmitEditing: true,
};
type DefaultProps = {
bufferDelay: number;
};
type Event = Object;
/**
* A foundational component for inputting text into the app via a
* keyboard. Props provide configurability for several features, such as auto-
@ -206,12 +213,12 @@ var TextInput = React.createClass({
validAttributes: RCTTextFieldAttributes,
},
isFocused: function() {
isFocused: function(): boolean {
return TextInputState.currentlyFocusedField() ===
this.refs.input.getNativeNode();
},
getDefaultProps: function() {
getDefaultProps: function(): DefaultProps {
return {
bufferDelay: 100,
};
@ -229,6 +236,8 @@ var TextInput = React.createClass({
focusEmitter: React.PropTypes.instanceOf(EventEmitter),
},
_focusSubscription: (undefined: ?Function),
componentDidMount: function() {
if (!this.context.focusEmitter) {
if (this.props.autoFocus) {
@ -255,7 +264,9 @@ var TextInput = React.createClass({
this._focusSubscription && this._focusSubscription.remove();
},
componentWillReceiveProps: function(newProps) {
_bufferTimeout: (undefined: ?number),
componentWillReceiveProps: function(newProps: {value: any}) {
if (newProps.value !== this.props.value) {
if (!this.isFocused()) {
// Set the value immediately if the input is not focused since that
@ -385,17 +396,17 @@ var TextInput = React.createClass({
);
},
_onFocus: function(event) {
_onFocus: function(event: Event) {
if (this.props.onFocus) {
this.props.onFocus(event);
}
},
_onPress: function(event) {
_onPress: function(event: Event) {
this.focus();
},
_onChange: function(event) {
_onChange: function(event: Event) {
if (this.props.controlled && event.nativeEvent.text !== this.props.value) {
this.refs.input.setNativeProps({text: this.props.value});
}
@ -403,14 +414,14 @@ var TextInput = React.createClass({
this.props.onChangeText && this.props.onChangeText(event.nativeEvent.text);
},
_onBlur: function(event) {
_onBlur: function(event: Event) {
this.blur();
if (this.props.onBlur) {
this.props.onBlur(event);
}
},
_onSelectionChange: function(event) {
_onSelectionChange: function(event: Event) {
if (this.props.selectionState) {
var selection = event.nativeEvent.selection;
this.props.selectionState.update(selection.start, selection.end);
@ -418,7 +429,7 @@ var TextInput = React.createClass({
this.props.onSelectionChange && this.props.onSelectionChange(event);
},
_onTextInput: function(event) {
_onTextInput: function(event: Event) {
this.props.onTextInput && this.props.onTextInput(event);
var counter = event.nativeEvent.eventCounter;
if (counter > this.state.mostRecentEventCounter) {

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule TextInputState
* @flow
*
* This class is responsible for coordinating the "focused"
* state for TextInputs. All calls relating to the keyboard
@ -20,13 +21,13 @@ var TextInputState = {
/**
* Internal state
*/
_currentlyFocusedID: null,
_currentlyFocusedID: (null: ?string),
/**
* Returns the ID of the currently focused text field, if one exists
* If no text field is focused it returns null
*/
currentlyFocusedField: function() {
currentlyFocusedField: function(): ?string {
return this._currentlyFocusedID;
},
@ -35,7 +36,7 @@ var TextInputState = {
* Focuses the specified text field
* noop if the text field was already focused
*/
focusTextInput: function(textFieldID) {
focusTextInput: function(textFieldID: string) {
if (this._currentlyFocusedID != textFieldID && textFieldID != null) {
this._currentlyFocusedID = textFieldID;
RCTUIManager.focus(textFieldID);
@ -47,7 +48,7 @@ var TextInputState = {
* Unfocuses the specified text field
* noop if it wasn't focused
*/
blurTextInput: function(textFieldID) {
blurTextInput: function(textFieldID: string) {
if (this._currentlyFocusedID == textFieldID && textFieldID != null) {
this._currentlyFocusedID = null;
RCTUIManager.blur(textFieldID);

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule TouchableBounce
* @flow
*/
'use strict';
@ -20,6 +21,10 @@ var merge = require('merge');
var copyProperties = require('copyProperties');
var onlyChild = require('onlyChild');
type State = {
animationID: ?number;
};
/**
* When the scroll view is disabled, this defines how far your touch may move
* off of the button, before deactivating the button. Once deactivated, try
@ -47,11 +52,17 @@ var TouchableBounce = React.createClass({
onPressAnimationComplete: React.PropTypes.func,
},
getInitialState: function() {
getInitialState: function(): State {
return merge(this.touchableGetInitialState(), {animationID: null});
},
bounceTo: function(value, velocity, bounciness, fromValue, callback) {
bounceTo: function(
value: number,
velocity: number,
bounciness: number,
fromValue?: ?Function | number,
callback?: ?Function
) {
if (POPAnimation) {
this.state.animationID && this.removeAnimation(this.state.animationID);
var anim = {
@ -60,6 +71,7 @@ var TouchableBounce = React.createClass({
toValue: [value, value],
velocity: [velocity, velocity],
springBounciness: bounciness,
fromValue: (undefined: ?any),
};
if (fromValue) {
anim.fromValue = [fromValue, fromValue];
@ -90,8 +102,9 @@ var TouchableBounce = React.createClass({
},
touchableHandlePress: function() {
if (this.props.onPressWithCompletion) {
this.props.onPressWithCompletion(
var onPressWithCompletion = this.props.onPressWithCompletion;
if (onPressWithCompletion) {
onPressWithCompletion(
this.bounceTo.bind(this, 1, 10, 10, 0.93, this.props.onPressAnimationComplete)
);
return;
@ -101,11 +114,11 @@ var TouchableBounce = React.createClass({
this.props.onPress && this.props.onPress();
},
touchableGetPressRectOffset: function() {
touchableGetPressRectOffset: function(): typeof PRESS_RECT_OFFSET {
return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant!
},
touchableGetHighlightDelayMS: function() {
touchableGetHighlightDelayMS: function(): number {
return 0;
},

Просмотреть файл

@ -10,6 +10,8 @@
*/
'use strict';
// Note (avik): add @flow when Flow supports spread properties in propTypes
var NativeMethodsMixin = require('NativeMethodsMixin');
var React = require('React');
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');

Просмотреть файл

@ -10,6 +10,8 @@
*/
'use strict';
// Note (avik): add @flow when Flow supports spread properties in propTypes
var NativeMethodsMixin = require('NativeMethodsMixin');
var POPAnimationMixin = require('POPAnimationMixin');
var React = require('React');

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule TouchableWithoutFeedback
* @flow
*/
'use strict';
@ -23,6 +24,7 @@ var onlyChild = require('onlyChild');
*/
var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
type Event = Object;
/**
* Do not use unless you have a very good reason. All the elements that
@ -51,7 +53,7 @@ var TouchableWithoutFeedback = React.createClass({
* `Touchable.Mixin` self callbacks. The mixin will invoke these if they are
* defined on your component.
*/
touchableHandlePress: function(e) {
touchableHandlePress: function(e: Event) {
this.props.onPress && this.props.onPress(e);
},
@ -67,18 +69,19 @@ var TouchableWithoutFeedback = React.createClass({
this.props.onLongPress && this.props.onLongPress();
},
touchableGetPressRectOffset: function() {
touchableGetPressRectOffset: function(): typeof PRESS_RECT_OFFSET {
return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant!
},
touchableGetHighlightDelayMS: function() {
touchableGetHighlightDelayMS: function(): number {
return 0;
},
render: function() {
render: function(): ReactElement {
// Note(vjeux): use cloneWithProps once React has been upgraded
var child = onlyChild(this.props.children);
return React.cloneElement(child, {
// Note(avik): remove dynamic typecast once Flow has been upgraded
return (React: any).cloneElement(child, {
accessible: true,
testID: this.props.testID,
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,

Просмотреть файл

@ -7,12 +7,13 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ensureComponentIsNative
* @flow
*/
'use strict';
var invariant = require('invariant');
var ensureComponentIsNative = function(component) {
var ensureComponentIsNative = function(component: any) {
invariant(
component && typeof component.setNativeProps === 'function',
'Touchable child must either be native or forward setNativeProps to a ' +

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule View
* @flow
*/
'use strict';

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ViewStylePropTypes
* @flow
*/
'use strict';

Просмотреть файл

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule WebView
* @flow
*/
'use strict';
@ -24,6 +25,8 @@ var merge = require('merge');
var PropTypes = React.PropTypes;
var RCTWebViewManager = require('NativeModules').WebViewManager;
var invariant = require('invariant');
var RCT_WEBVIEW_REF = 'webview';
var WebViewState = keyMirror({
@ -41,6 +44,14 @@ var NavigationType = {
other: RCTWebViewManager.NavigationType.Other,
};
type ErrorEvent = {
domain: any;
code: any;
description: any;
}
type Event = Object;
var WebView = React.createClass({
statics: {
NavigationType: NavigationType,
@ -61,7 +72,7 @@ var WebView = React.createClass({
getInitialState: function() {
return {
viewState: WebViewState.IDLE,
lastErrorEvent: null,
lastErrorEvent: (null: ?ErrorEvent),
startInLoadingState: true,
};
},
@ -79,6 +90,10 @@ var WebView = React.createClass({
otherView = this.props.renderLoading();
} else if (this.state.viewState === WebViewState.ERROR) {
var errorEvent = this.state.lastErrorEvent;
invariant(
errorEvent != null,
'lastErrorEvent expected to be non-null'
);
otherView = this.props.renderError(
errorEvent.domain,
errorEvent.code,
@ -132,21 +147,21 @@ var WebView = React.createClass({
* We return an event with a bunch of fields including:
* url, title, loading, canGoBack, canGoForward
*/
updateNavigationState: function(event) {
updateNavigationState: function(event: Event) {
if (this.props.onNavigationStateChange) {
this.props.onNavigationStateChange(event.nativeEvent);
}
},
getWebWiewHandle: function() {
getWebWiewHandle: function(): any {
return this.refs[RCT_WEBVIEW_REF].getNodeHandle();
},
onLoadingStart: function(event) {
onLoadingStart: function(event: Event) {
this.updateNavigationState(event);
},
onLoadingError: function(event) {
onLoadingError: function(event: Event) {
event.persist(); // persist this event because we need to store it
console.error("encountered an error loading page", event.nativeEvent);
@ -156,7 +171,7 @@ var WebView = React.createClass({
});
},
onLoadingFinish: function(event) {
onLoadingFinish: function(event: Event) {
this.setState({
viewState: WebViewState.IDLE,
});