UNPKG

@nex-ui/react

Version:

🎉 A beautiful, modern, and reliable React component library.

217 lines (213 loc) • 7.41 kB
"use client"; 'use strict'; var jsxRuntime = require('react/jsx-runtime'); var styled = require('@nex-ui/styled'); var react = require('react'); var utils = require('@nex-ui/utils'); var hooks = require('@nex-ui/hooks'); var CheckboxGroupContext = require('./CheckboxGroupContext.cjs'); var CheckedIcon = require('./CheckedIcon.cjs'); var Context = require('../provider/Context.cjs'); var useDefaultProps = require('../utils/useDefaultProps.cjs'); var useStyles = require('../utils/useStyles.cjs'); var useSlotProps = require('../utils/useSlotProps.cjs'); var Box = require('../box/Box.cjs'); var composeClasses = require('../utils/composeClasses.cjs'); var checkbox = require('../../theme/recipes/checkbox.cjs'); var getUtilityClass = require('../utils/getUtilityClass.cjs'); const useSlotClasses = (ownerState)=>{ const { prefix } = Context.useNexUI(); const checkboxRoot = `${prefix}-checkbox`; const { radius, size, color, disabled, checked, classes } = ownerState; const slots = { root: [ 'root', `radius-${radius}`, `size-${size}`, `color-${color}`, disabled && 'disabled', checked && 'checked' ], input: [ 'input' ], label: [ 'label' ], icon: [ 'icon' ] }; const composedClasses = composeClasses.composeClasses(slots, getUtilityClass.getUtilityClass(checkboxRoot), classes); return composedClasses; }; const useSlotAriaProps = (ownerState)=>{ const id = react.useId(); const { as, disabled, tabIndex, type, checked, children, value } = ownerState; const childrenString = utils.isString(children); let input = { disabled, checked, type, tabIndex: disabled ? -1 : tabIndex }; if (as === 'input') { input = { ...input, value, 'aria-labelledby': childrenString ? id : undefined, 'aria-label': childrenString ? children : undefined }; } else { input = { role: 'checkbox', tabIndex: disabled ? -1 : tabIndex, 'aria-checked': checked, 'aria-disabled': disabled || undefined, 'aria-labelledby': childrenString ? id : undefined, 'aria-label': childrenString ? children : undefined }; } const label = { id: childrenString ? id : undefined }; return { input, label }; }; const Checkbox = (inProps)=>{ const { primaryThemeColor } = Context.useNexUI(); const inputRef = react.useRef(null); const props = useDefaultProps.useDefaultProps({ name: 'Checkbox', props: inProps }); const groupCtx = CheckboxGroupContext.useCheckboxGroup(); const inGroup = !!groupCtx; if (utils.__DEV__ && inGroup) { if ('checked' in props) { console.warn('[Nex UI] Checkbox: The Checkbox.Group is being used, `checked` will be ignored. Use the `value` of the Checkbox.Group instead.'); } if ('defaultChecked' in props) { console.warn('[Nex UI] Checkbox: The Checkbox.Group is being used, `defaultChecked` will be ignored. Use the `defaultValue` of the Checkbox.Group instead.'); } } const { sx, ref, icon, value, className, children, slotProps, onCheckedChange, checked: checkedProp, type = 'checkbox', defaultChecked = false, as = 'input', tabIndex = 0, name = groupCtx?.name, color = groupCtx?.color ?? primaryThemeColor, disabled = groupCtx?.disabled ?? false, size = groupCtx?.size ?? 'md', radius = groupCtx?.radius ?? groupCtx?.size ?? size, ...remainingProps } = props; const [rawChecked, setRawChecked] = hooks.useControlledState(checkedProp, defaultChecked, onCheckedChange); const [focusVisible] = hooks.useFocusVisible({ ref: inputRef }); const checked = inGroup ? groupCtx.isChecked(value) : rawChecked; const ownerState = { ...props, defaultChecked, type, tabIndex, name, disabled, color, checked, size, radius, as, inGroup }; const handleChange = hooks.useEvent((event)=>{ if (inGroup && value) { groupCtx.toggleValue(value); } if (!inGroup) { setRawChecked(event.target.checked); } }); const handleClick = hooks.useEvent(()=>{ if (utils.isString(as) && as !== 'input') { if (inGroup && value) { groupCtx.toggleValue(value); } if (!inGroup) { setRawChecked(!checked); } } }); const handleKeyUp = hooks.useEvent((event)=>{ // Keyboard accessibility for non interactive elements if (focusVisible && as !== 'input' && event.code === 'Space') { event.currentTarget.click(); } }); const classes = useSlotClasses(ownerState); const styles = useStyles.useStyles({ name: 'Checkbox', ownerState, recipe: checkbox.checkboxRecipe }); const slotAriaProps = useSlotAriaProps(ownerState); const mergedRefs = utils.mergeRefs(ref, inputRef); const rootProps = useSlotProps.useSlotProps({ ownerState, externalSlotProps: slotProps?.root, externalForwardedProps: { sx, className }, sx: styles.root, classNames: classes.root }); const inputProps = useSlotProps.useSlotProps({ ownerState, externalForwardedProps: remainingProps, classNames: classes.input, sx: styles.input, additionalProps: { as, name, onChange: handleChange, onClick: handleClick, onKeyUp: handleKeyUp, ref: mergedRefs, ...slotAriaProps.input } }); const iconProps = useSlotProps.useSlotProps({ ownerState, externalSlotProps: slotProps?.icon, sx: styles.icon, classNames: classes.icon }); const labelProps = useSlotProps.useSlotProps({ ownerState, externalSlotProps: slotProps?.label, sx: styles.label, classNames: classes.label, additionalProps: slotAriaProps.label }); const customIcon = icon ? utils.isFunction(icon) ? icon(ownerState) : icon : null; const checkedIcon = customIcon ? /*#__PURE__*/ react.isValidElement(customIcon) ? /*#__PURE__*/ jsxRuntime.jsx(Box.Box, { // @ts-ignore as: customIcon.type, sx: styles.checkedIcon, ...customIcon.props ?? {} }, customIcon.key) : customIcon : /*#__PURE__*/ jsxRuntime.jsx(CheckedIcon.CheckedIcon, { checked: checked }); return /*#__PURE__*/ jsxRuntime.jsxs(styled.nex.label, { ...rootProps, children: [ /*#__PURE__*/ jsxRuntime.jsx(styled.nex.input, { ...inputProps }), /*#__PURE__*/ jsxRuntime.jsx(styled.nex.span, { ...iconProps, children: checkedIcon }), children && /*#__PURE__*/ jsxRuntime.jsx(styled.nex.span, { ...labelProps, children: children }) ] }); }; Checkbox.displayName = 'Checkbox'; exports.Checkbox = Checkbox;