UNPKG

@wix/design-system

Version:

@wix/design-system

85 lines 5.02 kB
import React, { useLayoutEffect, useRef, useState } from 'react'; import { CircleLoaderCheck, CircleLoaderCheckSmall, FormFieldError, FormFieldErrorSmall, } from '@wix/wix-ui-icons-common/system'; import { StatusCompleteFilled, StatusAlertFilled, } from '@wix/wix-ui-icons-common'; import Tooltip from '../Tooltip'; import { ThemeProviderConsumerBackwardCompatible } from '../ThemeProvider/ThemeProviderConsumerBackwardCompatible'; import { st, classes } from './CircularProgressBar.st.css.js'; import PropTypes from 'prop-types'; import { dataHooks, Size, sizesMap } from './constants'; import { CircularProgressBarCore } from './CircularProgressBarCore'; import { ProgressLabel } from './CircularProgressBarCore/ProgressLabel'; const sizeToSuccessIcon = { [Size.tiny]: StatusCompleteFilled, [Size.small]: CircleLoaderCheckSmall, [Size.medium]: CircleLoaderCheck, [Size.large]: CircleLoaderCheck, }; const sizeToErrorIcon = { [Size.tiny]: React.createElement(StatusAlertFilled, null), [Size.small]: React.createElement(FormFieldErrorSmall, null), [Size.medium]: React.createElement(FormFieldError, null), [Size.large]: React.createElement(FormFieldError, null), }; // This is a workaround for tokens to work with JS based solution, it has drawbacks: // 1. it's not reactive (if token changes, UI won't update) // 2. it's checking for css vars loaded on body only const extractSizeFromCSSVariable = (variableName, element, fallback) => { const cssValue = getComputedStyle(element) .getPropertyValue(variableName) .trim(); if (cssValue) { const numericValue = parseFloat(cssValue); return !isNaN(numericValue) ? numericValue : fallback; } return fallback; }; const CircularProgressBar = ({ size = 'medium', skin = 'standard', labelPlacement = 'bottom', label, value, dataHook, error, errorMessage, className, light, ...restProps }) => { const [dynamicSizesMap, setDynamicSizesMap] = useState(sizesMap); const rootRef = useRef(null); useLayoutEffect(() => { const newSizesMap = { tiny: extractSizeFromCSSVariable('--wds-circular-progress-bar-size-tiny', rootRef.current, sizesMap.tiny), small: extractSizeFromCSSVariable('--wds-circular-progress-bar-size-small', rootRef.current, sizesMap.small), medium: extractSizeFromCSSVariable('--wds-circular-progress-bar-size-medium', rootRef.current, sizesMap.medium), large: extractSizeFromCSSVariable('--wds-circular-progress-bar-size-large', rootRef.current, sizesMap.large), }; setDynamicSizesMap(newSizesMap); }, []); const renderSuccessIcon = size => (React.createElement(ThemeProviderConsumerBackwardCompatible, { defaultIcons: { CircularProgressBar: sizeToSuccessIcon, } }, ({ icons }) => { const IconToRender = icons.CircularProgressBar[size]; return React.createElement(IconToRender, null); })); const renderProgressLabel = () => (React.createElement(ProgressLabel, { size: size, value: value, "data-skin": skin, label: label })); const renderProgressBar = () => { return (React.createElement(CircularProgressBarCore, { className: st(classes.progressBar, { light, size, skin }), ...restProps, value: value, label: label, error: error, errorMessage: errorMessage, labelPlacement: labelPlacement, "data-hook": dataHooks.circularProgressBar, size: dynamicSizesMap[size], "data-size": size, "data-skin": skin, successIcon: renderSuccessIcon(size), errorIcon: sizeToErrorIcon[size], renderProgressLabel: renderProgressLabel })); }; return (React.createElement("div", { ref: rootRef, "data-hook": dataHook, className: st(classes.root, className) }, error && errorMessage ? (React.createElement(Tooltip, { className: classes.tooltip, content: errorMessage, dataHook: dataHooks.tooltip }, renderProgressBar())) : (renderProgressBar()))); }; CircularProgressBar.displayName = 'CircularProgressBar'; CircularProgressBar.propTypes = { /** Should be true if had failure during the progress */ error: PropTypes.bool, /** Label to display when an error happens */ errorLabel: PropTypes.string, /** Message to display when an error happens */ errorMessage: PropTypes.string, /** Use light theme instead of dark theme */ light: PropTypes.bool, /** Use to display a percentage progress */ showProgressIndication: PropTypes.bool, /** Use to display custom text in the progress bar */ label: PropTypes.string, /** Placement of the label in the progress bar */ labelPlacement: PropTypes.oneOf(['bottom', 'center']), /** Size of the bar */ size: PropTypes.string, /** Skin of the bar */ skin: PropTypes.oneOf(['standard', 'premium', 'success']), /** The number of the percentage progress */ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), dataHook: PropTypes.string, }; export default CircularProgressBar; //# sourceMappingURL=CircularProgressBar.js.map