rsuite
Version:
A suite of react components
145 lines (142 loc) • 5.21 kB
JavaScript
'use client';
import _extends from "@babel/runtime/helpers/esm/extends";
import React, { useContext, useMemo } from 'react';
import Box from "../internals/Box/index.js";
import { useControlled, useStyles, useCustom, useEventCallback, useUniqueId } from "../internals/hooks/index.js";
import { forwardRef, partitionHTMLProps, mergeRefs } from "../internals/utils/index.js";
import { useIndeterminateCheckbox } from "./hooks/useIndeterminateCheckbox.js";
import { CheckboxGroupContext } from "../CheckboxGroup/index.js";
/**
* The Checkbox component is used for selecting multiple options from a set.
* @see https://rsuitejs.com/components/checkbox
*/
const Checkbox = forwardRef((props, ref) => {
const {
propsWithDefaults
} = useCustom('Checkbox', props);
const checkboxGroupContext = useContext(CheckboxGroupContext);
const {
inline: inlineContext,
name: nameContext,
disabled: disabledContext,
readOnly: readOnlyContext,
plaintext: plaintextContext,
onChange: onGroupChange
} = checkboxGroupContext !== null && checkboxGroupContext !== void 0 ? checkboxGroupContext : {};
const {
as,
checked: controlledChecked,
className,
children,
classPrefix = 'checkbox',
checkable = true,
color,
defaultChecked = false,
title,
inputRef,
inputProps,
indeterminate,
labelClickable = true,
tabIndex = 0,
disabled = disabledContext,
readOnly = readOnlyContext,
plaintext = plaintextContext,
inline = inlineContext,
name = nameContext,
value,
onClick,
onCheckboxClick,
onChange,
...rest
} = propsWithDefaults;
const [selfChecked, setSelfChecked, selfControlled] = useControlled(controlledChecked, defaultChecked);
// Either <Checkbox> is checked itself or by parent <CheckboxGroup>
const checked = useMemo(() => {
var _checkboxGroupContext, _checkboxGroupContext2;
if (!checkboxGroupContext) {
return selfChecked;
}
// fixme value from group should not be nullable
return (_checkboxGroupContext = (_checkboxGroupContext2 = checkboxGroupContext.value) === null || _checkboxGroupContext2 === void 0 ? void 0 : _checkboxGroupContext2.some(checkedValue => checkedValue === value)) !== null && _checkboxGroupContext !== void 0 ? _checkboxGroupContext : false;
}, [checkboxGroupContext, selfChecked, value]);
const {
merge,
prefix,
withPrefix
} = useStyles(classPrefix);
const classes = merge(className, withPrefix());
const [htmlInputProps, restProps] = partitionHTMLProps(rest);
// If <Checkbox> is within a <CheckboxGroup>, it's bound to be controlled
// because its checked state is inferred from group's value, not retrieved from the DOM
const controlled = checkboxGroupContext ? true : selfControlled;
if (typeof controlled !== 'undefined') {
// In uncontrolled situations, use defaultChecked instead of checked
htmlInputProps[controlled ? 'checked' : 'defaultChecked'] = checked;
}
const checkboxRef = useIndeterminateCheckbox(indeterminate);
const handleChange = useEventCallback(event => {
const nextChecked = event.target.checked;
if (disabled || readOnly) {
return;
}
setSelfChecked(nextChecked);
onChange === null || onChange === void 0 || onChange(value, nextChecked, event);
onGroupChange === null || onGroupChange === void 0 || onGroupChange(value, nextChecked, event);
});
const handleLabelClick = useEventCallback(event => {
// Prevent check when label is not clickable
if (!labelClickable && event.target !== checkboxRef.current) {
event.preventDefault();
}
});
const labelId = useUniqueId('label-');
if (plaintext) {
return checked ? /*#__PURE__*/React.createElement(Box, _extends({
as: as
}, restProps, {
ref: ref,
className: classes
}), children) : null;
}
const control = /*#__PURE__*/React.createElement("span", {
className: prefix`control`
}, /*#__PURE__*/React.createElement("input", _extends({}, htmlInputProps, inputProps, {
"aria-disabled": disabled,
"aria-checked": indeterminate ? 'mixed' : checked,
"aria-labelledby": labelId,
name: name,
value: value,
type: "checkbox",
ref: mergeRefs(checkboxRef, inputRef),
tabIndex: tabIndex,
readOnly: readOnly,
disabled: disabled,
onClick: onCheckboxClick,
onChange: handleChange
})), /*#__PURE__*/React.createElement("span", {
className: prefix`inner`,
"aria-hidden": true,
"data-testid": "checkbox-control-inner"
}));
return /*#__PURE__*/React.createElement(Box, _extends({
as: as
}, restProps, {
ref: ref,
onClick: onClick,
className: classes,
"data-color": color,
"data-checked": indeterminate ? 'mixed' : checked,
"data-disabled": disabled,
"data-inline": inline
}), /*#__PURE__*/React.createElement("div", {
className: prefix`checker`
}, /*#__PURE__*/React.createElement("label", {
title: title,
onClick: handleLabelClick
}, checkable ? control : null, /*#__PURE__*/React.createElement("span", {
className: prefix`label`,
id: labelId
}, children))));
});
Checkbox.displayName = 'Checkbox';
export default Checkbox;