UNPKG

@equinor/eds-core-react

Version:

The React implementation of the Equinor Design System

115 lines (112 loc) 3.67 kB
import { forwardRef, useState, useEffect } from 'react'; import styled, { keyframes, css } from 'styled-components'; import * as CircularProgress_tokens from './CircularProgress.tokens.js'; import { jsxs, Fragment, jsx } from 'react/jsx-runtime'; const indeterminate = keyframes(["100%{transform:rotate(360deg);}"]); const Svg = styled.svg.withConfig({ displayName: "CircularProgress__Svg", componentId: "sc-hib054-0" })(["display:inline-block;", ";"], ({ $variant }) => $variant === 'indeterminate' ? css(["animation:", " 1.4s linear infinite;"], indeterminate) : css(["transform:rotate(-90deg);"])); const SrOnlyOutput = styled.output.withConfig({ displayName: "CircularProgress__SrOnlyOutput", componentId: "sc-hib054-1" })(["position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0;"]); const TrackCircle = styled.circle.withConfig({ displayName: "CircularProgress__TrackCircle", componentId: "sc-hib054-2" })([""]); const ProgressCircle = styled.circle.withConfig({ displayName: "CircularProgress__ProgressCircle", componentId: "sc-hib054-3" })([""]); const getToken = color => { if (CircularProgress_tokens[color]) { return CircularProgress_tokens[color]; } return { background: 'transparent', entities: { progress: { background: color } } }; }; const CircularProgress = /*#__PURE__*/forwardRef(function CircularProgress({ variant = 'indeterminate', value = null, size = 48, color = 'primary', ...rest }, ref) { const thickness = 4; const progress = Math.round(value); const trackStyle = {}; const props = { ...rest, ref, $variant: variant }; const token = getToken(color); const [srProgress, setSrProgress] = useState(0); const circumference = 2 * Math.PI * ((48 - thickness) / 2); if (variant === 'determinate') { trackStyle.stroke = circumference.toFixed(3); trackStyle.strokeDashoffset = `${((100 - progress) / 100 * circumference).toFixed(3)}px`; props['aria-valuenow'] = progress; if (value !== undefined) { props['aria-valuenow'] = progress; props['aria-valuemin'] = 0; props['aria-valuemax'] = 100; } } useEffect(() => { if (variant === 'indeterminate') return; if (progress >= 25 && progress < 50) { setSrProgress(25); } else if (progress >= 50 && progress < 75) { setSrProgress(50); } else if (progress >= 75 && progress < 100) { setSrProgress(75); } else if (progress === 100) { setSrProgress(100); } }, [progress, variant]); const getProgressFormatted = () => { return `Loading ${srProgress}%`; }; return /*#__PURE__*/jsxs(Fragment, { children: [/*#__PURE__*/jsxs(Svg, { ...props, viewBox: "24 24 48 48", role: "progressbar", height: size, width: size, preserveAspectRatio: "xMidYMid meet", children: [/*#__PURE__*/jsx(TrackCircle, { style: trackStyle, cx: 48, cy: 48, r: (48 - thickness) / 2, fill: "none", strokeWidth: thickness, stroke: token.background }), /*#__PURE__*/jsx(ProgressCircle, { style: trackStyle, cx: 48, cy: 48, r: (48 - thickness) / 2, fill: "none", strokeLinecap: "round", strokeWidth: thickness, strokeDasharray: variant === 'determinate' ? circumference : 48, stroke: token.entities.progress.background })] }), variant === 'determinate' && /*#__PURE__*/jsx(SrOnlyOutput, { children: getProgressFormatted() })] }); }); export { CircularProgress };