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:
parent
5e9c111e0f
commit
a9a220273f
67 changed files with 238 additions and 220 deletions
|
@ -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>
|
||||
);
|
|
@ -1,6 +0,0 @@
|
|||
@import 'src/styles/variables';
|
||||
|
||||
.icon {
|
||||
fill: $color_danger;
|
||||
stroke: none;
|
||||
}
|
|
@ -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';
|
||||
|
|
|
@ -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 };
|
|
@ -1,8 +0,0 @@
|
|||
@keyframes bounce {
|
||||
0% { transform: translate(0, -5%); }
|
||||
100% { transform: translate(0, 5%); }
|
||||
}
|
||||
|
||||
.arrow {
|
||||
animation: bounce alternate infinite 0.25s;
|
||||
}
|
|
@ -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>
|
||||
);
|
|
@ -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>
|
||||
);
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
)}
|
||||
|
|
|
@ -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>
|
||||
);
|
|
@ -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;
|
||||
}
|
|
@ -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 };
|
|
@ -1,6 +0,0 @@
|
|||
@import "src/styles/variables";
|
||||
|
||||
.icon {
|
||||
fill: currentColor;
|
||||
stroke: none;
|
||||
}
|
|
@ -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 };
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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'> {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue