diff --git a/Examples/Movies/SearchScreen.js b/Examples/Movies/SearchScreen.js index 05ab80187..e7eb7f2b4 100644 --- a/Examples/Movies/SearchScreen.js +++ b/Examples/Movies/SearchScreen.js @@ -281,7 +281,7 @@ var SearchScreen = React.createClass({ renderRow={this.renderRow} onEndReached={this.onEndReached} automaticallyAdjustContentInsets={false} - keyboardDismissMode="onDrag" + keyboardDismissMode="on-drag" keyboardShouldPersistTaps={true} showsVerticalScrollIndicator={false} />; diff --git a/Examples/UIExplorer/StatusBarIOSExample.js b/Examples/UIExplorer/StatusBarIOSExample.js index 545136c49..ab649197e 100644 --- a/Examples/UIExplorer/StatusBarIOSExample.js +++ b/Examples/UIExplorer/StatusBarIOSExample.js @@ -32,11 +32,11 @@ exports.examples = [{ render() { return ( - {Object.keys(StatusBarIOS.Style).map((key) => + {['default', 'light-content'].map((style) => StatusBarIOS.setStyle(StatusBarIOS.Style[key])}> + onPress={() => StatusBarIOS.setStyle(style)}> - setStyle(StatusBarIOS.Style.{key}) + setStyle('{style}') )} @@ -48,11 +48,11 @@ exports.examples = [{ render() { return ( - {Object.keys(StatusBarIOS.Style).map((key) => + {['default', 'light-content'].map((style) => StatusBarIOS.setStyle(StatusBarIOS.Style[key], true)}> + onPress={() => StatusBarIOS.setStyle(style, true)}> - setStyle(StatusBarIOS.Style.{key}, true) + setStyle('{style}', true) )} @@ -64,18 +64,18 @@ exports.examples = [{ render() { return ( - {Object.keys(StatusBarIOS.Animation).map((key) => + {['none', 'fade', 'slide'].map((animation) => StatusBarIOS.setHidden(true, StatusBarIOS.Animation[key])}> + onPress={() => StatusBarIOS.setHidden(true, animation)}> - setHidden(true, StatusBarIOS.Animation.{key}) + setHidden(true, '{animation}') StatusBarIOS.setHidden(false, StatusBarIOS.Animation[key])}> + onPress={() => StatusBarIOS.setHidden(false, animation)}> - setHidden(false, StatusBarIOS.Animation.{key}) + setHidden(false, '{animation}') diff --git a/Examples/UIExplorer/UIExplorerList.js b/Examples/UIExplorer/UIExplorerList.js index df9a3b123..cd73e6d06 100644 --- a/Examples/UIExplorer/UIExplorerList.js +++ b/Examples/UIExplorer/UIExplorerList.js @@ -157,7 +157,7 @@ class UIExplorerList extends React.Component { renderSectionHeader={this._renderSectionHeader} keyboardShouldPersistTaps={true} automaticallyAdjustContentInsets={false} - keyboardDismissMode="onDrag" + keyboardDismissMode="on-drag" /> ); diff --git a/Libraries/Components/DatePicker/DatePickerIOS.ios.js b/Libraries/Components/DatePicker/DatePickerIOS.ios.js index 41fc9b877..f184c6f79 100644 --- a/Libraries/Components/DatePicker/DatePickerIOS.ios.js +++ b/Libraries/Components/DatePicker/DatePickerIOS.ios.js @@ -120,7 +120,7 @@ var DatePickerIOS = React.createClass({ ), onTouchStart: this.scrollResponderHandleTouchStart, onTouchMove: this.scrollResponderHandleTouchMove, @@ -308,7 +299,7 @@ var ScrollView = React.createClass({ onResponderRelease: this.scrollResponderHandleResponderRelease, onResponderReject: this.scrollResponderHandleResponderReject, }; - + var ScrollViewClass; if (Platform.OS === 'ios') { ScrollViewClass = RCTScrollView; @@ -318,6 +309,13 @@ var ScrollView = React.createClass({ } else { ScrollViewClass = AndroidScrollView; } + var keyboardDismissModeConstants = { + 'none': RCTScrollViewConsts.KeyboardDismissMode.None, // default + 'interactive': RCTScrollViewConsts.KeyboardDismissMode.Interactive, + 'on-drag': RCTScrollViewConsts.KeyboardDismissMode.OnDrag, + }; + props.keyboardDismissMode = props.keyboardDismissMode ? + keyboardDismissModeConstants[props.keyboardDismissMode] : undefined; } invariant( ScrollViewClass !== undefined, diff --git a/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js b/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js index 23d952776..ec3b6c614 100644 --- a/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js +++ b/Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js @@ -108,13 +108,7 @@ var styles = StyleSheet.create({ var RCTSegmentedControl = requireNativeComponent( 'RCTSegmentedControl', - null + SegmentedControlIOS ); -if (__DEV__) { - verifyPropTypes( - RCTSegmentedControl, - RCTSegmentedControl.viewConfig - ); -} module.exports = SegmentedControlIOS; diff --git a/Libraries/Components/StatusBar/StatusBarIOS.ios.js b/Libraries/Components/StatusBar/StatusBarIOS.ios.js index 14a5cecf2..adfed78b7 100644 --- a/Libraries/Components/StatusBar/StatusBarIOS.ios.js +++ b/Libraries/Components/StatusBar/StatusBarIOS.ios.js @@ -13,26 +13,26 @@ var RCTStatusBarManager = require('NativeModules').StatusBarManager; +type StatusBarStyle = $Enum<{ + 'default': string, + 'light-content': string, +}>; + +type StatusBarAnimation = $Enum<{ + 'none': string, + 'fade': string, + 'slide': string, +}>; + var StatusBarIOS = { - Style: { - default: RCTStatusBarManager.Style.default, - lightContent: RCTStatusBarManager.Style.lightContent - }, - - Animation: { - none: RCTStatusBarManager.Animation.none, - fade: RCTStatusBarManager.Animation.fade, - slide: RCTStatusBarManager.Animation.slide, - }, - - setStyle(style: number, animated?: boolean) { + setStyle(style: StatusBarStyle, animated?: boolean) { animated = animated || false; RCTStatusBarManager.setStyle(style, animated); }, - setHidden(hidden: boolean, animation: number) { - animation = animation || StatusBarIOS.Animation.none; + setHidden(hidden: boolean, animation?: StatusBarAnimation) { + animation = animation || 'none'; RCTStatusBarManager.setHidden(hidden, animation); }, }; diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 03f374b67..7d3f04b33 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -31,10 +31,6 @@ var emptyFunction = require('emptyFunction'); var invariant = require('invariant'); var merge = require('merge'); -var autoCapitalizeConsts = RCTUIManager.UIText.AutocapitalizationType; -var keyboardTypeConsts = RCTUIManager.UIKeyboardType; -var returnKeyTypeConsts = RCTUIManager.UIReturnKeyType; - var RCTTextViewAttributes = merge(ReactNativeViewAttributes.UIView, { autoCorrect: true, autoCapitalize: true, @@ -96,10 +92,6 @@ var viewConfigAndroid = { validAttributes: AndroidTextInputAttributes, }; -var crossPlatformKeyboardTypeMap = { - 'numeric': 'decimal-pad', -}; - type DefaultProps = { bufferDelay: number; }; @@ -171,8 +163,11 @@ var TextInput = React.createClass({ * Determines which keyboard to open, e.g.`numeric`. */ keyboardType: PropTypes.oneOf([ - 'default', - // iOS + // Cross-platform + 'default', + 'numeric', + 'email-address', + // iOS-only 'ascii-capable', 'numbers-and-punctuation', 'url', @@ -182,9 +177,6 @@ var TextInput = React.createClass({ 'decimal-pad', 'twitter', 'web-search', - // Cross-platform - 'numeric', - 'email-address', ]), /** * Determines how the return key should look. @@ -426,18 +418,12 @@ var TextInput = React.createClass({ _renderIOS: function() { var textContainer; - var autoCapitalize = autoCapitalizeConsts[this.props.autoCapitalize]; - var clearButtonMode = RCTUIManager.UITextField.clearButtonMode[this.props.clearButtonMode]; + var props = this.props; + props.style = [styles.input, this.props.style]; - var keyboardType = keyboardTypeConsts[ - crossPlatformKeyboardTypeMap[this.props.keyboardType] || - this.props.keyboardType - ]; - var returnKeyType = returnKeyTypeConsts[this.props.returnKeyType]; - - if (!this.props.multiline) { + if (!props.multiline) { for (var propKey in onlyMultiline) { - if (this.props[propKey]) { + if (props[propKey]) { throw new Error( 'TextInput prop `' + propKey + '` is only supported with multiline.' ); @@ -446,77 +432,48 @@ var TextInput = React.createClass({ textContainer = true} - onLayout={this.props.onLayout} - placeholder={this.props.placeholder} - placeholderTextColor={this.props.placeholderTextColor} text={this.state.bufferedValue} - autoCapitalize={autoCapitalize} - autoCorrect={this.props.autoCorrect} - clearButtonMode={clearButtonMode} - clearTextOnFocus={this.props.clearTextOnFocus} - selectTextOnFocus={this.props.selectTextOnFocus} />; } else { for (var propKey in notMultiline) { - if (this.props[propKey]) { + if (props[propKey]) { throw new Error( 'TextInput prop `' + propKey + '` cannot be used with multiline.' ); } } - var children = this.props.children; + var children = props.children; var childCount = 0; ReactChildren.forEach(children, () => ++childCount); invariant( - !(this.props.value && childCount), + !(props.value && childCount), 'Cannot specify both value and children.' ); if (childCount > 1) { children = {children}; } - if (this.props.inputView) { - children = [children, this.props.inputView]; + if (props.inputView) { + children = [children, props.inputView]; } textContainer = ; } @@ -524,14 +481,14 @@ var TextInput = React.createClass({ + testID={props.testID}> {textContainer} ); }, _renderAndroid: function() { - var autoCapitalize = autoCapitalizeConsts[this.props.autoCapitalize]; + var autoCapitalize = RCTUIManager.UIText.AutocapitalizationType[this.props.autoCapitalize]; var children = this.props.children; var childCount = 0; ReactChildren.forEach(children, () => ++childCount); diff --git a/Libraries/Image/Image.ios.js b/Libraries/Image/Image.ios.js index 9b84937af..23e2c7a63 100644 --- a/Libraries/Image/Image.ios.js +++ b/Libraries/Image/Image.ios.js @@ -146,20 +146,11 @@ var Image = React.createClass({ if (this.props.style && this.props.style.tintColor) { warning(RawImage === RCTStaticImage, 'tintColor style only supported on static images.'); } - var resizeMode = this.props.resizeMode || style.resizeMode; - var contentModes = NativeModules.UIManager.UIView.ContentMode; - var contentMode; - if (resizeMode === ImageResizeMode.stretch) { - contentMode = contentModes.ScaleToFill; - } else if (resizeMode === ImageResizeMode.contain) { - contentMode = contentModes.ScaleAspectFit; - } else { // ImageResizeMode.cover or undefined - contentMode = contentModes.ScaleAspectFill; - } + var resizeMode = this.props.resizeMode || style.resizeMode || 'cover'; var nativeProps = merge(this.props, { style, - contentMode, + resizeMode, tintColor: style.tintColor, }); if (isStored) { @@ -187,7 +178,7 @@ var nativeOnlyProps = { src: true, defaultImageSrc: true, imageTag: true, - contentMode: true, + resizeMode: true, }; if (__DEV__) { verifyPropTypes(Image, RCTStaticImage.viewConfig, nativeOnlyProps); diff --git a/Libraries/Image/RCTNetworkImageViewManager.m b/Libraries/Image/RCTNetworkImageViewManager.m index 2ecf69971..005b726cf 100644 --- a/Libraries/Image/RCTNetworkImageViewManager.m +++ b/Libraries/Image/RCTNetworkImageViewManager.m @@ -29,6 +29,6 @@ RCT_EXPORT_MODULE() RCT_REMAP_VIEW_PROPERTY(defaultImageSrc, defaultImage, UIImage) RCT_REMAP_VIEW_PROPERTY(src, imageURL, NSURL) -RCT_EXPORT_VIEW_PROPERTY(contentMode, UIViewContentMode) +RCT_REMAP_VIEW_PROPERTY(resizeMode, contentMode, UIViewContentMode) @end diff --git a/Libraries/Image/RCTStaticImageManager.m b/Libraries/Image/RCTStaticImageManager.m index ce6aab187..bdc6f0596 100644 --- a/Libraries/Image/RCTStaticImageManager.m +++ b/Libraries/Image/RCTStaticImageManager.m @@ -26,7 +26,7 @@ RCT_EXPORT_MODULE() } RCT_EXPORT_VIEW_PROPERTY(capInsets, UIEdgeInsets) -RCT_EXPORT_VIEW_PROPERTY(contentMode, UIViewContentMode) +RCT_REMAP_VIEW_PROPERTY(resizeMode, contentMode, UIViewContentMode) RCT_CUSTOM_VIEW_PROPERTY(src, NSURL, RCTStaticImage) { if (json) { diff --git a/Libraries/Picker/PickerIOS.ios.js b/Libraries/Picker/PickerIOS.ios.js index b1b1d06f4..42302fa26 100644 --- a/Libraries/Picker/PickerIOS.ios.js +++ b/Libraries/Picker/PickerIOS.ios.js @@ -59,7 +59,7 @@ var PickerIOS = React.createClass({ ", NSStringFromClass(self.class), self, _methodName, _JSMethodName]; + return [NSString stringWithFormat:@"<%@: %p; exports %@ as %@();>", + [self class], self, [self methodName], _JSMethodName]; } @end @@ -562,19 +498,10 @@ static RCTSparseArray *RCTExportedMethodsByModuleID(void) const char **entries = (const char **)(mach_header + addr); // Create method - RCTModuleMethod *moduleMethod; - if (entries[2] == NULL) { - - // Legacy support for RCT_EXPORT() - moduleMethod = [[RCTModuleMethod alloc] initWithReactMethodName:@(entries[0]) - objCMethodName:@(entries[0]) - JSMethodName:strlen(entries[1]) ? @(entries[1]) : nil]; - } else { - moduleMethod = [[RCTModuleMethod alloc] initWithReactMethodName:@(entries[0]) - objCMethodName:strlen(entries[1]) ? @(entries[1]) : nil - JSMethodName:strlen(entries[2]) ? @(entries[2]) : nil]; - } - + RCTModuleMethod *moduleMethod = + [[RCTModuleMethod alloc] initWithReactMethodName:@(entries[0]) + objCMethodName:@(entries[1]) + JSMethodName:strlen(entries[2]) ? @(entries[2]) : nil]; // Cache method NSArray *methods = methodsByModuleClassName[moduleMethod.moduleClassName]; methodsByModuleClassName[moduleMethod.moduleClassName] = @@ -726,7 +653,7 @@ static NSDictionary *RCTLocalModulesConfig() @"methodID": @(methods.count), @"type": @"local" }; - [RCTLocalMethodNames addObject:methodName]; + [RCTLocalMethodNames addObject:methodName]; } // Add module and method lookup @@ -1610,7 +1537,7 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin - (void)stopProfiling { - RCTAssertMainThread(); + RCTAssertMainThread(); [_javaScriptExecutor executeBlockOnJavaScriptQueue:^{ NSString *log = RCTProfileEnd(self); diff --git a/React/Base/RCTBridgeModule.h b/React/Base/RCTBridgeModule.h index 34b861ff3..f3a9a5a3e 100644 --- a/React/Base/RCTBridgeModule.h +++ b/React/Base/RCTBridgeModule.h @@ -145,15 +145,6 @@ extern const dispatch_queue_t RCTJSThread; static const char *__rct_export_entry__[] = { __func__, #method, #js_name }; \ } -/** - * Deprecated, do not use. - */ -#define RCT_EXPORT(js_name) \ - _Pragma("message(\"RCT_EXPORT is deprecated. Use RCT_EXPORT_METHOD instead.\")") \ - __attribute__((used, section("__DATA,RCTExport"))) \ - __attribute__((__aligned__(1))) \ - static const char *__rct_export_entry__[] = { __func__, #js_name, NULL } - /** * The queue that will be used to call all exported methods. If omitted, this * will call on the default background queue, which is avoids blocking the main diff --git a/React/Base/RCTConvert.h b/React/Base/RCTConvert.h index ee43c1159..145e88b21 100644 --- a/React/Base/RCTConvert.h +++ b/React/Base/RCTConvert.h @@ -23,6 +23,8 @@ */ @interface RCTConvert : NSObject ++ (id)id:(id)json; + + (BOOL)BOOL:(id)json; + (double)double:(id)json; + (float)float:(id)json; @@ -52,7 +54,6 @@ + (NSWritingDirection)NSWritingDirection:(id)json; + (UITextAutocapitalizationType)UITextAutocapitalizationType:(id)json; + (UITextFieldViewMode)UITextFieldViewMode:(id)json; -+ (UIScrollViewKeyboardDismissMode)UIScrollViewKeyboardDismissMode:(id)json; + (UIKeyboardType)UIKeyboardType:(id)json; + (UIReturnKeyType)UIReturnKeyType:(id)json; diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index 3c9143c17..3bdf59753 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -21,6 +21,8 @@ void RCTLogConvertError(id json, const char *type) json, [json classForCoder], type); } +RCT_CONVERTER(id, id, self) + RCT_CONVERTER(BOOL, BOOL, boolValue) RCT_NUMBER_CONVERTER(double, doubleValue) RCT_NUMBER_CONVERTER(float, floatValue) @@ -219,12 +221,6 @@ RCT_ENUM_CONVERTER(UITextFieldViewMode, (@{ @"always": @(UITextFieldViewModeAlways), }), UITextFieldViewModeNever, integerValue) -RCT_ENUM_CONVERTER(UIScrollViewKeyboardDismissMode, (@{ - @"none": @(UIScrollViewKeyboardDismissModeNone), - @"on-drag": @(UIScrollViewKeyboardDismissModeOnDrag), - @"interactive": @(UIScrollViewKeyboardDismissModeInteractive), -}), UIScrollViewKeyboardDismissModeNone, integerValue) - RCT_ENUM_CONVERTER(UIKeyboardType, (@{ @"default": @(UIKeyboardTypeDefault), @"ascii-capable": @(UIKeyboardTypeASCIICapable), @@ -237,6 +233,8 @@ RCT_ENUM_CONVERTER(UIKeyboardType, (@{ @"decimal-pad": @(UIKeyboardTypeDecimalPad), @"twitter": @(UIKeyboardTypeTwitter), @"web-search": @(UIKeyboardTypeWebSearch), + // Added for Android compatibility + @"numeric": @(UIKeyboardTypeDecimalPad), }), UIKeyboardTypeDefault, integerValue) RCT_ENUM_CONVERTER(UIReturnKeyType, (@{ @@ -267,7 +265,11 @@ RCT_ENUM_CONVERTER(UIViewContentMode, (@{ @"top-right": @(UIViewContentModeTopRight), @"bottom-left": @(UIViewContentModeBottomLeft), @"bottom-right": @(UIViewContentModeBottomRight), -}), UIViewContentModeScaleToFill, integerValue) + // Cross-platform values + @"cover": @(UIViewContentModeScaleAspectFill), + @"contain": @(UIViewContentModeScaleAspectFit), + @"stretch": @(UIViewContentModeScaleToFill), +}), UIViewContentModeScaleAspectFill, integerValue) RCT_ENUM_CONVERTER(UIBarStyle, (@{ @"default": @(UIBarStyleDefault), diff --git a/React/Base/RCTRedBox.m b/React/Base/RCTRedBox.m index 2d35dcd6f..6330454ab 100644 --- a/React/Base/RCTRedBox.m +++ b/React/Base/RCTRedBox.m @@ -85,11 +85,6 @@ selector:@selector(dismiss) name:RCTReloadNotification object:nil]; - - [notificationCenter addObserver:self - selector:@selector(dismiss) - name:RCTJavaScriptDidLoadNotification - object:nil]; } return self; } diff --git a/React/Modules/RCTStatusBarManager.h b/React/Modules/RCTStatusBarManager.h index 40feee5c0..aee9b8642 100644 --- a/React/Modules/RCTStatusBarManager.h +++ b/React/Modules/RCTStatusBarManager.h @@ -10,6 +10,14 @@ #import #import "RCTBridgeModule.h" +#import "RCTConvert.h" + +@interface RCTConvert (UIStatusBar) + ++ (UIStatusBarStyle)UIStatusBarStyle:(id)json; ++ (UIStatusBarAnimation)UIStatusBarAnimation:(id)json; + +@end @interface RCTStatusBarManager : NSObject diff --git a/React/Modules/RCTStatusBarManager.m b/React/Modules/RCTStatusBarManager.m index 04bb39038..cb9ddfe69 100644 --- a/React/Modules/RCTStatusBarManager.m +++ b/React/Modules/RCTStatusBarManager.m @@ -11,6 +11,21 @@ #import "RCTLog.h" +@implementation RCTConvert (UIStatusBar) + +RCT_ENUM_CONVERTER(UIStatusBarStyle, (@{ + @"default": @(UIStatusBarStyleDefault), + @"light-content": @(UIStatusBarStyleLightContent), +}), UIStatusBarStyleDefault, integerValue); + +RCT_ENUM_CONVERTER(UIStatusBarAnimation, (@{ + @"none": @(UIStatusBarAnimationNone), + @"fade": @(UIStatusBarAnimationFade), + @"slide": @(UIStatusBarAnimationSlide), +}), UIStatusBarAnimationNone, integerValue); + +@end + @implementation RCTStatusBarManager static BOOL RCTViewControllerBasedStatusBarAppearance() @@ -18,7 +33,8 @@ static BOOL RCTViewControllerBasedStatusBarAppearance() static BOOL value; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - value = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"] ?: @YES boolValue]; + value = [[[NSBundle mainBundle] objectForInfoDictionaryKey: + @"UIViewControllerBasedStatusBarAppearance"] ?: @YES boolValue]; }); return value; @@ -55,19 +71,4 @@ RCT_EXPORT_METHOD(setHidden:(BOOL)hidden } } -- (NSDictionary *)constantsToExport -{ - return @{ - @"Style": @{ - @"default": @(UIStatusBarStyleDefault), - @"lightContent": @(UIStatusBarStyleLightContent), - }, - @"Animation": @{ - @"none": @(UIStatusBarAnimationNone), - @"fade": @(UIStatusBarAnimationFade), - @"slide": @(UIStatusBarAnimationSlide), - }, - }; -} - @end diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m index cc580e903..570bdfef7 100644 --- a/React/Modules/RCTUIManager.m +++ b/React/Modules/RCTUIManager.m @@ -1397,11 +1397,6 @@ RCT_EXPORT_METHOD(clearJSResponder) NSMutableDictionary *allJSConstants = [@{ @"customBubblingEventTypes": [self customBubblingEventTypes], @"customDirectEventTypes": [self customDirectEventTypes], - @"NSTextAlignment": @{ - @"Left": @(NSTextAlignmentLeft), - @"Center": @(NSTextAlignmentCenter), - @"Right": @(NSTextAlignmentRight), - }, @"Dimensions": @{ @"window": @{ @"width": @(RCTScreenSize().width), @@ -1413,73 +1408,6 @@ RCT_EXPORT_METHOD(clearJSResponder) @"height": @(RCTScreenSize().height), }, }, - @"StyleConstants": @{ - @"PointerEventsValues": @{ - @"none": @(RCTPointerEventsNone), - @"box-none": @(RCTPointerEventsBoxNone), - @"box-only": @(RCTPointerEventsBoxOnly), - @"auto": @(RCTPointerEventsUnspecified), - }, - }, - @"UIText": @{ - @"AutocapitalizationType": @{ - @"characters": @(UITextAutocapitalizationTypeAllCharacters), - @"sentences": @(UITextAutocapitalizationTypeSentences), - @"words": @(UITextAutocapitalizationTypeWords), - @"none": @(UITextAutocapitalizationTypeNone), - }, - }, - @"UITextField": @{ - @"clearButtonMode": @{ - @"never": @(UITextFieldViewModeNever), - @"while-editing": @(UITextFieldViewModeWhileEditing), - @"unless-editing": @(UITextFieldViewModeUnlessEditing), - @"always": @(UITextFieldViewModeAlways), - }, - }, - @"UIKeyboardType": @{ - @"default": @(UIKeyboardTypeDefault), - @"ascii-capable": @(UIKeyboardTypeASCIICapable), - @"numbers-and-punctuation": @(UIKeyboardTypeNumbersAndPunctuation), - @"url": @(UIKeyboardTypeURL), - @"number-pad": @(UIKeyboardTypeNumberPad), - @"phone-pad": @(UIKeyboardTypePhonePad), - @"name-phone-pad": @(UIKeyboardTypeNamePhonePad), - @"decimal-pad": @(UIKeyboardTypeDecimalPad), - @"email-address": @(UIKeyboardTypeEmailAddress), - @"twitter": @(UIKeyboardTypeTwitter), - @"web-search": @(UIKeyboardTypeWebSearch), - }, - @"UIReturnKeyType": @{ - @"default": @(UIReturnKeyDefault), - @"go": @(UIReturnKeyGo), - @"google": @(UIReturnKeyGoogle), - @"join": @(UIReturnKeyJoin), - @"next": @(UIReturnKeyNext), - @"route": @(UIReturnKeyRoute), - @"search": @(UIReturnKeySearch), - @"send": @(UIReturnKeySend), - @"yahoo": @(UIReturnKeyYahoo), - @"done": @(UIReturnKeyDone), - @"emergency-call": @(UIReturnKeyEmergencyCall), - }, - @"UIView": @{ - @"ContentMode": @{ - @"ScaleToFill": @(UIViewContentModeScaleToFill), - @"ScaleAspectFit": @(UIViewContentModeScaleAspectFit), - @"ScaleAspectFill": @(UIViewContentModeScaleAspectFill), - @"Redraw": @(UIViewContentModeRedraw), - @"Center": @(UIViewContentModeCenter), - @"Top": @(UIViewContentModeTop), - @"Bottom": @(UIViewContentModeBottom), - @"Left": @(UIViewContentModeLeft), - @"Right": @(UIViewContentModeRight), - @"TopLeft": @(UIViewContentModeTopLeft), - @"TopRight": @(UIViewContentModeTopRight), - @"BottomLeft": @(UIViewContentModeBottomLeft), - @"BottomRight": @(UIViewContentModeBottomRight), - }, - }, } mutableCopy]; [_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, RCTViewManager *manager, BOOL *stop) { diff --git a/React/Views/RCTDatePickerManager.h b/React/Views/RCTDatePickerManager.h index eb424085d..73d88b6dd 100644 --- a/React/Views/RCTDatePickerManager.h +++ b/React/Views/RCTDatePickerManager.h @@ -8,6 +8,13 @@ */ #import "RCTViewManager.h" +#import "RCTConvert.h" + +@interface RCTConvert(UIDatePicker) + ++ (UIDatePickerMode)UIDatePickerMode:(id)json; + +@end @interface RCTDatePickerManager : RCTViewManager diff --git a/React/Views/RCTDatePickerManager.m b/React/Views/RCTDatePickerManager.m index 36397d6e5..d8bbde703 100644 --- a/React/Views/RCTDatePickerManager.m +++ b/React/Views/RCTDatePickerManager.m @@ -10,7 +10,6 @@ #import "RCTDatePickerManager.h" #import "RCTBridge.h" -#import "RCTConvert.h" #import "RCTEventDispatcher.h" #import "UIView+React.h" @@ -20,7 +19,7 @@ RCT_ENUM_CONVERTER(UIDatePickerMode, (@{ @"time": @(UIDatePickerModeTime), @"date": @(UIDatePickerModeDate), @"datetime": @(UIDatePickerModeDateAndTime), - //@"countdown": @(UIDatePickerModeCountDownTimer) // not supported yet + @"countdown": @(UIDatePickerModeCountDownTimer), // not supported yet }), UIDatePickerModeTime, integerValue) @end @@ -31,9 +30,12 @@ RCT_EXPORT_MODULE() - (UIView *)view { + // TODO: we crash here if the RCTDatePickerManager is released + // while the UIDatePicker is still sending onChange events. To + // fix this we should maybe subclass UIDatePicker and make it + // be its own event target. UIDatePicker *picker = [[UIDatePicker alloc] init]; - [picker addTarget:self - action:@selector(onChange:) + [picker addTarget:self action:@selector(onChange:) forControlEvents:UIControlEventValueChanged]; return picker; } @@ -56,17 +58,10 @@ RCT_REMAP_VIEW_PROPERTY(timeZoneOffsetInMinutes, timeZone, NSTimeZone) - (NSDictionary *)constantsToExport { - UIDatePicker *dp = [[UIDatePicker alloc] init]; - [dp layoutIfNeeded]; - + UIDatePicker *view = [[UIDatePicker alloc] init]; return @{ - @"ComponentHeight": @(CGRectGetHeight(dp.frame)), - @"ComponentWidth": @(CGRectGetWidth(dp.frame)), - @"DatePickerModes": @{ - @"time": @(UIDatePickerModeTime), - @"date": @(UIDatePickerModeDate), - @"datetime": @(UIDatePickerModeDateAndTime), - } + @"ComponentHeight": @(view.intrinsicContentSize.height), + @"ComponentWidth": @(view.intrinsicContentSize.width), }; } diff --git a/React/Views/RCTPickerManager.m b/React/Views/RCTPickerManager.m index 3bbc60b94..de6c1f916 100644 --- a/React/Views/RCTPickerManager.m +++ b/React/Views/RCTPickerManager.m @@ -27,10 +27,10 @@ RCT_EXPORT_VIEW_PROPERTY(selectedIndex, NSInteger) - (NSDictionary *)constantsToExport { - RCTPicker *pv = [[RCTPicker alloc] init]; + RCTPicker *view = [[RCTPicker alloc] init]; return @{ - @"ComponentHeight": @(CGRectGetHeight(pv.frame)), - @"ComponentWidth": @(CGRectGetWidth(pv.frame)) + @"ComponentHeight": @(view.intrinsicContentSize.height), + @"ComponentWidth": @(view.intrinsicContentSize.width) }; } diff --git a/React/Views/RCTScrollViewManager.h b/React/Views/RCTScrollViewManager.h index 9fec3422d..83b3126e8 100644 --- a/React/Views/RCTScrollViewManager.h +++ b/React/Views/RCTScrollViewManager.h @@ -8,6 +8,13 @@ */ #import "RCTViewManager.h" +#import "RCTConvert.h" + +@interface RCTConvert (UIScrollView) + ++ (UIScrollViewKeyboardDismissMode)UIScrollViewKeyboardDismissMode:(id)json; + +@end @interface RCTScrollViewManager : RCTViewManager diff --git a/React/Views/RCTScrollViewManager.m b/React/Views/RCTScrollViewManager.m index 8441de74d..15803df1e 100644 --- a/React/Views/RCTScrollViewManager.m +++ b/React/Views/RCTScrollViewManager.m @@ -10,11 +10,22 @@ #import "RCTScrollViewManager.h" #import "RCTBridge.h" -#import "RCTConvert.h" #import "RCTScrollView.h" #import "RCTSparseArray.h" #import "RCTUIManager.h" +@implementation RCTConvert (UIScrollView) + +RCT_ENUM_CONVERTER(UIScrollViewKeyboardDismissMode, (@{ + @"none": @(UIScrollViewKeyboardDismissModeNone), + @"on-drag": @(UIScrollViewKeyboardDismissModeOnDrag), + @"interactive": @(UIScrollViewKeyboardDismissModeInteractive), + // Backwards compatibility + @"onDrag": @(UIScrollViewKeyboardDismissModeOnDrag), +}), UIScrollViewKeyboardDismissModeNone, integerValue) + +@end + @implementation RCTScrollViewManager RCT_EXPORT_MODULE() @@ -53,14 +64,10 @@ RCT_DEPRECATED_VIEW_PROPERTY(throttleScrollCallbackMS, scrollEventThrottle) - (NSDictionary *)constantsToExport { return @{ + // TODO: unused - remove these? @"DecelerationRate": @{ - @"Normal": @(UIScrollViewDecelerationRateNormal), - @"Fast": @(UIScrollViewDecelerationRateFast), - }, - @"KeyboardDismissMode": @{ - @"None": @(UIScrollViewKeyboardDismissModeNone), - @"Interactive": @(UIScrollViewKeyboardDismissModeInteractive), - @"OnDrag": @(UIScrollViewKeyboardDismissModeOnDrag), + @"normal": @(UIScrollViewDecelerationRateNormal), + @"fast": @(UIScrollViewDecelerationRateFast), }, }; } diff --git a/React/Views/RCTTextFieldManager.m b/React/Views/RCTTextFieldManager.m index ff401a719..7b867bd0d 100644 --- a/React/Views/RCTTextFieldManager.m +++ b/React/Views/RCTTextFieldManager.m @@ -25,7 +25,7 @@ RCT_EXPORT_MODULE() RCT_EXPORT_VIEW_PROPERTY(caretHidden, BOOL) RCT_EXPORT_VIEW_PROPERTY(autoCorrect, BOOL) -RCT_EXPORT_VIEW_PROPERTY(enabled, BOOL) +RCT_REMAP_VIEW_PROPERTY(editable, enabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(placeholder, NSString) RCT_EXPORT_VIEW_PROPERTY(placeholderTextColor, UIColor) RCT_EXPORT_VIEW_PROPERTY(text, NSString) @@ -36,6 +36,7 @@ RCT_EXPORT_VIEW_PROPERTY(keyboardType, UIKeyboardType) RCT_EXPORT_VIEW_PROPERTY(returnKeyType, UIReturnKeyType) RCT_EXPORT_VIEW_PROPERTY(enablesReturnKeyAutomatically, BOOL) RCT_EXPORT_VIEW_PROPERTY(secureTextEntry, BOOL) +RCT_REMAP_VIEW_PROPERTY(password, secureTextEntry, BOOL) // backwards compatibility RCT_REMAP_VIEW_PROPERTY(color, textColor, UIColor) RCT_REMAP_VIEW_PROPERTY(autoCapitalize, autocapitalizationType, UITextAutocapitalizationType) RCT_CUSTOM_VIEW_PROPERTY(fontSize, CGFloat, RCTTextField)