diff --git a/README.md b/README.md index 53fcaf3a22881a..0869139d7fa927 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Contributions of Components and APIs are very welcomed! - [ ] TabBarIOS - [ ] TabBarIOS.Item - [x] Text -- [ ] TextInput +- [x] TextInput - [ ] ToolbarAndroid - [x] TouchableHighlight - [ ] TouchableNativeFeedback diff --git a/src/components/textInputRe.re b/src/components/textInputRe.re new file mode 100644 index 00000000000000..a9165554a8e9c9 --- /dev/null +++ b/src/components/textInputRe.re @@ -0,0 +1,352 @@ +open Utils; + +external view : ReactRe.reactClass = "TextInput" [@@bs.module "react-native"]; + +external _isFocused: ReactRe.reactRef => Js.boolean = "" [@@bs.send]; +let isFocused = Js.to_bool << _isFocused; + +external clear: ReactRe.reactRef => unit = "" [@@bs.send]; + +let createElement + ::accessibleLeft=? + ::accessible=? + ::hitSlop=? + ::onAccessibilityTap=? + ::onLayout=? + ::onMagicTap=? + ::onMoveShouldSetResponder=? + ::onMoveShouldSetResponderCapture=? + ::onResponderGrant=? + ::onResponderMove=? + ::onResponderReject=? + ::onResponderRelease=? + ::onResponderTerminate=? + ::onResponderTerminationRequest=? + ::onStartShouldSetResponder=? + ::onStartShouldSetResponderCapture=? + ::pointerEvents=? + ::removeClippedSubviews=? + ::style=? + ::testID=? + ::accessibilityComponentType=? + ::accessibilityLiveRegion=? + ::collapsable=? + ::importantForAccessibility=? + ::needsOffscreenAlphaCompositing=? + ::renderToHardwareTextureAndroid=? + ::accessibilityTraits=? + ::accessibilityViewIsModal=? + ::shouldRasterizeIOS=? + ::autoCapitalize=? + ::autoCorrect=? + ::autoFocus=? + ::blurOnSubmit=? + ::caretHidden=? + ::defaultValue=? + ::editable=? + ::keyboardType=? + ::maxLength=? + ::multiline=? + ::onBlur=? + ::onChange=? + ::onChangeText=? + ::onContentSizeChange=? + ::onEndEditing=? + ::onFocus=? + ::onScroll=? + ::onSelectionChange=? + ::onSubmitEditing=? + ::placeholder=? + ::placeholderTextColor=? + ::returnKeyType=? + ::secureTextEntry=? + ::selectTextOnFocus=? + ::selection=? + ::selectionColor=? + ::value=? + ::disableFullscreenUI=? + ::inlineImageLeft=? + ::inlineImagePadding=? + ::numberOfLines=? + ::returnKeyLabel=? + ::textBreakStrategy=? + ::underlineColorAndroid=? + ::clearButtonMode=? + ::clearTextOnFocus=? + ::dataDetectorTypes=? + ::enablesReturnKeyAutomatically=? + ::keyboardAppearance=? + ::onKeyPress=? + ::selectionState=? + ::spellCheck=? => + ReactRe.wrapPropsShamelessly + view + { + "accessibleLeft": from_opt accessibleLeft, + "accessible": from_opt (option_map to_js_boolean accessible), + "hitSlop": from_opt hitSlop, + "onAccessibilityTap": from_opt onAccessibilityTap, + "onLayout": from_opt onLayout, + "onMagicTap": from_opt onMagicTap, + "onMoveShouldSetResponder": + from_opt (option_map ((<<) to_js_boolean) onMoveShouldSetResponder), + "onMoveShouldSetResponderCapture": + from_opt (option_map ((<<) to_js_boolean) onMoveShouldSetResponderCapture), + "onResponderGrant": from_opt onResponderGrant, + "onResponderMove": from_opt onResponderMove, + "onResponderReject": from_opt onResponderReject, + "onResponderRelease": from_opt onResponderRelease, + "onResponderTerminate": from_opt onResponderTerminate, + "onResponderTerminationRequest": from_opt onResponderTerminationRequest, + "onStartShouldSetResponder": + from_opt (option_map ((<<) to_js_boolean) onStartShouldSetResponder), + "onStartShouldSetResponderCapture": + from_opt (option_map ((<<) to_js_boolean) onStartShouldSetResponderCapture), + "removeClippedSubviews": from_opt (option_map to_js_boolean removeClippedSubviews), + "pointerEvents": + from_opt ( + option_map + ( + fun x => + switch x { + | `auto => "auto" + | `none => "none" + | `boxNone => "box-none" + | `boxOnly => "box-only" + } + ) + pointerEvents + ), + "style": from_opt style, + "testID": from_opt testID, + "accessibilityComponentType": + from_opt ( + option_map + ( + fun x => + switch x { + | `none => "none" + | `button => "button" + | `radiobutton_checked => "radiobutton_checked-none" + | `radiobutton_unchecked => "radiobutton_unchecked" + } + ) + accessibilityComponentType + ), + "accessibilityLiveRegion": + from_opt ( + option_map + ( + fun x => + switch x { + | `polite => "polite" + | `none => "none" + | `assertive => "assertive" + } + ) + accessibilityLiveRegion + ), + "collapsable": from_opt (option_map to_js_boolean collapsable), + "importantForAccessibility": + from_opt ( + option_map + ( + fun prop => + switch prop { + | `auto => "auto" + | `yes => "yes" + | `no => "no" + | `noHideDescendants => "noHideDescendants" + } + ) + importantForAccessibility + ), + "needsOffscreenAlphaCompositing": + from_opt (option_map to_js_boolean needsOffscreenAlphaCompositing), + "renderToHardwareTextureAndroid": + from_opt (option_map to_js_boolean renderToHardwareTextureAndroid), + "accessibilityTraits": + from_opt ( + option_map + ( + fun traits => { + let to_string = + fun + | `none => "none" + | `button => "button" + | `link => "link" + | `header => "header" + | `search => "search" + | `image => "image" + | `selected => "selected" + | `plays => "plays" + | `key => "key" + | `text => "text" + | `summary => "summary" + | `disabled => "disabled" + | `frequentUpdates => "frequentUpdates" + | `startsMedia => "startsMedia" + | `adjustable => "adjustable" + | `allowsDirectInteraction => "allowsDirectInteraction" + | `pageTurn => "pageTurn"; + traits |> List.map to_string |> Array.of_list + } + ) + accessibilityTraits + ), + "accessibilityViewIsModal": from_opt (option_map to_js_boolean accessibilityViewIsModal), + "shouldRasterizeIOS": from_opt (option_map to_js_boolean shouldRasterizeIOS), + "autoCapitalize": + from_opt ( + option_map + ( + fun x => + switch x { + | `none => "none" + | `sentences => "sentences" + | `words => "words" + | `characters => "characters" + } + ) + autoCapitalize + ), + "autoCorrect": from_opt (option_map to_js_boolean autoCorrect), + "autoFocus": from_opt (option_map to_js_boolean autoFocus), + "blurOnSubmit": from_opt (option_map to_js_boolean blurOnSubmit), + "caretHidden": from_opt (option_map to_js_boolean caretHidden), + "defaultValue": from_opt defaultValue, + "editable": from_opt (option_map to_js_boolean editable), + "keyboardType": + from_opt ( + option_map + ( + fun x => + switch x { + | `default => "default" + | `emailAddress => "email-address" + | `numeric => "numeric" + | `phonePad => "phone-pad" + | `asciiCapable => "ascii-capable" + | `numbersAndPunctuation => "numbers-and-punctuation" + | `url => "url" + | `numberPad => "number-pad" + | `namePhonePad => "name-phone-pad" + | `decimalPad => "decimal-pad" + | `twitter => "twitter" + | `webSearch => "web-search" + } + ) + keyboardType + ), + "maxLength": from_opt maxLength, + "multiline": from_opt (option_map to_js_boolean multiline), + "onBlur": from_opt onBlur, + "onChange": from_opt onChange, + "onChangeText": from_opt onChangeText, + "onContentSizeChange": from_opt onContentSizeChange, + "onEndEditing": from_opt onEndEditing, + "onFocus": from_opt onFocus, + "onScroll": from_opt onScroll, + "onSelectionChange": from_opt onSelectionChange, + "onSubmitEditing": from_opt onSubmitEditing, + "placeholder": from_opt placeholder, + "placeholderTextColor": from_opt placeholderTextColor, + "returnKeyType": + from_opt ( + option_map + ( + fun x => + switch x { + | `done_ => "done_" + | `go => "go" + | `next => "next" + | `search => "search" + | `send => "send" + | `none => "none" + | `previous => "previous" + | `default => "default" + | `emergencyCall => "emergencyCall" + | `google => "google" + | `join => "join" + | `route => "route" + | `yahoo => "yahoo" + } + ) + returnKeyType + ), + "secureTextEntry": from_opt (option_map to_js_boolean secureTextEntry), + "selectTextOnFocus": from_opt (option_map to_js_boolean selectTextOnFocus), + "selection": from_opt selection, + "selectionColor": from_opt selectionColor, + "value": from_opt value, + "disableFullscreenUI": from_opt (option_map to_js_boolean disableFullscreenUI), + /* TODO */ + "inlineImageLeft": from_opt inlineImageLeft, + "inlineImagePadding": from_opt inlineImagePadding, + "numberOfLines": from_opt numberOfLines, + "returnKeyLabel": from_opt returnKeyLabel, + "textBreakStrategy": + from_opt ( + option_map + ( + fun x => + switch x { + | `simple => "simple" + | `highQuality => "highQuality" + | `balanced => "balanced" + } + ) + textBreakStrategy + ), + "underlineColorAndroid": from_opt underlineColorAndroid, + "clearButtonMode": + from_opt ( + option_map + ( + fun x => + switch x { + | `never => "never" + | `whileEditing => "whileEditing" + | `unlessEditing => "unless-editing" + | `always => "always" + } + ) + clearButtonMode + ), + "clearTextOnFocus": from_opt (option_map to_js_boolean clearTextOnFocus), + "dataDetectorTypes": + from_opt ( + option_map + ( + Array.map ( + fun x => + switch x { + | `phoneNumber => "phoneNumber" + | `link => "link" + | `calendarEvent => "calendarEvent" + | `none => "none" + | `all => "all" + } + ) + ) + dataDetectorTypes + ), + "enablesReturnKeyAutomatically": + from_opt (option_map to_js_boolean enablesReturnKeyAutomatically), + "keyboardAppearance": + from_opt ( + option_map + ( + fun x => + switch x { + | `default => "never" + | `light => "light" + | `dark => "dark" + } + ) + keyboardAppearance + ), + "onKeyPress": from_opt onKeyPress, + "selectionState": from_opt selectionState, + "spellCheck": from_opt (option_map to_js_boolean spellCheck) + }; \ No newline at end of file diff --git a/src/components/textInputRe.rei b/src/components/textInputRe.rei new file mode 100644 index 00000000000000..ee9f501301292f --- /dev/null +++ b/src/components/textInputRe.rei @@ -0,0 +1,130 @@ +let isFocused: ReactRe.reactRef => bool; + +let clear: ReactRe.reactRef => unit; + +let createElement: + accessibleLeft::ReactRe.reactElement? => + accessible::bool? => + hitSlop::Js.t {. left : int, right : int, top : int, bottom : int}? => + onAccessibilityTap::(unit => unit)? => + onLayout::(RNEvent.NativeLayoutEvent.t => unit)? => + onMagicTap::(unit => unit)? => + onMoveShouldSetResponder::(RNEvent.NativeEvent.t => bool)? => + onMoveShouldSetResponderCapture::(RNEvent.NativeEvent.t => bool)? => + onResponderGrant::(RNEvent.NativeEvent.t => unit)? => + onResponderMove::(RNEvent.NativeEvent.t => unit)? => + onResponderReject::(RNEvent.NativeEvent.t => unit)? => + onResponderRelease::(RNEvent.NativeEvent.t => unit)? => + onResponderTerminate::(RNEvent.NativeEvent.t => unit)? => + onResponderTerminationRequest::(RNEvent.NativeEvent.t => unit)? => + onStartShouldSetResponder::(RNEvent.NativeEvent.t => bool)? => + onStartShouldSetResponderCapture::(RNEvent.NativeEvent.t => bool)? => + pointerEvents::[ | `auto | `none | `boxNone | `boxOnly]? => + removeClippedSubviews::bool? => + style::Style.t? => + testID::string? => + accessibilityComponentType::[ | `none | `button | `radiobutton_checked | `radiobutton_unchecked]? => + accessibilityLiveRegion::[ | `none | `polite | `assertive]? => + collapsable::bool? => + importantForAccessibility::[ | `auto | `yes | `no | `noHideDescendants]? => + needsOffscreenAlphaCompositing::bool? => + renderToHardwareTextureAndroid::bool? => + accessibilityTraits:: + list [ + | `none + | `button + | `link + | `header + | `search + | `image + | `selected + | `plays + | `key + | `text + | `summary + | `disabled + | `frequentUpdates + | `startsMedia + | `adjustable + | `allowsDirectInteraction + | `pageTurn + ]? => + accessibilityViewIsModal::bool? => + shouldRasterizeIOS::bool? => + autoCapitalize::[< | `characters | `none | `sentences | `words]? => + autoCorrect::bool? => + autoFocus::bool? => + blurOnSubmit::bool? => + caretHidden::bool? => + defaultValue::string? => + editable::bool? => + keyboardType:: + [ + | `asciiCapable + | `decimalPad + | `default + | `emailAddress + | `namePhonePad + | `numberPad + | `numbersAndPunctuation + | `numeric + | `phonePad + | `twitter + | `url + | `webSearch + ]? => + maxLength::int? => + multiline::bool? => + onBlur::(unit => unit)? => + onChange::(unit => unit)? => + onChangeText::(string => unit)? => + onContentSizeChange:: + Js.t {. nativeEvent : Js.t {. contentSize : Js.t {. width : float, height : float}}}? => + onEndEditing::(unit => unit)? => + onFocus::(unit => unit)? => + onScroll::Js.t {. nativeEvent : Js.t {. contentOffset : Js.t {. x : float, y : float}}}? => + onSelectionChange::Js.t {. nativeEvent : Js.t {. selection : Js.t {. start : int, _end : int}}}? => + onSubmitEditing::(unit => unit)? => + placeholder::string? => + placeholderTextColor::string? => + returnKeyType:: + [ + | `default + | `done_ + | `emergencyCall + | `go + | `google + | `join + | `next + | `none + | `previous + | `route + | `search + | `send + | `yahoo + ]? => + secureTextEntry::bool? => + selectTextOnFocus::bool? => + selection::Js.t {. start : int, _end : int}? => + selectionColor::string? => + value::string? => + disableFullscreenUI::bool? => + inlineImageLeft::string? => + inlineImagePadding::int? => + numberOfLines::int? => + returnKeyLabel::string? => + textBreakStrategy::[ | `balanced | `highQuality | `simple]? => + underlineColorAndroid::string? => + clearButtonMode::[ | `always | `never | `unlessEditing | `whileEditing]? => + clearTextOnFocus::bool? => + dataDetectorTypes::array [ | `all | `calendarEvent | `link | `none | `phoneNumber]? => + enablesReturnKeyAutomatically::bool? => + keyboardAppearance::[ | `dark | `default | `light]? => + onKeyPress::Js.t {. nativeEvent : Js.t {. key : string}}? => + selectionState::'documentSelectionState? => + spellCheck::bool? => + children::list ReactRe.reactElement => + ref::(ReactRe.reactRef => unit)? => + key::string? => + unit => + ReactRe.reactElement; \ No newline at end of file diff --git a/src/reactNative.re b/src/reactNative.re index ad73c9b1160d3e..3ce192f718633b 100644 --- a/src/reactNative.re +++ b/src/reactNative.re @@ -7,6 +7,7 @@ module FlatList = FlatListRe; module Modal = ModalRe; module ScrollView = ScrollViewRe; module Text = TextRe; +module TextInput = TextInputRe; module TouchableHighlight = TouchableHighlightRe; module TouchableOpacity = TouchableOpacityRe; module TouchableWithoutFeedback = TouchableWithoutFeedbackRe;