UNPKG

@tamagui/react-native-web-lite

Version:
258 lines (257 loc) 10.1 kB
import * as React from "react"; import { StyleSheet } from "@tamagui/react-native-web-internals"; import { TextInputState, forwardedProps, getLocaleDirection, pick, useElementLayout, useLocaleContext, useMergeRefs, usePlatformMethods, useResponderEvents } from "@tamagui/react-native-web-internals"; import { useCreateElement } from "../createElement/index"; const isSelectionStale = (node, selection) => { const { selectionEnd, selectionStart } = node, { start, end } = selection; return start !== selectionStart || end !== selectionEnd; }, setSelection = (node, selection) => { if (isSelectionStale(node, selection)) { const { start, end } = selection; try { node.setSelectionRange(start, end || start); } catch { } } }, forwardPropsList = Object.assign( {}, forwardedProps.defaultProps, forwardedProps.accessibilityProps, forwardedProps.clickProps, forwardedProps.focusProps, forwardedProps.keyboardProps, forwardedProps.mouseProps, forwardedProps.touchProps, forwardedProps.styleProps, { autoCapitalize: !0, className: !0, autoComplete: !0, autoCorrect: !0, autoFocus: !0, defaultValue: !0, disabled: !0, lang: !0, maxLength: !0, onChange: !0, onScroll: !0, placeholder: !0, pointerEvents: !0, readOnly: !0, rows: !0, spellCheck: !0, value: !0, type: !0 } ), pickProps = (props) => pick(props, forwardPropsList), useIsomorphicLayoutEffect = typeof window > "u" ? React.useEffect : React.useLayoutEffect; function isEventComposing(nativeEvent) { return nativeEvent.isComposing || nativeEvent.keyCode === 229; } let focusTimeout = null; const TextInput = React.forwardRef( (props, forwardedRef) => { const { autoCapitalize = "sentences", autoComplete, autoCompleteType, autoCorrect = !0, blurOnSubmit, clearTextOnFocus, dir, editable, enterKeyHint, inputMode = "text", keyboardType, multiline = !1, numberOfLines, onBlur, onChange, onChangeText, onContentSizeChange, onFocus, onKeyPress, onLayout, onMoveShouldSetResponder, onMoveShouldSetResponderCapture, onResponderEnd, onResponderGrant, onResponderMove, onResponderReject, onResponderRelease, onResponderStart, onResponderTerminate, onResponderTerminationRequest, onScrollShouldSetResponder, onScrollShouldSetResponderCapture, onSelectionChange, onSelectionChangeShouldSetResponder, onSelectionChangeShouldSetResponderCapture, onStartShouldSetResponder, onStartShouldSetResponderCapture, onSubmitEditing, placeholderTextColor, readOnly = !1, returnKeyType, rows = 1, secureTextEntry = !1, selection, selectTextOnFocus, showSoftInputOnFocus, caretHidden, spellCheck } = props; let type, _inputMode; if (inputMode != null) _inputMode = inputMode, inputMode === "email" ? type = "email" : inputMode === "tel" ? type = "tel" : inputMode === "search" ? type = "search" : inputMode === "url" ? type = "url" : type = "text"; else if (keyboardType != null) switch (warn("keyboardType", "keyboardType is deprecated. Use inputMode."), keyboardType) { case "email-address": type = "email"; break; case "number-pad": case "numeric": _inputMode = "numeric"; break; case "decimal-pad": _inputMode = "decimal"; break; case "phone-pad": type = "tel"; break; case "search": case "web-search": type = "search"; break; case "url": type = "url"; break; default: type = "text"; } secureTextEntry && (type = "password"); const dimensions = React.useRef({ height: null, width: null }), hostRef = React.useRef(null), handleContentSizeChange = React.useCallback( (hostNode) => { if (multiline && onContentSizeChange && hostNode != null) { const newHeight = hostNode.scrollHeight, newWidth = hostNode.scrollWidth; (newHeight !== dimensions.current.height || newWidth !== dimensions.current.width) && (dimensions.current.height = newHeight, dimensions.current.width = newWidth, onContentSizeChange({ nativeEvent: { contentSize: { height: dimensions.current.height, width: dimensions.current.width } } })); } }, [multiline, onContentSizeChange] ), imperativeRef = React.useMemo( () => (hostNode) => { hostNode != null && (hostNode.clear = () => { hostNode != null && (hostNode.value = ""); }, hostNode.isFocused = () => hostNode != null && TextInputState.currentlyFocusedField() === hostNode, handleContentSizeChange(hostNode)); }, [handleContentSizeChange] ); function handleBlur(e) { TextInputState._currentlyFocusedNode = null, onBlur && (e.nativeEvent.text = e.target.value, onBlur(e)); } function handleChange(e) { const hostNode = e.target, text = hostNode.value; e.nativeEvent.text = text, handleContentSizeChange(hostNode), onChange && onChange(e), onChangeText && onChangeText(text); } function handleFocus(e) { const hostNode = e.target; onFocus && (e.nativeEvent.text = hostNode.value, onFocus(e)), hostNode != null && (TextInputState._currentlyFocusedNode = hostNode, clearTextOnFocus && (hostNode.value = ""), selectTextOnFocus && (focusTimeout != null && clearTimeout(focusTimeout), focusTimeout = setTimeout(() => { hostNode?.select(); }, 0))); } function handleKeyDown(e) { const hostNode = e.target; e.stopPropagation(); const shouldBlurOnSubmit = blurOnSubmit ?? !multiline, nativeEvent = e.nativeEvent, isComposing = isEventComposing(nativeEvent); onKeyPress && onKeyPress(e), e.key === "Enter" && !e.shiftKey && // Do not call submit if composition is occuring. !isComposing && !e.isDefaultPrevented() && ((blurOnSubmit || !multiline) && onSubmitEditing && (e.preventDefault(), nativeEvent.text = e.target.value, onSubmitEditing(e)), shouldBlurOnSubmit && hostNode != null && setTimeout(() => hostNode.blur(), 0)); } function handleSelectionChange(e) { if (onSelectionChange) try { const node = e.target, { selectionStart, selectionEnd } = node; e.nativeEvent.selection = { start: selectionStart, end: selectionEnd }, e.nativeEvent.text = e.target.value, onSelectionChange(e); } catch { } } useIsomorphicLayoutEffect(() => { const node = hostRef.current; node != null && selection != null && setSelection(node, selection), document.activeElement === node && (TextInputState._currentlyFocusedNode = node); }, [hostRef, selection]); const component = multiline ? "textarea" : "input"; useElementLayout(hostRef, onLayout), useResponderEvents(hostRef, { onMoveShouldSetResponder, onMoveShouldSetResponderCapture, onResponderEnd, onResponderGrant, onResponderMove, onResponderReject, onResponderRelease, onResponderStart, onResponderTerminate, onResponderTerminationRequest, onScrollShouldSetResponder, onScrollShouldSetResponderCapture, onSelectionChangeShouldSetResponder, onSelectionChangeShouldSetResponderCapture, onStartShouldSetResponder, onStartShouldSetResponderCapture }); const { direction: contextDirection } = useLocaleContext(), supportedProps = pickProps(props); supportedProps.autoCapitalize = autoCapitalize, supportedProps.autoComplete = autoComplete || autoCompleteType || "on", supportedProps.autoCorrect = autoCorrect ? "on" : "off", supportedProps.dir = dir !== void 0 ? dir : "auto", returnKeyType != null && warn("returnKeyType", "returnKeyType is deprecated. Use enterKeyHint."), supportedProps.enterKeyHint = enterKeyHint || returnKeyType, supportedProps.inputMode = _inputMode, supportedProps.onBlur = handleBlur, supportedProps.onChange = handleChange, supportedProps.onFocus = handleFocus, supportedProps.onKeyDown = handleKeyDown, supportedProps.onSelect = handleSelectionChange, editable != null && warn("editable", "editable is deprecated. Use readOnly."), supportedProps.readOnly = readOnly === !0 || editable === !1, numberOfLines != null && warn("numberOfLines", "TextInput numberOfLines is deprecated. Use rows."), supportedProps.rows = multiline ? rows ?? numberOfLines : 1, supportedProps.spellCheck = spellCheck ?? autoCorrect, supportedProps.style = [ { "--placeholderTextColor": placeholderTextColor }, styles.textinput$raw, styles.placeholder, props.style, caretHidden && styles.caretHidden ], supportedProps.type = multiline ? void 0 : type, supportedProps.virtualkeyboardpolicy = showSoftInputOnFocus === !1 ? "manual" : "auto"; const platformMethodsRef = usePlatformMethods(supportedProps), setRef = useMergeRefs(hostRef, platformMethodsRef, imperativeRef, forwardedRef); supportedProps.ref = setRef; const langDirection = props.lang != null ? getLocaleDirection(props.lang) : null, writingDirection = props.dir || langDirection || contextDirection; return useCreateElement(component, supportedProps, { writingDirection }); } ); function warn(...args) { process.env.NODE_ENV !== "production" && console.warn(...args); } TextInput.displayName = "TextInput"; TextInput.State = TextInputState; const styles = StyleSheet.create({ textinput$raw: { MozAppearance: "textfield", WebkitAppearance: "none", appearance: "none" }, placeholder: { placeholderTextColor: "var(--placeholderTextColor)" }, caretHidden: { caretColor: "transparent" } }); var TextInput_default = TextInput; export { TextInput_default as default }; //# sourceMappingURL=index.js.map