mirror of
https://github.com/storytold/placeholder-artcraft.git
synced 2026-10-21 07:55:00 +00:00
mirror repo (WIP)
Need to remove secrets before entire repo can be made public.
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
export * from "./lib/progress";
|
||||
export * from "./lib/progress-circle";
|
||||
@@ -0,0 +1,104 @@
|
||||
import { HTMLAttributes } from "react";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
interface ProgressCircleProps extends HTMLAttributes<HTMLDivElement> {
|
||||
value?: number;
|
||||
max?: number;
|
||||
isLow?: boolean;
|
||||
size?: "small" | "large";
|
||||
showPercentage?: boolean;
|
||||
reverse?: boolean;
|
||||
}
|
||||
|
||||
export const ProgressCircle = ({
|
||||
value = 0,
|
||||
max = 100,
|
||||
isLow = false,
|
||||
size = "large",
|
||||
showPercentage = false,
|
||||
reverse = false,
|
||||
className,
|
||||
...props
|
||||
}: ProgressCircleProps) => {
|
||||
const percentage = Math.min(Math.max(0, value), max);
|
||||
const displayPercentage = percentage;
|
||||
|
||||
// Make small circles actually smaller
|
||||
const radius = size === "small" ? 8 : 40;
|
||||
const strokeWidth = size === "small" ? 4 : 6;
|
||||
const circumference = 2 * Math.PI * radius;
|
||||
|
||||
// Calculate stroke dashoffset differently based on direction
|
||||
const strokeDashoffset = reverse
|
||||
? (percentage / 100) * circumference // Counter-clockwise
|
||||
: circumference - (percentage / 100) * circumference; // Clockwise
|
||||
|
||||
const viewBoxSize = (radius + strokeWidth) * 2;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={twMerge(
|
||||
"relative inline-flex items-center justify-center",
|
||||
size === "small" ? "h-5 w-5" : "h-24 w-24",
|
||||
showPercentage && size === "small" ? "mr-6" : "", // Add margin for small with label
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{/* For small size, show percentage label outside to the right */}
|
||||
{showPercentage && size === "small" && (
|
||||
<div className="absolute -right-6 flex items-center justify-center">
|
||||
<span className="text-xs font-medium">
|
||||
{Math.round(displayPercentage)}%
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<svg
|
||||
className={`absolute h-full w-full ${
|
||||
reverse ? "rotate-90" : "-rotate-90"
|
||||
}`}
|
||||
viewBox={`0 0 ${viewBoxSize} ${viewBoxSize}`}
|
||||
>
|
||||
<circle
|
||||
className="stroke-white/20"
|
||||
cx={viewBoxSize / 2}
|
||||
cy={viewBoxSize / 2}
|
||||
r={radius}
|
||||
fill="none"
|
||||
strokeWidth={strokeWidth}
|
||||
/>
|
||||
<circle
|
||||
className={twMerge(
|
||||
"transition-all",
|
||||
isLow ? "stroke-red/80" : "stroke-primary"
|
||||
)}
|
||||
cx={viewBoxSize / 2}
|
||||
cy={viewBoxSize / 2}
|
||||
r={radius}
|
||||
fill="none"
|
||||
strokeWidth={strokeWidth}
|
||||
strokeDasharray={circumference}
|
||||
strokeDashoffset={strokeDashoffset}
|
||||
strokeLinecap="round"
|
||||
transform={
|
||||
reverse
|
||||
? `rotate(180, ${viewBoxSize / 2}, ${viewBoxSize / 2})`
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</svg>
|
||||
|
||||
{/* For large size, show percentage in the center */}
|
||||
{showPercentage && size === "large" && (
|
||||
<div className="absolute flex flex-col items-center justify-center text-center">
|
||||
<span className="text-xl font-medium">
|
||||
{Math.round(displayPercentage)}%
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProgressCircle;
|
||||
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Replace this with your own classes
|
||||
*
|
||||
* e.g.
|
||||
* .container {
|
||||
* }
|
||||
*/
|
||||
@@ -0,0 +1,12 @@
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
import StorytellerUiProgress from './progress';
|
||||
|
||||
describe('StorytellerUiProgress', () => {
|
||||
|
||||
it('should render successfully', () => {
|
||||
const { baseElement } = render(<StorytellerUiProgress />);
|
||||
expect(baseElement).toBeTruthy();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
import { HTMLAttributes } from "react";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
interface ProgressProps extends HTMLAttributes<HTMLDivElement> {
|
||||
value?: number;
|
||||
max?: number;
|
||||
isLow?: boolean;
|
||||
}
|
||||
|
||||
export const Progress = ({
|
||||
value = 0,
|
||||
max = 100,
|
||||
isLow = false,
|
||||
className,
|
||||
...props
|
||||
}: ProgressProps) => {
|
||||
const percentage = Math.min(Math.max(0, value), max);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={twMerge(
|
||||
"relative h-2 w-full overflow-hidden rounded-full bg-secondary",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<div
|
||||
className={twMerge(
|
||||
"h-full w-full flex-1 transition-all",
|
||||
isLow ? "bg-red/60" : "bg-primary"
|
||||
)}
|
||||
style={{ transform: `translateX(-${100 - percentage}%)` }}
|
||||
role="progressbar"
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={max}
|
||||
aria-valuenow={percentage}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Progress;
|
||||
Reference in New Issue
Block a user