Skip to content

Commit

Permalink
Fix issue with TextField floating placeholder offset when it includes…
Browse files Browse the repository at this point in the history
… a leading accessory (#1700)
  • Loading branch information
ethanshar authored Dec 1, 2021
1 parent 58f878d commit ebd9fb6
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,10 @@ export default class TextFieldScreen extends Component {
<TextField
ref={this.input2}
placeholder="Enter URL"
floatingPlaceholder
text70
leadingAccessory={
<Text text70 blue30>
<Text text70 blue30 marginR-2>
Https://
</Text>
}
Expand Down
1 change: 1 addition & 0 deletions generatedTypes/src/hooks/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { default as useCombinedRefs } from './useCombinedRefs';
export { default as useToggleValue } from './useToggleValue';
export { default as useDidUpdate } from './useDidUpdate';
export { default as useMeasure } from './useMeasure';
export { default as useOrientation } from './useOrientation';
export { default as useScrollEnabler } from './useScrollEnabler';
export { default as useScrollReached } from './useScrollReached';
Expand Down
15 changes: 15 additions & 0 deletions generatedTypes/src/hooks/useMeasure/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/// <reference types="react" />
import { View as RNView } from 'react-native';
interface Measurements {
x: number;
y: number;
width: number;
height: number;
pageX: number;
pageY: number;
}
declare const _default: () => {
ref: import("react").MutableRefObject<RNView | undefined>;
measurements: Measurements | undefined;
};
export default _default;
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ export interface FloatingPlaceholderProps {
*/
floatOnFocus?: boolean;
validationMessagePosition?: ValidationMessagePosition;
extraOffset?: number;
}
declare const FloatingPlaceholder: {
({ placeholder, floatingPlaceholderColor, floatingPlaceholderStyle, floatOnFocus, validationMessagePosition }: FloatingPlaceholderProps): JSX.Element;
({ placeholder, floatingPlaceholderColor, floatingPlaceholderStyle, floatOnFocus, validationMessagePosition, extraOffset }: FloatingPlaceholderProps): JSX.Element;
displayName: string;
};
export default FloatingPlaceholder;
3 changes: 3 additions & 0 deletions generatedTypes/src/incubator/TextField/usePreset.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export default function usePreset({ preset, ...props }: InternalTextFieldProps):
floatingPlaceholderColor?: import("./types").ColorType | undefined;
floatingPlaceholderStyle?: ((false | import("react-native").TextStyle | import("react-native").RegisteredStyle<import("react-native").TextStyle> | import("react-native").RecursiveArray<import("react-native").TextStyle | import("react-native").Falsy | import("react-native").RegisteredStyle<import("react-native").TextStyle>> | null) & import("react-native").TextStyle) | undefined;
floatOnFocus?: boolean | undefined;
extraOffset?: number | undefined;
enableErrors?: boolean | undefined;
validationMessage?: string | string[] | undefined;
validationMessageStyle?: import("react-native").TextStyle | undefined;
Expand Down Expand Up @@ -475,6 +476,7 @@ export default function usePreset({ preset, ...props }: InternalTextFieldProps):
floatingPlaceholderColor?: import("./types").ColorType | undefined;
floatingPlaceholderStyle?: ((false | import("react-native").TextStyle | import("react-native").RegisteredStyle<import("react-native").TextStyle> | import("react-native").RecursiveArray<import("react-native").TextStyle | import("react-native").Falsy | import("react-native").RegisteredStyle<import("react-native").TextStyle>> | null) & import("react-native").TextStyle) | undefined;
floatOnFocus?: boolean | undefined;
extraOffset?: number | undefined;
enableErrors?: boolean | undefined;
validationMessage?: string | string[] | undefined;
validationMessageStyle?: import("react-native").TextStyle | undefined;
Expand Down Expand Up @@ -1036,6 +1038,7 @@ export default function usePreset({ preset, ...props }: InternalTextFieldProps):
includeFontPadding?: boolean | undefined;
};
floatOnFocus?: boolean | undefined;
extraOffset?: number | undefined;
enableErrors: boolean;
validationMessage?: string | string[] | undefined;
validationMessageStyle?: import("react-native").TextStyle | undefined;
Expand Down
1 change: 1 addition & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export {default as useCombinedRefs} from './useCombinedRefs';
export {default as useToggleValue} from './useToggleValue';
export {default as useDidUpdate} from './useDidUpdate';
export {default as useMeasure} from './useMeasure';
export {default as useOrientation} from './useOrientation';
export {default as useScrollEnabler} from './useScrollEnabler';
export {default as useScrollReached} from './useScrollReached';
Expand Down
35 changes: 35 additions & 0 deletions src/hooks/useMeasure/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {useEffect, useRef, useState} from 'react';
import {MeasureOnSuccessCallback, View as RNView} from 'react-native';

interface Measurements {
x: number;
y: number;
width: number;
height: number;
pageX: number;
pageY: number;
}

export default () => {
const ref = useRef<RNView>();
const [measurements, setMeasurements] = useState<Measurements | undefined>();

const onMeasure: MeasureOnSuccessCallback = (x, y, width, height, pageX, pageY) => {
setMeasurements({
x,
y,
width,
height,
pageX,
pageY
});
};

useEffect(() => {
setTimeout(() => {
ref.current?.measure?.(onMeasure);
}, 0);
}, []);

return {ref, measurements};
};
11 changes: 8 additions & 3 deletions src/incubator/TextField/FloatingPlaceholder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface FloatingPlaceholderProps {
*/
floatOnFocus?: boolean;
validationMessagePosition?: ValidationMessagePosition;
extraOffset?: number;
}

const FLOATING_PLACEHOLDER_SCALE = 0.875;
Expand All @@ -35,7 +36,8 @@ const FloatingPlaceholder = ({
floatingPlaceholderColor = Colors.grey40,
floatingPlaceholderStyle,
floatOnFocus,
validationMessagePosition
validationMessagePosition,
extraOffset = 0
}: FloatingPlaceholderProps) => {
const context = useContext(FieldContext);
const [placeholderOffset, setPlaceholderOffset] = useState({
Expand All @@ -52,14 +54,17 @@ const FloatingPlaceholder = ({
scale: interpolateValue(animation, [1, FLOATING_PLACEHOLDER_SCALE])
},
{
translateX: interpolateValue(animation, [0, -placeholderOffset.left])
translateX: interpolateValue(animation, [
0,
-placeholderOffset.left - extraOffset / FLOATING_PLACEHOLDER_SCALE
])
},
{
translateY: interpolateValue(animation, [0, -placeholderOffset.top])
}
]
};
}, [placeholderOffset]);
}, [placeholderOffset, extraOffset]);

