UNPKG

@yamada-ui/checkbox

Version:

Yamada UI checkbox component

272 lines (270 loc) • 7.36 kB
"use client" // src/use-checkbox.ts import { formControlProperties, useFormControlProps } from "@yamada-ui/form-control"; import { trackFocusVisible } from "@yamada-ui/use-focus-visible"; import { dataAttr, handlerAll, mergeRefs, splitObject, useCallbackRef, useSafeLayoutEffect, useUpdateEffect } from "@yamada-ui/utils"; import { useCallback, useEffect, useId, useRef, useState } from "react"; var useCheckbox = ({ id, ...props }) => { const uuid = useId(); id != null ? id : id = uuid; const { id: _id, name, isChecked, checked: checkedProp = isChecked, defaultIsChecked, defaultChecked = defaultIsChecked, isIndeterminate, indeterminate = isIndeterminate, selectOnEnter, tabIndex, value, onChange: onChangeProp, ...computedProps } = useFormControlProps({ id, ...props }); const [ { "aria-readonly": _ariaReadonly, disabled, readOnly, required, onBlur: onBlurProp, onFocus: onFocusProp, ...formControlProps }, rest ] = splitObject(computedProps, formControlProperties); const [focusVisible, setFocusVisible] = useState(false); const [focused, setFocused] = useState(false); const [hovered, setHovered] = useState(false); const [active, setActive] = useState(false); const inputRef = useRef(null); const [label, setLabel] = useState(true); const [checked, setIsChecked] = useState(!!defaultChecked); const controlled = checkedProp !== void 0; const resolvedChecked = controlled ? checkedProp : checked; const onChange = useCallbackRef( (ev) => { if (readOnly || disabled) { ev.preventDefault(); return; } if (!controlled) setIsChecked( !resolvedChecked || indeterminate ? true : ev.target.checked ); onChangeProp == null ? void 0 : onChangeProp(ev); }, [readOnly, disabled, controlled, resolvedChecked, indeterminate] ); const onFocus = useCallbackRef(onFocusProp); const onBlur = useCallbackRef(onBlurProp); const onKeyDown = useCallback( ({ key }) => { var _a; if (key === " ") setActive(true); if (selectOnEnter && key === "Enter") (_a = inputRef.current) == null ? void 0 : _a.click(); }, [setActive, selectOnEnter] ); const onKeyUp = useCallback( ({ key }) => { if (key === " ") setActive(false); }, [setActive] ); useEffect(() => { return trackFocusVisible(setFocusVisible); }, []); useSafeLayoutEffect(() => { if (inputRef.current) inputRef.current.indeterminate = Boolean(isIndeterminate); }, [isIndeterminate]); useUpdateEffect(() => { if (disabled) setFocused(false); }, [disabled, setFocused]); useSafeLayoutEffect(() => { var _a; if (!((_a = inputRef.current) == null ? void 0 : _a.form)) return; inputRef.current.form.onreset = () => setIsChecked(!!defaultChecked); }, []); useSafeLayoutEffect(() => { if (!inputRef.current) return; if (inputRef.current.checked !== resolvedChecked) setIsChecked(inputRef.current.checked); }, [inputRef.current]); const getContainerProps = useCallback( (props2 = {}, ref = null) => ({ ...formControlProps, ...props2, ref: mergeRefs(ref, (el) => { if (el) setLabel(el.tagName === "LABEL"); }), "data-checked": dataAttr(resolvedChecked), "data-focus": dataAttr(focused), "data-focus-visible": dataAttr(focused && focusVisible), onClick: handlerAll(props2.onClick, () => { var _a; if (label) return; (_a = inputRef.current) == null ? void 0 : _a.click(); requestAnimationFrame(() => { var _a2; return (_a2 = inputRef.current) == null ? void 0 : _a2.focus(); }); }) }), [resolvedChecked, label, focused, focusVisible, formControlProps] ); const getIconProps = useCallback( (props2 = {}, ref = null) => ({ ...formControlProps, ...props2, ref, "aria-hidden": true, "data-active": dataAttr(active), "data-checked": dataAttr(resolvedChecked), "data-focus": dataAttr(focused), "data-focus-visible": dataAttr(focused && focusVisible), "data-hover": dataAttr(hovered), "data-indeterminate": dataAttr(indeterminate), onMouseDown: handlerAll(props2.onMouseDown, (ev) => { if (focused) ev.preventDefault(); setActive(true); }), onMouseEnter: handlerAll(props2.onMouseEnter, () => setHovered(true)), onMouseLeave: handlerAll(props2.onMouseLeave, () => setHovered(false)), onMouseUp: handlerAll(props2.onMouseUp, () => setActive(false)) }), [ active, resolvedChecked, focused, hovered, focusVisible, indeterminate, formControlProps ] ); const getInputProps = useCallback( (props2 = {}, ref = null) => ({ ...formControlProps, ...props2, id, ref: mergeRefs(inputRef, ref), type: "checkbox", name, style: { border: "0px", clip: "rect(0px, 0px, 0px, 0px)", height: "1px", margin: "-1px", overflow: "hidden", padding: "0px", position: "absolute", whiteSpace: "nowrap", width: "1px" }, "aria-checked": indeterminate ? "mixed" : resolvedChecked, checked: resolvedChecked, disabled, readOnly, required, tabIndex, value, onBlur: handlerAll(props2.onBlur, onBlur, () => setFocused(false)), onChange: handlerAll(props2.onChange, onChange), onFocus: handlerAll(props2.onFocus, onFocus, () => setFocused(true)), onKeyDown: handlerAll(props2.onKeyDown, onKeyDown), onKeyUp: handlerAll(props2.onKeyUp, onKeyUp) }), [ indeterminate, formControlProps, id, name, value, tabIndex, required, disabled, readOnly, resolvedChecked, onChange, onBlur, onFocus, onKeyDown, onKeyUp ] ); const getLabelProps = useCallback( (props2 = {}, ref = null) => ({ ...formControlProps, ...props2, ref, "data-checked": dataAttr(resolvedChecked), onMouseDown: handlerAll(props2.onMouseDown, (ev) => { ev.preventDefault(); ev.stopPropagation(); }), onTouchStart: handlerAll(props2.onTouchStart, (ev) => { ev.preventDefault(); ev.stopPropagation(); }) }), [resolvedChecked, formControlProps] ); return { active, checked: resolvedChecked, focused, focusVisible, hovered, indeterminate, /** * @deprecated Use `active` instead. */ isActive: active, /** * @deprecated Use `checked` instead. */ isChecked: resolvedChecked, /** * @deprecated Use `focused` instead. */ isFocused: focused, /** * @deprecated Use `focusVisible` instead. */ isFocusVisible: focusVisible, /** * @deprecated Use `hovered` instead. */ isHovered: hovered, /** * @deprecated Use `indeterminate` instead. */ isIndeterminate, props: rest, getContainerProps, getIconProps, getInputProps, getLabelProps }; }; export { useCheckbox }; //# sourceMappingURL=chunk-AA57K3IT.mjs.map