UNPKG

@furystack/shades-common-components

Version:

Common UI components for FuryStack Shades

82 lines 3.92 kB
import { Shade, createComponent } from '@furystack/shades'; import { cssVariableTheme } from '../services/css-variable-theme.js'; import { ThemeProviderService } from '../services/theme-provider-service.js'; const SVG_SIZE = 44; const DEFAULT_SIZE = 40; const DEFAULT_THICKNESS = 3.6; const clampValue = (v) => Math.max(0, Math.min(100, v)); export const CircularProgress = Shade({ customElementName: 'shade-circular-progress', css: { display: 'inline-flex', fontFamily: cssVariableTheme.typography.fontFamily, alignItems: 'center', justifyContent: 'center', lineHeight: '1', '& svg': { display: 'block', }, '& .progress-track': { stroke: 'color-mix(in srgb, var(--circular-progress-color) 20%, transparent)', fill: 'none', }, '& .progress-circle': { stroke: 'var(--circular-progress-color)', fill: 'none', strokeLinecap: 'round', transition: `stroke-dashoffset ${cssVariableTheme.transitions.duration.normal} ${cssVariableTheme.transitions.easing.easeInOut}`, }, }, render: ({ props, injector, useHostProps }) => { const themeProvider = injector.get(ThemeProviderService); const variant = props.variant || 'indeterminate'; const value = clampValue(props.value ?? 0); const size = props.size ?? DEFAULT_SIZE; const thickness = props.thickness ?? DEFAULT_THICKNESS; const indeterminate = variant === 'indeterminate'; const radius = (SVG_SIZE - thickness) / 2; const circumference = 2 * Math.PI * radius; const color = themeProvider.theme.palette[props.color || 'primary'].main; useHostProps({ role: 'progressbar', ...(variant === 'determinate' ? { 'aria-valuenow': String(value), 'aria-valuemin': '0', 'aria-valuemax': '100', } : { 'aria-valuenow': undefined, }), style: { '--circular-progress-color': color }, }); const dashOffset = variant === 'determinate' ? circumference - (value / 100) * circumference : 0; const center = SVG_SIZE / 2; return (createComponent("svg", { width: size, height: size, viewBox: `0 0 ${SVG_SIZE} ${SVG_SIZE}`, style: indeterminate ? { animation: 'circular-rotate 1.4s linear infinite' } : undefined }, indeterminate && (createComponent("style", null, ` @keyframes circular-rotate { 100% { transform: rotate(360deg); } } @keyframes circular-dash { 0% { stroke-dasharray: ${circumference * 0.05} ${circumference}; stroke-dashoffset: 0; } 50% { stroke-dasharray: ${circumference * 0.7} ${circumference}; stroke-dashoffset: ${-circumference * 0.12}; } 100% { stroke-dasharray: ${circumference * 0.7} ${circumference}; stroke-dashoffset: ${-circumference * 0.88}; } } `)), createComponent("circle", { className: "progress-track", cx: center, cy: center, r: radius, "stroke-width": thickness }), createComponent("circle", { className: "progress-circle", cx: center, cy: center, r: radius, "stroke-width": thickness, "stroke-dasharray": indeterminate ? `${circumference * 0.05} ${circumference}` : `${circumference}`, style: { strokeDashoffset: `${dashOffset}`, ...(indeterminate ? { animation: 'circular-dash 1.4s ease-in-out infinite' } : {}), }, transform: `rotate(-90 ${SVG_SIZE / 2} ${SVG_SIZE / 2})` }))); }, }); //# sourceMappingURL=circular-progress.js.map