@syncfusion/react-buttons
Version:
Syncfusion React Buttons package is a feature-rich collection of UI components including Button, CheckBox, RadioButton, Switch, Chip, and more for building modern, interactive React applications.
145 lines (144 loc) • 7.74 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useEffect, useCallback, useImperativeHandle, useRef, forwardRef } from 'react';
import { preRender, useProviderContext, useRippleEffect, getUniqueID, Color, Size, Position } from '@syncfusion/react-base';
import { CheckLargeIcon, IntermediateBarIcon } from '@syncfusion/react-icons';
const CHECK = 'sf-checkbox-checked';
const DISABLED = 'sf-disabled sf-no-pointer';
const FRAME = 'sf-checkbox-frame';
const INDETERMINATE = 'sf-checkbox-indeterminate';
const LABEL = 'sf-label';
const WRAPPER = 'sf-control sf-checkbox-wrapper';
const CHECKBOX_CLASS = 'sf-checkbox';
/**
* The Checkbox component allows users to select one or multiple options from a list, providing a visual representation of a binary choice with states like checked, unchecked, or indeterminate.
*
* ```typescript
* import { Checkbox } from "@syncfusion/react-buttons";
*
* <Checkbox checked={true} label="Accept Terms and Conditions" />
* ```
*/
export const Checkbox = forwardRef((props, ref) => {
const { onChange, checked, defaultChecked = false, color = Color.Primary, icon, checkedIcon, indeterminateIcon, className = '', disabled = false, indeterminate = false, labelPlacement = Position.Right, name = '', label = '', value = '', size = Size.Medium, id = getUniqueID('checkbox'), ...domProps } = props;
const isControlled = checked !== undefined;
const [checkedState, setCheckedState] = useState(() => {
if (isControlled) {
return checked;
}
return defaultChecked;
});
const [isIndeterminate, setIsIndeterminate] = useState(indeterminate);
const [isFocused, setIsFocused] = useState(false);
const inputRef = useRef(null);
const wrapperRef = useRef(null);
const rippleContainerRef = useRef(null);
const { dir, ripple } = useProviderContext();
const { rippleMouseDown, Ripple } = useRippleEffect(ripple, { isCenterRipple: true });
const publicAPI = {
checked,
indeterminate,
value,
color,
size,
icon,
checkedIcon
};
useImperativeHandle(ref, () => ({
...publicAPI,
element: inputRef.current
}), [publicAPI]);
useEffect(() => {
if (isControlled) {
setCheckedState(!!checked);
}
}, [checked, isControlled]);
useEffect(() => {
preRender('checkbox');
}, []);
useEffect(() => {
setIsIndeterminate(indeterminate);
}, [indeterminate]);
const handleStateChange = useCallback((event) => {
const newChecked = event.target.checked;
setIsIndeterminate(isIndeterminate);
setIsFocused(false);
if (!isControlled) {
setCheckedState(newChecked);
}
if (onChange) {
onChange({ event, value: newChecked });
}
}, [onChange, isControlled, isIndeterminate]);
const handleFocus = () => {
setIsFocused(true);
};
const handleBlur = () => {
setIsFocused(false);
};
const handleMouseDown = useCallback((e) => {
if (!ripple || !rippleContainerRef.current || !rippleMouseDown) {
return;
}
const syntheticEvent = {
...e,
currentTarget: rippleContainerRef.current,
target: rippleContainerRef.current,
preventDefault: e.preventDefault,
stopPropagation: e.stopPropagation
};
rippleMouseDown(syntheticEvent);
}, [ripple, rippleMouseDown]);
const wrapperClass = [
WRAPPER,
className,
color && color.toLowerCase() !== 'secondary' ? `sf-${color.toLowerCase()}` : '',
disabled ? DISABLED : '',
isFocused ? 'sf-focus' : '',
dir === 'rtl' ? 'sf-rtl' : '',
size && size.toLowerCase() !== 'medium' ? `sf-${size.toLowerCase()}` : ''
].filter(Boolean).join(' ');
const renderRipple = useCallback(() => (_jsx("span", { ref: rippleContainerRef, className: `sf-checkbox-ripple sf-checkbox-ripple-${size.toLowerCase().substring(0, 2)} ${(labelPlacement === 'Top' || labelPlacement === 'Bottom') ? 'sf-checkbox-vertical' : 'sf-checkbox-horizontal'}`, children: ripple && _jsx(Ripple, {}) })), [ripple, size, labelPlacement, rippleContainerRef]);
const sizeMap = {
small: 'sf-font-size-sm',
large: 'sf-font-size-base'
};
const labelFontSizeClass = size ? sizeMap[size.toLowerCase()] ?? 'sf-font-size-sm' : 'sf-font-size-sm';
const renderIcons = () => {
const getSizeDimensions = (size) => {
const sizeMap = {
[Size.Small]: 12,
[Size.Medium]: 14,
[Size.Large]: 16
};
return sizeMap[size] ?? 14;
};
const dimensions = getSizeDimensions(size);
return (_jsxs("span", { className: `sf-checkbox-icons ${FRAME}-${size.toLowerCase().substring(0, 2)} ${isIndeterminate ? INDETERMINATE : checkedState ? CHECK : ''}`, children: [isIndeterminate && indeterminateIcon ? (indeterminateIcon) : isIndeterminate && (_jsx(IntermediateBarIcon, { width: 20, height: 20, fill: 'currentColor' })), checkedState && !isIndeterminate && (_jsx(CheckLargeIcon, { width: dimensions, height: dimensions, fill: "currentColor" }))] }));
};
return (_jsx("div", { ref: wrapperRef, className: wrapperClass, "aria-disabled": disabled ? 'true' : 'false', onMouseDown: handleMouseDown, children: _jsxs("label", { className: `sf-checkbox-label sf-${labelPlacement.toLowerCase()} sf-checkbox-${size.toLowerCase()}`, children: [_jsx("input", { ref: inputRef, id: id, className: `${CHECKBOX_CLASS} ${className}`, type: "checkbox", name: name, value: value, checked: isControlled ? checked : checkedState, disabled: disabled, onFocus: handleFocus, onBlur: handleBlur, onChange: handleStateChange, ...domProps }), label && (_jsx("span", { className: `${LABEL} ${labelFontSizeClass}`, children: label })), ripple && renderRipple(), checkedState ? checkedIcon : icon, !checkedIcon && !icon && renderIcons()] }) }));
});
Checkbox.displayName = 'Checkbox';
export default Checkbox;
const createCSSCheckbox = (props) => {
const { className = '', checked = false, label = '', ...domProps } = props;
const { dir, ripple } = useProviderContext();
const rippleContainerRef = useRef(null);
const { rippleMouseDown, Ripple } = useRippleEffect(ripple, { isCenterRipple: true });
const handleMouseDown = useCallback((e) => {
if (ripple && rippleContainerRef.current && rippleMouseDown) {
const syntheticEvent = {
...e,
currentTarget: rippleContainerRef.current,
target: rippleContainerRef.current,
preventDefault: e.preventDefault,
stopPropagation: e.stopPropagation
};
rippleMouseDown(syntheticEvent);
}
}, [ripple, rippleMouseDown]);
return (_jsxs("div", { className: `sf-checkbox-wrapper ${className} ${(dir === 'rtl') ? 'sf-rtl' : ''}`, onMouseDown: handleMouseDown, ...domProps, children: [_jsx("span", { ref: rippleContainerRef, className: `sf-ripple-container sf-checkbox-ripple sf-checkbox-ripple-me ${checked ? 'sf-ripple-check' : ''} sf-checkbox-horizontal`, children: ripple && _jsx(Ripple, {}) }), _jsx("span", { className: `sf-checkbox-frame-me sf-checkbox-icons ${checked ? 'sf-checkbox-checked' : ''}`, children: checked && (_jsx(CheckLargeIcon, { width: 12, height: 12, fill: 'currentColor' })) }), label && (_jsx("span", { className: LABEL, children: label }))] }));
};
// Component definition for Checkbox using create function
export const CSSCheckbox = (props) => {
return createCSSCheckbox(props);
};