1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 04:46:40 +07:00

refactored some common components

This commit is contained in:
Fedor Katurov 2023-11-20 22:29:13 +06:00
parent 5e9c111e0f
commit a9a220273f
67 changed files with 238 additions and 220 deletions

View file

@ -1,16 +0,0 @@
import React, { FC } from 'react';
import { describeArc } from '~/utils/dom';
import styles from './styles.module.scss';
interface IProps {
size: number;
progress?: number;
}
export const ArcProgress: FC<IProps> = ({ size, progress = 0 }) => (
<svg className={styles.icon} width={size} height={size}>
<path d={describeArc(size / 2, size / 2, size / 2 - 2, 360 * (1 - progress), 360)} />
</svg>
);

View file

@ -1,6 +0,0 @@
@import 'src/styles/variables';
.icon {
fill: $color_danger;
stroke: none;
}

View file

@ -9,8 +9,8 @@ import React, {
import Tippy from '@tippyjs/react';
import classnames from 'classnames';
import { Icon } from '~/components/input/Icon';
import { LoaderCircle } from '~/components/input/LoaderCircle';
import { Icon } from '~/components/common/Icon';
import { LoaderCircle } from '~/components/common/LoaderCircle';
import { IIcon } from '~/types';
import styles from './styles.module.scss';

View file

@ -1,20 +0,0 @@
import React, { FC } from 'react';
import { SVGProps } from '~/utils/types';
import styles from './styles.module.scss';
interface Props extends SVGProps {}
const DropHereIcon: FC<Props> = ({ ...rest }) => (
<svg viewBox="0 0 24 24" stroke="none" {...rest}>
<path d="M18,15v3H6v-3H4v3c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-3H18z" />
<path
d="M17,11l-1.41-1.41L13,12.17V4h-2v8.17L8.41,9.59L7,11l5,5 L17,11z"
className={styles.arrow}
/>
</svg>
);
export { DropHereIcon };

View file

@ -1,8 +0,0 @@
@keyframes bounce {
0% { transform: translate(0, -5%); }
100% { transform: translate(0, 5%); }
}
.arrow {
animation: bounce alternate infinite 0.25s;
}

View file

@ -1,23 +0,0 @@
import React, { FC } from 'react';
import { IIcon } from '~/types';
type IProps = React.SVGAttributes<SVGElement> & {
size?: number;
icon: IIcon;
};
export const Icon: FC<IProps> = ({
size = 20, icon, style, ...props
}) => (
<svg
width={size}
height={size}
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid slice"
style={{ ...style, outline: 'none' }}
{...props}
>
<use xlinkHref={`#${icon}`} />
</svg>
);

View file

@ -1,22 +0,0 @@
import * as React from 'react';
import classNames from 'classnames';
const style = require('./style.scss');
interface IInfoProps {
text?: string;
children?: string;
level?: string;
}
export const Info: React.FunctionComponent<IInfoProps> = ({
text,
children,
level = 'normal',
}) => (
<div className={classNames(style.container, { [level]: true })}>
{
text || children || ''
}
</div>
);

View file

@ -1,28 +0,0 @@
@import 'src/styles/variables';
.container {
min-height: $info_height;
border-radius: $radius;
display: flex;
align-items: center;
justify-content: center;
font: $font_14_regular;
line-height: 1.2em;
padding: $gap;
background: $gray_90;
&:global(.danger) {
color: white;
background: $content_bg_danger;
}
&:global(.warning) {
color: white;
background: $content_bg_danger;
}
&:global(.primary) {
color: white;
background: $content_bg_danger;
}
}

View file

@ -10,7 +10,7 @@ import React, {
import classNames from 'classnames';
import { Icon } from '~/components/input/Icon';
import { Icon } from '~/components/common/Icon';
import { InputWrapper } from '~/components/input/InputWrapper';
import { useTranslatedError } from '~/hooks/data/useTranslatedError';
import { useFocusEvent } from '~/hooks/dom/useFocusEvent';
@ -50,17 +50,25 @@ const InputText: FC<InputTextProps> = ({
handler(target.value);
},
[handler]
[handler],
);
const toggleRevealed = useCallback(() => setRevealed(!revealed), [setRevealed, revealed]);
const toggleRevealed = useCallback(
() => setRevealed(!revealed),
[setRevealed, revealed],
);
const translatedError = useTranslatedError(error);
const type = props.type === 'password' && revealed ? 'text' : props.type;
return (
<InputWrapper title={title} error={translatedError} focused={focused} notEmpty={!!value}>
<InputWrapper
title={title}
error={translatedError}
focused={focused}
notEmpty={!!value}
>
<div
className={classNames(styles.input, {
[styles.has_error]: !!error,
@ -83,7 +91,11 @@ const InputText: FC<InputTextProps> = ({
<div className={styles.suffix}>
{suffix}
{props.type === 'password' && (
<Icon icon="eye" onClick={toggleRevealed} className={styles.reveal} />
<Icon
icon="eye"
onClick={toggleRevealed}
className={styles.reveal}
/>
)}
</div>
)}

View file

@ -1,19 +0,0 @@
import React, { FC } from 'react';
import classNames from 'classnames';
import { LoaderCircleInner } from '~/components/input/LoaderCircleInner';
import { SVGProps } from '~/utils/types';
import styles from './styles.module.scss';
interface IProps extends SVGProps {
size?: number;
className?: string;
}
export const LoaderCircle: FC<IProps> = ({ size = 24, className }) => (
<div className={classNames(styles.wrap, 'loader-circle', className)}>
<LoaderCircleInner size={size} />
</div>
);

View file

@ -1,29 +0,0 @@
@import "src/styles/variables";
@keyframes spin {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
@keyframes fade {
0% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0.1;
transform: scale(4);
}
}
.wrap {
animation: spin infinite 0.75s linear;
display: inline-flex;
transform-origin: 50% 50%;
align-items: center;
justify-content: center;
}

View file

@ -1,21 +0,0 @@
import React, { FC, SVGAttributes } from 'react';
import classNames from 'classnames';
import { describeArc } from '~/utils/dom';
import styles from './styles.module.scss';
interface IProps extends SVGAttributes<SVGElement> {
size: number;
className?: string;
}
const LoaderCircleInner: FC<IProps> = ({ size, className, ...props }) => (
<svg className={classNames(styles.icon, className)} width={size} height={size} {...props}>
<path d={describeArc(size / 2, size / 2, size / 2, 0, 90)} />
<path d={describeArc(size / 2, size / 2, size / 2, 180, 270)} />
</svg>
);
export { LoaderCircleInner };

View file

@ -1,6 +0,0 @@
@import "src/styles/variables";
.icon {
fill: currentColor;
stroke: none;
}

View file

@ -1,25 +0,0 @@
import React, { FC } from 'react';
import classNames from 'classnames';
import { LoaderCircle } from '../LoaderCircle';
import styles from './styles.module.scss';
interface LoaderScreenProps {
className?: string;
align?: 'top' | 'middle';
}
const LoaderScreen: FC<LoaderScreenProps> = ({
className,
align = 'middle',
}) => (
<div
className={classNames(styles.screen, styles[`align-${align}`], className)}
>
<LoaderCircle size={32} />
</div>
);
export { LoaderScreen };

View file

@ -1,14 +0,0 @@
@import 'src/styles/variables';
.screen {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: $gap;
&.align-top {
align-items: flex-start;
}
}

View file

@ -1,6 +1,6 @@
import React, { VFC } from 'react';
import { Icon } from '~/components/input/Icon';
import { Icon } from '~/components/common/Icon';
import { InputText, InputTextProps } from '~/components/input/InputText';
interface SearchInputProps extends Omit<InputTextProps, 'prefix' | 'suffix'> {}