/*! Strand UI | MIT License | dillingerstaffing.com */ import type { JSX } from "preact"; import { forwardRef } from "preact/compat"; import { cx } from "../../internal/index.js"; export interface ProgressProps extends Omit, "size" | "label"> { variant?: "bar" | "ring"; /** Percent complete, 0 to 100; omit for indeterminate. */ value?: number; size?: "sm" | "md" | "lg"; /** Accessible name: what is progressing. */ label?: string; /** Read in place of the percentage, such as "3 of 10 steps". */ valueText?: string; } const RING_SIZES: Record = { sm: 24, md: 40, lg: 56 }; const RING_STROKE = 3; /** * Determinate or indeterminate progress, as a bar or a ring. * * @example * */ export const Progress = forwardRef(({ variant = "bar", value, size = "md", label, valueText, className = "", ...rest }, ref) => { const isDeterminate = value != null; const classes = cx("strand-progress", `strand-progress--${variant}`, `strand-progress--${size}`, !isDeterminate && "strand-progress--indeterminate", className); const aria: Record = { role: "progressbar", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": isDeterminate ? value : undefined, "aria-valuetext": valueText, "aria-label": label, }; if (variant === "ring") { const dim = RING_SIZES[size] ?? RING_SIZES.md; const radius = (dim - RING_STROKE) / 2; const circumference = 2 * Math.PI * radius; const offset = isDeterminate ? circumference - (circumference * (value as number)) / 100 : 0; return (
); } return (
); }); Progress.displayName = "Progress";