useEffect(() => {
const toValue = floatOnFocus ? context.isFocused || context.hasValue : context.hasValue;
Expand Down
6 changes: 5 additions & 1 deletion src/incubator/TextField/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
} from '../../commons/new';
import View from '../../components/view';
import {Colors} from '../../style';
import {useMeasure} from '../../hooks';
import {ValidationMessagePosition, Validator} from './types';
import {shouldHidePlaceholder} from './Presenter';
import Input, {InputProps} from './Input';
Expand Down Expand Up @@ -151,6 +152,7 @@ const TextField = (props: InternalTextFieldProps) => {
children,
...others
} = usePreset(props);
const {ref: leadingAccessoryRef, measurements: leadingAccessoryMeasurements} = useMeasure();
const {onFocus, onBlur, onChangeText, fieldState, validateField} = useFieldState(others);

const context = useMemo(() => {
Expand Down Expand Up @@ -186,7 +188,8 @@ const TextField = (props: InternalTextFieldProps) => {
)}
<View style={[paddings, fieldStyle]} row centerV>
{/* <View row centerV> */}
{leadingAccessory}
{/* @ts-expect-error */}
{leadingAccessory && <View ref={leadingAccessoryRef}>{leadingAccessory}</View>}
<View flexG>
{floatingPlaceholder && (
<FloatingPlaceholder
Expand All @@ -195,6 +198,7 @@ const TextField = (props: InternalTextFieldProps) => {
floatingPlaceholderColor={floatingPlaceholderColor}
floatOnFocus={floatOnFocus}
validationMessagePosition={validationMessagePosition}
extraOffset={leadingAccessoryMeasurements?.width}
/>
)}
{children || (
Expand Down

0 comments on commit ebd9fb6

Please sign in to comment.