520
common/resources/client/ui/progress/animation.css
vendored
Executable file
520
common/resources/client/ui/progress/animation.css
vendored
Executable file
@@ -0,0 +1,520 @@
|
||||
.progress-circle-fills-animate {
|
||||
will-change: transform;
|
||||
transform: translateZ(0);
|
||||
animation: progress-circle-fills-rotate 1s infinite cubic-bezier(.25,.78,.48,.89);
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.progress-circle-fill-submask-1-animate {
|
||||
will-change: transform;
|
||||
transform: translateZ(0);
|
||||
animation: progress-circle-fill-mask-1 1s infinite linear;
|
||||
}
|
||||
|
||||
.progress-circle-fill-submask-2-animate {
|
||||
will-change: transform;
|
||||
transform: translateZ(0);
|
||||
animation: progress-circle-fill-mask-2 1s infinite linear;
|
||||
}
|
||||
|
||||
@keyframes progress-circle-fill-mask-1 {
|
||||
0% {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
1.69% {
|
||||
transform: rotate(72.3deg);
|
||||
}
|
||||
|
||||
3.39% {
|
||||
transform: rotate(55.5deg);
|
||||
}
|
||||
|
||||
5.08% {
|
||||
transform: rotate(40.3deg);
|
||||
}
|
||||
|
||||
6.78% {
|
||||
transform: rotate(25deg);
|
||||
}
|
||||
|
||||
8.47% {
|
||||
transform: rotate(10.6deg);
|
||||
}
|
||||
|
||||
10.17% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
11.86% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
13.56% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
15.25% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
16.95% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
18.64% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
20.34% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
22.03% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
23.73% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
25.42% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
27.12% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
28.81% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
30.51% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
32.2% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
33.9% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
35.59% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
37.29% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
38.98% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
40.68% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
42.37% {
|
||||
transform: rotate(5.3deg);
|
||||
}
|
||||
|
||||
44.07% {
|
||||
transform: rotate(13.4deg);
|
||||
}
|
||||
|
||||
45.76% {
|
||||
transform: rotate(20.6deg);
|
||||
}
|
||||
|
||||
47.46% {
|
||||
transform: rotate(29deg);
|
||||
}
|
||||
|
||||
49.15% {
|
||||
transform: rotate(36.5deg);
|
||||
}
|
||||
|
||||
50.85% {
|
||||
transform: rotate(42.6deg);
|
||||
}
|
||||
|
||||
52.54% {
|
||||
transform: rotate(48.8deg);
|
||||
}
|
||||
|
||||
54.24% {
|
||||
transform: rotate(54.2deg);
|
||||
}
|
||||
|
||||
55.93% {
|
||||
transform: rotate(59.4deg);
|
||||
}
|
||||
|
||||
57.63% {
|
||||
transform: rotate(63.2deg);
|
||||
}
|
||||
|
||||
59.32% {
|
||||
transform: rotate(67.2deg);
|
||||
}
|
||||
|
||||
61.02% {
|
||||
transform: rotate(70.8deg);
|
||||
}
|
||||
|
||||
62.71% {
|
||||
transform: rotate(73.8deg);
|
||||
}
|
||||
|
||||
64.41% {
|
||||
transform: rotate(76.2deg);
|
||||
}
|
||||
|
||||
66.1% {
|
||||
transform: rotate(78.7deg);
|
||||
}
|
||||
|
||||
67.8% {
|
||||
transform: rotate(80.6deg);
|
||||
}
|
||||
|
||||
69.49% {
|
||||
transform: rotate(82.6deg);
|
||||
}
|
||||
|
||||
71.19% {
|
||||
transform: rotate(83.7deg);
|
||||
}
|
||||
|
||||
72.88% {
|
||||
transform: rotate(85deg);
|
||||
}
|
||||
|
||||
74.58% {
|
||||
transform: rotate(86.3deg);
|
||||
}
|
||||
|
||||
76.27% {
|
||||
transform: rotate(87deg);
|
||||
}
|
||||
|
||||
77.97% {
|
||||
transform: rotate(87.7deg);
|
||||
}
|
||||
|
||||
79.66% {
|
||||
transform: rotate(88.3deg);
|
||||
}
|
||||
|
||||
81.36% {
|
||||
transform: rotate(88.6deg);
|
||||
}
|
||||
|
||||
83.05% {
|
||||
transform: rotate(89.2deg);
|
||||
}
|
||||
|
||||
84.75% {
|
||||
transform: rotate(89.2deg);
|
||||
}
|
||||
|
||||
86.44% {
|
||||
transform: rotate(89.5deg);
|
||||
}
|
||||
|
||||
88.14% {
|
||||
transform: rotate(89.9deg);
|
||||
}
|
||||
|
||||
89.83% {
|
||||
transform: rotate(89.7deg);
|
||||
}
|
||||
|
||||
91.53% {
|
||||
transform: rotate(90.1deg);
|
||||
}
|
||||
|
||||
93.22% {
|
||||
transform: rotate(90.2deg);
|
||||
}
|
||||
|
||||
94.92% {
|
||||
transform: rotate(90.1deg);
|
||||
}
|
||||
|
||||
96.61% {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
98.31% {
|
||||
transform: rotate(89.8deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
@keyframes progress-circle-fill-mask-2 {
|
||||
0% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
1.69% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
3.39% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
5.08% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
6.78% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
8.47% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
10.17% {
|
||||
transform: rotate(179.2deg);
|
||||
}
|
||||
|
||||
11.86% {
|
||||
transform: rotate(164deg);
|
||||
}
|
||||
|
||||
13.56% {
|
||||
transform: rotate(151.8deg);
|
||||
}
|
||||
|
||||
15.25% {
|
||||
transform: rotate(140.8deg);
|
||||
}
|
||||
|
||||
16.95% {
|
||||
transform: rotate(130.3deg);
|
||||
}
|
||||
|
||||
18.64% {
|
||||
transform: rotate(120.4deg);
|
||||
}
|
||||
|
||||
20.34% {
|
||||
transform: rotate(110.8deg);
|
||||
}
|
||||
|
||||
22.03% {
|
||||
transform: rotate(101.6deg);
|
||||
}
|
||||
|
||||
23.73% {
|
||||
transform: rotate(93.5deg);
|
||||
}
|
||||
|
||||
25.42% {
|
||||
transform: rotate(85.4deg);
|
||||
}
|
||||
|
||||
27.12% {
|
||||
transform: rotate(78.1deg);
|
||||
}
|
||||
|
||||
28.81% {
|
||||
transform: rotate(71.2deg);
|
||||
}
|
||||
|
||||
30.51% {
|
||||
transform: rotate(89.1deg);
|
||||
}
|
||||
|
||||
32.2% {
|
||||
transform: rotate(105.5deg);
|
||||
}
|
||||
|
||||
33.9% {
|
||||
transform: rotate(121.3deg);
|
||||
}
|
||||
|
||||
35.59% {
|
||||
transform: rotate(135.5deg);
|
||||
}
|
||||
|
||||
37.29% {
|
||||
transform: rotate(148.4deg);
|
||||
}
|
||||
|
||||
38.98% {
|
||||
transform: rotate(161deg);
|
||||
}
|
||||
|
||||
40.68% {
|
||||
transform: rotate(173.5deg);
|
||||
}
|
||||
|
||||
42.37% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
44.07% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
45.76% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
47.46% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
49.15% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
50.85% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
52.54% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
54.24% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
55.93% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
57.63% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
59.32% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
61.02% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
62.71% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
64.41% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
66.1% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
67.8% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
69.49% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
71.19% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
72.88% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
74.58% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
76.27% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
77.97% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
79.66% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
81.36% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
83.05% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
84.75% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
86.44% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
88.14% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
89.83% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
91.53% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
93.22% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
94.92% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
96.61% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
98.31% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes progress-circle-fills-rotate {
|
||||
0% {transform: rotate(-90deg)}
|
||||
100% {transform: rotate(270deg)}
|
||||
}
|
||||
|
||||
|
||||
.progress-bar-indeterminate-animate {
|
||||
animation: progress-bar-indeterminate 1s infinite;
|
||||
}
|
||||
|
||||
@keyframes progress-bar-indeterminate {
|
||||
from {
|
||||
transform: translate(calc(100% * -1));
|
||||
}
|
||||
to {
|
||||
transform: translate(100%);
|
||||
}
|
||||
}
|
||||
21
common/resources/client/ui/progress/full-page-loader.tsx
Executable file
21
common/resources/client/ui/progress/full-page-loader.tsx
Executable file
@@ -0,0 +1,21 @@
|
||||
import {ProgressCircle} from './progress-circle';
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
|
||||
interface FullPageLoaderProps {
|
||||
className?: string;
|
||||
screen?: boolean;
|
||||
}
|
||||
export function FullPageLoader({className, screen}: FullPageLoaderProps) {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'flex items-center justify-center flex-auto',
|
||||
screen ? 'h-screen w-screen' : 'h-full w-full',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<ProgressCircle isIndeterminate aria-label="Loading page..." />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
6
common/resources/client/ui/progress/meter.tsx
Executable file
6
common/resources/client/ui/progress/meter.tsx
Executable file
@@ -0,0 +1,6 @@
|
||||
import React from 'react';
|
||||
import {ProgressBarBase, ProgressBarBaseProps} from './progress-bar-base';
|
||||
|
||||
export function Meter(props: ProgressBarBaseProps) {
|
||||
return <ProgressBarBase {...props} role="meter progressbar" />;
|
||||
}
|
||||
110
common/resources/client/ui/progress/progress-bar-base.tsx
Executable file
110
common/resources/client/ui/progress/progress-bar-base.tsx
Executable file
@@ -0,0 +1,110 @@
|
||||
import React, {CSSProperties, ReactNode, useId} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import {InputSize} from '../forms/input-field/input-size';
|
||||
import {getInputFieldClassNames} from '../forms/input-field/get-input-field-class-names';
|
||||
import {useNumberFormatter} from '../../i18n/use-number-formatter';
|
||||
import {clamp} from '../../utils/number/clamp';
|
||||
|
||||
export interface ProgressBarBaseProps {
|
||||
value?: number;
|
||||
minValue?: number;
|
||||
maxValue?: number;
|
||||
className?: string;
|
||||
showValueLabel?: boolean;
|
||||
size?: 'xs' | 'sm' | 'md';
|
||||
labelPosition?: 'top' | 'bottom';
|
||||
isIndeterminate?: boolean;
|
||||
label?: ReactNode;
|
||||
formatOptions?: Intl.NumberFormatOptions;
|
||||
role?: string;
|
||||
radius?: string;
|
||||
trackColor?: string;
|
||||
trackHeight?: string;
|
||||
progressColor?: string;
|
||||
}
|
||||
|
||||
export function ProgressBarBase(props: ProgressBarBaseProps) {
|
||||
let {
|
||||
value = 0,
|
||||
minValue = 0,
|
||||
maxValue = 100,
|
||||
size = 'md',
|
||||
label,
|
||||
showValueLabel = !!label,
|
||||
isIndeterminate = false,
|
||||
labelPosition = 'top',
|
||||
className,
|
||||
role,
|
||||
formatOptions = {
|
||||
style: 'percent',
|
||||
},
|
||||
radius = 'rounded',
|
||||
trackColor = 'bg-primary-light',
|
||||
progressColor = 'bg-primary',
|
||||
trackHeight = getSize(size),
|
||||
} = props;
|
||||
|
||||
const id = useId();
|
||||
|
||||
value = clamp(value, minValue, maxValue);
|
||||
|
||||
const percentage = (value - minValue) / (maxValue - minValue);
|
||||
const formatter = useNumberFormatter(formatOptions);
|
||||
|
||||
let valueLabel = '';
|
||||
if (!isIndeterminate && showValueLabel) {
|
||||
const valueToFormat =
|
||||
formatOptions.style === 'percent' ? percentage : value;
|
||||
valueLabel = formatter.format(valueToFormat);
|
||||
}
|
||||
|
||||
const barStyle: CSSProperties = {};
|
||||
if (!isIndeterminate) {
|
||||
barStyle.width = `${Math.round(percentage * 100)}%`;
|
||||
}
|
||||
|
||||
const style = getInputFieldClassNames({size});
|
||||
|
||||
const labelEl = (label || valueLabel) && (
|
||||
<div className={clsx('flex gap-10 justify-between my-4', style.label)}>
|
||||
{label && <span id={id}>{label}</span>}
|
||||
{valueLabel && <div>{valueLabel}</div>}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
aria-valuenow={isIndeterminate ? undefined : value}
|
||||
aria-valuemin={minValue}
|
||||
aria-valuemax={maxValue}
|
||||
aria-valuetext={isIndeterminate ? undefined : (valueLabel as string)}
|
||||
aria-labelledby={label ? id : undefined}
|
||||
role={role || 'progressbar'}
|
||||
className={clsx(className, 'min-w-42')}
|
||||
>
|
||||
{labelPosition === 'top' && labelEl}
|
||||
<div className={`${trackHeight} ${radius} ${trackColor} overflow-hidden`}>
|
||||
<div
|
||||
className={clsx(
|
||||
progressColor,
|
||||
'fill h-full transition-width duration-200 rounded-l',
|
||||
isIndeterminate && 'progress-bar-indeterminate-animate'
|
||||
)}
|
||||
style={barStyle}
|
||||
/>
|
||||
</div>
|
||||
{labelPosition === 'bottom' && labelEl}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getSize(size: InputSize) {
|
||||
switch (size) {
|
||||
case 'sm':
|
||||
return 'h-6';
|
||||
case 'xs':
|
||||
return 'h-4';
|
||||
default:
|
||||
return 'h-8';
|
||||
}
|
||||
}
|
||||
10
common/resources/client/ui/progress/progress-bar.tsx
Executable file
10
common/resources/client/ui/progress/progress-bar.tsx
Executable file
@@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import {ProgressBarBase, ProgressBarBaseProps} from './progress-bar-base';
|
||||
|
||||
interface Props extends ProgressBarBaseProps {
|
||||
isIndeterminate?: boolean;
|
||||
}
|
||||
|
||||
export function ProgressBar(props: Props) {
|
||||
return <ProgressBarBase {...props} />;
|
||||
}
|
||||
159
common/resources/client/ui/progress/progress-circle.tsx
Executable file
159
common/resources/client/ui/progress/progress-circle.tsx
Executable file
@@ -0,0 +1,159 @@
|
||||
import React, {ComponentPropsWithoutRef, CSSProperties} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import {clamp} from '../../utils/number/clamp';
|
||||
import {useNumberFormatter} from '../../i18n/use-number-formatter';
|
||||
|
||||
export interface ProgressCircleProps extends ComponentPropsWithoutRef<'div'> {
|
||||
value?: number;
|
||||
minValue?: number;
|
||||
maxValue?: number;
|
||||
size?: 'xs' | 'sm' | 'md' | 'lg' | string;
|
||||
isIndeterminate?: boolean;
|
||||
className?: string;
|
||||
position?: string;
|
||||
trackColor?: string;
|
||||
fillColor?: string;
|
||||
}
|
||||
export const ProgressCircle = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
ProgressCircleProps
|
||||
>((props, ref) => {
|
||||
let {
|
||||
value = 0,
|
||||
minValue = 0,
|
||||
maxValue = 100,
|
||||
size = 'md',
|
||||
isIndeterminate = false,
|
||||
className,
|
||||
position = 'relative',
|
||||
trackColor,
|
||||
fillColor = 'border-primary',
|
||||
...domProps
|
||||
} = props;
|
||||
|
||||
value = clamp(value, minValue, maxValue);
|
||||
const circleSize = getCircleStyle(size);
|
||||
|
||||
const percentage = (value - minValue) / (maxValue - minValue);
|
||||
const formatter = useNumberFormatter({style: 'percent'});
|
||||
|
||||
let valueLabel = '';
|
||||
if (!isIndeterminate && !valueLabel) {
|
||||
valueLabel = formatter.format(percentage);
|
||||
}
|
||||
|
||||
const subMask1Style: CSSProperties = {};
|
||||
const subMask2Style: CSSProperties = {};
|
||||
if (!isIndeterminate) {
|
||||
const percentage = ((value - minValue) / (maxValue - minValue)) * 100;
|
||||
let angle;
|
||||
if (percentage > 0 && percentage <= 50) {
|
||||
angle = -180 + (percentage / 50) * 180;
|
||||
subMask1Style.transform = `rotate(${angle}deg)`;
|
||||
subMask2Style.transform = 'rotate(-180deg)';
|
||||
} else if (percentage > 50) {
|
||||
angle = -180 + ((percentage - 50) / 50) * 180;
|
||||
subMask1Style.transform = 'rotate(0deg)';
|
||||
subMask2Style.transform = `rotate(${angle}deg)`;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
{...domProps}
|
||||
aria-valuenow={isIndeterminate ? undefined : value}
|
||||
aria-valuemin={minValue}
|
||||
aria-valuemax={maxValue}
|
||||
aria-valuetext={isIndeterminate ? undefined : valueLabel}
|
||||
role="progressbar"
|
||||
ref={ref}
|
||||
className={clsx(
|
||||
'progress-circle',
|
||||
position,
|
||||
circleSize,
|
||||
isIndeterminate && 'indeterminate',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div className={clsx(circleSize, trackColor, 'rounded-full border-4')} />
|
||||
<div
|
||||
className={clsx(
|
||||
'fills absolute left-0 top-0 h-full w-full',
|
||||
isIndeterminate && 'progress-circle-fills-animate'
|
||||
)}
|
||||
>
|
||||
<FillMask
|
||||
circleSize={circleSize}
|
||||
subMaskStyle={subMask1Style}
|
||||
isIndeterminate={isIndeterminate}
|
||||
className="rotate-180"
|
||||
fillColor={fillColor}
|
||||
subMaskClassName={clsx(
|
||||
isIndeterminate && 'progress-circle-fill-submask-1-animate'
|
||||
)}
|
||||
/>
|
||||
<FillMask
|
||||
circleSize={circleSize}
|
||||
subMaskStyle={subMask2Style}
|
||||
isIndeterminate={isIndeterminate}
|
||||
fillColor={fillColor}
|
||||
subMaskClassName={clsx(
|
||||
isIndeterminate && 'progress-circle-fill-submask-2-animate'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
interface FillMaskProps {
|
||||
className?: string;
|
||||
circleSize?: string;
|
||||
subMaskStyle: CSSProperties;
|
||||
subMaskClassName: string;
|
||||
isIndeterminate?: boolean;
|
||||
fillColor?: string;
|
||||
}
|
||||
function FillMask({
|
||||
subMaskStyle,
|
||||
subMaskClassName,
|
||||
className,
|
||||
circleSize,
|
||||
isIndeterminate,
|
||||
fillColor,
|
||||
}: FillMaskProps) {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'absolute h-full w-1/2 origin-[100%] overflow-hidden',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
'h-full w-full origin-[100%] rotate-180 overflow-hidden',
|
||||
!isIndeterminate && 'transition-transform duration-100',
|
||||
subMaskClassName
|
||||
)}
|
||||
style={subMaskStyle}
|
||||
>
|
||||
<div className={clsx(circleSize, fillColor, 'rounded-full border-4')} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getCircleStyle(size: ProgressCircleProps['size']) {
|
||||
switch (size) {
|
||||
case 'xs':
|
||||
return 'w-20 h-20';
|
||||
case 'sm':
|
||||
return 'w-24 h-24';
|
||||
case 'md':
|
||||
return 'w-32 h-32';
|
||||
case 'lg':
|
||||
return 'w-42 h-42';
|
||||
default:
|
||||
return size;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user