react-native#TextStyle TypeScript Examples

The following examples show how to use react-native#TextStyle. 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: utilities.ts    From react-native-jigsaw with MIT License 7 votes vote down vote up
export function extractStyles(style: StyleProp<any>) {
  const {
    color,
    fontFamily,
    fontWeight,
    fontSize,
    lineHeight,
    letterSpacing,
    textTransform,
    textAlign,
    textDecorationLine,
    textDecorationColor,
    textDecorationStyle,
    ...viewStyles
  } = StyleSheet.flatten(style || {});

  const textStyles: TextStyle = {
    color,
    fontFamily,
    fontWeight,
    fontSize,
    lineHeight,
    letterSpacing,
    textTransform,
    textAlign,
    textDecorationLine,
    textDecorationColor,
    textDecorationStyle,
  };

  return { viewStyles, textStyles };
}
Example #2
Source File: CheckboxRow.tsx    From react-native-jigsaw with MIT License 6 votes vote down vote up
renderLabel = (
  value: string | React.ReactNode,
  labelStyle: StyleProp<TextStyle>,
  textStyle: StyleProp<TextStyle>
) => {
  if (isString(value)) {
    return <Text style={[textStyle, labelStyle]}>{value}</Text>;
  } else {
    return <>{value}</>;
  }
}
Example #3
Source File: Text.tsx    From sellflow with MIT License 6 votes vote down vote up
function resolveTextStyle(
  fonts: ReactNativePaper.ThemeFonts,
  fontWeight: 'bold' | 'medium' | 'normal',
  fontStyle: 'normal' | 'italic',
): TextStyle | undefined {
  let useItalicPreset = fontStyle === 'italic';

  let fontFamily = useItalicPreset
    ? fonts.italic.fontFamily
    : fonts.regular.fontFamily;
  switch (fontWeight) {
    case 'bold':
      fontFamily = fonts.bold?.fontFamily;
      break;
    case 'medium':
      fontFamily = fonts.medium.fontFamily;
      break;
  }

  return {
    fontFamily,
  };
}
Example #4
Source File: Avatar.tsx    From sellflow with MIT License 6 votes vote down vote up
export default function Avatar(props: Props) {
  let { firstName, lastName, size, containerStyle } = props;

  let avatarSize: StyleProp<ViewStyle> = {
    width: size,
    height: size,
    borderRadius: Math.round(size / 2),
  };
  let textSize: StyleProp<TextStyle> = {
    fontSize: Math.round(size / 2),
  };

  return (
    <View style={[styles.avatar, containerStyle, avatarSize]}>
      <Text
        style={[styles.nameInitial, textSize]}
      >{`${firstName[0]}${lastName[0]}`}</Text>
    </View>
  );
}
Example #5
Source File: ExternalLink.tsx    From selftrace with MIT License 6 votes vote down vote up
export default function ExternalLink({
  isColored = true,
  href,
  target = 'blank',
  children,
  style,
}: Props) {
  const linkStyles: [TextStyle] = [isColored ? styles.bright : styles.plain];

  return (
    <A href={href} target={target} style={[linkStyles, style]}>
      <Text>{children}</Text>
    </A>
  );
}
Example #6
Source File: RadioButtonRow.tsx    From react-native-jigsaw with MIT License 6 votes vote down vote up
renderLabel = (
  value: string | React.ReactNode,
  labelStyle: StyleProp<TextStyle>,
  textStyle: StyleProp<TextStyle>
) => {
  if (typeof value === "string") {
    return <Text style={[labelStyle, textStyle]}>{value}</Text>;
  } else {
    return <>{value}</>;
  }
}
Example #7
Source File: index.tsx    From react-native-floating-label-input with MIT License 6 votes vote down vote up
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 #8
Source File: CheckboxGroupRow.tsx    From react-native-jigsaw with MIT License 6 votes vote down vote up
renderLabel = (
  value: string | React.ReactNode,
  labelStyle: StyleProp<TextStyle>,
  textStyle: StyleProp<TextStyle>
) => {
  if (typeof value === "string") {
    return <Text style={[labelStyle, textStyle]}>{value}</Text>;
  } else {
    return <>{value}</>;
  }
}
Example #9
Source File: utils.ts    From react-native-controlled-mentions with MIT License 6 votes vote down vote up
defaultMentionTextStyle: StyleProp<TextStyle> = {fontWeight: 'bold', color: 'blue'}
Example #10
Source File: ButtonSelect.tsx    From mobile with Apache License 2.0 5 votes vote down vote up
ButtonSelect = ({
  text,
  onPress,
  variant,
  color: buttonColorName,
  disabled,
  iconName,
  testID,
}: ButtonSelectProps) => {
  const theme = useTheme<Theme>();
  const variantProps = theme.buttonVariants[variant];
  const disabledProps = disabled ? variantProps.disabled || {} : {};
  const themedStyles = {...variantProps, ...disabledProps};
  const {fontSize, fontWeight, fontFamily} = (themedStyles as unknown) as TextStyle & ViewStyle;
  const textColor = themedStyles.textColor;
  const buttonColor = buttonColorName && theme.colors[buttonColorName];
  const borderColorName = (themedStyles.color as keyof Theme['colors']) || 'bodyText';
  const onPressHandler = onPress;
  const borderRadius = 5;

  const content = (
    <Box
      borderColor={borderColorName}
      borderWidth={2}
      borderRadius={borderRadius}
      alignItems="center"
      justifyContent="flex-start"
      shadowColor="bodyText"
      paddingHorizontal="m"
      paddingVertical="m"
      flexDirection="row"
      marginBottom="m"
    >
      <Text style={{...styles.content, color: textColor || buttonColor, fontWeight, fontFamily, fontSize}}>{text}</Text>
      <Box style={{...styles.iconOffset}}>{iconName && <Icon size={12} name={iconName} />}</Box>
    </Box>
  );

  const accessibilityProps = {
    accessibilityRole: 'button' as 'button',
    accessibilityState: {disabled},
  };
  return (
    <TouchableOpacity
      activeOpacity={0.8}
      onPress={onPressHandler}
      style={styles.stretch}
      disabled={disabled}
      testID={testID}
      {...accessibilityProps}
    >
      {content}
    </TouchableOpacity>
  );
}
Example #11
Source File: Button.tsx    From sellflow with MIT License 5 votes vote down vote up
function useButtonStyle(options: Options) {
  let { preset, disabled, buttonColor } = options;
  let { colors, roundness } = useTheme();

  let elevation = 0;
  let textColor = colors.text;
  let backgroundColor = 'transparent';
  let borderColor = 'transparent';
  let borderWidth = 0;

  if (preset === 'primary') {
    elevation = 2;
    backgroundColor = disabled
      ? color(colors.primary)
          .alpha(0.12)
          .rgb()
          .string()
      : !!buttonColor
      ? buttonColor
      : colors.primary;
  } else if (preset === 'secondary') {
    borderColor = disabled
      ? color(colors.primary)
          .alpha(0.4)
          .rgb()
          .string()
      : colors.primary;
    borderWidth = 2;
  }

  let isBackgroundDark =
    backgroundColor === 'transparent' ? false : color(backgroundColor).isDark();
  if (disabled) {
    textColor = color(isBackgroundDark ? 'white' : colors.primary)
      .alpha(0.4)
      .rgb()
      .string();
  } else if (preset === 'primary') {
    textColor = isBackgroundDark ? 'white' : 'black';
  } else if (buttonColor) {
    textColor = buttonColor;
  } else {
    textColor = colors.primary;
  }

  let textStyle = { color: textColor } as TextStyle;
  let buttonStyle = {
    backgroundColor,
    borderColor,
    borderWidth,
    borderRadius: roundness,
    elevation: disabled ? 0 : elevation,
  } as ViewStyle;
  let noShadowStyle = {
    shadowOffset: { width: 0, height: 0 },
    shadowColor: 'transparent',
  } as ViewStyle;

  return { textStyle, buttonStyle, noShadowStyle, textColor };
}
Example #12
Source File: Button.tsx    From mobile with Apache License 2.0 5 votes vote down vote up
Button = ({
  text,
  onPress,
  variant,
  color: buttonColorName,
  disabled,
  loading,
  externalLink,
}: ButtonProps) => {
  const [i18n] = useI18n();
  const theme = useTheme<Theme>();
  const variantProps = theme.buttonVariants[variant];
  const disabledProps = disabled ? variantProps.disabled || {} : {};
  const themedStyles = {...variantProps, ...disabledProps};
  const {fontSize, fontWeight, fontFamily, color, borderWidth, height} = (themedStyles as unknown) as TextStyle &
    ViewStyle;
  const textColor = themedStyles.textColor;
  const buttonColor = buttonColorName && theme.colors[buttonColorName];

  const onPressHandler = loading ? () => {} : onPress;
  const externalLinkProps = externalLink
    ? {
        accessibilityLabel: text,
        accessibilityHint: i18n.translate('Home.ExternalLinkHint'),
        accessibilityRole: 'link' as AccessibilityRole,
      }
    : {};
  const externalArrowIcon = textColor === palette.white ? 'icon-external-arrow-light' : 'icon-external-arrow';

  const content = (
    <Box
      borderRadius={4}
      alignItems="center"
      justifyContent="center"
      style={{backgroundColor: color, minHeight: height, borderWidth, borderColor: buttonColor}}
      paddingHorizontal="m"
      flexDirection="row"
    >
      {loading ? (
        <ActivityIndicator color={textColor} size="large" />
      ) : (
        <>
          <Text style={{...styles.content, color: textColor || buttonColor, fontWeight, fontFamily, fontSize}}>
            {text}
          </Text>
          {externalLink && <Icon name={externalArrowIcon} />}
        </>
      )}
    </Box>
  );

  const accessibilityProps = {
    accessibilityRole: 'button' as 'button',
    accessibilityState: {disabled},
    ...externalLinkProps,
  };

  if (Platform.OS === 'android') {
    return (
      <Ripple rippleContainerBorderRadius={4} onPress={onPressHandler} {...accessibilityProps}>
        {content}
      </Ripple>
    );
  }
  return (
    <TouchableOpacity onPress={onPressHandler} style={styles.stretch} disabled={disabled} {...accessibilityProps}>
      {content}
    </TouchableOpacity>
  );
}
Example #13
Source File: Button.tsx    From react-native-jigsaw with MIT License 5 votes vote down vote up
function Base({
  Icon,
  icon,
  title,
  onPress,
  loading,
  disabled,
  style,
  ...props
}: BaseProps): JSX.Element {
  const {
    color,
    fontFamily,
    fontWeight,
    fontSize,
    lineHeight,
    letterSpacing,
    textTransform,
    textAlign,
    textDecorationLine,
    textDecorationColor,
    textDecorationStyle,
    ...buttonStyles
  } = StyleSheet.flatten(style || ({} as TextStyle));

  const titleStyles: TextStyle = {
    color,
    fontFamily,
    fontWeight,
    fontSize,
    lineHeight,
    letterSpacing,
    textTransform,
    textAlign,
    textDecorationLine,
    textDecorationColor,
    textDecorationStyle,
  };

  if (textAlign === "left") {
    buttonStyles.justifyContent = "flex-start";
  }

  if (textAlign === "right") {
    buttonStyles.justifyContent = "flex-end";
  }

  return (
    <Pressable
      onPress={onPress}
      disabled={disabled || loading}
      style={({ pressed }) => {
        return [
          styles.base,
          {
            opacity: pressed || disabled ? 0.75 : 1,
          },
          buttonStyles,
        ];
      }}
      {...props}
    >
      {loading ? (
        <ActivityIndicator size="small" color={color} style={styles.loading} />
      ) : null}
      {icon && !loading ? (
        <Icon
          name={icon}
          color={color as string}
          style={styles.icon}
          size={CONSTANTS.icon}
        />
      ) : null}
      <Text style={titleStyles}>{title}</Text>
    </Pressable>
  );
}
Example #14
Source File: theme.tsx    From sellflow with MIT License 5 votes vote down vote up
textInputLabel: StyleProp<TextStyle> = {
  fontSize: FONT_SIZE.small,
}
Example #15
Source File: theme.tsx    From sellflow with MIT License 5 votes vote down vote up
defaultButtonLabel: StyleProp<TextStyle> = {
  fontSize: FONT_SIZE.medium,
  fontFamily: FONT_FAMILY.MEDIUM,
}
Example #16
Source File: utils.tsx    From lowkey-react-native-mentions-input with MIT License 5 votes vote down vote up
parseMarkdown = (
  text: string,
  mentionStyle: TextStyle,
  urlStyle?: TextStyle,
  handleURL?: (url: string) => void
) => {
  let textToParse = text;
  let parsedTextArray: Array<React.ReactNode> = [];
  let parseHeadIndex = 0;
  let matches = [...matchAll(text, PATTERNS.MENTION)];

  if (matches.length === 0) {
    let currentParsable = decodeURIComponentSafely(textToParse);
    let matchesURL = [...matchAll(currentParsable, PATTERNS.URL)];
    if (matchesURL.length > 0) {
      parsedTextArray.push(
        <Text key={getKeyComponent()}>
          {currentParsable.substring(0, matchesURL[0].index)}
        </Text>
      );
      matchesURL.map((url, index) => {
        let urlIndex = 0;
        if (typeof url.index !== 'undefined') {
          urlIndex = url.index;
        }
        parsedTextArray.push(
          <TouchableWithoutFeedback
            key={getKeyComponent()}
            onPress={() => (handleURL ? handleURL(url[0]) : null)}
          >
            <Text style={urlStyle}>
              {currentParsable.substring(urlIndex, url[0].length + urlIndex)}
            </Text>
          </TouchableWithoutFeedback>
        );
        parsedTextArray.push(
          <Text key={getKeyComponent()}>
            {currentParsable.substring(
              url[0].length +
                (typeof url.index !== 'undefined' ? url.index : 0),
              index === matchesURL.length - 1
                ? currentParsable.length
                : matchesURL[index + 1].index
            )}
          </Text>
        );
      });
    } else {
      return <Text>{decodeURIComponentSafely(textToParse)}</Text>;
    }
    return parsedTextArray;
  }
  matches.map((match, index) => {
    const matchedUser = match[0].slice(2, -1);
    const mention = {
      id: matchedUser.split('::')[1],
      name: matchedUser.split('::')[0],
    };

    let currentParsable = decodeURIComponentSafely(
      textToParse.substring(parseHeadIndex, match.index)
    );
    let matchesURL = [...matchAll(currentParsable, PATTERNS.URL)];
    if (matchesURL.length > 0) {
      parsedTextArray.push(
        <Text key={getKeyComponent()}>
          {currentParsable.substring(0, matchesURL[0].index)}
        </Text>
      );
      matchesURL.map((url, index) => {
        let urlIndex = 0;
        if (typeof url.index !== 'undefined') {
          urlIndex = url.index;
        }
        parsedTextArray.push(
          <TouchableWithoutFeedback
            key={getKeyComponent()}
            onPress={() => (handleURL ? handleURL(url[0]) : null)}
          >
            <Text style={urlStyle}>
              {currentParsable.substring(urlIndex, url[0].length + urlIndex)}
            </Text>
          </TouchableWithoutFeedback>
        );
        parsedTextArray.push(
          <Text key={getKeyComponent()}>
            {currentParsable.substring(
              url[0].length + urlIndex,
              index === matchesURL.length - 1
                ? currentParsable.length
                : matchesURL[index + 1].index
            )}
          </Text>
        );
      });
    } else {
      parsedTextArray.push(
        <Text key={getKeyComponent()}>
          {decodeURIComponentSafely(
            textToParse.substring(parseHeadIndex, match.index)
          )}
        </Text>
      );
    }
    parsedTextArray.push(
      <TouchableWithoutFeedback
        onPress={() => (handleURL ? handleURL(mention.id) : null)}
      >
        <Text style={mentionStyle} key={getKeyComponent()}>{`@${decodeURI(
          mention.name
        )}`}</Text>
      </TouchableWithoutFeedback>
    );
    if (typeof match.index === 'number') {
      parseHeadIndex = match.index + match[0].length;
    }

    if (index === matches.length - 1) {
      let lastParsable = decodeURIComponentSafely(
        textToParse.substring(parseHeadIndex, textToParse.length)
      );
      let matchesURL = [...matchAll(lastParsable, PATTERNS.URL)];
      if (matchesURL.length > 0) {
        parsedTextArray.push(
          <Text key={getKeyComponent()}>
            {lastParsable.substring(0, matchesURL[0].index)}
          </Text>
        );
        matchesURL.map((url, index) => {
          let urlIndex = 0;
          if (typeof url.index !== 'undefined') {
            urlIndex = url.index;
          }
          parsedTextArray.push(
            <TouchableWithoutFeedback
              key={getKeyComponent()}
              onPress={() => (handleURL ? handleURL(url[0]) : null)}
            >
              <Text style={urlStyle}>
                {lastParsable.substring(urlIndex, url[0].length + urlIndex)}
              </Text>
            </TouchableWithoutFeedback>
          );
          parsedTextArray.push(
            <Text key={getKeyComponent()}>
              {lastParsable.substring(
                url[0].length + urlIndex,
                index === matchesURL.length - 1
                  ? lastParsable.length
                  : matchesURL[index + 1].index
              )}
            </Text>
          );
        });
      } else {
        parsedTextArray.push(
          <Text key={getKeyComponent()}>
            {decodeURIComponentSafely(
              textToParse.substring(parseHeadIndex, textToParse.length)
            )}
          </Text>
        );
      }
    }
  });
  return parsedTextArray;
}
Example #17
Source File: fonts.ts    From lexicon with MIT License 5 votes vote down vote up
FONT_VARIANTS = {
  normal: { fontWeight: '400' } as TextStyle,
  semiBold: { fontWeight: '600' } as TextStyle,
  bold: { fontWeight: '700' } as TextStyle,
}
Example #18
Source File: styles.ts    From iotc-cpm-sample with MIT License 5 votes vote down vote up
DefaultStyles: {
  header: TextStyle;
  centerFragment: ViewStyle;
  centeredButton: ViewStyle;
  elevated: ViewStyle;
  itemName: TextStyle;
  itemDetail: TextStyle;
} = {
  header: {
    fontWeight: 'bold',
    fontSize: 24,
  },
  centerFragment: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  centeredButton: {
    width: 230,
    height: 50,
    marginVertical: 20,
    justifyContent: 'center',
  },
  elevated: {
    ...Platform.select({
      ios: {
        shadowColor: "'rgba(0, 0, 0, 0.14)'",
        shadowOffset: {
          width: 0,
          height: 3,
        },
        shadowOpacity: 0.25,
        shadowRadius: 3.84,
        elevation: 5,
      },
      android: {
        elevation: 2,
      },
    }),
  },
  itemName: {
    fontWeight: 'bold',
    fontSize: 16,
  },
  itemDetail: {
    fontSize: 14,
  },
}
Example #19
Source File: typography.ts    From selftrace with MIT License 5 votes vote down vote up
INACTIVE_TEXT_STYLES: TextStyle = {
  fontWeight: '600',
  color: Colors.INACTIVE_TEXT.toString(),
}
Example #20
Source File: ProgressBarCircle.tsx    From companion-kit with MIT License 5 votes vote down vote up
export function ProgressBarCircleGradient(this: never, props: PropsGradient) {
    const { animationStep, title, diameter, gradient, progress, style, titleStyle, startFromBottom } = props;
    const length = Math.round(diameter * Math.PI);

    const [ offset ] = React.useState(() => {
        const startProgress = progress - (animationStep || 0.1);
        return new Animated.Value(getOffset(diameter, startProgress));
    });

    React.useEffect(() => {
        Animated.timing(offset, {
            toValue: getOffset(diameter, progress),
            duration: 2000,
            delay: 750,
        }).start();
    }, [progress]);

    const boxSize = diameter + 6;
    const origin = diameter / 2;

    const defaultTitleStyles: StyleProp<TextStyle> = {
        position: 'absolute',
        alignItems: 'center',
        justifyContent: 'center',
    };

    return (
        <View style={style}>
            <Text style={[TextStyles.p3, defaultTitleStyles, titleStyle]}>{title}</Text>
            <Svg id="progress-bar-circle" width="100%" height="100%" viewBox={`0 0 ${boxSize} ${boxSize}`} fill="none">
                <G x={3} y={3}>
                    <Circle
                        id="circle-bg"
                        opacity="0.2"
                        cx={diameter / 2}
                        cy={diameter / 2}
                        r={diameter / 2}
                        strokeWidth="3"
                        stroke="url(#paint0_linear)"
                        fill="none"
                    />
                    <AnimatedContainer
                        id="circle-progress"
                        fill="none"
                        cx={diameter / 2}
                        cy={diameter / 2}
                        r={diameter / 2}
                        strokeWidth="3"
                        stroke="url(#paint0_linear)"
                        strokeDasharray={length}
                        strokeDashoffset={offset}
                        origin={`${origin}, ${origin}`}
                        rotation={startFromBottom ? 90 : -90}
                    />
                </G>
                <Defs>
                    {gradient ? (
                        <LinearGradient id="paint0_linear" x1={diameter / 2} y1={diameter} x2={diameter} y2={0} gradientUnits="userSpaceOnUse">
                            {gradient.map((color, i) => {
                                // tslint:disable-next-line: no-unused-expression
                                return <Stop key={`${color.title}_${i}`} offset={color.offset} stopColor={color.title}/>;
                            })}
                        </LinearGradient>
                    ) : (
                        <LinearGradient id="paint0_linear" x1={0} y1={diameter / 2} x2={diameter} y2={diameter / 2} gradientUnits="userSpaceOnUse">
                            <Stop offset="0.0996095" stopColor="#FFCECF"/>
                            <Stop offset="0.238673" stopColor="#9A87E7"/>
                            <Stop offset="0.384948" stopColor="#FFAFD5"/>
                            <Stop offset="0.512681" stopColor="#FA8989"/>
                            <Stop offset="0.642474" stopColor="#CFC4FF"/>
                            <Stop offset="0.776388" stopColor="#FFAFD5"/>
                            <Stop offset="0.90206" stopColor="#FFCED0"/>
                        </LinearGradient>
                    )}
                </Defs>
            </Svg>
        </View>
    );
}
Example #21
Source File: index.tsx    From react-native-floating-label-input with MIT License 4 votes vote down vote up
FloatingLabelInput: React.ForwardRefRenderFunction<InputRef, Props> = (
  {
    label,
    labelProps,
    mask,
    isPassword,
    maxLength,
    inputStyles,
    showCountdown,
    showCountdownStyles,
    labelStyles,
    darkTheme,
    countdownLabel,
    currencyDivider,
    currency,
    maskType,
    onChangeText,
    customHidePasswordComponent,
    customShowPasswordComponent,
    isFocused,
    onBlur,
    onFocus,
    onTogglePassword,
    togglePassword,
    leftComponent,
    rightComponent,
    customHidePasswordImage,
    customLabelStyles = {},
    staticLabel = false,
    hint,
    hintTextColor,
    onSubmit,
    containerStyles,
    customShowPasswordImage,
    showPasswordContainerStyles,
    maxDecimalPlaces,
    multiline,
    showPasswordImageStyles,
    value = '',
    animationDuration,
    ...rest
  }: Props,
  ref: any,
) => {
  const [halfTop, setHalfTop] = useState(0);
  const [isFocusedState, setIsFocused] = useState(false);
  const [secureText, setSecureText] = useState(true);
  const inputRef = useRef<any>(null);

  customLabelStyles = {
    fontSizeFocused: 10,
    fontSizeBlurred: 14,
    colorFocused: '#49658c',
    colorBlurred: '#49658c',
    ...setGlobalStyles?.customLabelStyles,
    ...customLabelStyles,
  };

  const [fontColorAnimated] = useState(new Animated.Value(0));

  const [fontSizeAnimated] = useState(
    new Animated.Value(
      isFocused
        ? customLabelStyles.fontSizeFocused
          ? customLabelStyles.fontSizeFocused
          : 10
        : customLabelStyles.fontSizeBlurred
        ? customLabelStyles.fontSizeBlurred
        : 14,
    ),
  );

  const [leftAnimated] = useState(
    new Animated.Value(
      staticLabel
        ? customLabelStyles?.leftFocused !== undefined
          ? customLabelStyles.leftFocused
          : 15
        : customLabelStyles != undefined &&
          customLabelStyles.leftBlurred !== undefined
        ? customLabelStyles.leftBlurred
        : 0,
    ),
  );

  const [topAnimated] = useState(
    new Animated.Value(
      staticLabel
        ? customLabelStyles?.topFocused !== undefined
          ? customLabelStyles.topFocused
          : 0
        : customLabelStyles.topBlurred
        ? customLabelStyles.topBlurred
        : 0,
    ),
  );

  useEffect(() => {
    if (isFocused === undefined) {
      if (value !== '' || isFocusedState) {
        setIsFocused(true);
      } else if (value === '' || value === null) {
        setIsFocused(false);
      }
    }
  }, [value]);

  useEffect(() => {
    if (isFocused !== undefined) {
      if (value !== '' || isFocused) {
        setIsFocused(true);
      } else {
        setIsFocused(false);
      }
    }
  }, [isFocused, value]);

  useEffect(() => {
    if (togglePassword !== undefined) {
      _toggleVisibility(togglePassword);
    }
  }, [togglePassword]);

  useEffect(() => {
    if (isFocusedState || value !== '') {
      if (halfTop !== 0) {
        animateFocus();
      }
    } else {
      animateBlur();
    }
  }, [isFocusedState, halfTop]);

  useImperativeHandle(ref, () => ({
    focus() {
      inputRef.current.focus();
    },
    blur() {
      inputRef.current.blur();
    },
  }));

  useEffect(() => {
    if (
      !staticLabel &&
      customLabelStyles.topFocused === undefined &&
      isFocusedState
    ) {
      ReactAnimated.parallel([
        timing(leftAnimated, {
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
          toValue: customLabelStyles.leftFocused
            ? customLabelStyles.leftFocused
            : 0,
        }),
        timing(fontSizeAnimated, {
          toValue: customLabelStyles.fontSizeFocused
            ? customLabelStyles.fontSizeFocused
            : 10,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
        timing(topAnimated, {
          toValue: customLabelStyles.topFocused
            ? customLabelStyles.topFocused
            : -halfTop +
              (isFocusedState
                ? customLabelStyles.fontSizeFocused
                  ? customLabelStyles.fontSizeFocused
                  : 10
                : customLabelStyles.fontSizeBlurred
                ? customLabelStyles.fontSizeBlurred
                : 14),
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
        // @ts-ignore
        timing(fontColorAnimated, {
          toValue: 1,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
      ]).start();
    } else if (staticLabel && isFocusedState) {
      Animated.timing(fontColorAnimated, {
        toValue: 1,
        duration: animationDuration ? animationDuration : 300,
        easing: EasingNode.linear,
      }).start();
    }
  }, [halfTop]);

  function animateFocus() {
    if (!staticLabel) {
      ReactAnimated.parallel([
        timing(leftAnimated, {
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
          toValue: customLabelStyles.leftFocused
            ? customLabelStyles.leftFocused
            : 0,
        }),
        timing(fontSizeAnimated, {
          toValue: customLabelStyles.fontSizeFocused
            ? customLabelStyles.fontSizeFocused
            : 10,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
        timing(topAnimated, {
          toValue: customLabelStyles.topFocused
            ? customLabelStyles.topFocused
            : -halfTop +
              (isFocusedState
                ? customLabelStyles.fontSizeFocused
                  ? customLabelStyles.fontSizeFocused
                  : 10
                : customLabelStyles.fontSizeBlurred
                ? customLabelStyles.fontSizeBlurred
                : 14),
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
        // @ts-ignore
        timing(fontColorAnimated, {
          toValue: 1,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
      ]).start();
    } else {
      Animated.timing(fontColorAnimated, {
        toValue: 1,
        duration: animationDuration ? animationDuration : 300,
        easing: EasingNode.linear,
      }).start();
    }
  }

  function animateBlur() {
    if (!staticLabel) {
      ReactAnimated.parallel([
        timing(leftAnimated, {
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
          toValue: customLabelStyles.leftBlurred
            ? customLabelStyles.leftBlurred
            : 0,
        }),
        timing(fontSizeAnimated, {
          toValue: customLabelStyles.fontSizeBlurred
            ? customLabelStyles.fontSizeBlurred
            : 14,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
        timing(topAnimated, {
          toValue: customLabelStyles.topBlurred
            ? customLabelStyles.topBlurred
            : 0,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
        // @ts-ignore
        timing(fontColorAnimated, {
          toValue: 0,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
      ]).start();
    } else {
      Animated.timing(fontColorAnimated, {
        toValue: 0,
        duration: animationDuration ? animationDuration : 300,
        easing: EasingNode.linear,
      }).start();
    }
  }

  function handleFocus() {
    setIsFocused(true);
  }

  function handleBlur() {
    if (value === '') {
      setIsFocused(false);
    }
  }

  function setFocus() {
    inputRef.current?.focus();
  }

  function setBlur() {
    inputRef.current?.blur();
  }

  function _toggleVisibility(toggle?: boolean) {
    if (toggle === undefined) {
      if (onTogglePassword) {
        onTogglePassword(!secureText);
      }
      setSecureText(!secureText);
      secureText ? setFocus() : setBlur();
    } else {
      if (!((secureText && !toggle) || (!secureText && toggle))) {
        if (onTogglePassword) {
          onTogglePassword(!toggle);
        }
        setSecureText(!toggle);
        toggle ? setFocus() : setBlur();
      }
    }
  }

  function onSubmitEditing() {
    if (onSubmit !== undefined) {
      onSubmit();
    }
  }

  const imgSource = darkTheme
    ? secureText
      ? customShowPasswordImage || makeVisibleBlack
      : customHidePasswordImage || makeInvisibleBlack
    : secureText
    ? customShowPasswordImage || makeVisibleWhite
    : customHidePasswordImage || makeInvisibleWhite;

  const style: TextStyle = {
    ...setGlobalStyles?.labelStyles,
    ...labelStyles,
    left: labelStyles?.left !== undefined ? labelStyles?.left : 5,
    fontSize: staticLabel
      ? customLabelStyles?.fontSizeFocused !== undefined
        ? customLabelStyles.fontSizeFocused
        : 10
      : !isFocusedState
      ? customLabelStyles.fontSizeBlurred
      : customLabelStyles.fontSizeFocused,
    // @ts-ignore
    color: interpolateColors(fontColorAnimated, {
      inputRange: [0, 1],
      outputColorRange: [
        // @ts-ignore
        customLabelStyles.colorBlurred,
        // @ts-ignore
        customLabelStyles.colorFocused,
      ],
    }),
    alignSelf: 'center',
    position: 'absolute',
    flex: 1,
    zIndex: 999,
  };

  let input: TextStyle =
    inputStyles !== undefined
      ? inputStyles
      : setGlobalStyles?.inputStyles !== undefined
      ? setGlobalStyles.inputStyles
      : styles.input;

  input = {
    ...input,
    flex: 1,
    color:
      input.color !== undefined ? input.color : customLabelStyles.colorFocused,
    zIndex: style?.zIndex !== undefined ? style.zIndex - 2 : 0,
  };

  containerStyles =
    containerStyles !== undefined
      ? containerStyles
      : setGlobalStyles?.containerStyles !== undefined
      ? setGlobalStyles?.containerStyles
      : styles.container;

  containerStyles = {
    ...containerStyles,
    alignItems: 'center',
    flexDirection: 'row',
    flex: 1,
    zIndex: style?.zIndex !== undefined ? style.zIndex - 6 : 0,
  };

  let toggleButton =
    showPasswordContainerStyles !== undefined
      ? showPasswordContainerStyles
      : setGlobalStyles?.showPasswordContainerStyles !== undefined
      ? setGlobalStyles.showPasswordContainerStyles
      : styles.toggleButton;

  toggleButton = {
    ...toggleButton,
    alignSelf: 'center',
  };

  let img =
    showPasswordImageStyles !== undefined
      ? showPasswordImageStyles
      : setGlobalStyles?.showPasswordImageStyles !== undefined
      ? setGlobalStyles.showPasswordImageStyles
      : styles.img;

  img = {
    height: 25,
    width: 25,
    ...img,
  };

  const countdown = {
    ...styles.countdown,
    ...setGlobalStyles?.showCountdownStyles,
    ...showCountdownStyles,
  };

  function onChangeTextCallback(val: string): void | undefined {
    if (onChangeText === undefined) return undefined;

    if (maskType === undefined && mask === undefined) return onChangeText(val);

    let newValue: string | undefined;

    if (maskType !== 'currency' && mask !== undefined) {
      newValue = getValueWithNonCurrencyMask({ value: val, mask });
    }

    if (maskType === 'currency') {
      if (
        currency !== undefined &&
        !/^[0-9]+$/g.test(val.replace(/[.,]/g, '').replace(currency, '')) &&
        val.replace(/[.,]/g, '').replace(currency, '') !== ''
      ) {
        return undefined;
      } else if (
        currency === undefined &&
        !/^[0-9]+$/g.test(val.replace(/[.,]/g, '')) &&
        val.replace(/[.,]/g, '') !== ''
      ) {
        return undefined;
      }

      newValue = getValueWithCurrencyMask({
        value: currency !== undefined ? value.replace(currency, '') : value,
        newValue: currency !== undefined ? val.replace(currency, '') : val,
        currencyDivider,
        maxDecimalPlaces,
      });
    }

    if (newValue !== undefined) {
      return onChangeText((currency !== undefined ? currency : '') + newValue);
    }
  }

  function onLayout(event: LayoutChangeEvent) {
    const { height } = event.nativeEvent.layout;
    setHalfTop(height / 2);
  }

  return (
    <TouchableWithoutFeedback onPress={setFocus} onLayout={onLayout}>
      <View style={{ flexDirection: 'row' }}>
        {staticLabel && (
          <AnimatedText
            {...labelProps}
            onPress={setFocus}
            style={[
              style,
              {
                left: labelStyles?.left
                  ? labelStyles?.left
                  : customLabelStyles.leftFocused
                  ? customLabelStyles.leftFocused
                  : 20,
                top: -(style?.fontSize ? style?.fontSize : 10) / 2,
              },
            ]}
          >
            {label}
          </AnimatedText>
        )}
        <View style={containerStyles}>
          {leftComponent && leftComponent}
          <View style={{ flex: 1, flexDirection: 'row' }}>
            {!staticLabel && (
              <AnimatedText
                {...labelProps}
                onPress={setFocus}
                style={[
                  style,
                  // @ts-ignore
                  {
                    fontSize: fontSizeAnimated,
                    transform: [
                      { translateX: leftAnimated },
                      { translateY: topAnimated },
                    ],
                  },
                ]}
              >
                {label}
              </AnimatedText>
            )}
            <TextInput
              value={value}
              onSubmitEditing={onSubmitEditing}
              secureTextEntry={
                isPassword !== undefined ? isPassword && secureText : false
              }
              onFocus={onFocus !== undefined ? onFocus : handleFocus}
              onBlur={onBlur !== undefined ? onBlur : handleBlur}
              ref={inputRef}
              {...rest}
              maxLength={
                mask !== undefined
                  ? mask.length
                  : maxLength !== undefined
                  ? maxLength
                  : undefined
              }
              placeholderTextColor={hintTextColor}
              placeholder={(staticLabel || isFocusedState) && hint ? hint : ''}
              multiline={multiline}
              onChangeText={onChangeTextCallback}
              style={input}
            />
            {rightComponent && rightComponent}
            {isPassword && (
              <TouchableOpacity
                style={toggleButton}
                onPress={() => _toggleVisibility()}
              >
                {secureText && customShowPasswordComponent !== undefined ? (
                  customShowPasswordComponent
                ) : !secureText && customHidePasswordComponent !== undefined ? (
                  customHidePasswordComponent
                ) : (
                  <Image source={imgSource} resizeMode="contain" style={img} />
                )}
              </TouchableOpacity>
            )}
          </View>
          {showCountdown && maxLength && (
            <Text style={countdown}>
              {maxLength - (value ? value.length : 0)} {countdownLabel}
            </Text>
          )}
        </View>
      </View>
    </TouchableWithoutFeedback>
  );
}
Example #22
Source File: ButtonMultiline.tsx    From mobile with Apache License 2.0 4 votes vote down vote up
ButtonMultiline = ({
  text,
  text1,
  onPress,
  variant,
  color: buttonColorName,
  disabled,
  loading,
  externalLink,
  internalLink,
}: ButtonMultilineProps) => {
  const i18n = useI18n();
  const theme = useTheme<Theme>();
  const variantProps = theme.buttonVariants[variant];
  const disabledProps = disabled ? variantProps.disabled || {} : {};
  const themedStyles = {...variantProps, ...disabledProps};
  const {fontSize, fontWeight, fontFamily, color, borderWidth, height} = (themedStyles as unknown) as TextStyle &
    ViewStyle;
  const textColor = themedStyles.textColor;
  const buttonColor = buttonColorName && theme.colors[buttonColorName];

  const onPressHandler = loading ? () => {} : onPress;
  const externalLinkProps = externalLink
    ? {
        accessibilityLabel: text,
        accessibilityHint: i18n.translate('Home.ExternalLinkHint'),
        accessibilityRole: 'link' as AccessibilityRole,
      }
    : {};
  const externalArrowIcon = textColor === palette.white ? 'icon-external-arrow-light' : 'icon-external-arrow';
  const borderRadius = 10;
  const boxStyles: BoxProps['style'] = {
    backgroundColor: Platform.OS === 'ios' ? color : 'transparent',
    minHeight: height,
    borderWidth,
    borderColor: buttonColor,
  };
  const content = (
    <Box
      borderRadius={borderRadius}
      alignItems="center"
      justifyContent="center"
      style={boxStyles}
      paddingHorizontal="m"
      paddingVertical="m"
      flexDirection="row"
    >
      {loading ? (
        <ActivityIndicator color={textColor} size="large" />
      ) : (
        <>
          <Box
            flex={1}
            flexBasis="100%"
            flexDirection="row-reverse"
            alignItems="flex-start"
            justifyContent="flex-start"
          >
            <Box flexBasis={25} style={{...styles.iconOffset}}>
              {externalLink && <Icon name={externalArrowIcon} size={25} />}
              {internalLink && <Icon name="icon-chevron-white" size={25} />}
            </Box>

            <Box flex={1} flexBasis="90%" alignItems="flex-start" justifyContent="flex-end">
              <Text
                style={{
                  ...styles.content,
                  color: textColor || buttonColor,
                  fontFamily,
                  fontSize,
                  ...styles.strong,
                }}
              >
                {text}
              </Text>
              <Text style={{...styles.content, color: textColor || buttonColor, fontWeight, fontFamily, fontSize}}>
                {text1}
              </Text>
            </Box>
          </Box>
        </>
      )}
    </Box>
  );

  const accessibilityProps = {
    accessibilityRole: 'button' as 'button',
    accessibilityState: {disabled},
    ...externalLinkProps,
  };

  if (Platform.OS === 'android') {
    return (
      <Ripple
        disabled={disabled}
        onPress={onPressHandler}
        backgroundColor={color}
        borderRadius={borderRadius}
        {...accessibilityProps}
      >
        {content}
      </Ripple>
    );
  }
  return (
    <TouchableOpacity
      activeOpacity={0.6}
      onPress={onPressHandler}
      style={styles.stretch}
      disabled={disabled}
      {...accessibilityProps}
    >
      {content}
    </TouchableOpacity>
  );
}
Example #23
Source File: index.tsx    From frontatish with MIT License 4 votes vote down vote up
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 #24
Source File: TextField.tsx    From react-native-jigsaw with MIT License 4 votes vote down vote up
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>
    );
  }
Example #25
Source File: ProgressBarHaflCircle.tsx    From companion-kit with MIT License 4 votes vote down vote up
export default function ProgressBarHaflCircle(this: never, props: PropsGradient) {
    const { animationStep, title, diameter, gradient, progress, style, titleStyle } = props;
    const length = Math.round(diameter * Math.PI);

    const [ offset ] = React.useState(() => {
        const startProgress = (progress - (animationStep || 0.1));
        return new Animated.Value(getOffset(diameter, startProgress));
    });

    React.useEffect(() => {
        Animated.timing(offset, {
            toValue: getOffset(diameter, progress),
            duration: 2000,
            delay: 750,
        }).start();
    }, [progress]);

    const boxSize = diameter + 6;
    const origin = diameter / 2;

    const defaultTitleStyles: StyleProp<TextStyle> = {
        position: 'absolute',
        alignItems: 'center',
        justifyContent: 'center',
    };

    return (
        <View style={style}>
            <Text style={[TextStyles.p3, defaultTitleStyles, titleStyle]}>{title}</Text>
            <Svg id="progress-bar-circle" width="100%" height="100%" viewBox={`0 0 ${boxSize} ${boxSize}`} fill="none">
                <G x={3} y={3}>
                    <Circle
                        id="circle-bg"
                        opacity="0.2"
                        cx={diameter / 2}
                        cy={diameter / 2}
                        r={diameter / 2}
                        strokeWidth="3"
                        stroke="url(#paint0_linear)"
                        fill="none"
                    />
                    <AnimatedContainer
                        id="circle-progress"
                        fill="none"
                        cx={diameter / 2}
                        cy={diameter / 2}
                        r={diameter / 2}
                        strokeWidth="3"
                        stroke="url(#paint0_linear)"
                        strokeDasharray={length}
                        strokeDashoffset={offset}
                        origin={`${origin}, ${origin}`}
                        rotation={90}
                    />
                    <AnimatedContainer
                        id="circle-progress2"
                        fill="none"
                        cx={diameter / 2}
                        cy={diameter / 2}
                        r={diameter / 2}
                        strokeWidth="3"
                        stroke="url(#paint0_linear)"
                        strokeDasharray={length}
                        strokeDashoffset={offset}
                        origin={`${origin}, ${origin}`}
                        scaleX={-1}
                        rotation={-90}
                    />
                </G>
                <Defs>
                    {gradient ? (
                        <LinearGradient id="paint0_linear" x1={diameter / 2} y1={diameter} x2={diameter} y2={0} gradientUnits="userSpaceOnUse">
                            {gradient.map((color, i) => {
                                // tslint:disable-next-line: no-unused-expression
                                return <Stop key={`${color.title}_${i}`} offset={color.offset} stopColor={color.title}/>;
                            })}
                        </LinearGradient>
                    ) : (
                        <LinearGradient id="paint0_linear" x1={0} y1={diameter / 2} x2={diameter} y2={diameter / 2} gradientUnits="userSpaceOnUse">
                            <Stop offset="0.0996095" stopColor="#FFCECF"/>
                            <Stop offset="0.238673" stopColor="#9A87E7"/>
                            <Stop offset="0.384948" stopColor="#FFAFD5"/>
                            <Stop offset="0.512681" stopColor="#FA8989"/>
                            <Stop offset="0.642474" stopColor="#CFC4FF"/>
                            <Stop offset="0.776388" stopColor="#FFAFD5"/>
                            <Stop offset="0.90206" stopColor="#FFCED0"/>
                        </LinearGradient>
                    )}
                </Defs>
            </Svg>
        </View>
    );
}
Example #26
Source File: DeprecatedFAB.tsx    From react-native-jigsaw with MIT License 4 votes vote down vote up
FAB: React.FC<Props> = ({
  Icon,
  icon,
  disabled = false,
  type = "solid",
  loading = false,
  color: colorOverride,
  label,
  onPress,
  elevation = 0,
  style,
  theme: { colors, disabledOpacity, roundness, typography },
  ...rest
}) => {
  let backgroundColor, borderColor, textColor, borderWidth;
  const buttonColor = colorOverride || colors.primary;

  if (type === "standard" || type === "extended" || type === "fixed") {
    backgroundColor = buttonColor;

    if (disabled) {
      textColor = color(colors.surface).alpha(disabledOpacity).rgb().string();
    } else {
      textColor = colors.surface;
    }
  } else {
    backgroundColor = "transparent";

    if (disabled) {
      textColor = color(buttonColor).alpha(disabledOpacity).rgb().string();
    } else {
      textColor = buttonColor;
    }
  }

  if (type === "outline") {
    if (disabled) {
      borderColor = color(buttonColor).alpha(disabledOpacity).rgb().string();
    } else {
      borderColor = buttonColor;
    }
    borderWidth = StyleSheet.hairlineWidth;
  } else {
    borderColor = "transparent";
    borderWidth = 0;
  }

  const buttonStyle: StyleProp<ViewStyle> = {
    backgroundColor,
    borderColor,
    borderWidth,
    borderRadius: roundness,
    alignItems: "center",
    justifyContent: "center",
  };

  const buttonStyles: StyleProp<ViewStyle>[] = [styles.button, buttonStyle];

  const contentStyle: StyleProp<ViewStyle>[] = [styles.content];

  const textStyle: StyleProp<TextStyle> = {
    textAlign: "center",
    color: textColor,
  };

  const iconStyle: StyleProp<ViewStyle>[] = [
    styles.icon,
    {
      width: Config.buttonIconSize,
    },
  ];

  if (type === "standard" || type === "outline") {
    buttonStyle.width = Config.FABSize;
    buttonStyle.height = Config.FABSize;
    buttonStyle.borderRadius = Config.FABBorderRadius;

    contentStyle.push({
      width: Config.FABSize,
      height: Config.FABSize,
    });
  }

  if (type === "extended" || type === "fixed") {
    iconStyle.push({
      marginLeft: 16,
      marginRight: -8,
    });

    textStyle.margin = 16;
  }

  if (type === "fixed") {
    buttonStyles.push({
      height: Config.FABFixedHeight,
      alignSelf: "stretch",
    });
  }

  return (
    <Elevation style={[{ elevation }, style]}>
      <Touchable
        {...rest}
        onPress={onPress}
        accessibilityState={{ disabled }}
        accessibilityRole="button"
        disabled={disabled || loading}
        style={buttonStyles}
      >
        <View style={styles.content}>
          {icon && loading !== true ? (
            <View style={iconStyle}>
              <Icon
                name={icon}
                size={Config.buttonIconSize}
                color={textColor}
              />
            </View>
          ) : null}
          {loading ? (
            <ActivityIndicator
              size="small"
              color={textColor}
              style={iconStyle}
            />
          ) : null}
          {label ? (
            <Text numberOfLines={1} style={[textStyle, typography.button]}>
              {label}
            </Text>
          ) : null}
        </View>
      </Touchable>
    </Elevation>
  );
}
Example #27
Source File: DeprecatedButton.tsx    From react-native-jigsaw with MIT License 4 votes vote down vote up
Button: React.FC<Props> = ({
  Icon,
  icon,
  disabled = false,
  type = "solid",
  loading = false,
  labelColor,
  color: colorOverride,
  children,
  onPress,
  elevation = 0,
  style,
  theme: { colors, disabledOpacity, roundness, typography },
  ...rest
}) => {
  let backgroundColor, borderColor, textColor, borderWidth;
  const buttonColor = colorOverride || colors.primary;

  if (type === "solid") {
    backgroundColor = buttonColor;

    if (disabled) {
      textColor = color(colors.surface).alpha(disabledOpacity).rgb().string();
    } else {
      textColor = labelColor || colors.surface;
    }
  } else {
    backgroundColor = "transparent";

    if (disabled) {
      textColor = color(buttonColor).alpha(disabledOpacity).rgb().string();
    } else {
      textColor = labelColor || buttonColor;
    }
  }

  if (type === "outline") {
    if (disabled) {
      borderColor = color(buttonColor).alpha(disabledOpacity).rgb().string();
    } else {
      borderColor = buttonColor;
    }
    borderWidth = StyleSheet.hairlineWidth;
  } else {
    borderColor = "transparent";
    borderWidth = 0;
  }

  const buttonStyle = {
    backgroundColor,
    borderColor,
    borderWidth,
    borderRadius: roundness,
  };

  const textStyle: StyleProp<TextStyle> = {
    textAlign: "center",
    color: textColor,
    marginVertical: 16,
    marginHorizontal: 16,
  };

  const iconStyle = [
    styles.icon,
    {
      marginLeft: 16,
      marginRight: -8,
      width: Config.buttonIconSize,
    },
  ];

  const {
    margin,
    marginEnd,
    marginTop,
    marginLeft,
    marginRight,
    marginBottom,
    marginHorizontal,
    marginVertical,
    ...innerStyles
  } = StyleSheet.flatten(style || {});

  const margins = {
    margin,
    marginEnd,
    marginTop,
    marginLeft,
    marginRight,
    marginBottom,
    marginHorizontal,
    marginVertical,
  };

  return (
    <Elevation style={{ elevation, alignSelf: "stretch", ...margins }}>
      <Touchable
        {...rest}
        onPress={onPress}
        accessibilityState={{ disabled }}
        accessibilityRole="button"
        disabled={disabled || loading}
        style={[styles.button, buttonStyle, innerStyles]}
      >
        <View style={styles.content}>
          {icon && loading !== true ? (
            <View style={iconStyle}>
              <Icon
                name={icon}
                size={Config.buttonIconSize}
                color={textColor}
              />
            </View>
          ) : null}
          {loading ? (
            <ActivityIndicator
              size="small"
              color={textColor}
              style={iconStyle}
            />
          ) : null}
          <Text numberOfLines={1} style={[textStyle, typography.button]}>
            {children}
          </Text>
        </View>
      </Touchable>
    </Elevation>
  );
}
Example #28
Source File: DatePicker.tsx    From react-native-jigsaw with MIT License 4 votes vote down vote up
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 #29
Source File: IterableInboxMessageCell.tsx    From react-native-sdk with MIT License 4 votes vote down vote up
function defaultMessageListLayout(
   last: boolean,
   dataModel: IterableInboxDataModel,
   rowViewModel: InboxRowViewModel,
   customizations: IterableInboxCustomizations,
   isPortrait: boolean
) {
   const messageTitle = rowViewModel.inAppMessage.inboxMetadata?.title ?? ""
   const messageBody = rowViewModel.inAppMessage.inboxMetadata?.subtitle ?? ""
   const messageCreatedAt = dataModel.getFormattedDate(rowViewModel.inAppMessage) ?? ""
   const thumbnailURL = rowViewModel.imageUrl

   let styles = StyleSheet.create({
      unreadIndicatorContainer: {
         height: '100%',
         flexDirection: 'column',
         justifyContent: 'flex-start'
      },

      unreadIndicator: {
         width: 15,
         height: 15,
         borderRadius: 15 / 2,
         backgroundColor: 'blue',
         marginLeft: 10,
         marginRight: 5,
         marginTop: 10
      },

      unreadMessageThumbnailContainer: {
         paddingLeft: 10,
         flexDirection: 'column',
         justifyContent: 'center'
      },

      readMessageThumbnailContainer: {
         paddingLeft: 30,
         flexDirection: 'column',
         justifyContent: 'center'
      },

      messageContainer: {
         paddingLeft: 10,
         width: '75%',
         flexDirection: 'column',
         justifyContent: 'center'
      },

      title: {
         fontSize: 22,
         width: '85%',
         paddingBottom: 10
      },

      body: {
         fontSize: 15,
         color: 'lightgray',
         width: '85%',
         flexWrap: "wrap",
         paddingBottom: 10
      },

      createdAt: {
         fontSize: 12,
         color: 'lightgray'
      },

      messageRow: {
         flexDirection: 'row',
         backgroundColor: 'white',
         paddingTop: 10,
         paddingBottom: 10,
         width: '100%',
         height: 150,
         borderStyle: 'solid',
         borderColor: 'lightgray',
         borderTopWidth: 1
      }
   })

   const resolvedStyles = { ...styles, ...customizations }

   let {
      unreadIndicatorContainer,
      unreadIndicator,
      unreadMessageThumbnailContainer,
      readMessageThumbnailContainer,
      messageContainer,
      title,
      body,
      createdAt,
      messageRow
   } = resolvedStyles

   unreadIndicator = (!isPortrait) ? { ...unreadIndicator, marginLeft: 40 } : unreadIndicator
   readMessageThumbnailContainer = (!isPortrait) ? { ...readMessageThumbnailContainer, paddingLeft: 65 } : readMessageThumbnailContainer
   messageContainer = (!isPortrait) ? { ...messageContainer, width: '90%' } : messageContainer

   function messageRowStyle(rowViewModel: InboxRowViewModel) {
      return last ? { ...messageRow, borderBottomWidth: 1 } : messageRow
   }

   return (
      <View style={messageRowStyle(rowViewModel) as ViewStyle} >
         <View style={unreadIndicatorContainer as ViewStyle}>
            {rowViewModel.read ? null : <View style={unreadIndicator} />}
         </View>
         <View style={(rowViewModel.read ? readMessageThumbnailContainer : unreadMessageThumbnailContainer) as ViewStyle}>
            {thumbnailURL ? <Image style={{ height: 80, width: 80 }} source={{ uri: thumbnailURL }} /> : null}
         </View>
         <View style={messageContainer as ViewStyle}>
            <Text numberOfLines={1} ellipsizeMode='tail' style={title}>{messageTitle as TextStyle}</Text>
            <Text numberOfLines={3} ellipsizeMode='tail' style={body as TextStyle}>{messageBody}</Text>
            <Text style={createdAt}>{messageCreatedAt as TextStyle}</Text>
         </View>
      </View>
   )
}