@yamada-ui/checkbox
Version:
Yamada UI checkbox component
272 lines (270 loc) • 7.36 kB
JavaScript
"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