@wix/design-system
Version:
@wix/design-system
85 lines • 5.02 kB
JavaScript
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