Skip to content

Commit

Permalink
Fix autogrow of baseTextInput for markdown text input
Browse files Browse the repository at this point in the history
Signed-off-by: Tsaqif <[email protected]>
  • Loading branch information
tsa321 committed Sep 26, 2024
1 parent 21e519c commit 42c8cbc
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 12 deletions.
25 changes: 19 additions & 6 deletions src/components/TextInput/BaseTextInput/index.native.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Str} from 'expensify-common';
import type {ForwardedRef} from 'react';
import React, {forwardRef, useCallback, useEffect, useRef, useState} from 'react';
import React, {forwardRef, useCallback, useEffect, useRef, useState, useMemo} from 'react';
import type {GestureResponderEvent, LayoutChangeEvent, NativeSyntheticEvent, StyleProp, TextInput, TextInputFocusEventData, ViewStyle} from 'react-native';
import {ActivityIndicator, Animated, StyleSheet, View} from 'react-native';
import Checkbox from '@components/Checkbox';
Expand Down Expand Up @@ -71,6 +71,7 @@ function BaseTextInput(
ref: ForwardedRef<BaseTextInputRef>,
) {
const InputComponent = isMarkdownEnabled ? RNMarkdownTextInput : RNTextInput;
const isAutoGrowHeightMarkdown = isMarkdownEnabled && autoGrowHeight;

const inputProps = {shouldSaveDraft: false, shouldUseDefaultValue: false, ...props};
const theme = useTheme();
Expand Down Expand Up @@ -261,6 +262,17 @@ function BaseTextInput(

const inputPaddingLeft = !!prefixCharacter && StyleUtils.getPaddingLeft(StyleUtils.getCharacterPadding(prefixCharacter) + styles.pl1.paddingLeft);

const verticalPadding = useMemo (() => {
const flattenedInputStyle = StyleSheet.flatten(inputStyle);
const topBottomPadding = (flattenedInputStyle.paddingTop ?? 0) + (flattenedInputStyle.paddingBottom ?? 0);
if (topBottomPadding !== 0) {
return topBottomPadding;
}

return flattenedInputStyle.padding ?? 0;
}, [inputStyle]);


return (
<>
<View style={[containerStyles]}>
Expand All @@ -273,7 +285,7 @@ function BaseTextInput(
onLayout={onLayout}
accessibilityLabel={label}
style={[
autoGrowHeight && styles.autoGrowHeightInputContainer(textInputHeight, variables.componentSizeLarge, typeof maxAutoGrowHeight === 'number' ? maxAutoGrowHeight : 0),
autoGrowHeight && !isAutoGrowHeightMarkdown && styles.autoGrowHeightInputContainer(textInputHeight, variables.componentSizeLarge, typeof maxAutoGrowHeight === 'number' ? maxAutoGrowHeight : 0),
!isMultiline && styles.componentHeightLarge,
touchableInputWrapperStyle,
]}
Expand All @@ -300,7 +312,7 @@ function BaseTextInput(
/>
</>
) : null}
<View style={[styles.textInputAndIconContainer, isMultiline && hasLabel && styles.textInputMultilineContainer, styles.pointerEventsBoxNone]}>
<View style={[isAutoGrowHeightMarkdown ? undefined : styles.textInputAndIconContainer, isMultiline && hasLabel && styles.textInputMultilineContainer, styles.pointerEventsBoxNone]}>
{iconLeft && (
<View style={styles.textInputLeftIconContainer}>
<Icon
Expand Down Expand Up @@ -346,12 +358,13 @@ function BaseTextInput(
inputStyle,
(!hasLabel || isMultiline) && styles.pv0,
inputPaddingLeft,
isAutoGrowHeightMarkdown ? {maxHeight: maxAutoGrowHeight - verticalPadding} : undefined,
inputProps.secureTextEntry && styles.secureInput,

!isMultiline && {height, lineHeight: undefined},

// Stop scrollbar flashing when breaking lines with autoGrowHeight enabled.
...(autoGrowHeight
...(autoGrowHeight && !isAutoGrowHeightMarkdown
? [StyleUtils.getAutoGrowHeightInputStyle(textInputHeight, typeof maxAutoGrowHeight === 'number' ? maxAutoGrowHeight : 0), styles.verticalAlignTop]
: []),
// Add disabled color theme when field is not editable.
Expand Down Expand Up @@ -415,7 +428,7 @@ function BaseTextInput(
/>
)}
</View>
{contentWidth && (
{contentWidth && !isAutoGrowHeightMarkdown (
<View
style={[inputStyle as ViewStyle, styles.hiddenElementOutsideOfWindow, styles.visibilityHidden, styles.wAuto, inputPaddingLeft]}
onLayout={(e) => {
Expand Down Expand Up @@ -444,7 +457,7 @@ function BaseTextInput(
This text view is used to calculate width or height of the input value given textStyle in this component.
This Text component is intentionally positioned out of the screen.
*/}
{(!!autoGrow || autoGrowHeight) && (
{(!!autoGrow || autoGrowHeight) && !isAutoGrowHeightMarkdown && (
// Add +2 to width on Safari browsers so that text is not cut off due to the cursor or when changing the value
// https://github.com/Expensify/App/issues/8158
// https://github.com/Expensify/App/issues/26628
Expand Down
27 changes: 21 additions & 6 deletions src/components/TextInput/BaseTextInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ function BaseTextInput(
ref: ForwardedRef<BaseTextInputRef>,
) {
const InputComponent = isMarkdownEnabled ? RNMarkdownTextInput : RNTextInput;
const isAutoGrowHeightMarkdown = isMarkdownEnabled && autoGrowHeight;

const theme = useTheme();
const styles = useThemeStyles();
Expand All @@ -95,6 +96,7 @@ function BaseTextInput(
const [textInputHeight, setTextInputHeight] = useState(0);
const [height, setHeight] = useState<number>(variables.componentSizeLarge);
const [width, setWidth] = useState<number | null>(null);

const labelScale = useRef(new Animated.Value(initialActiveLabel ? styleConst.ACTIVE_LABEL_SCALE : styleConst.INACTIVE_LABEL_SCALE)).current;
const labelTranslateY = useRef(new Animated.Value(initialActiveLabel ? styleConst.ACTIVE_LABEL_TRANSLATE_Y : styleConst.INACTIVE_LABEL_TRANSLATE_Y)).current;
const input = useRef<HTMLInputElement | null>(null);
Expand Down Expand Up @@ -282,6 +284,16 @@ function BaseTextInput(
const inputPaddingLeft = !!prefixCharacter && StyleUtils.getPaddingLeft(StyleUtils.getCharacterPadding(prefixCharacter) + styles.pl1.paddingLeft);
const inputPaddingRight = !!suffixCharacter && StyleUtils.getPaddingRight(StyleUtils.getCharacterPadding(suffixCharacter) + styles.pr1.paddingRight);

const verticalPadding = useMemo (() => {
const flattenedInputStyle = StyleSheet.flatten(inputStyle);
const topBottomPadding = (flattenedInputStyle.paddingTop ?? 0) + (flattenedInputStyle.paddingBottom ?? 0);
if (topBottomPadding !== 0) {
return topBottomPadding;
}

return flattenedInputStyle.padding ?? 0;
}, [inputStyle]);

return (
<>
<View
Expand All @@ -298,9 +310,10 @@ function BaseTextInput(
// or if multiline is not supplied we calculate the textinput height, using onLayout.
onLayout={onLayout}
style={[
autoGrowHeight && styles.autoGrowHeightInputContainer(textInputHeight, variables.componentSizeLarge, typeof maxAutoGrowHeight === 'number' ? maxAutoGrowHeight : 0),
(autoGrowHeight && !isAutoGrowHeightMarkdown && styles.autoGrowHeightInputContainer(textInputHeight, variables.componentSizeLarge, typeof maxAutoGrowHeight === 'number' ? maxAutoGrowHeight : 0)),
!isMultiline && styles.componentHeightLarge,
touchableInputWrapperStyle,
isAutoGrowHeightMarkdown ? {minHeight: variables.componentSizeLarge} : undefined,
]}
>
<View
Expand All @@ -325,7 +338,8 @@ function BaseTextInput(
/>
</>
) : null}
<View style={[styles.textInputAndIconContainer, isMultiline && hasLabel && styles.textInputMultilineContainer, styles.pointerEventsBoxNone]}>

<View style={[isAutoGrowHeightMarkdown ? undefined : styles.textInputAndIconContainer, isMultiline && hasLabel && styles.textInputMultilineContainer, styles.pointerEventsBoxNone]}>
{iconLeft && (
<View style={[styles.textInputLeftIconContainer, !isReadOnly ? styles.cursorPointer : styles.pointerEventsNone]}>
<Icon
Expand Down Expand Up @@ -372,11 +386,12 @@ function BaseTextInput(
(!hasLabel || isMultiline) && styles.pv0,
inputPaddingLeft,
inputPaddingRight,
isAutoGrowHeightMarkdown? {maxHeight: maxAutoGrowHeight - verticalPadding} : undefined,
inputProps.secureTextEntry && styles.secureInput,

// Explicitly remove `lineHeight` from single line inputs so that long text doesn't disappear
// once it exceeds the input space (See https://github.com/Expensify/App/issues/13802)
!isMultiline && {height, lineHeight},
!isMultiline && !isAutoGrowHeightMarkdown && {height, lineHeight},

// Explicitly change boxSizing attribute for mobile chrome in order to apply line-height
// for the issue mentioned here https://github.com/Expensify/App/issues/26735
Expand All @@ -385,7 +400,7 @@ function BaseTextInput(
!isMultiline && Browser.isMobileChrome() && {boxSizing: 'content-box', height: undefined, ...styles.overflowAuto},

// Stop scrollbar flashing when breaking lines with autoGrowHeight enabled.
...(autoGrowHeight
...(autoGrowHeight && !isAutoGrowHeightMarkdown
? [StyleUtils.getAutoGrowHeightInputStyle(textInputHeight, typeof maxAutoGrowHeight === 'number' ? maxAutoGrowHeight : 0), styles.verticalAlignTop]
: []),

Expand Down Expand Up @@ -460,7 +475,7 @@ function BaseTextInput(
/>
)}
</View>
{contentWidth && (
{contentWidth && !isAutoGrowHeightMarkdown (
<View
style={[inputStyle as ViewStyle, styles.hiddenElementOutsideOfWindow, styles.visibilityHidden, styles.wAuto, inputPaddingLeft]}
onLayout={(e) => {
Expand Down Expand Up @@ -489,7 +504,7 @@ function BaseTextInput(
This text view is used to calculate width or height of the input value given textStyle in this component.
This Text component is intentionally positioned out of the screen.
*/}
{(!!autoGrow || autoGrowHeight) && (
{(!!autoGrow || autoGrowHeight) && !isAutoGrowHeightMarkdown && (
// Add +2 to width on Safari browsers so that text is not cut off due to the cursor or when changing the value
// Reference: https://github.com/Expensify/App/issues/8158, https://github.com/Expensify/App/issues/26628
// For mobile Chrome, ensure proper display of the text selection handle (blue bubble down).
Expand Down

0 comments on commit 42c8cbc

Please sign in to comment.