styled-components#useTheme JavaScript Examples

The following examples show how to use styled-components#useTheme. 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.native.js    From polaris with Apache License 2.0 6 votes vote down vote up
Header = () => {
  const { t } = useTranslation()
  const navigation = useNavigation()
  const theme = useTheme()
  const { currentRoute, params } = usePlatformLocation()
  const { defaultPath } = useContext(RoutesContext)
  const isHome = currentRoute.path === defaultPath
  const translatedName = t(currentRoute.name)
  const title = replaceParams(translatedName, params)
  return (
    <NativeHeader
      leftComponent={<Left isHome={isHome} goBack={navigation.goBack} />}
      centerComponent={{
        text: title,
        style: {
          color: theme.colors.white,
          fontSize: 21
        }
      }}
      rightComponent={<Right toggleDrawer={navigation.toggleDrawer} />}
    />
  )
}
Example #2
Source File: nav.test.web.js    From polaris with Apache License 2.0 6 votes vote down vote up
ThemeSwitchFixture = () => {
  const theme = useTheme()
  return (
    <View>
      <Navigation />
      <Text>Theme: {theme.name}</Text>
    </View>
  )
}
Example #3
Source File: index.web.jsx    From polaris with Apache License 2.0 6 votes vote down vote up
export default function Header() {
  const { t } = useTranslation()
  const { toggleTheme } = useContext(ThemeActionsContext)
  const theme = useTheme()

  return (
    <Wrapper>
      <Left>
        <Link title={t('home:title')} path={'/'} />
      </Left>
      <Center>
        <ThemeText>{t('nav:topCenter')}</ThemeText>
      </Center>
      <Right>
        <Link title={t('home:settingsButton')} path={'/settings'} />
        <Switch
          onValueChange={toggleTheme}
          value={theme.name !== 'light'}
          testID="theme-switch"
        />
      </Right>
    </Wrapper>
  )
}
Example #4
Source File: index.jsx    From polaris with Apache License 2.0 6 votes vote down vote up
HomeScreen = () => {
  const { t } = useTranslation()
  const theme = useTheme()

  return (
    <Container>
      <NearformLogo
        width={200}
        height={50}
        fill={theme.colors.primary}
        title="Nearform logo"
      />
      <StyledLinkButton title={t('home:simpleButton')} path="/simple" />
      <StyledLinkButton title={t('home:listViewButton')} path="/listView" />
      {Platform.OS !== 'web' && (
        <StyledLinkButton title={t('home:cameraButton')} path="/camera" />
      )}
      <StyledLinkButton
        title={t('home:pushNotificationsButton')}
        path="/pushNotifications"
      />
      <StyledLinkButton title={t('home:responsiveButton')} path="/responsive" />
      <StyledLinkButton title={t('home:authButton')} path="/auth" />
      {Platform.OS !== 'web' && (
        <>
          <StyledLinkButton title={t('home:qrCodeButton')} path="/qrCode" />
          <StyledLinkButton title={t('home:mapButton')} path="/map" />
        </>
      )}
      <Text testID="welcome">Text for tests</Text>
    </Container>
  )
}
Example #5
Source File: fixtures.js    From polaris with Apache License 2.0 6 votes vote down vote up
ContextualView = () => {
  const theme = useTheme()
  const translation = useTranslation()

  if (!translation) throw new Error('Nothing returned from useTranslation')
  if (!theme || !theme.name)
    throw new Error(`${!theme ? 'No' : 'Empty'} theme returned from useTheme`)

  const { t, i18n } = translation

  return (
    <View>
      <Text>{t('headingText')}</Text>
      <Text testID="lang-name">Current language is {i18n.language}</Text>
      <Text testID="theme-name">Current theme is {theme.name}</Text>
    </View>
  )
}
Example #6
Source File: theme-switcher.js    From polaris with Apache License 2.0 6 votes vote down vote up
ThemeSwitcher = () => {
  const { toggleTheme } = React.useContext(ThemeActionsContext);
  const theme = useTheme();
  return (
    <Container>
      <Text>Switch theme</Text>
      <Switch onValueChange={toggleTheme} value={theme.name !== 'light'} testID="theme-switch" />
    </Container>
  );
}
Example #7
Source File: Icon.web.js    From blade with MIT License 6 votes vote down vote up
Icon = ({ size, fill, children, ...rest }) => {
  const theme = useTheme();

  return (
    <svg
      focusable={false}
      aria-hidden={true}
      fill={getColor(theme, fill)}
      height={iconSize[size]}
      width={iconSize[size]}
      {...automation('ds-icon')}
      {...rest}
    >
      {children}
    </svg>
  );
}
Example #8
Source File: UserHeader.js    From plataforma-sabia with MIT License 6 votes vote down vote up
UserHeader = () => {
	const { colors } = useTheme();
	const { user } = useAuth();
	const { t } = useTranslation(['common']);
	const [ref, isDropDownVisible, setIsDropDownVisible] = useVisibleComponent();
	const userFirstName = user.full_name && user.full_name.split(' ')[0];
	const router = useRouter();

	const toggleVisible = () => setIsDropDownVisible((prev) => !prev);

	const handleToggleDropDown = (e) => {
		e.preventDefault();
		if (!user?.email) {
			router.push(internalPages.signIn);
		} else {
			toggleVisible();
		}
	};

	return (
		<LoginBox ref={ref}>
			<UserButton type="button" onClick={handleToggleDropDown} data-cy="user-dropdown-button">
				<MdAccountCircle color={colors.secondary} />
				<span>{userFirstName || t('common:login')}</span>
			</UserButton>
			<UserProfileDropDown visible={isDropDownVisible} toggleVisible={toggleVisible} />
		</LoginBox>
	);
}
Example #9
Source File: new.js    From plataforma-sabia with MIT License 5 votes vote down vote up
NewSolutionPage = () => {
	const { colors } = useTheme();
	const { t } = useTranslation(['pages']);

	return (
		<>
			<Head
				title={t('pages:solution.new.title')}
				description={t('pages:solution.new.description')}
				keywords={t('pages:solution.new.keywords')}
			/>
			<Wrapper>
				<Container>
					<Title color={colors.black}>Que tipo de solução você irá cadastrar?</Title>

					<RegisterType>
						<Link href={internalPages.newTechnology} passHref>
							<RectangularButton
								as="a"
								variant="backgroundImage"
								backgroundUrl="/buttons/agro-machine.png"
								colorVariant="orange"
								fullWidth
							>
								Tecnologias
							</RectangularButton>
						</Link>
						<Link href={internalPages.newService} passHref>
							<RectangularButton
								as="a"
								variant="backgroundImage"
								backgroundUrl="/buttons/hand-holding-earth.png"
								colorVariant="green"
								fullWidth
							>
								Serviços
							</RectangularButton>
						</Link>
					</RegisterType>
				</Container>
			</Wrapper>
		</>
	);
}
Example #10
Source File: index.native.jsx    From polaris with Apache License 2.0 5 votes vote down vote up
ButtonAtom = props => {
  const theme = useTheme()
  return <Button color={theme.colors.primary} {...props} />
}
Example #11
Source File: index.js    From plataforma-sabia with MIT License 5 votes vote down vote up
Button = ({
	children,
	disabled,
	onClick,
	variant,
	type,
	fullWidth,
	isLink,
	linkType,
	...rest
}) => {
	const { colors } = useTheme();
	const Link = isLink && linkType === 'default' ? StyledNextLink : StyledScrollLink;

	let bgColor;

	switch (variant) {
		case 'primary':
			bgColor = colors.primary;
			break;
		case 'secondary':
			bgColor = colors.secondary;
			break;
		default:
			bgColor = colors.primary;
	}

	return isLink ? (
		<Link $bgColor={bgColor} $color={colors.white} {...rest}>
			{children}
		</Link>
	) : (
		<StyledButton
			onClick={onClick}
			disabled={disabled}
			type={type}
			$bgColor={bgColor}
			$color={colors.white}
			fullWidth={fullWidth}
		>
			{children}
		</StyledButton>
	);
}
Example #12
Source File: CircularButton.js    From plataforma-sabia with MIT License 5 votes vote down vote up
Button = ({
	children,
	disabled,
	onClick,
	variant,
	type,
	title,
	size,
	float,
	name,
	height,
	width,
}) => {
	const { colors } = useTheme();

	let bgColor;

	switch (variant) {
		case 'primary':
			bgColor = colors.primary;
			break;
		case 'secondary':
			bgColor = colors.lightGray;
			break;
		case 'success':
			bgColor = colors.green;
			break;
		case 'info':
			bgColor = colors.lightBlue;
			break;
		case 'remove':
			bgColor = colors.lightGray3;
			break;
		default:
			bgColor = colors.primary;
	}

	return (
		<CircularButton
			onClick={onClick}
			disabled={disabled}
			type={type}
			bgColor={bgColor}
			color={colors.white}
			size={size}
			title={title}
			float={float}
			name={name}
			height={height}
			width={width}
		>
			{children}
		</CircularButton>
	);
}
Example #13
Source File: Button.js    From plataforma-sabia with MIT License 5 votes vote down vote up
Button = ({
	children,
	disabled,
	onClick,
	variant,
	type,
	title,
	uppercase,
	name,
	as,
	href,
}) => {
	const { colors } = useTheme();

	let bgColor;

	switch (variant) {
		case 'primary':
			bgColor = colors.primary;
			break;
		case 'secondary':
			bgColor = colors.lightGray;
			break;
		case 'success':
			bgColor = colors.secondary;
			break;
		case 'info':
			bgColor = colors.blue;
			break;
		default:
			bgColor = colors.primary;
	}

	return (
		<StyledButton
			onClick={onClick}
			disabled={disabled}
			type={type}
			bgColor={bgColor}
			color={colors.white}
			title={title}
			uppercase={uppercase}
			name={name}
			as={as}
			href={href}
		>
			{children}
		</StyledButton>
	);
}
Example #14
Source File: Label.web.js    From blade with MIT License 5 votes vote down vote up
AnimatedLabel = ({
  children,
  position,
  disabled,
  isFocused,
  hasError,
  variant,
  value,
  hasText,
  layoutDimensions,
  width,
  id,
}) => {
  const theme = useTheme();
  const floatViewAnimationStyle = getFloatViewAnimationStyle({
    isFocused,
    hasText,
    layoutDimensions,
  });

  return (
    <Space
      margin={styles.label.margin({
        position,
        variant,
      })}
    >
      <FloatView layoutDimensions={layoutDimensions} style={floatViewAnimationStyle}>
        <StyledText
          as="label"
          htmlFor={id}
          isFocused={isFocused}
          hasError={hasError}
          hasText={hasText}
          disabled={disabled}
          variant={variant}
          value={value}
          theme={theme}
          position={position}
          width={width}
        >
          {children}
        </StyledText>
      </FloatView>
    </Space>
  );
}
Example #15
Source File: Label.web.js    From blade with MIT License 5 votes vote down vote up
RegularLabel = ({
  children,
  position,
  hasError,
  hasText,
  disabled,
  variant,
  value,
  isFocused,
  width,
  id,
}) => {
  const theme = useTheme();

  return (
    <Space
      margin={styles.label.margin({
        position,
        variant,
      })}
    >
      <StyledText
        as="label"
        htmlFor={id}
        hasError={hasError}
        disabled={disabled}
        variant={variant}
        value={value}
        hasText={hasText}
        theme={theme}
        isFocused={isFocused}
        position={position}
        width={width}
        id={id}
      >
        {children}
      </StyledText>
    </Space>
  );
}
Example #16
Source File: TextInput.web.js    From blade with MIT License 4 votes vote down vote up
TextInput = ({
  placeholder,
  onChange,
  onBlur,
  helpText,
  errorText,
  variant,
  prefix,
  suffix,
  disabled,
  value,
  iconLeft,
  iconRight,
  onRightIconClick,
  maxLength,
  label,
  testID,
  labelPosition,
  width,
  type,
  id,
  name,
  _isMultiline,
  autoCapitalize,
}) => {
  const theme = useTheme();
  const inputRef = useRef();
  const containerRef = useRef();
  const [isFocused, setIsFocused] = useState(false);
  const [input, setInput] = useState(value || '');
  // Used for storing layout value of TextInput
  const [layoutDimensions, setLayoutDimensions] = useState(null);
  // Used to hide placeholder while label is inside the TextInput
  const [isPlaceholderVisible, setIsPlaceholderVisible] = useState(isFocused);

  const hasText = !isEmpty(input);
  const hasAnimatedLabel = variant === 'outlined';

  const placeholderTextColor = getPlaceholderTextColor({
    theme,
    disabled,
    isPlaceholderVisible,
    hasAnimatedLabel,
  });

  // Derive accessory conditions based on props
  const { hasError, hasPrefix, hasSuffix, hasLeftIcon, hasRightIcon } = getAccessoryConfig({
    errorText,
    prefix,
    suffix,
    iconLeft,
    iconRight,
  });

  if (labelPosition === 'left' && variant === 'outlined') {
    // Outlined Text Input has only a top label
    throw Error('Cannot have a left label on an outlined Text Input');
  }

  if (!isEmpty(prefix) && !isEmpty(iconLeft)) {
    throw Error('Cannot have prefix and left icon together');
  }

  if (!isEmpty(suffix) && !isEmpty(iconRight)) {
    throw Error('Cannot have suffix and right icon together');
  }

  const onFocus = useCallback(() => {
    setIsFocused(true);
    /* Wait for 90ms to show the placeholder since it takes 100ms for Label to animate from inside to top of the TextInput.
       Otherwise they both overlap */
    /* Don't have any delay if label is on left of TextInput */

    setTimeout(() => {
      setIsPlaceholderVisible(true);
    }, 90);
  }, [setIsFocused, setIsPlaceholderVisible]);

  const onBlurText = useCallback(
    (event) => {
      setIsFocused(false);
      setIsPlaceholderVisible(false);
      const inputValue = event.target.value;
      setInput(inputValue);
      onBlur(inputValue);
    },
    [onBlur],
  );

  const onChangeText = useCallback(
    (event) => {
      let inputValue = event.target.value;
      if (inputValue.length > maxLength) {
        return;
      }
      if (autoCapitalize !== 'none') {
        inputValue = transformString(inputValue, autoCapitalize);
      }
      setInput(inputValue);
      onChange(inputValue);
    },
    [maxLength, onChange, autoCapitalize],
  );

  // allowed values = 0-9 "." "," "whitespace" "-"
  const isInputNumberAllowed = (inputValue) => /^[0-9., -]+$/g.test(inputValue);

  const onKeyPress = useCallback(
    (event) => {
      if (type === 'number') {
        const charCode = typeof event.which === 'number' ? event.which : event.keyCode;
        const char = String.fromCharCode(charCode);
        const isAllowed = isInputNumberAllowed(char);

        if (!isAllowed) {
          event.preventDefault();
        }
      }
    },
    [type],
  );

  const onPaste = useCallback(
    (event) => {
      if (type === 'number') {
        const inputValue = event.clipboardData.getData('Text');
        const isAllowed = isInputNumberAllowed(inputValue);

        if (!isAllowed) {
          event.preventDefault();
        }
      }
    },
    [type],
  );

  useEffect(() => {
    if (value === '' || value) {
      setInput(value);
    }
  }, [value]);

  useEffect(() => {
    if (inputRef.current && containerRef.current) {
      const containerRect = containerRef.current.getBoundingClientRect();
      const inputRect = inputRef.current.getBoundingClientRect();
      const initialLeftPosition = inputRect.x - containerRect.x;
      const finalTopPosition = inputRef.current.offsetHeight;

      setLayoutDimensions({
        initialLeftPosition,
        finalTopPosition,
      });
    }
  }, [inputRef, containerRef]);

  useEffect(() => {
    // Adjust height of textarea as user types for outlined variant
    if (inputRef.current && _isMultiline && variant === 'outlined') {
      inputRef.current.style.height = 'inherit';
      const height = inputRef.current.scrollHeight;
      // if scroll-height is greater than 60 then keep height at 60 for some space between Input & Line
      if (height > 60) {
        inputRef.current.style.height = `60px`;
      } else {
        inputRef.current.style.height = `${height}px`;
      }
    }
  }, [_isMultiline, variant, inputRef, input]);

  // Due to browser issues, if type=number we use type=text and show numpad on mobile devices using inputMode=numeric
  const inputType = type === 'number' ? 'text' : type;

  /* Specifies the initial value for rows in textarea(_isMultiline)
   * Has no effect on text-input as rows is not passed if _isMultiline = false */
  const noOfRows = variant === 'outlined' ? 1 : 3;

  return (
    <Flex flexDirection="column" justifyContent="flex-end">
      <View ref={containerRef}>
        {labelPosition === 'top' && !hasAnimatedLabel ? (
          <Label.Regular
            position={labelPosition}
            disabled={disabled}
            //@ts-expect-error
            isFocused={isFocused}
            variant={variant}
            hasError={hasError}
            hasText={hasText}
            value={input}
            width={width}
            id={id}
          >
            {label}
          </Label.Regular>
        ) : null}

        {/* Text Input Container */}
        <Flex flexDirection="row" alignItems="flex-start">
          <View>
            {!hasAnimatedLabel && labelPosition === 'left' ? (
              <Label.Regular
                position={labelPosition}
                disabled={disabled}
                //@ts-expect-error
                isFocused={isFocused}
                variant={variant}
                hasError={hasError}
                hasText={hasText}
                value={input}
                width={width}
                id={id}
              >
                {label}
              </Label.Regular>
            ) : null}
            {/* Text Input */}
            <Flex flexDirection="column" flex={width === 'auto' ? 1 : 0}>
              <View>
                <InteractionContainer disabled={disabled} hasError={hasError}>
                  <Size
                    height={styles.fillContainer.height({
                      variant,
                      _isMultiline,
                    })}
                    maxHeight={8}
                  >
                    <Space
                      padding={styles.fillContainer.padding({
                        variant,
                      })}
                    >
                      <FillContainer variant={variant} isFocused={isFocused} disabled={disabled}>
                        {hasAnimatedLabel && !isEmpty(layoutDimensions) ? (
                          <Label.Animated
                            //@ts-expect-error
                            position={labelPosition}
                            disabled={disabled}
                            isFocused={isFocused}
                            variant={variant}
                            hasError={hasError}
                            value={input}
                            hasText={hasText}
                            layoutDimensions={layoutDimensions}
                            width={width}
                            id={id}
                          >
                            {label}
                          </Label.Animated>
                        ) : null}
                        <Flex flexDirection="row" alignItems="center">
                          <Size
                            width={styles.inputContainer.width({
                              width,
                            })}
                            maxHeight="100%"
                          >
                            <InputContainer>
                              {hasPrefix ? (
                                <AccessoryText
                                  //@ts-expect-error
                                  position="left"
                                  variant={variant}
                                  disabled={disabled}
                                  isFocused={isFocused}
                                >
                                  {prefix}
                                </AccessoryText>
                              ) : null}
                              {hasLeftIcon ? (
                                <AccessoryIcon
                                  variant={variant}
                                  icon={iconLeft}
                                  disabled={disabled}
                                  hasError={hasError}
                                  //@ts-expect-error
                                  isFocused={isFocused}
                                  position="left"
                                />
                              ) : null}
                              <Flex flex={1}>
                                <Space
                                  padding={styles.textInput.padding({
                                    variant,
                                  })}
                                >
                                  <Size maxHeight={8}>
                                    <StyledInput
                                      id={id}
                                      name={name}
                                      type={inputType}
                                      placeholder={placeholder}
                                      placeholderTextColor={placeholderTextColor}
                                      onFocus={onFocus}
                                      onBlur={onBlurText}
                                      onChange={onChangeText}
                                      onKeyPress={onKeyPress}
                                      onPaste={onPaste}
                                      hasText={hasText}
                                      readonly={disabled}
                                      disabled={disabled}
                                      variant={variant}
                                      hasPrefix={hasPrefix}
                                      hasLeftIcon={hasLeftIcon}
                                      maxLength={maxLength}
                                      value={input}
                                      ref={inputRef}
                                      as={_isMultiline ? 'textarea' : 'input'}
                                      rows={_isMultiline ? noOfRows : ''}
                                      inputMode={type === 'number' ? 'numeric' : null} // pass only for type=number, otherwise let browser infer via type
                                      {...automation(testID)}
                                    />
                                  </Size>
                                </Space>
                              </Flex>
                              {hasSuffix ? (
                                <AccessoryText
                                  //@ts-expect-error
                                  position="right"
                                  variant={variant}
                                  disabled={disabled}
                                  isFocused={isFocused}
                                >
                                  {suffix}
                                </AccessoryText>
                              ) : null}
                              {hasRightIcon ? (
                                <View
                                  onClick={onRightIconClick}
                                  {...automation(`${testID}-right-icon`)}
                                >
                                  <AccessoryIcon
                                    variant={variant}
                                    icon={iconRight}
                                    disabled={disabled}
                                    hasError={hasError}
                                    //@ts-expect-error
                                    isFocused={isFocused}
                                    position="right"
                                  />
                                </View>
                              ) : null}
                            </InputContainer>
                          </Size>
                        </Flex>
                      </FillContainer>
                    </Space>
                  </Size>
                  <Line isFocused={isFocused} hasError={hasError} disabled={disabled} />
                </InteractionContainer>
                {/* Bottom texts */}
                {hasError || helpText ? (
                  <Flex flexDirection="row" justifyContent="space-between">
                    <View>
                      <Text errorText={errorText} helpText={helpText} disabled={disabled} />
                      {maxLength ? (
                        <CharacterCount
                          disabled={disabled}
                          maxLength={maxLength}
                          currentLength={input.length || 0}
                        />
                      ) : null}
                    </View>
                  </Flex>
                ) : null}
              </View>
            </Flex>
          </View>
        </Flex>
      </View>
    </Flex>
  );
}
Example #17
Source File: Controls.js    From plataforma-sabia with MIT License 4 votes vote down vote up
Controls = ({
	data,
	sortOptions,
	handleSortBy,
	currentOrder,
	handlePagination,
	currentPage,
	totalPages,
	totalItems,
	itemsPerPage,
}) => {
	const [sortOption, setSortOption] = useState('');
	const isSelectFocusedRef = useRef(false);
	const { t } = useTranslation(['datagrid']);
	const {
		colors: { lightGray },
	} = useTheme();

	/**
	 * Formats page items count based on current page
	 *
	 * @returns {string} Formatted pagination data, e.g. `1-10 of 20`
	 */
	const getFirstAndLastItem = () => {
		if (currentPage === 1) {
			return {
				firstItem: 1,
				lastItem: data.length,
			};
		}

		if (currentPage === totalPages) {
			return {
				firstItem: totalItems - data.length + 1,
				lastItem: totalItems,
			};
		}

		return {
			firstItem: (currentPage - 1) * itemsPerPage + 1,
			lastItem: data.length + (currentPage - 1) * itemsPerPage,
		};
	};

	const getItemsCountByPage = () => {
		const { firstItem, lastItem } = getFirstAndLastItem();

		return `${firstItem} - ${lastItem} ${t('datagrid:paginationLabel')} ${totalItems}`;
	};

	const sortByI18 = t('datagrid:sortByOption');
	const customSelectStyles = useMemo(
		() => ({
			container: (base, state) => {
				isSelectFocusedRef.current = state.isFocused;
				return {
					...base,
					display: 'inline-block',
				};
			},
			placeholder: (base, state) => {
				return {
					...base,
					...(isSelectFocusedRef.current && state.value
						? {}
						: {
								position: 'static',
								top: 'auto',
								transform: 'none',
						  }),
				};
			},
			input: (base, state) => {
				return {
					...base,
					...(isSelectFocusedRef.current && state.value
						? {}
						: {
								position: 'absolute',
						  }),
				};
			},
			singleValue: (base, state) => {
				return {
					...base,
					maxWidth: 'none',
					...(isSelectFocusedRef.current && state.value
						? {}
						: {
								position: 'static',
								top: 'auto',
								transform: 'none',
						  }),
				};
			},
			valueContainer: (base) => ({
				...base,
				alignItems: 'center',
				display: 'flex',

				':before': {
					content: `"${sortByI18}"`,
					color: lightGray,
				},
			}),
		}),
		[sortByI18, lightGray],
	);

	return (
		<GridControls>
			{handleSortBy && (
				<div className="sort-by">
					<Select
						instanceId="bookmarks-ordering-select"
						options={sortOptions}
						styles={customSelectStyles}
						value={sortOption}
						placeholder={t('datagrid:sortByPlaceholder')}
						onChange={(option) => {
							setSortOption(option);
							handleSortBy(option.value);
						}}
						isSearchable={false}
					/>

					{sortOption && (
						<div className="sort-order">
							<button
								type="button"
								aria-label="Ascending Order"
								onClick={() => handleSortBy(sortOption.value, orderEnum.ASC)}
							>
								<AscOrderIcon
									className={
										currentOrder === orderEnum.ASC ? 'active' : undefined
									}
								/>
							</button>
							<button
								type="button"
								aria-label="Descending Order"
								onClick={() => handleSortBy(sortOption.value, orderEnum.DESC)}
							>
								<DescOrderIcon
									className={
										currentOrder === orderEnum.DESC ? 'active' : undefined
									}
								/>
							</button>
						</div>
					)}
				</div>
			)}

			{handlePagination && (
				<div className="pagination">
					<button
						type="button"
						onClick={() => handlePagination(1)}
						disabled={currentPage === 1}
						aria-label="First Page"
					>
						<DoubleArrowLeftIcon />
					</button>
					<button
						type="button"
						onClick={() => handlePagination(currentPage - 1)}
						disabled={currentPage === 1}
						aria-label="Previous Page"
					>
						<ArrowLeftIcon />
					</button>
					<span>{getItemsCountByPage()}</span>
					<button
						type="button"
						onClick={() => handlePagination(currentPage + 1)}
						disabled={currentPage === totalPages}
						aria-label="Next Page"
					>
						<ArrowRightIcon />
					</button>
					<button
						type="button"
						onClick={() => handlePagination(totalPages)}
						disabled={currentPage === totalPages}
						aria-label="Last Page"
					>
						<DoubleArrowRightIcon />
					</button>
				</div>
			)}
		</GridControls>
	);
}
Example #18
Source File: RadioOption.web.js    From blade with MIT License 4 votes vote down vote up
RadioOption = ({ value, disabled, title, helpText, errorText, testID, name, id }) => {
  const context = useRadioButtonContext();
  const theme = useTheme();

  const checked = isChecked({
    context,
    value,
  });
  const variantColor = context.variantColor;
  const size = context.size;
  const radioColor = styles.radio.color({
    theme,
    disabled,
    checked,
    variantColor,
  });

  const onClick = (event) => {
    /* prevent default behaviour of label firing click event on the associated input */
    event.preventDefault();
    if (isDefined(context.onChange) && !disabled) {
      context.onChange(value);
    }
  };

  const descriptionText = errorText || helpText;
  const shouldShowDescriptionText = (!isEmpty(helpText) || !isEmpty(errorText)) && size !== 'small';

  return (
    <Flex flexDirection="column" alignSelf="flex-start">
      <View>
        <Flex alignItems="center">
          <Label as="label" onClick={onClick} htmlFor={id} disabled={disabled}>
            <Input
              id={id}
              name={name}
              value={value}
              disabled={disabled}
              checked={checked}
              size={size}
              backdropStyles={styles.backdrop}
              variantColor={variantColor}
              {...automation(testID)}
            />
            <Flex flexDirection="column" justifyContent="center" alignItems="center">
              <Size
                width={
                  styles.backdrop.dimensions({
                    size,
                  }).width
                }
                height={
                  styles.backdrop.dimensions({
                    size,
                  }).height
                }
              >
                <Backdrop>
                  <Size
                    width={
                      styles.circle.dimensions({
                        size,
                      }).width
                    }
                    height={
                      styles.circle.dimensions({
                        size,
                      }).height
                    }
                  >
                    <Circle
                      borderWidth={
                        styles.circle.dimensions({
                          size,
                        }).borderWidth
                      }
                      color={radioColor}
                    >
                      {checked ? (
                        <Size
                          width={
                            styles.dot.dimensions({
                              size,
                            }).width
                          }
                          height={
                            styles.dot.dimensions({
                              size,
                            }).height
                          }
                        >
                          <Dot backgroundColor={radioColor} />
                        </Size>
                      ) : null}
                    </Circle>
                  </Size>
                </Backdrop>
              </Size>
            </Flex>
            <Space margin={styles.title.margin()}>
              <Text
                color={styles.title.color({
                  disabled,
                })}
                size={size}
              >
                {title}
              </Text>
            </Space>
          </Label>
        </Flex>

        {shouldShowDescriptionText ? (
          <Space
            margin={styles.descriptionText.margin({
              size,
            })}
          >
            <Text
              size={styles.descriptionText.textSize({
                size,
              })}
              color={styles.descriptionText.color({
                disabled,
                errorText,
              })}
            >
              {descriptionText}
            </Text>
          </Space>
        ) : null}
      </View>
    </Flex>
  );
}
Example #19
Source File: new.js    From plataforma-sabia with MIT License 4 votes vote down vote up
NewServicePage = ({ keywordTerms }) => {
	const form = useForm({
		defaultValues: {
			name: '',
			keywords: null,
			description: '',
			measure_unit: null,
			price: '',
			type: null,
			payment_message: '',
			thumbnail_id: null,
		},
	});
	const { colors } = useTheme();
	const [addedServices, setAddedServices] = useState([]);
	const [isSubmitting, setIsSubmitting] = useState(false);
	const [uploadError, setUploadError] = useState('');
	const [thumbnailPreview, setThumbnailPreview] = useState('');
	const router = useRouter();
	const { user } = useAuth();
	const { openModal } = useModal();

	const handleSubmit = async (values, _, isFinalize) => {
		setIsSubmitting(true);

		const preparedData = prepareFormData(values);
		const result = await createService(preparedData);

		if (result) {
			toast.success('Serviço criado com sucesso!');
			form.reset();
			setThumbnailPreview(null);
			setAddedServices((prevValue) => [...prevValue, result]);
		} else {
			return toast.error('Erro ao criar serviço, tente novamente em instantes');
		}

		if (isFinalize) {
			return router.push('/');
		}

		return setIsSubmitting(false);
	};

	const handleDeleteService = async (serviceId) => {
		setIsSubmitting(true);

		const result = await deleteService(serviceId);

		if (!result)
			toast.error(
				'Ocorreu um erro ao tentar deletar o serviço. Tente novamente em instantes',
			);
		else {
			toast.success('Serviço deletado com sucesso');
			setAddedServices((prevValue) => prevValue.filter((item) => item.id !== serviceId));
		}

		setIsSubmitting(false);
	};

	/*
	 * If user's adding the first service he can click in finalize button so it'll
	 * add the service and then redirect to home
	 * If user already added some services he can click in finalize button and then
	 * he'll be just redirected to home
	 * The advantage is that user can register only one service and get redirected to home
	 * in just one click
	 */
	const handleFinalizeRegistration = async () => {
		if (addedServices.length) {
			return router.push('/');
		}

		const isValidForm = await form.trigger();
		if (isValidForm) {
			await handleSubmit(form.getValues(), null, true);
		}

		return true;
	};

	const onCreateTerm = async (inputValue, taxonomy) => {
		const term = await createTerm(inputValue, taxonomy);
		return { label: term.term, value: `${term.id}` };
	};

	const onDropAttachment = async (acceptedFiles) => {
		if (!acceptedFiles) return null;

		const formData = new FormData();
		if (acceptedFiles.length !== 0) {
			formData.append(`files[0]`, acceptedFiles[0], acceptedFiles[0].name);
		}

		const response = await upload(formData);

		if (response.status === 200) {
			const { id, url } = response.data[0];
			setThumbnailPreview(url);
			form.setValue('thumbnail_id', id);
		} else {
			setUploadError(response.data.error.message[0].message);
		}

		return true;
	};

	return (
		<Wrapper>
			<Protected>
				<Container onSubmit={form.handleSubmit(handleSubmit)}>
					<Details>
						<Title align="left" color={colors.black}>
							Novo serviço
						</Title>

						<Fields>
							<Dropzone
								accept="image/*"
								onDrop={(acceptedFiles) => onDropAttachment(acceptedFiles)}
								multiple={false}
							>
								{({ getRootProps, getInputProps }) => (
									<UploadWrapper>
										{thumbnailPreview && (
											<ThumbnailWrapper>
												<Image
													src={thumbnailPreview}
													width={80}
													height={80}
													alt="Service thumbnail"
												/>
											</ThumbnailWrapper>
										)}
										<UploadThumbnail {...getRootProps()}>
											<UploadBody>
												<FiImage fontSize={24} />
												<div>
													<p>Selecione uma imagem de capa</p>
													<p>Limite de 5mb</p>
												</div>
											</UploadBody>
											<input name="logo" {...getInputProps()} />
										</UploadThumbnail>
										{uploadError && <UploadError>{uploadError}</UploadError>}
									</UploadWrapper>
								)}
							</Dropzone>
							<InputHiddenField form={form} name="thumbnail_id" />

							<Inputs>
								<InputField
									form={form}
									name="name"
									label="Nome do serviço"
									validation={{ required: true }}
									placeholder="Digite o nome"
									variant="gray"
								/>

								<SelectField
									form={form}
									name="keywords"
									instanceId="keywords-select"
									placeholder="Busque por palavras chaves (pode adicionar mais de um item)"
									label="Palavras-chave"
									validation={{ required: true }}
									options={mapArrayOfObjectToSelect(keywordTerms, 'term', 'id')}
									onCreate={(inputValue) => onCreateTerm(inputValue, 'KEYWORDS')}
									variant="gray"
									isMulti
									creatable
								/>

								<TextField
									form={form}
									name="description"
									validation={{ required: true }}
									label="Descrição"
									placeholder="Digite a descrição"
									variant="gray"
									resize="none"
								/>

								<SelectField
									form={form}
									name="measure_unit"
									instanceId="measure_unit-select"
									label="Unidade de Medida"
									placeholder="Escolha uma unidade"
									validation={{ required: true }}
									options={measureUnitOptions}
									variant="rounded"
								/>

								<CurrencyInputField
									form={form}
									name="price"
									validation={{ required: true }}
									label="Preço"
									placeholder="Digite o preço"
									variant="gray"
								/>

								<SelectField
									form={form}
									name="type"
									instanceId="type-select"
									label="Tipo"
									placeholder="Escolha um tipo"
									validation={{ required: true }}
									options={typeOptions}
									variant="rounded"
								/>
							</Inputs>

							<RectangularButton
								disabled={isSubmitting}
								variant="outlined"
								colorVariant="blue"
								type="submit"
								fullWidth
							>
								Adicionar novo serviço
							</RectangularButton>
							<RectangularButton
								variant="filled"
								colorVariant="orange"
								disabled={isSubmitting}
								onClick={handleFinalizeRegistration}
								fullWidth
							>
								Finalizar cadastro
							</RectangularButton>
						</Fields>

						<PaymentMessage>
							<div>
								<p>Responsável:</p>
								<p>{user.full_name}</p>

								<p>Instituição:</p>
								<p>{user.institution?.name}</p>
							</div>

							<Watcher
								form={form}
								property="payment_message"
								render={(paymentMessageHtml) => (
									<HtmlViewField
										label="Mensagem de pagamento"
										placeholder="Insira a mensagem de pagamento"
										html={paymentMessageHtml}
									/>
								)}
							/>

							<RectangularButton
								fullWidth
								variant="text"
								colorVariant="blue"
								onClick={() =>
									openModal(
										'ckEditor',
										{
											form,
											name: 'payment_message',
											config: {
												placeholder: 'Insira a mensagem de pagamento',
												removePlugins: [
													'ImageUpload',
													'Table',
													'MediaEmbed',
												],
											},
											onChange: (editorData) =>
												form.setValue('payment_message', editorData),
											renderWithController: false,
											defaultValue: form.getValues()?.payment_message,
										},
										{
											customModal: true,
											overlayClick: false,
										},
									)
								}
							>
								<FiEdit3 fontSize={14} />
								Editar mensagem
							</RectangularButton>
							<InputHiddenField form={form} name="payment_message" />
						</PaymentMessage>
					</Details>

					<Review>
						<Title align="left" color={colors.black}>
							Serviços
						</Title>

						{addedServices.map((service) => (
							<ServiceCard key={service.id}>
								<div>
									<ServiceThumbnailWrapper>
										<Image
											src={service.thumbnail?.url || '/card-image.jpg'}
											width={80}
											height={80}
										/>
									</ServiceThumbnailWrapper>

									<ServiceInfos>
										<p>{service.name}</p>
										<span>{service.description}</span>
										<p>{formatMoney(service.price)}</p>
									</ServiceInfos>
								</div>

								<RectangularButton
									variant="text"
									colorVariant="red"
									onClick={() => handleDeleteService(service.id)}
								>
									Remover
								</RectangularButton>
							</ServiceCard>
						))}
					</Review>
				</Container>
			</Protected>
		</Wrapper>
	);
}
Example #20
Source File: Button.web.js    From blade with MIT License 4 votes vote down vote up
Button = ({
  onClick,
  children,
  variant,
  size,
  disabled,
  variantColor,
  icon: Icon,
  iconAlign,
  align,
  block,
  type,
  testID,
  id,
  name,
}) => {
  const theme = useTheme();

  /* children can only be string or undefined (icon only button) */
  if (typeof children !== 'string' && typeof children !== 'undefined') {
    throw new Error(
      `Error in Button: expected \`children\` of type \`string\` but found ${typeof children}.`,
    );
  }

  /* Button remains focused on Chrome after click until focused on any other element.
   * This causes the focus styles to be present on the button.
   * Manually call blur on the button when user click and releases the mouse button. */
  const onMouseUp = ({ currentTarget }) => {
    currentTarget.blur();
  };

  return (
    <Flex
      flex={block ? 1 : 0}
      flexDirection="row"
      alignItems="center"
      alignSelf={styles.align({
        align,
      })}
      justifyContent="center"
    >
      <Size
        height={styles.height({
          size,
          theme,
        })}
      >
        <Space
          padding={styles.padding({
            size,
            children,
            theme,
          })}
        >
          <StyledButton
            variantColor={variantColor}
            onClick={onClick}
            onMouseUp={onMouseUp}
            disabled={disabled}
            size={size}
            block={block}
            variant={variant}
            type={type}
            id={id}
            name={name}
            {...automation(testID)}
          >
            <React.Fragment>
              {isValidElement(Icon) && iconAlign === 'left' ? (
                <Space
                  margin={styles.spaceBetween({
                    size,
                    iconAlign,
                    children,
                  })}
                >
                  <Icon
                    size={styles.iconSize({
                      size,
                      children,
                    })}
                    fill={styles.fontColor({
                      variant,
                      variantColor,
                      disabled,
                    })}
                    testID="button-left-icon"
                  />
                </Space>
              ) : null}
              {children ? (
                <Text
                  color={styles.fontColor({
                    variant,
                    variantColor,
                    disabled,
                  })}
                  size={styles.fontSize({
                    size,
                  })}
                  align="center"
                  weight="bold"
                  _letterSpacing={styles.letterSpacing({
                    size,
                  })}
                  _lineHeight={styles.lineHeight({
                    size,
                  })}
                >
                  {size === 'xsmall' ? children.toUpperCase() : children}
                </Text>
              ) : null}
              {isValidElement(Icon) && iconAlign === 'right' ? (
                <Space
                  margin={styles.spaceBetween({
                    size,
                    iconAlign,
                    children,
                  })}
                >
                  <Icon
                    size={styles.iconSize({
                      size,
                      children,
                    })}
                    fill={styles.fontColor({
                      variant,
                      variantColor,
                      disabled,
                    })}
                    testID="button-right-icon"
                  />
                </Space>
              ) : null}
            </React.Fragment>
          </StyledButton>
        </Space>
      </Size>
    </Flex>
  );
}