diff --git a/Examples/UIExplorer/TextInputExample.js b/Examples/UIExplorer/TextInputExample.js index a52284b85ec11f..4e54c38b827a54 100644 --- a/Examples/UIExplorer/TextInputExample.js +++ b/Examples/UIExplorer/TextInputExample.js @@ -174,6 +174,89 @@ exports.examples = [ ); } }, + { + title: 'Keyboard types', + render: function() { + var keyboardTypes = [ + 'default', + 'ascii-capable', + 'numbers-and-punctuation', + 'url', + 'number-pad', + 'phone-pad', + 'name-phone-pad', + 'email-address', + 'decimal-pad', + 'twitter', + 'web-search', + 'numeric', + ]; + var examples = keyboardTypes.map((type) => { + return ( + + + + ); + }); + return {examples}; + } + }, + { + title: 'Return key types', + render: function() { + var returnKeyTypes = [ + 'default', + 'go', + 'google', + 'join', + 'next', + 'route', + 'search', + 'send', + 'yahoo', + 'done', + 'emergency-call', + ]; + var examples = returnKeyTypes.map((type) => { + return ( + + + + ); + }); + return {examples}; + } + }, + { + title: 'Enable return key automatically', + render: function() { + return ( + + + + + + ); + } + }, + { + title: 'Secure text entry', + render: function() { + return ( + + + + + + ); + } + }, { title: 'Event handling', render: function(): ReactElement { return }, diff --git a/Libraries/Components/TextInput/TextInput.ios.js b/Libraries/Components/TextInput/TextInput.ios.js index 02fec4d5a3a700..e73debbb0ee8b6 100644 --- a/Libraries/Components/TextInput/TextInput.ios.js +++ b/Libraries/Components/TextInput/TextInput.ios.js @@ -33,6 +33,8 @@ var merge = require('merge'); var autoCapitalizeConsts = RCTUIManager.UIText.AutocapitalizationType; var clearButtonModeConsts = RCTUIManager.UITextField.clearButtonMode; +var keyboardTypeConsts = RCTUIManager.UIKeyboardType; +var returnKeyTypeConsts = RCTUIManager.UIReturnKeyType; var RCTTextViewAttributes = merge(ReactIOSViewAttributes.UIView, { autoCorrect: true, @@ -44,6 +46,9 @@ var RCTTextViewAttributes = merge(ReactIOSViewAttributes.UIView, { fontStyle: true, fontWeight: true, keyboardType: true, + returnKeyType: true, + enablesReturnKeyAutomatically: true, + secureTextEntry: true, mostRecentEventCounter: true, placeholder: true, placeholderTextColor: true, @@ -66,6 +71,10 @@ var notMultiline = { onSubmitEditing: true, }; +var crossPlatformKeyboardTypeMap = { + 'numeric': 'decimal-pad', +}; + type DefaultProps = { bufferDelay: number; }; @@ -138,8 +147,47 @@ var TextInput = React.createClass({ */ keyboardType: PropTypes.oneOf([ 'default', + // iOS + 'ascii-capable', + 'numbers-and-punctuation', + 'url', + 'number-pad', + 'phone-pad', + 'name-phone-pad', + 'email-address', + 'decimal-pad', + 'twitter', + 'web-search', + // Cross-platform 'numeric', ]), + /** + * Determines how the return key should look. + */ + returnKeyType: PropTypes.oneOf([ + 'default', + 'go', + 'google', + 'join', + 'next', + 'route', + 'search', + 'send', + 'yahoo', + 'done', + 'emergency-call', + ]), + /** + * If true, the keyboard disables the return key when there is no text and + * automatically enables it when there is text. Default value is false. + */ + enablesReturnKeyAutomatically: PropTypes.bool, + + /** + * If true, the text input obscures the text entered so that sensitive text + * like passwords stay secure. Default value is false. + */ + secureTextEntry: PropTypes.bool, /** * If true, the text input can be multiple lines. Default value is false. */ @@ -317,6 +365,11 @@ var TextInput = React.createClass({ var autoCapitalize = autoCapitalizeConsts[this.props.autoCapitalize]; var clearButtonMode = clearButtonModeConsts[this.props.clearButtonMode]; + var keyboardType = keyboardTypeConsts[ + crossPlatformKeyboardTypeMap[this.props.keyboardType] || + this.props.keyboardType + ]; + var returnKeyType = returnKeyTypeConsts[this.props.returnKeyType]; if (!this.props.multiline) { for (var propKey in onlyMultiline) { @@ -331,7 +384,10 @@ var TextInput = React.createClass({ ref="input" style={[styles.input, this.props.style]} enabled={this.props.editable} - keyboardType={this.props.keyboardType} + keyboardType={keyboardType} + returnKeyType={returnKeyType} + enablesReturnKeyAutomatically={this.props.enablesReturnKeyAutomatically} + secureTextEntry={this.props.secureTextEntry} onFocus={this._onFocus} onBlur={this._onBlur} onChange={this._onChange} @@ -373,6 +429,10 @@ var TextInput = React.createClass({ children={children} mostRecentEventCounter={this.state.mostRecentEventCounter} editable={this.props.editable} + keyboardType={keyboardType} + returnKeyType={returnKeyType} + enablesReturnKeyAutomatically={this.props.enablesReturnKeyAutomatically} + secureTextEntry={this.props.secureTextEntry} onFocus={this._onFocus} onBlur={this._onBlur} onChange={this._onChange} diff --git a/React/Base/RCTConvert.h b/React/Base/RCTConvert.h index c8d6ecadab5501..0f2ecf68ed0dc9 100644 --- a/React/Base/RCTConvert.h +++ b/React/Base/RCTConvert.h @@ -51,6 +51,7 @@ + (UITextFieldViewMode)UITextFieldViewMode:(id)json; + (UIScrollViewKeyboardDismissMode)UIScrollViewKeyboardDismissMode:(id)json; + (UIKeyboardType)UIKeyboardType:(id)json; ++ (UIReturnKeyType)UIReturnKeyType:(id)json; + (UIViewContentMode)UIViewContentMode:(id)json; + (UIBarStyle)UIBarStyle:(id)json; diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index 9bf7104c996b0d..36de37f21c50c2 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -116,10 +116,33 @@ + (NSURLRequest *)NSURLRequest:(id)json }), UIScrollViewKeyboardDismissModeNone, integerValue) RCT_ENUM_CONVERTER(UIKeyboardType, (@{ - @"numeric": @(UIKeyboardTypeDecimalPad), @"default": @(UIKeyboardTypeDefault), + @"ascii-capable": @(UIKeyboardTypeASCIICapable), + @"numbers-and-punctuation": @(UIKeyboardTypeNumbersAndPunctuation), + @"url": @(UIKeyboardTypeURL), + @"number-pad": @(UIKeyboardTypeNumberPad), + @"phone-pad": @(UIKeyboardTypePhonePad), + @"name-phone-pad": @(UIKeyboardTypeNamePhonePad), + @"email-address": @(UIKeyboardTypeEmailAddress), + @"decimal-pad": @(UIKeyboardTypeDecimalPad), + @"twitter": @(UIKeyboardTypeTwitter), + @"web-search": @(UIKeyboardTypeWebSearch), }), UIKeyboardTypeDefault, integerValue) +RCT_ENUM_CONVERTER(UIReturnKeyType, (@{ + @"default": @(UIReturnKeyDefault), + @"go": @(UIReturnKeyGo), + @"google": @(UIReturnKeyGoogle), + @"join": @(UIReturnKeyJoin), + @"next": @(UIReturnKeyNext), + @"route": @(UIReturnKeyRoute), + @"search": @(UIReturnKeySearch), + @"send": @(UIReturnKeySend), + @"yahoo": @(UIReturnKeyYahoo), + @"done": @(UIReturnKeyDone), + @"emergency-call": @(UIReturnKeyEmergencyCall), +}), UIReturnKeyDefault, integerValue) + RCT_ENUM_CONVERTER(UIViewContentMode, (@{ @"scale-to-fill": @(UIViewContentModeScaleToFill), @"scale-aspect-fit": @(UIViewContentModeScaleAspectFit), diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m index a0e7285c6b0dfb..ae6e54d69404c0 100644 --- a/React/Modules/RCTUIManager.m +++ b/React/Modules/RCTUIManager.m @@ -1291,6 +1291,32 @@ - (NSDictionary *)constantsToExport @"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), diff --git a/React/Views/RCTTextField.m b/React/Views/RCTTextField.m index 1ccf17d7f5f658..953c3421cd6118 100644 --- a/React/Views/RCTTextField.m +++ b/React/Views/RCTTextField.m @@ -31,7 +31,6 @@ - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher [self addTarget:self action:@selector(_textFieldEndEditing) forControlEvents:UIControlEventEditingDidEnd]; [self addTarget:self action:@selector(_textFieldSubmitEditing) forControlEvents:UIControlEventEditingDidEndOnExit]; _reactSubviews = [[NSMutableArray alloc] init]; - self.returnKeyType = UIReturnKeyDone; } return self; } diff --git a/React/Views/RCTTextFieldManager.m b/React/Views/RCTTextFieldManager.m index 087dc5b26421d2..ddf6d6f924f9e9 100644 --- a/React/Views/RCTTextFieldManager.m +++ b/React/Views/RCTTextFieldManager.m @@ -29,6 +29,9 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(text, NSString) RCT_EXPORT_VIEW_PROPERTY(clearButtonMode, UITextFieldViewMode) 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(color, textColor, UIColor) RCT_REMAP_VIEW_PROPERTY(autoCapitalize, autocapitalizationType, UITextAutocapitalizationType) RCT_CUSTOM_VIEW_PROPERTY(fontSize, CGFloat, RCTTextField)