misc_pterodactyl-panel/resources/scripts/components/elements/Spinner.tsx

72 lines
2 KiB
TypeScript
Raw Normal View History

2022-11-25 20:25:03 +00:00
import type { FC, ReactNode } from 'react';
import { Suspense } from 'react';
import styled, { css, keyframes } from 'styled-components';
2020-07-04 19:39:55 +00:00
import tw from 'twin.macro';
2022-11-25 20:25:03 +00:00
import ErrorBoundary from '@/components/elements/ErrorBoundary';
2020-07-04 19:39:55 +00:00
export type SpinnerSize = 'small' | 'base' | 'large';
2019-12-22 22:53:27 +00:00
interface Props {
2022-11-25 20:25:03 +00:00
children?: ReactNode;
2019-12-22 22:53:27 +00:00
size?: SpinnerSize;
centered?: boolean;
2020-07-04 19:39:55 +00:00
isBlue?: boolean;
2019-12-22 22:53:27 +00:00
}
2022-11-25 20:25:03 +00:00
interface Spinner extends FC<Props> {
Size: Record<'SMALL' | 'BASE' | 'LARGE', SpinnerSize>;
2022-11-25 20:25:03 +00:00
Suspense: FC<Props>;
}
2020-07-04 19:39:55 +00:00
const spin = keyframes`
to { transform: rotate(360deg); }
`;
// noinspection CssOverwrittenProperties
const SpinnerComponent = styled.div<Props>`
${tw`w-8 h-8`};
border-width: 3px;
border-radius: 50%;
animation: ${spin} 1s cubic-bezier(0.55, 0.25, 0.25, 0.7) infinite;
2022-11-25 20:25:03 +00:00
${props =>
props.size === 'small'
? tw`w-4 h-4 border-2`
: props.size === 'large'
? css`
${tw`w-16 h-16`};
border-width: 6px;
`
: null};
2022-11-25 20:25:03 +00:00
border-color: ${props => (!props.isBlue ? 'rgba(255, 255, 255, 0.2)' : 'hsla(212, 92%, 43%, 0.2)')};
border-top-color: ${props => (!props.isBlue ? 'rgb(255, 255, 255)' : 'hsl(212, 92%, 43%)')};
2020-07-04 19:39:55 +00:00
`;
const Spinner: Spinner = ({ centered, ...props }) =>
centered ? (
<div css={[tw`flex justify-center items-center`, props.size === 'large' ? tw`m-20` : tw`m-6`]}>
<SpinnerComponent {...props} />
</div>
) : (
<SpinnerComponent {...props} />
);
Spinner.displayName = 'Spinner';
2020-02-08 23:23:08 +00:00
Spinner.Size = {
SMALL: 'small',
BASE: 'base',
LARGE: 'large',
};
Spinner.Suspense = ({ children, centered = true, size = Spinner.Size.LARGE, ...props }) => (
<Suspense fallback={<Spinner centered={centered} size={size} {...props} />}>
<ErrorBoundary>{children}</ErrorBoundary>
</Suspense>
);
Spinner.Suspense.displayName = 'Spinner.Suspense';
2020-02-08 23:23:08 +00:00
export default Spinner;