react-native#ImageStyle TypeScript Examples
The following examples show how to use
react-native#ImageStyle.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx From react-native-floating-label-input with MIT License | 6 votes |
setGlobalStyles: SetGlobalStyles = {
/**Set global styles to all floating-label-inputs container */
containerStyles: undefined as ViewStyle | undefined,
/**Set global custom styles to all floating-label-inputs labels */
customLabelStyles: undefined as CustomLabelProps | undefined,
/**Set global styles to all floating-label-inputs input */
inputStyles: undefined as TextStyle | undefined,
/**Set global styles to all floating-label-inputs label */
labelStyles: undefined as TextStyle | undefined,
/**Set global styles to all floating-label-inputs show password container */
showPasswordContainerStyles: undefined as ViewStyle | undefined,
/**Set global styles to all floating-label-inputs show password image */
showPasswordImageStyles: undefined as ImageStyle | undefined,
/**Set global style to the countdown text */
showCountdownStyles: undefined as TextStyle | undefined,
}
Example #2
Source File: index.tsx From frontatish with MIT License | 4 votes |
Searchbar = (props: SearchbarProps) => {
const Colors = useColors();
const styles = getStyles(Colors);
// destructure custom props and TextInput props separately
const customProps = getCustomProps(props);
const textInputProps = getTextInputProps(customProps, props);
const {
backIcon,
backIconStyle,
clearIcon,
clearIconStyle,
containerStyle,
inputStyle,
leftIcon,
leftIconStyle,
leftLogo,
leftLogoStyle,
onBackIconPress,
onClearIconPress,
onLeftIconPress,
onLeftLogoPress,
onRightIconPress,
onRightLogoPress,
onPress,
rightIcon,
rightIconStyle,
rightLogo,
rightLogoStyle,
showClearIcon,
showBackIcon,
} = customProps;
const { onChangeText, editable, value } = textInputProps;
const renderClearIcon = () => {
if (!showClearIcon) {
return null;
}
// we have to show transparent clear icon when value in textinput is empty
// otherwise the text will move left once the clear icon is rendered
const opacity = value ? 1 : 0;
const onPressUtil = () => {
if (opacity) {
if (onClearIconPress) {
onClearIconPress();
} else if (onChangeText) {
onChangeText('');
}
}
};
return renderIcon(clearIcon, clearIconStyle, onPressUtil, opacity);
};
const renderBackIcon = () => {
if (!showBackIcon) {
return null;
}
const opacity = 1;
return renderIcon(backIcon, backIconStyle, onBackIconPress, opacity);
};
const renderLogo = (
name: ImageSourcePropType,
logoStyle: StyleProp<ImageStyle> | undefined,
onLogoPress: (() => void) | undefined,
) => {
const source = name;
const onPressUtil = onLogoPress || onPress;
return (
<TouchableWithoutFeedback onPress={onPressUtil}>
<Image
source={source}
style={{
alignSelf: 'center',
height: customScaleDimension(30, 'width', 0.2),
width: customScaleDimension(30, 'width', 0.2),
...(logoStyle as object),
}}
/>
</TouchableWithoutFeedback>
);
};
const renderIcon = (
name: string | undefined,
iconStyle: StyleProp<TextStyle> | undefined,
onIconPress: (() => void) | undefined,
opacity: number,
) => {
const onPressUtil = onIconPress || onPress;
return (
<Icon
name={name}
size={customScaleDimension(30, 'width', 0.2)}
onPress={onPressUtil}
color={Colors.font_1}
style={{ opacity, alignSelf: 'center', ...(iconStyle as object) }}
/>
);
};
const renderLogoOrIcon = (
logo: ImageSourcePropType | undefined,
logoStyle: StyleProp<ImageStyle> | undefined,
onLogoPress: (() => void) | undefined,
icon: string | undefined,
iconStyle: StyleProp<TextStyle> | undefined,
onIconPress: (() => void) | undefined,
) => {
if (logo) {
return renderLogo(logo, logoStyle, onLogoPress);
}
if (icon) {
const opacity = 1;
return renderIcon(icon, iconStyle, onIconPress, opacity);
}
return null;
};
const renderLeft = () => {
if (!editable) {
return renderLogoOrIcon(
leftLogo,
leftLogoStyle,
onLeftLogoPress,
leftIcon,
leftIconStyle,
onLeftIconPress,
);
}
return renderBackIcon();
};
const renderRight = () => {
if (!editable) {
return renderLogoOrIcon(
rightLogo,
rightLogoStyle,
onRightLogoPress,
rightIcon,
rightIconStyle,
onRightIconPress,
);
}
return renderClearIcon();
};
// define some default values
const searchbarContainerStyle = containerStyle
? { ...styles.searchbarContainer, ...(containerStyle as object) }
: styles.searchbarContainer;
const searchbarTextInputStyle = inputStyle
? { ...styles.textInput, ...(inputStyle as object) }
: styles.textInput;
textInputProps.onTouchStart = editable
? textInputProps.onTouchStart
: onPress;
textInputProps.selectionColor = textInputProps.selectionColor
? textInputProps.selectionColor
: Colors.primary;
textInputProps.placeholderTextColor = textInputProps.placeholderTextColor
? textInputProps.placeholderTextColor
: Colors.font_3;
return (
<TouchableWithoutFeedback onPress={onPress}>
<View style={searchbarContainerStyle}>
{renderLeft()}
<TextInput {...textInputProps} style={searchbarTextInputStyle} />
{renderRight()}
</View>
</TouchableWithoutFeedback>
);
}
Example #3
Source File: tracing.tsx From protect-scotland with Apache License 2.0 | 4 votes |
Tracing: FC = () => {
const [showSpinner, setShowSpinner] = useState(false);
const {checked, paused, deleteReminder} = useReminder();
const {t} = useTranslation();
const navigation = useNavigation();
const {enabled, status, contacts, start} = useExposure();
const tracingActive = enabled && status.state === StatusState.active;
const pauseDate = new Date(Number(paused));
const {isolationDuration} = useSettings();
const hasContact = hasCurrentExposure(isolationDuration, contacts);
if (!checked) {
return null;
}
const renderActive = () => (
<>
<Text variant="h3" style={styles.active}>
{t('tracing:status:heading')}
</Text>
<Spacing s={20} />
<View style={styles.row}>
<Image
style={styles.moduleImage as ImageStyle}
source={IconTracingActive}
accessibilityIgnoresInvertColors={false}
/>
<Text variant="h1" style={styles.active}>
{t('tracing:status:active')}
</Text>
</View>
<Spacing s={20} />
<Markdown>{t('tracing:message')}</Markdown>
</>
);
const renderInactive = () => (
<>
<Text variant="h3" style={styles.notActive}>
{t('tracing:status:heading')}
</Text>
<Spacing s={20} />
<View style={styles.row}>
<Image
style={styles.moduleImage as ImageStyle}
source={IconTracingInactive}
accessibilityIgnoresInvertColors={false}
/>
<Text variant="h1" style={styles.notActive} maxFontSizeMultiplier={3}>
{t('tracing:status:inactive')}
</Text>
</View>
<Spacing s={20} />
<Markdown>{t('tracing:inactiveMessage')}</Markdown>
<Spacing s={20} />
<Text bold maxFontSizeMultiplier={3}>
{t('tracing:turnOn1')}
</Text>
<Spacing s={20} />
<Text bold maxFontSizeMultiplier={3}>
{t('tracing:turnOn2')}
</Text>
<Spacing s={30} />
<GoToSettings />
<Spacing s={40} />
<Markdown>{t('tracing:inactiveMessage1')}</Markdown>
</>
);
const renderPaused = () => (
<>
<Text variant="h3" style={styles.notActive}>
{t('tracing:status:heading')}
</Text>
<Spacing s={20} />
<View style={styles.row}>
<View>
<Image
style={styles.moduleImage as ImageStyle}
source={IconPaused}
accessibilityIgnoresInvertColors={false}
/>
</View>
<View>
<Text variant="h1" style={styles.notActive}>
{t('tracing:paused:title')}
</Text>
</View>
</View>
<Spacing s={20} />
<Text bold color="errorRed">
{t('tracing:paused:reminder')} {format(pauseDate, 'HH:mm')}{' '}
{isToday(pauseDate)
? t('common:today')
: isTomorrow(pauseDate)
? t('common:tomorrow')
: ''}
</Text>
{showSpinner ? (
<View>
<Spacing s={36} />
<ActivityIndicator color={colors.darkGrey} size="large" />
<Spacing s={36} />
</View>
) : (
<Markdown markdownStyles={inactiveMarkdownStyles}>
{t('tracing:paused:text')}
</Markdown>
)}
<Spacing s={20} />
<Button
type="primary"
variant="dark"
rounded
onPress={async () => {
setShowSpinner(true);
await start();
deleteReminder();
setShowSpinner(false);
}}>
{t('tracing:paused:buttonLabel')}
</Button>
</>
);
return (
<ScrollView style={styles.container}>
<ModalHeader
icon={TracingIcon}
closeIcon={CloseIcon}
heading="tracing:heading"
color="validationGreen"
/>
<Spacing s={34} />
<Container center="horizontal">
{hasContact && (
<>
<TouchableWithoutFeedback
onPress={() => navigation.navigate(ScreenNames.closeContact)}>
<Container center="horizontal">
<RoundedBox style={styles.notification}>
<Text variant="h3" color="errorRed">
{t('tracing:notificationTitle')}
</Text>
<Spacing s={10} />
<Markdown markdownStyles={notificationMarkdownStyles}>
{t('tracing:notificationBody')}
</Markdown>
</RoundedBox>
</Container>
</TouchableWithoutFeedback>
<Spacing s={55} />
</>
)}
<Image
source={TracingIllustration}
accessibilityIgnoresInvertColors={false}
/>
<Spacing s={43} />
<Text variant="leader" color="darkGrey" align="center">
{t('tracing:body')}
</Text>
<Spacing s={30} />
<Markdown accessibleLink={t('links:o')}>
{t('tracing:additional', {link: t('links:o')})}
</Markdown>
<Spacing s={34} />
<RoundedBox
style={tracingActive && !paused ? styles.active : undefined}>
{paused
? renderPaused()
: tracingActive
? renderActive()
: renderInactive()}
</RoundedBox>
<Spacing s={20} />
{!paused && tracingActive && (
<Button
type="secondary"
rounded
textColor="validationGreen"
onPress={() => navigation.navigate(ScreenNames.pause)}
style={styles.button}
buttonStyle={styles.buttonStyle}>
I want to pause Tracing
</Button>
)}
</Container>
<Spacing s={120} />
</ScrollView>
);
}
Example #4
Source File: DatePicker.tsx From react-native-jigsaw with MIT License | 4 votes |
DatePicker: React.FC<Props> = ({
Icon,
style,
theme: { colors, typography, roundness, disabledOpacity },
date,
onDateChange = () => {},
defaultValue,
disabled = false,
mode = "date",
format,
type = "underline",
leftIconName,
rightIconName,
leftIconMode = "inset",
label,
placeholder,
...props
}) => {
const [value, setValue] = React.useState<any>(date || defaultValue);
React.useEffect(() => {
if (defaultValue != null) {
setValue(defaultValue);
}
}, [defaultValue]);
const [pickerVisible, setPickerVisible] = React.useState(false);
const [labeled] = React.useState<Animated.Value>(
new Animated.Value(date ? 0 : 1)
);
const [placeholder1, setPlaceholder1] = React.useState("");
const [focused, setFocused] = React.useState<boolean>(false);
const [labelLayout, setLabelLayout] = React.useState<{
measured: Boolean;
width: number;
}>({ measured: false, width: 0 });
const getValidDate = (): Date => {
if (!value) {
return new Date();
}
return typeof value?.getMonth === "function" ? value : new Date();
};
const formatDate = (): string => {
if (!value) return "";
let newDate = getValidDate();
if (format) return dateFormat(newDate, format);
if (mode === "time") {
return `${newDate.toLocaleTimeString()}`;
}
if (mode === "datetime") {
return `${newDate.toLocaleString()}`;
}
return `${
MONTHS[newDate.getMonth()]
} ${newDate.getDate()}, ${newDate.getFullYear()}`;
};
const toggleVisibility = async () => {
setPickerVisible(!pickerVisible);
focused ? _handleBlur() : _handleFocus();
};
const insets = useSafeAreaInsets();
// const _restoreLabel = () =>
// Animated.timing(labeled, {
// toValue: 1,
// duration: FOCUS_ANIMATION_DURATION,
// useNativeDriver: true,
// }).start();
// const _minmizeLabel = () =>
// Animated.timing(labeled, {
// toValue: 0,
// duration: BLUR_ANIMATION_DURATION,
// useNativeDriver: true,
// }).start();
// const _showPlaceholder = () =>
// setTimeout(() => setPlaceholder1(placeholder || ""), 50);
const _hidePlaceholder = () => {
setPlaceholder1("");
};
React.useEffect(() => {
setValue(date);
}, [date]);
React.useEffect(() => {
if (value || focused || placeholder1) {
// _minmizeLabel();
Animated.timing(labeled, {
toValue: 0,
duration: BLUR_ANIMATION_DURATION,
useNativeDriver: true,
}).start();
} else {
// _restoreLabel();
Animated.timing(labeled, {
toValue: 1,
duration: FOCUS_ANIMATION_DURATION,
useNativeDriver: true,
}).start();
}
}, [value, focused, placeholder1, labeled]);
React.useEffect(() => {
const _showPlaceholder = () =>
setTimeout(() => setPlaceholder1(placeholder || ""), 50);
if (focused || !label) {
_showPlaceholder();
} else {
_hidePlaceholder();
}
return () => {
clearTimeout(_showPlaceholder());
};
}, [focused, label, placeholder]);
const _handleFocus = () => {
if (disabled) {
return;
}
setFocused(true);
};
const _handleBlur = () => {
if (disabled) {
return;
}
setFocused(false);
};
const MINIMIZED_LABEL_Y_OFFSET = -(typography.caption.lineHeight + 4);
const OUTLINE_MINIMIZED_LABEL_Y_OFFSET = -(16 * 0.5 + 4);
const MAXIMIZED_LABEL_FONT_SIZE = typography.subtitle1.fontSize;
const MINIMIZED_LABEL_FONT_SIZE = typography.caption.fontSize;
const hasActiveOutline = focused;
let inputTextColor,
activeColor,
underlineColor,
borderColor,
placeholderColor,
containerStyle: StyleProp<ViewStyle>,
backgroundColor,
inputStyle: StyleProp<TextStyle>;
inputTextColor = colors.strong;
if (disabled) {
activeColor = colors.light;
placeholderColor = colors.light;
borderColor = "transparent";
underlineColor = "transparent";
backgroundColor = colors.divider;
} else {
activeColor = colors.primary;
placeholderColor = borderColor = colors.light;
underlineColor = colors.light;
backgroundColor = colors.background;
}
const { lineHeight, ...subtitle1 } = typography.subtitle1;
inputStyle = {
paddingVertical: 0,
color: inputTextColor,
paddingLeft:
leftIconName && leftIconMode === "inset"
? ICON_SIZE + (type === "solid" ? 16 : 12)
: 0,
paddingRight: rightIconName ? ICON_SIZE + 16 + 4 : 12,
...subtitle1,
height: lineHeight,
};
if (type === "underline") {
containerStyle = {
borderTopLeftRadius: roundness,
borderTopRightRadius: roundness,
paddingBottom: 12,
marginTop: 16,
};
} else {
containerStyle = {
borderRadius: roundness,
borderColor: hasActiveOutline ? activeColor : borderColor,
borderWidth: 1,
paddingTop: labeled ? 16 * 1.5 : 16,
paddingBottom: labeled ? 16 * 0.5 : 16,
opacity: disabled ? disabledOpacity : 1,
backgroundColor,
};
inputStyle.paddingHorizontal = 12;
}
if (leftIconName && leftIconMode === "outset") {
containerStyle.marginLeft = ICON_SIZE + 8;
}
let leftIconColor;
if (focused) {
leftIconColor = colors.primary;
} else {
leftIconColor = colors.light;
}
const leftIconProps = {
size: 24,
color: leftIconColor,
name: leftIconName || "",
};
const leftIconStyle: ImageStyle = {
position: "absolute",
marginTop:
type === "solid"
? leftIconMode === "inset"
? MINIMIZED_LABEL_FONT_SIZE + 4
: 16
: leftIconMode === "outset"
? 16
: 0,
};
const labelStyle = {
...typography.subtitle1,
top: type === "solid" ? 16 : 0,
left:
leftIconName && leftIconMode === "inset"
? ICON_SIZE + (type === "solid" ? 16 : 12)
: 0,
transform: [
{
// Move label to top
translateY: labeled.interpolate({
inputRange: [0, 1],
outputRange: [
type === "solid"
? OUTLINE_MINIMIZED_LABEL_Y_OFFSET
: MINIMIZED_LABEL_Y_OFFSET,
0,
],
}),
},
{
// Make label smaller
scale: labeled.interpolate({
inputRange: [0, 1],
outputRange: [
MINIMIZED_LABEL_FONT_SIZE / MAXIMIZED_LABEL_FONT_SIZE,
1,
],
}),
},
{
// Offset label scale since RN doesn't support transform origin
translateX: labeled.interpolate({
inputRange: [0, 1],
outputRange: [
-(1 - MINIMIZED_LABEL_FONT_SIZE / MAXIMIZED_LABEL_FONT_SIZE) *
(labelLayout.width / 2),
0,
],
}),
},
],
};
const inputStyles = [
styles.input,
inputStyle,
type === "solid" ? { marginHorizontal: 12 } : {},
];
// const render = (props) => <NativeTextInput {...props} />;
return (
<View style={[styles.container, style]}>
<Touchable disabled={disabled} onPress={toggleVisibility}>
<View pointerEvents="none">
<View style={[styles.container, style]}>
{leftIconName && leftIconMode === "outset" ? (
<Icon {...leftIconProps} style={leftIconStyle} />
) : null}
<View
style={[containerStyle, style ? { height: style.height } : {}]}
>
{type === "underline" ? (
// When type === 'flat', render an underline
<Animated.View
style={[
styles.underline,
{
backgroundColor: focused ? activeColor : underlineColor,
// Underlines is thinner when input is not focused
transform: [{ scaleY: focused ? 1 : 0.5 }],
},
]}
/>
) : null}
{label ? (
// Position colored placeholder and gray placeholder on top of each other and crossfade them
// This gives the effect of animating the color, but allows us to use native driver
<View
pointerEvents="none"
style={[
StyleSheet.absoluteFill,
{
opacity:
// Hide the label in minimized state until we measure its width
date || focused ? (labelLayout.measured ? 1 : 0) : 1,
},
]}
>
<AnimatedText
onLayout={(e: LayoutChangeEvent) =>
setLabelLayout({
width: e.nativeEvent.layout.width,
measured: true,
})
}
style={[
styles.placeholder,
type === "solid" ? { paddingHorizontal: 12 } : {},
labelStyle,
{
color: colors.light,
opacity: labeled.interpolate({
inputRange: [0, 1],
outputRange: [hasActiveOutline ? 1 : 0, 0],
}),
},
]}
numberOfLines={1}
>
{label}
</AnimatedText>
<AnimatedText
style={[
styles.placeholder,
type === "solid" ? { paddingHorizontal: 12 } : {},
labelStyle,
{
color: placeholderColor,
opacity: hasActiveOutline ? labeled : 1,
},
]}
numberOfLines={1}
>
{label}
</AnimatedText>
</View>
) : null}
{leftIconName && leftIconMode === "inset" ? (
<Icon
{...leftIconProps}
style={{
...leftIconStyle,
marginLeft: type === "solid" ? 16 : 0,
}}
/>
) : null}
<NativeTextInput
value={formatDate()}
placeholder={label ? placeholder1 : placeholder}
editable={!disabled}
placeholderTextColor={placeholderColor}
selectionColor={activeColor}
onFocus={_handleFocus}
onBlur={_handleBlur}
underlineColorAndroid={"transparent"}
style={inputStyles}
{...props}
/>
</View>
{rightIconName ? (
<Icon
name={rightIconName}
size={ICON_SIZE}
color={colors.light}
style={{
position: "absolute",
right: 16,
marginTop:
type === "solid" ? MINIMIZED_LABEL_FONT_SIZE + 4 : 16,
}}
/>
) : null}
</View>
</View>
</Touchable>
{pickerVisible && (
<Portal>
<View
style={[
styles.picker,
{
backgroundColor: colors.divider,
},
]}
>
<View
style={[
styles.pickerContainer,
{
paddingTop: insets.top,
paddingBottom: insets.bottom,
paddingLeft: insets.left,
paddingRight: insets.right,
},
]}
>
<DateTimePicker
value={getValidDate()}
mode={mode}
isVisible={pickerVisible}
toggleVisibility={toggleVisibility}
onChange={(_event: any, data: any) => {
toggleVisibility();
setValue(data);
onDateChange(data);
}}
/>
</View>
</View>
</Portal>
)}
</View>
);
}
Example #5
Source File: TextField.tsx From react-native-jigsaw with MIT License | 4 votes |
render() {
const {
Icon,
type = "underline",
disabled = false,
label,
error = false,
leftIconName,
leftIconMode,
rightIconName,
assistiveText,
underlineColor: underlineColorProp,
multiline = false,
numberOfLines = 4,
style,
theme: { colors, typography, roundness, disabledOpacity },
render = (props) => <NativeTextInput {...props} />,
...rest
} = this.props;
const MINIMIZED_LABEL_Y_OFFSET = -(typography.caption.lineHeight + 4);
const OUTLINE_MINIMIZED_LABEL_Y_OFFSET = -(16 * 0.5 + 4);
const MAXIMIZED_LABEL_FONT_SIZE = typography.subtitle1.fontSize;
const MINIMIZED_LABEL_FONT_SIZE = typography.caption.fontSize;
const hasActiveOutline = this.state.focused || error;
let inputTextColor,
activeColor,
underlineColor,
borderColor,
placeholderColor,
containerStyle: StyleProp<ViewStyle>,
backgroundColor,
inputStyle: StyleProp<TextStyle>;
inputTextColor = colors.strong;
if (disabled) {
activeColor = colors.light;
placeholderColor = colors.light;
borderColor = "transparent";
underlineColor = "transparent";
backgroundColor = colors.divider;
} else {
activeColor = error ? colors.error : colors.primary;
placeholderColor = borderColor = colors.light;
underlineColor = underlineColorProp;
backgroundColor = colors.background;
}
if (rest.placeholderTextColor) {
placeholderColor = rest.placeholderTextColor;
}
const { lineHeight, ...subtitle1 } = typography.subtitle1;
inputStyle = {
paddingVertical: 0,
color: inputTextColor,
paddingLeft:
leftIconName && leftIconMode === "inset"
? ICON_SIZE + 12 + (type === "solid" ? 16 : 0)
: 0,
paddingRight: rightIconName ? ICON_SIZE + 16 + 4 : 12,
...subtitle1,
};
if (!multiline) {
inputStyle.height = lineHeight;
}
let assistiveTextLeftMargin;
if (type === "underline") {
containerStyle = {
borderTopLeftRadius: roundness,
borderTopRightRadius: roundness,
paddingBottom: 12,
marginTop: 16,
};
if (leftIconName && leftIconMode === "outset") {
assistiveTextLeftMargin = ICON_SIZE + 8;
} else {
assistiveTextLeftMargin = 0;
}
} else {
containerStyle = {
borderRadius: roundness,
borderColor: hasActiveOutline ? activeColor : borderColor,
borderWidth: 1,
paddingTop: label ? 16 * 1.5 : 16,
paddingBottom: label ? 16 * 0.5 : 16,
opacity: disabled ? disabledOpacity : 1,
backgroundColor,
};
if (leftIconName && leftIconMode === "inset") {
assistiveTextLeftMargin = 16 + 4;
} else if (leftIconName && leftIconMode === "outset") {
assistiveTextLeftMargin = ICON_SIZE + 8 + 12;
} else {
assistiveTextLeftMargin = 12;
}
inputStyle.paddingHorizontal = 12;
}
if (leftIconName && leftIconMode === "outset") {
containerStyle.marginLeft = ICON_SIZE + 8;
}
let leftIconColor;
if (error) {
leftIconColor = colors.error;
} else if (this.state.focused) {
leftIconColor = colors.primary;
} else {
leftIconColor = colors.light;
}
const leftIconProps = {
size: 24,
color: leftIconColor,
name: leftIconName || "",
};
const leftIconStyle: ImageStyle = {
position: "absolute",
marginTop:
type === "solid"
? MINIMIZED_LABEL_FONT_SIZE + 4
: leftIconMode === "outset"
? 16
: 0,
marginLeft: leftIconMode === "inset" && type === "solid" ? 16 : 0,
};
const labelStyle = {
...typography.subtitle1,
top: type === "solid" ? 16 : 0,
left:
leftIconName && leftIconMode === "inset"
? ICON_SIZE + (type === "solid" ? 16 : 12)
: 0,
transform: [
{
// Move label to top
translateY: this.state.labeled.interpolate({
inputRange: [0, 1],
outputRange: [
type === "solid"
? OUTLINE_MINIMIZED_LABEL_Y_OFFSET
: MINIMIZED_LABEL_Y_OFFSET,
0,
],
}),
},
{
// Make label smaller
scale: this.state.labeled.interpolate({
inputRange: [0, 1],
outputRange: [
MINIMIZED_LABEL_FONT_SIZE / MAXIMIZED_LABEL_FONT_SIZE,
1,
],
}),
},
{
// Offset label scale since RN doesn't support transform origin
translateX: this.state.labeled.interpolate({
inputRange: [0, 1],
outputRange: [
-(1 - MINIMIZED_LABEL_FONT_SIZE / MAXIMIZED_LABEL_FONT_SIZE) *
(this.state.labelLayout.width / 2),
0,
],
}),
},
],
};
const { textStyles } = extractStyles(style);
const inputStyles = applyStyles(
[
styles.input,
inputStyle,
type === "solid" ? { marginHorizontal: 12 } : {},
],
textStyles
);
const {
backgroundColor: bgColor,
padding,
paddingTop,
paddingBottom,
paddingLeft,
paddingRight,
borderRadius,
borderWidth,
borderTopWidth,
borderRightWidth,
borderBottomWidth,
borderLeftWidth,
borderColor: borderCol,
...styleProp
} = StyleSheet.flatten(style || {}) as ViewStyle & { height?: number };
return (
<View style={[styles.container, styleProp]}>
{leftIconName && leftIconMode === "outset" ? (
<Icon {...leftIconProps} style={leftIconStyle} />
) : null}
<View
style={applyStyles([containerStyle], {
height: style?.height,
backgroundColor: bgColor,
padding,
paddingTop,
paddingBottom,
paddingLeft,
paddingRight,
borderRadius,
borderWidth,
borderTopWidth,
borderRightWidth,
borderBottomWidth,
borderLeftWidth,
borderColor: borderCol,
})}
>
{type === "underline" ? (
// When type === 'flat', render an underline
<Animated.View
style={[
styles.underline,
{
backgroundColor:
bgColor ||
(error
? colors.error
: this.state.focused
? activeColor
: underlineColor),
// Underlines is thinner when input is not focused
transform: [{ scaleY: this.state.focused ? 1 : 0.5 }],
},
]}
/>
) : null}
{label ? (
// Position colored placeholder and gray placeholder on top of each other and crossfade them
// This gives the effect of animating the color, but allows us to use native driver
<View
pointerEvents="none"
style={[
StyleSheet.absoluteFill,
{
opacity:
// Hide the label in minimized state until we measure its width
this.state.value || this.state.focused
? this.state.labelLayout.measured
? 1
: 0
: 1,
},
]}
>
<AnimatedText
onLayout={(e: LayoutChangeEvent) =>
this.setState({
labelLayout: {
width: e.nativeEvent.layout.width,
measured: true,
},
})
}
style={[
styles.placeholder,
type === "solid" ? { paddingHorizontal: 12 } : {},
labelStyle,
{
color: placeholderColor,
opacity: this.state.labeled.interpolate({
inputRange: [0, 1],
outputRange: [hasActiveOutline ? 1 : 0, 0],
}),
},
]}
numberOfLines={1}
>
{label}
</AnimatedText>
<AnimatedText
style={[
styles.placeholder,
type === "solid" ? { paddingHorizontal: 12 } : {},
labelStyle,
{
color: placeholderColor,
opacity: hasActiveOutline ? this.state.labeled : 1,
},
]}
numberOfLines={1}
>
{label}
</AnimatedText>
</View>
) : null}
{leftIconName && leftIconMode === "inset" ? (
<View
style={{
justifyContent: type === "solid" ? "center" : undefined,
}}
>
<Icon {...leftIconProps} style={leftIconStyle} />
</View>
) : null}
{render({
ref: (c: NativeTextInput) => {
this._root = c;
},
onChange: this._handleChangeText,
placeholder: label
? this.state.placeholder
: this.props.placeholder,
placeholderTextColor: placeholderColor,
editable: !disabled,
selectionColor: activeColor,
multiline,
numberOfLines,
onFocus: this._handleFocus,
onBlur: this._handleBlur,
underlineColorAndroid: "transparent",
style: inputStyles,
...rest,
value: this.state.value,
})}
</View>
{rightIconName ? (
<Icon
name={rightIconName}
size={ICON_SIZE}
color={colors.light}
style={{
position: "absolute",
right: 16,
marginTop: type === "solid" ? MINIMIZED_LABEL_FONT_SIZE + 4 : 16,
}}
/>
) : null}
{assistiveText ? (
<Text
style={[
{
color: error ? colors.error : colors.light,
marginTop: 8,
marginLeft: assistiveTextLeftMargin,
},
]}
>
{assistiveText}
</Text>
) : null}
</View>
);
}