@mui/joy
Version:
Joy UI is an open-source React component library that implements MUI's own design principles. It's comprehensive and can be used in production out of the box.
357 lines (355 loc) • 13.5 kB
JavaScript
'use client';
import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
let _ = t => t,
_t;
const _excluded = ["color", "backgroundColor"],
_excluded2 = ["children", "className", "color", "size", "variant", "thickness", "determinate", "value", "component", "slots", "slotProps"];
import PropTypes from 'prop-types';
import * as React from 'react';
import clsx from 'clsx';
import { unstable_capitalize as capitalize } from '@mui/utils';
import { unstable_composeClasses as composeClasses } from '@mui/base';
import { css, keyframes } from '@mui/system';
import styled from '../styles/styled';
import useThemeProps from '../styles/useThemeProps';
import useSlot from '../utils/useSlot';
import { getCircularProgressUtilityClass } from './circularProgressClasses';
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
const circulate = keyframes({
'0%': {
// let the progress start at the top of the ring
transform: 'rotate(-90deg)'
},
'100%': {
transform: 'rotate(270deg)'
}
});
const useUtilityClasses = ownerState => {
const {
determinate,
color,
variant,
size
} = ownerState;
const slots = {
root: ['root', determinate && 'determinate', color && `color${capitalize(color)}`, variant && `variant${capitalize(variant)}`, size && `size${capitalize(size)}`],
svg: ['svg'],
track: ['track'],
progress: ['progress']
};
return composeClasses(slots, getCircularProgressUtilityClass, {});
};
function getThickness(slot, defaultValue) {
return `var(--CircularProgress-${slot}Thickness, var(--CircularProgress-thickness, ${defaultValue}))`;
}
const CircularProgressRoot = styled('span', {
name: 'JoyCircularProgress',
slot: 'Root',
overridesResolver: (props, styles) => styles.root
})(({
ownerState,
theme
}) => {
var _theme$variants, _theme$variants$solid, _theme$variants$softH, _theme$variants$solid2;
const _ref = ((_theme$variants = theme.variants[ownerState.variant]) == null ? void 0 : _theme$variants[ownerState.color]) || {},
{
color,
backgroundColor
} = _ref,
rest = _objectWithoutPropertiesLoose(_ref, _excluded);
return _extends({
// integration with icon
'--Icon-fontSize': 'calc(0.4 * var(--_root-size))',
// public variables
'--CircularProgress-trackColor': backgroundColor,
'--CircularProgress-progressColor': color,
'--CircularProgress-percent': ownerState.value,
// 0 - 100
'--CircularProgress-linecap': 'round'
}, ownerState.size === 'sm' && {
'--_root-size': 'var(--CircularProgress-size, 24px)',
// use --_root-size to let other components overrides via --CircularProgress-size
'--_track-thickness': getThickness('track', '3px'),
'--_progress-thickness': getThickness('progress', '3px')
}, ownerState.instanceSize === 'sm' && {
'--CircularProgress-size': '24px'
}, ownerState.size === 'md' && {
'--_track-thickness': getThickness('track', '6px'),
'--_progress-thickness': getThickness('progress', '6px'),
'--_root-size': 'var(--CircularProgress-size, 40px)'
}, ownerState.instanceSize === 'md' && {
'--CircularProgress-size': '40px'
}, ownerState.size === 'lg' && {
'--_track-thickness': getThickness('track', '8px'),
'--_progress-thickness': getThickness('progress', '8px'),
'--_root-size': 'var(--CircularProgress-size, 64px)'
}, ownerState.instanceSize === 'lg' && {
'--CircularProgress-size': '64px'
}, ownerState.thickness && {
'--_track-thickness': `${ownerState.thickness}px`,
'--_progress-thickness': `${ownerState.thickness}px`
}, {
// internal variables
'--_thickness-diff': 'calc(var(--_track-thickness) - var(--_progress-thickness))',
'--_inner-size': 'calc(var(--_root-size) - 2 * var(--variant-borderWidth, 0px))',
'--_outlined-inset': 'max(var(--_track-thickness), var(--_progress-thickness))',
width: 'var(--_root-size)',
height: 'var(--_root-size)',
borderRadius: 'var(--_root-size)',
margin: 'var(--CircularProgress-margin)',
boxSizing: 'border-box',
display: 'inline-flex',
justifyContent: 'center',
alignItems: 'center',
flexShrink: 0,
// prevent from shrinking when CircularProgress is in a flex container.
position: 'relative',
color
}, ownerState.children && {
// only add font related properties when there is a child.
// so that when there is no child, the size can be controlled by the parent font-size e.g. Link
fontFamily: theme.vars.fontFamily.body,
fontWeight: theme.vars.fontWeight.md,
fontSize: 'calc(0.2 * var(--_root-size))'
}, rest, ownerState.variant === 'outlined' && {
'&::before': _extends({
content: '""',
display: 'block',
position: 'absolute',
borderRadius: 'inherit',
top: 'var(--_outlined-inset)',
left: 'var(--_outlined-inset)',
right: 'var(--_outlined-inset)',
bottom: 'var(--_outlined-inset)'
}, rest)
}, ownerState.variant === 'soft' && {
'--CircularProgress-trackColor': theme.variants.soft.neutral.backgroundColor,
'--CircularProgress-progressColor': (_theme$variants$solid = theme.variants.solid) == null ? void 0 : _theme$variants$solid[ownerState.color].backgroundColor
}, ownerState.variant === 'solid' && {
'--CircularProgress-trackColor': (_theme$variants$softH = theme.variants.softHover) == null ? void 0 : _theme$variants$softH[ownerState.color].backgroundColor,
'--CircularProgress-progressColor': (_theme$variants$solid2 = theme.variants.solid) == null ? void 0 : _theme$variants$solid2[ownerState.color].backgroundColor
});
});
const CircularProgressSvg = styled('svg', {
name: 'JoyCircularProgress',
slot: 'Svg',
overridesResolver: (props, styles) => styles.svg
})({
width: 'inherit',
height: 'inherit',
display: 'inherit',
boxSizing: 'inherit',
position: 'absolute',
top: 'calc(-1 * var(--variant-borderWidth, 0px))',
// centered align
left: 'calc(-1 * var(--variant-borderWidth, 0px))' // centered align
});
const CircularProgressTrack = styled('circle', {
name: 'JoyCircularProgress',
slot: 'track',
overridesResolver: (props, styles) => styles.track
})({
cx: '50%',
cy: '50%',
r: 'calc(var(--_inner-size) / 2 - var(--_track-thickness) / 2 + min(0px, var(--_thickness-diff) / 2))',
fill: 'transparent',
strokeWidth: 'var(--_track-thickness)',
stroke: 'var(--CircularProgress-trackColor)'
});
const CircularProgressProgress = styled('circle', {
name: 'JoyCircularProgress',
slot: 'progress',
overridesResolver: (props, styles) => styles.progress
})({
'--_progress-radius': 'calc(var(--_inner-size) / 2 - var(--_progress-thickness) / 2 - max(0px, var(--_thickness-diff) / 2))',
'--_progress-length': 'calc(2 * 3.1415926535 * var(--_progress-radius))',
// the circumference around the progress
cx: '50%',
cy: '50%',
r: 'var(--_progress-radius)',
fill: 'transparent',
strokeWidth: 'var(--_progress-thickness)',
stroke: 'var(--CircularProgress-progressColor)',
strokeLinecap: 'var(--CircularProgress-linecap, round)',
// can't use CSS variable directly, need to cast type.
strokeDasharray: 'var(--_progress-length)',
strokeDashoffset: 'calc(var(--_progress-length) - var(--CircularProgress-percent) * var(--_progress-length) / 100)',
transformOrigin: 'center',
transform: 'rotate(-90deg)' // to initially appear at the top-center of the circle.
}, ({
ownerState
}) => !ownerState.determinate && css(_t || (_t = _`
animation: var(--CircularProgress-circulation, 0.8s linear 0s infinite normal none running)
${0};
`), circulate));
/**
* ## ARIA
*
* If the progress bar is describing the loading progress of a particular region of a page,
* you should use `aria-describedby` to point to the progress bar, and set the `aria-busy`
* attribute to `true` on that region until it has finished loading.
*
* Demos:
*
* - [Circular Progress](https://mui.com/joy-ui/react-circular-progress/)
*
* API:
*
* - [CircularProgress API](https://mui.com/joy-ui/api/circular-progress/)
*/
const CircularProgress = /*#__PURE__*/React.forwardRef(function CircularProgress(inProps, ref) {
const props = useThemeProps({
props: inProps,
name: 'JoyCircularProgress'
});
const {
children,
className,
color = 'primary',
size = 'md',
variant = 'soft',
thickness,
determinate = false,
value = determinate ? 0 : 25,
// `25` is the 1/4 of the circle.
component,
slots = {},
slotProps = {}
} = props,
other = _objectWithoutPropertiesLoose(props, _excluded2);
const ownerState = _extends({}, props, {
color,
size,
variant,
thickness,
value,
determinate,
instanceSize: inProps.size
});
const classes = useUtilityClasses(ownerState);
const externalForwardedProps = _extends({}, other, {
component,
slots,
slotProps
});
const [SlotRoot, rootProps] = useSlot('root', {
ref,
className: clsx(classes.root, className),
elementType: CircularProgressRoot,
externalForwardedProps,
ownerState,
additionalProps: _extends({
role: 'progressbar',
style: {
// Setting this CSS variable via inline-style
// prevents the generation of new CSS every time
// `value` prop updates
'--CircularProgress-percent': value
}
}, value && determinate && {
'aria-valuenow': typeof value === 'number' ? Math.round(value) : Math.round(Number(value || 0))
})
});
const [SlotSvg, svgProps] = useSlot('svg', {
className: classes.svg,
elementType: CircularProgressSvg,
externalForwardedProps,
ownerState
});
const [SlotTrack, trackProps] = useSlot('track', {
className: classes.track,
elementType: CircularProgressTrack,
externalForwardedProps,
ownerState
});
const [SlotProgress, progressProps] = useSlot('progress', {
className: classes.progress,
elementType: CircularProgressProgress,
externalForwardedProps,
ownerState
});
return /*#__PURE__*/_jsxs(SlotRoot, _extends({}, rootProps, {
children: [/*#__PURE__*/_jsxs(SlotSvg, _extends({}, svgProps, {
children: [/*#__PURE__*/_jsx(SlotTrack, _extends({}, trackProps)), /*#__PURE__*/_jsx(SlotProgress, _extends({}, progressProps))]
})), children]
}));
});
process.env.NODE_ENV !== "production" ? CircularProgress.propTypes /* remove-proptypes */ = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* @ignore
*/
children: PropTypes.node,
/**
* @ignore
*/
className: PropTypes.string,
/**
* The color of the component. It supports those theme colors that make sense for this component.
* @default 'primary'
*/
color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['danger', 'neutral', 'primary', 'success', 'warning']), PropTypes.string]),
/**
* The component used for the root node.
* Either a string to use a HTML element or a component.
*/
component: PropTypes.elementType,
/**
* The boolean to select a variant.
* Use indeterminate when there is no progress value.
* @default false
*/
determinate: PropTypes.bool,
/**
* The size of the component.
* It accepts theme values between 'sm' and 'lg'.
* @default 'md'
*/
size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['sm', 'md', 'lg']), PropTypes.string]),
/**
* The props used for each slot inside.
* @default {}
*/
slotProps: PropTypes.shape({
progress: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
svg: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
track: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
}),
/**
* The components used for each slot inside.
* @default {}
*/
slots: PropTypes.shape({
progress: PropTypes.elementType,
root: PropTypes.elementType,
svg: PropTypes.elementType,
track: PropTypes.elementType
}),
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
/**
* The thickness of the circle.
*/
thickness: PropTypes.number,
/**
* The value of the progress indicator for the determinate variant.
* Value between 0 and 100.
*
* @default determinate ? 0 : 25
*/
value: PropTypes.number,
/**
* The [global variant](https://mui.com/joy-ui/main-features/global-variants/) to use.
* @default 'soft'
*/
variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['outlined', 'plain', 'soft', 'solid']), PropTypes.string])
} : void 0;
export default CircularProgress;