UNPKG

@nex-ui/react

Version:

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

259 lines (255 loc) • 9.02 kB
"use client"; 'use strict'; var jsxRuntime = require('react/jsx-runtime'); 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 IndeterminateIcon = require('./IndeterminateIcon.cjs'); var Context = require('../provider/Context.cjs'); var useDefaultProps = require('../utils/useDefaultProps.cjs'); var useStyles = require('../utils/useStyles.cjs'); var useSlot = require('../utils/useSlot.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 { radius, size, color, disabled, checked, classes, indeterminate } = ownerState; return react.useMemo(()=>{ const checkboxRoot = `${prefix}-checkbox`; const slots = { root: [ 'root', `radius-${radius}`, `size-${size}`, `color-${color}`, disabled && 'disabled', checked && 'checked', indeterminate && 'indeterminate' ], input: [ 'input' ], label: [ 'label' ], icon: [ 'icon' ] }; return composeClasses.composeClasses(slots, getUtilityClass.getUtilityClass(checkboxRoot), classes); }, [ checked, classes, color, disabled, indeterminate, prefix, radius, size ]); }; const useSlotAriaProps = (ownerState)=>{ const { disabled, type, checked, children, value, role, slotProps, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-checked': ariaChecked, 'aria-disabled': ariaDisabled, as = 'input', tabIndex = 0 } = ownerState; const id = react.useId(); return react.useMemo(()=>{ const labelProps = slotProps?.label; const stringChildren = utils.isString(children); const label = { id: labelProps?.id ?? (stringChildren ? id : undefined) }; let input = { 'aria-labelledby': ariaLabelledBy ?? label.id, 'aria-label': ariaLabel ?? (stringChildren ? children : undefined), tabIndex: disabled ? -1 : tabIndex }; if (as === 'input' || utils.isFunction(as)) { input = { disabled, checked, type, value, ...input }; } else { input = { role: role ?? 'checkbox', 'aria-checked': ariaChecked ?? checked, 'aria-disabled': ariaDisabled ?? (disabled || undefined), ...input }; } return { input, label }; }, [ ariaChecked, ariaDisabled, ariaLabel, ariaLabelledBy, as, checked, children, disabled, id, role, slotProps?.label, tabIndex, type, value ]); }; const Checkbox = (inProps)=>{ const { primaryThemeColor, css } = Context.useNexUI(); 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 CheckboxGroup is being used, `checked` will be ignored. Use the `value` of the CheckboxGroup instead.'); } if ('defaultChecked' in props) { console.warn('[Nex UI] Checkbox: The CheckboxGroup is being used, `defaultChecked` will be ignored. Use the `defaultValue` of the CheckboxGroup instead.'); } if (!('value' in props)) { console.warn('[Nex UI] Checkbox: The CheckboxGroup is being used, but `value` is not provided.'); } } const { sx, icon, value, className, children, slotProps, onCheckedChange, indeterminate, checked: checkedProp, type = 'checkbox', defaultChecked = false, 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, focusProps } = hooks.useFocusRing(); const checked = inGroup ? groupCtx.isChecked(value) : rawChecked; const ownerState = { ...props, defaultChecked, type, name, disabled, color, checked, size, radius, inGroup }; const handleChange = hooks.useEvent((event)=>{ if (inGroup && value) { groupCtx.toggleValue(value); } if (!inGroup) { setRawChecked(event.target.checked); } }); const handleClick = hooks.useEvent((event)=>{ if (event.currentTarget.tagName !== 'INPUT' && event.currentTarget === event.target) { if (inGroup && value) { groupCtx.toggleValue(value); } if (!inGroup) { setRawChecked(!checked); } } }); const handleKeyUp = hooks.useEvent((event)=>{ // Keyboard accessibility for non interactive elements if (focusVisible && event.key === 'Space' && event.target === event.currentTarget && event.currentTarget.tagName !== 'INPUT' && event.currentTarget === event.target) { event.currentTarget.click(); } }); const classes = useSlotClasses(ownerState); const styles = useStyles.useStyles({ ownerState, name: 'Checkbox', recipe: checkbox.checkboxRecipe }); const slotAriaProps = useSlotAriaProps(ownerState); const [CheckboxRoot, getCheckboxRootProps] = useSlot.useSlot({ ownerState, elementType: 'label', externalSlotProps: slotProps?.root, style: styles.root, classNames: classes.root, additionalProps: { sx, className } }); const [CheckboxInput, getCheckboxInputProps] = useSlot.useSlot({ ownerState, elementType: 'input', externalForwardedProps: remainingProps, classNames: classes.input, style: styles.input, a11y: { ...slotAriaProps.input, onKeyUp: handleKeyUp }, additionalProps: { name, onChange: handleChange, onClick: handleClick, 'data-focus-visible': focusVisible || undefined, ...focusProps } }); const [CheckboxIcon, getCheckboxIconProps] = useSlot.useSlot({ ownerState, elementType: 'span', externalSlotProps: slotProps?.icon, style: styles.icon, classNames: classes.icon }); const [CheckboxLabel, getCheckboxLabelProps] = useSlot.useSlot({ ownerState, elementType: 'span', externalSlotProps: slotProps?.label, style: styles.label, classNames: classes.label, a11y: slotAriaProps.label }); const renderCheckedIcon = ()=>{ if (indeterminate) { return /*#__PURE__*/ jsxRuntime.jsx(IndeterminateIcon.IndeterminateIcon, {}); } const customIcon = icon ? utils.isFunction(icon) ? icon(ownerState) : icon : null; if (!customIcon) { return /*#__PURE__*/ jsxRuntime.jsx(CheckedIcon.CheckedIcon, { checked: checked }); } if (/*#__PURE__*/ react.isValidElement(customIcon)) { const element = customIcon; return /*#__PURE__*/ react.cloneElement(element, { ...element.props, style: { ...element.props.style, ...css(styles.checkedIcon) } }); } return customIcon; }; return /*#__PURE__*/ jsxRuntime.jsxs(CheckboxRoot, { ...getCheckboxRootProps(), children: [ /*#__PURE__*/ jsxRuntime.jsx(CheckboxInput, { ...getCheckboxInputProps() }), /*#__PURE__*/ jsxRuntime.jsx(CheckboxIcon, { ...getCheckboxIconProps(), children: renderCheckedIcon() }), children && /*#__PURE__*/ jsxRuntime.jsx(CheckboxLabel, { ...getCheckboxLabelProps(), children: children }) ] }); }; Checkbox.displayName = 'Checkbox'; exports.Checkbox = Checkbox;