@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.
508 lines (507 loc) • 20.6 kB
JavaScript
"use strict";
'use client';
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _utils = require("@mui/utils");
var _base = require("@mui/base");
var _useSwitch = require("@mui/base/useSwitch");
var _styles = require("../styles");
var _useSlot = _interopRequireDefault(require("../utils/useSlot"));
var _checkboxClasses = _interopRequireWildcard(require("./checkboxClasses"));
var _Check = _interopRequireDefault(require("../internal/svg-icons/Check"));
var _HorizontalRule = _interopRequireDefault(require("../internal/svg-icons/HorizontalRule"));
var _Typography = require("../Typography/Typography");
var _FormControlContext = _interopRequireDefault(require("../FormControl/FormControlContext"));
var _jsxRuntime = require("react/jsx-runtime");
const _excluded = ["checked", "uncheckedIcon", "checkedIcon", "label", "defaultChecked", "disabled", "disableIcon", "overlay", "id", "indeterminate", "indeterminateIcon", "name", "onBlur", "onChange", "onFocus", "onFocusVisible", "readOnly", "required", "value", "color", "variant", "size", "component", "slots", "slotProps"];
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const useUtilityClasses = ownerState => {
const {
checked,
disabled,
disableIcon,
focusVisible,
color,
variant,
size,
indeterminate
} = ownerState;
const slots = {
root: ['root', checked && 'checked', disabled && 'disabled', focusVisible && 'focusVisible', variant && `variant${(0, _utils.unstable_capitalize)(variant)}`, color && `color${(0, _utils.unstable_capitalize)(color)}`, size && `size${(0, _utils.unstable_capitalize)(size)}`],
checkbox: ['checkbox', checked && 'checked', indeterminate && 'indeterminate', disabled && 'disabled' // disabled class is necessary for displaying global variant
],
action: ['action', checked && 'checked', disableIcon && disabled && 'disabled',
// add disabled class to action element for displaying global variant
focusVisible && 'focusVisible'],
input: ['input'],
label: ['label']
};
return (0, _base.unstable_composeClasses)(slots, _checkboxClasses.getCheckboxUtilityClass, {});
};
const CheckboxRoot = (0, _styles.styled)('span', {
name: 'JoyCheckbox',
slot: 'Root',
overridesResolver: (props, styles) => styles.root
})(({
ownerState,
theme
}) => {
var _theme$variants$plain, _theme$variants, _theme$variants2;
return (0, _extends2.default)({
'--Icon-fontSize': 'var(--Checkbox-size)'
}, ownerState.size === 'sm' && {
'--Checkbox-size': '1rem',
'& ~ *': {
'--FormHelperText-margin': '0 0 0 1.5rem'
},
fontSize: theme.vars.fontSize.sm,
gap: 'var(--Checkbox-gap, 0.5rem)'
}, ownerState.size === 'md' && {
'--Checkbox-size': '1.25rem',
'& ~ *': {
'--FormHelperText-margin': '0.25rem 0 0 1.875rem'
},
fontSize: theme.vars.fontSize.md,
gap: 'var(--Checkbox-gap, 0.625rem)'
}, ownerState.size === 'lg' && {
'--Checkbox-size': '1.5rem',
'& ~ *': {
'--FormHelperText-margin': '0.375rem 0 0 2.25rem'
},
fontSize: theme.vars.fontSize.lg,
gap: 'var(--Checkbox-gap, 0.75rem)'
}, {
position: ownerState.overlay ? 'initial' : 'relative',
display: 'inline-flex',
fontFamily: theme.vars.fontFamily.body,
lineHeight: 'var(--Checkbox-size)',
color: theme.vars.palette.text.primary,
[`&.${_checkboxClasses.default.disabled}`]: {
color: (_theme$variants$plain = theme.variants.plainDisabled) == null || (_theme$variants$plain = _theme$variants$plain[ownerState.color]) == null ? void 0 : _theme$variants$plain.color
}
}, ownerState.disableIcon && {
color: (_theme$variants = theme.variants[ownerState.variant]) == null || (_theme$variants = _theme$variants[ownerState.color]) == null ? void 0 : _theme$variants.color,
[`&.${_checkboxClasses.default.disabled}`]: {
color: (_theme$variants2 = theme.variants[`${ownerState.variant}Disabled`]) == null || (_theme$variants2 = _theme$variants2[ownerState.color]) == null ? void 0 : _theme$variants2.color
}
});
});
const CheckboxCheckbox = (0, _styles.styled)('span', {
name: 'JoyCheckbox',
slot: 'Checkbox',
overridesResolver: (props, styles) => styles.checkbox
})(({
theme,
ownerState
}) => {
var _theme$variants3, _variantStyle$backgro, _theme$variants4, _theme$variants5, _theme$variants6;
const variantStyle = (_theme$variants3 = theme.variants[`${ownerState.variant}`]) == null ? void 0 : _theme$variants3[ownerState.color];
return [(0, _extends2.default)({
'--Icon-color': ownerState.color !== 'neutral' || ownerState.variant === 'solid' ? 'currentColor' : theme.vars.palette.text.icon,
boxSizing: 'border-box',
borderRadius: `min(${theme.vars.radius.sm}, 0.25rem)`,
width: 'var(--Checkbox-size)',
height: 'var(--Checkbox-size)',
display: 'inline-flex',
justifyContent: 'center',
alignItems: 'center',
flexShrink: 0
}, ownerState.disableIcon && {
display: 'contents'
}, {
[`&.${_checkboxClasses.default.checked}, &.${_checkboxClasses.default.indeterminate}`]: {
'--Icon-color': 'currentColor'
}
}), ...(!ownerState.disableIcon ? [(0, _extends2.default)({}, variantStyle, {
backgroundColor: (_variantStyle$backgro = variantStyle == null ? void 0 : variantStyle.backgroundColor) != null ? _variantStyle$backgro : theme.vars.palette.background.surface
}), {
'&:hover': {
'@media (hover: hover)': (_theme$variants4 = theme.variants[`${ownerState.variant}Hover`]) == null ? void 0 : _theme$variants4[ownerState.color]
}
}, {
'&:active': (_theme$variants5 = theme.variants[`${ownerState.variant}Active`]) == null ? void 0 : _theme$variants5[ownerState.color]
}, {
[`&.${_checkboxClasses.default.disabled}`]: (_theme$variants6 = theme.variants[`${ownerState.variant}Disabled`]) == null ? void 0 : _theme$variants6[ownerState.color]
}] : [])];
});
const CheckboxAction = (0, _styles.styled)('span', {
name: 'JoyCheckbox',
slot: 'Action',
overridesResolver: (props, styles) => styles.action
})(({
theme,
ownerState
}) => {
var _theme$variants7, _theme$variants8, _theme$variants9, _theme$variants10;
return [{
borderRadius: `var(--Checkbox-actionRadius, ${ownerState.overlay ? 'var(--unstable_actionRadius, inherit)' : 'inherit'})`,
textAlign: 'left',
// prevent text-align inheritance
position: 'absolute',
top: 'calc(-1 * var(--variant-borderWidth, 0px))',
// clickable on the border and focus outline does not move when checked/unchecked
left: 'calc(-1 * var(--variant-borderWidth, 0px))',
bottom: 'calc(-1 * var(--variant-borderWidth, 0px))',
right: 'calc(-1 * var(--variant-borderWidth, 0px))',
zIndex: 1,
// The action element usually cover the area of nearest positioned parent
[theme.focus.selector]: theme.focus.default
}, ...(ownerState.disableIcon ? [(_theme$variants7 = theme.variants[ownerState.variant]) == null ? void 0 : _theme$variants7[ownerState.color], {
'&:hover': (_theme$variants8 = theme.variants[`${ownerState.variant}Hover`]) == null ? void 0 : _theme$variants8[ownerState.color]
}, {
'&:active': (_theme$variants9 = theme.variants[`${ownerState.variant}Active`]) == null ? void 0 : _theme$variants9[ownerState.color]
}, {
[`&.${_checkboxClasses.default.disabled}`]: (_theme$variants10 = theme.variants[`${ownerState.variant}Disabled`]) == null ? void 0 : _theme$variants10[ownerState.color]
}] : [])];
});
const CheckboxInput = (0, _styles.styled)('input', {
name: 'JoyCheckbox',
slot: 'Input',
overridesResolver: (props, styles) => styles.input
})(() => ({
margin: 0,
opacity: 0,
position: 'absolute',
width: '100%',
height: '100%',
cursor: 'pointer'
}));
const CheckboxLabel = (0, _styles.styled)('label', {
name: 'JoyCheckbox',
slot: 'Label',
overridesResolver: (props, styles) => styles.label
})(({
ownerState
}) => (0, _extends2.default)({
flex: 1,
minWidth: 0
}, ownerState.disableIcon && {
zIndex: 1,
// label should stay on top of the action.
pointerEvents: 'none' // makes hover ineffect.
}));
const defaultCheckedIcon = /*#__PURE__*/(0, _jsxRuntime.jsx)(_Check.default, {});
const defaultIndeterminateIcon = /*#__PURE__*/(0, _jsxRuntime.jsx)(_HorizontalRule.default, {});
/**
*
* Demos:
*
* - [Checkbox](https://mui.com/joy-ui/react-checkbox/)
*
* API:
*
* - [Checkbox API](https://mui.com/joy-ui/api/checkbox/)
*/
const Checkbox = /*#__PURE__*/React.forwardRef(function Checkbox(inProps, ref) {
var _ref, _inProps$disabled, _ref2, _inProps$size, _formControl$color;
const props = (0, _styles.useThemeProps)({
props: inProps,
name: 'JoyCheckbox'
});
const {
checked: checkedProp,
uncheckedIcon,
checkedIcon = defaultCheckedIcon,
label,
defaultChecked,
disabled: disabledExternalProp,
disableIcon = false,
overlay,
id: idOverride,
indeterminate = false,
indeterminateIcon = defaultIndeterminateIcon,
name,
onBlur,
onChange,
onFocus,
onFocusVisible,
readOnly,
required,
value,
color: colorProp,
variant: variantProp,
size: sizeProp = 'md',
component,
slots = {},
slotProps = {}
} = props,
other = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded);
const formControl = React.useContext(_FormControlContext.default);
const disabledProp = (_ref = (_inProps$disabled = inProps.disabled) != null ? _inProps$disabled : formControl == null ? void 0 : formControl.disabled) != null ? _ref : disabledExternalProp;
const size = (_ref2 = (_inProps$size = inProps.size) != null ? _inProps$size : formControl == null ? void 0 : formControl.size) != null ? _ref2 : sizeProp;
if (process.env.NODE_ENV !== 'production') {
const registerEffect = formControl == null ? void 0 : formControl.registerEffect;
// eslint-disable-next-line react-hooks/rules-of-hooks
React.useEffect(() => {
if (registerEffect) {
return registerEffect();
}
return undefined;
}, [registerEffect]);
}
const id = (0, _utils.unstable_useId)(idOverride != null ? idOverride : formControl == null ? void 0 : formControl.htmlFor);
const useCheckboxProps = {
checked: checkedProp,
defaultChecked,
disabled: disabledProp,
onBlur,
onChange,
onFocus,
onFocusVisible
};
const {
getInputProps,
checked,
disabled,
focusVisible
} = (0, _useSwitch.useSwitch)(useCheckboxProps);
const isCheckboxActive = checked || indeterminate;
const activeVariant = variantProp || 'solid';
const inactiveVariant = variantProp || 'outlined';
const variant = isCheckboxActive ? activeVariant : inactiveVariant;
const color = inProps.color || (formControl != null && formControl.error ? 'danger' : (_formControl$color = formControl == null ? void 0 : formControl.color) != null ? _formControl$color : colorProp);
const activeColor = color || 'primary';
const inactiveColor = color || 'neutral';
const ownerState = (0, _extends2.default)({}, props, {
checked,
disabled,
disableIcon,
overlay,
focusVisible,
color: isCheckboxActive ? activeColor : inactiveColor,
variant,
size
});
const classes = useUtilityClasses(ownerState);
const externalForwardedProps = (0, _extends2.default)({}, other, {
component,
slots,
slotProps
});
const [SlotRoot, rootProps] = (0, _useSlot.default)('root', {
ref,
className: classes.root,
elementType: CheckboxRoot,
externalForwardedProps,
ownerState
});
const [SlotCheckbox, checkboxProps] = (0, _useSlot.default)('checkbox', {
className: classes.checkbox,
elementType: CheckboxCheckbox,
externalForwardedProps,
ownerState
});
const [SlotAction, actionProps] = (0, _useSlot.default)('action', {
className: classes.action,
elementType: CheckboxAction,
externalForwardedProps,
ownerState
});
const [SlotInput, inputProps] = (0, _useSlot.default)('input', {
additionalProps: (0, _extends2.default)({
id,
name,
value,
readOnly,
role: undefined,
required: required != null ? required : formControl == null ? void 0 : formControl.required,
'aria-describedby': formControl == null ? void 0 : formControl['aria-describedby']
}, indeterminate && {
// https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-checked#values
'aria-checked': 'mixed'
}),
className: classes.input,
elementType: CheckboxInput,
externalForwardedProps,
getSlotProps: getInputProps,
ownerState
});
const [SlotLabel, labelProps] = (0, _useSlot.default)('label', {
additionalProps: {
htmlFor: id
},
className: classes.label,
elementType: CheckboxLabel,
externalForwardedProps,
ownerState
});
let icon = uncheckedIcon;
if (disableIcon) {
icon = null;
} else if (indeterminate) {
icon = indeterminateIcon;
} else if (checked) {
icon = checkedIcon;
}
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(SlotRoot, (0, _extends2.default)({}, rootProps, {
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(SlotCheckbox, (0, _extends2.default)({}, checkboxProps, {
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(SlotAction, (0, _extends2.default)({}, actionProps, {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(SlotInput, (0, _extends2.default)({}, inputProps))
})), icon]
})), label && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.TypographyNestedContext.Provider, {
value: true,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(SlotLabel, (0, _extends2.default)({}, labelProps, {
children: label
}))
})]
}));
});
process.env.NODE_ENV !== "production" ? Checkbox.propTypes /* remove-proptypes */ = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* If `true`, the component is checked.
*/
checked: _propTypes.default.bool,
/**
* The icon to display when the component is checked.
* @default <CheckIcon />
*/
checkedIcon: _propTypes.default.node,
/**
* @ignore
*/
children: _propTypes.default.node,
/**
* Class name applied to the root element.
*/
className: _propTypes.default.string,
/**
* The color of the component. It supports those theme colors that make sense for this component.
* @default 'neutral'
*/
color: _propTypes.default /* @typescript-to-proptypes-ignore */.oneOfType([_propTypes.default.oneOf(['danger', 'neutral', 'primary', 'success', 'warning']), _propTypes.default.string]),
/**
* The component used for the root node.
* Either a string to use a HTML element or a component.
*/
component: _propTypes.default.elementType,
/**
* The default checked state. Use when the component is not controlled.
*/
defaultChecked: _propTypes.default.bool,
/**
* If `true`, the component is disabled.
*/
disabled: _propTypes.default.bool,
/**
* If `true`, the checked icon is removed and the selected variant is applied on the `action` element instead.
* @default false
*/
disableIcon: _propTypes.default.bool,
/**
* @ignore
*/
id: _propTypes.default.string,
/**
* If `true`, the component appears indeterminate.
* This does not set the native input element to indeterminate due
* to inconsistent behavior across browsers.
* However, we set a `data-indeterminate` attribute on the `input`.
* @default false
*/
indeterminate: _propTypes.default.bool,
/**
* The icon to display when the component is indeterminate.
* @default <IndeterminateIcon />
*/
indeterminateIcon: _propTypes.default.node,
/**
* The label element next to the checkbox.
*/
label: _propTypes.default.node,
/**
* The `name` attribute of the input.
*/
name: _propTypes.default.string,
/**
* @ignore
*/
onBlur: _propTypes.default.func,
/**
* Callback fired when the state is changed.
*
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
* You can pull out the new value by accessing `event.target.value` (string).
* You can pull out the new checked state by accessing `event.target.checked` (boolean).
*/
onChange: _propTypes.default.func,
/**
* @ignore
*/
onFocus: _propTypes.default.func,
/**
* @ignore
*/
onFocusVisible: _propTypes.default.func,
/**
* If `true`, the root element's position is set to initial which allows the action area to fill the nearest positioned parent.
* This prop is useful for composing Checkbox with ListItem component.
* @default false
*/
overlay: _propTypes.default.bool,
/**
* If `true`, the component is read only.
*/
readOnly: _propTypes.default.bool,
/**
* If `true`, the `input` element is required.
*/
required: _propTypes.default.bool,
/**
* The size of the component.
* @default 'md'
*/
size: _propTypes.default.oneOf(['sm', 'md', 'lg']),
/**
* The props used for each slot inside.
* @default {}
*/
slotProps: _propTypes.default.shape({
action: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]),
checkbox: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]),
input: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]),
label: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]),
root: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object])
}),
/**
* The components used for each slot inside.
* @default {}
*/
slots: _propTypes.default.shape({
action: _propTypes.default.elementType,
checkbox: _propTypes.default.elementType,
input: _propTypes.default.elementType,
label: _propTypes.default.elementType,
root: _propTypes.default.elementType
}),
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: _propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object, _propTypes.default.bool])), _propTypes.default.func, _propTypes.default.object]),
/**
* The icon when `checked` is false.
*/
uncheckedIcon: _propTypes.default.node,
/**
* The value of the component. The DOM API casts this to a string.
* The browser uses "on" as the default value.
*/
value: _propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.string), _propTypes.default.number, _propTypes.default.string]),
/**
* The [global variant](https://mui.com/joy-ui/main-features/global-variants/) to use.
* @default 'solid'
*/
variant: _propTypes.default.oneOf(['outlined', 'plain', 'soft', 'solid'])
} : void 0;
var _default = exports.default = Checkbox;