UNPKG

@base-ui-components/react

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

196 lines (194 loc) 6.41 kB
'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; import { useCheckboxGroupContext } from '../../checkbox-group/CheckboxGroupContext.js'; import { useFieldRootContext } from '../../field/root/FieldRootContext.js'; import { useComponentRenderer } from '../../utils/useComponentRenderer.js'; import { useCustomStyleHookMapping } from '../utils/useCustomStyleHookMapping.js'; import { useCheckboxRoot } from './useCheckboxRoot.js'; import { CheckboxRootContext } from './CheckboxRootContext.js'; /** * Represents the checkbox itself. * Renders a `<button>` element and a hidden `<input>` beside. * * Documentation: [Base UI Checkbox](https://base-ui.com/react/components/checkbox) */ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; const CheckboxRoot = /*#__PURE__*/React.forwardRef(function CheckboxRoot(props, forwardedRef) { const { name, onCheckedChange, defaultChecked, parent = false, readOnly = false, indeterminate = false, required = false, disabled: disabledProp = false, checked: checkedProp, render, className, inputRef, value, ...otherProps } = props; const groupContext = useCheckboxGroupContext(); const parentContext = groupContext?.parent; const isGrouped = parentContext && groupContext.allValues; let groupProps = {}; if (isGrouped) { if (parent) { groupProps = groupContext.parent.getParentProps(); } else if (name) { groupProps = groupContext.parent.getChildProps(name); } } const { checked: groupChecked = checkedProp, indeterminate: groupIndeterminate = indeterminate, onCheckedChange: groupOnChange = onCheckedChange, ...otherGroupProps } = groupProps; const { state: fieldState, disabled: fieldDisabled } = useFieldRootContext(); const disabled = fieldDisabled || groupContext?.disabled || disabledProp; const { checked, getInputProps, getButtonProps } = useCheckboxRoot({ ...props, disabled, inputRef, checked: groupChecked, indeterminate: groupIndeterminate, onCheckedChange: groupOnChange }); const computedChecked = isGrouped ? Boolean(groupChecked) : checked; const computedIndeterminate = isGrouped ? groupIndeterminate : indeterminate; React.useEffect(() => { if (parentContext && name) { parentContext.disabledStatesRef.current.set(name, disabled); } }, [parentContext, disabled, name]); const state = React.useMemo(() => ({ ...fieldState, checked: computedChecked, disabled, readOnly, required, indeterminate: computedIndeterminate }), [fieldState, computedChecked, disabled, readOnly, required, computedIndeterminate]); const customStyleHookMapping = useCustomStyleHookMapping(state); const { renderElement } = useComponentRenderer({ propGetter: getButtonProps, render: render ?? 'button', ref: forwardedRef, state, className, customStyleHookMapping, extraProps: { ...otherProps, ...otherGroupProps } }); return /*#__PURE__*/_jsxs(CheckboxRootContext.Provider, { value: state, children: [renderElement(), !checked && props.name && /*#__PURE__*/_jsx("input", { type: "hidden", name: props.name, value: "off" }), /*#__PURE__*/_jsx("input", { ...getInputProps() })] }); }); process.env.NODE_ENV !== "production" ? CheckboxRoot.propTypes /* remove-proptypes */ = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ // └─────────────────────────────────────────────────────────────────────┘ /** * Whether the checkbox is currently ticked. * * To render an uncontrolled checkbox, use the `defaultChecked` prop instead. * @default undefined */ checked: PropTypes.bool, /** * @ignore */ children: PropTypes.node, /** * CSS class applied to the element, or a function that * returns a class based on the component’s state. */ className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), /** * Whether the checkbox is initially ticked. * * To render a controlled checkbox, use the `checked` prop instead. * @default false */ defaultChecked: PropTypes.bool, /** * Whether the component should ignore user interaction. * @default false */ disabled: PropTypes.bool, /** * Whether the checkbox is in a mixed state: neither ticked, nor unticked. * @default false */ indeterminate: PropTypes.bool, /** * A React ref to access the hidden `<input>` element. */ inputRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.object })]), /** * Identifies the field when a form is submitted. * @default undefined */ name: PropTypes.string, /** * Event handler called when the checkbox is ticked or unticked. * * @param {boolean} checked The new checked state. * @param {Event} event The corresponding event that initiated the change. */ onCheckedChange: PropTypes.func, /** * Whether the checkbox controls a group of child checkboxes. * * Must be used in a [Checkbox Group](https://base-ui.com/react/components/checkbox-group). * @default false */ parent: PropTypes.bool, /** * Whether the user should be unable to tick or untick the checkbox. * @default false */ readOnly: PropTypes.bool, /** * Allows you to replace the component’s HTML element * with a different tag, or compose it with another component. * * Accepts a `ReactElement` or a function that returns the element to render. */ render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), /** * Whether the user must tick the checkbox before submitting a form. * @default false */ required: PropTypes.bool, /** * The value of the selected checkbox. */ value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]) } : void 0; export { CheckboxRoot };