99 lines
2.7 KiB
TypeScript
99 lines
2.7 KiB
TypeScript
import React, {
|
|
DetailedHTMLProps,
|
|
HTMLAttributes,
|
|
InputHTMLAttributes,
|
|
ReactNode,
|
|
} from "react";
|
|
import { twMerge } from "tailwind-merge";
|
|
import CheckMarkSVG from "../svgs/CheckMarkSVG";
|
|
|
|
export type CheckboxProps = DetailedHTMLProps<
|
|
InputHTMLAttributes<HTMLInputElement>,
|
|
HTMLInputElement
|
|
> & {
|
|
name: string;
|
|
wrapperProps?: DetailedHTMLProps<
|
|
HTMLAttributes<HTMLDivElement>,
|
|
HTMLDivElement
|
|
>;
|
|
label?: string | ReactNode;
|
|
labelProps?: DetailedHTMLProps<
|
|
HTMLAttributes<HTMLLabelElement>,
|
|
HTMLLabelElement
|
|
>;
|
|
defaultChecked?: boolean;
|
|
wrapperClassName?: string;
|
|
setChecked?: React.Dispatch<React.SetStateAction<boolean>>;
|
|
};
|
|
|
|
/**
|
|
* # Checkbox Component
|
|
* @className twui-checkbox
|
|
* @className twui-checkbox-checked
|
|
* @className twui-checkbox-unchecked
|
|
*/
|
|
export default function Checkbox({
|
|
wrapperProps,
|
|
label,
|
|
labelProps,
|
|
size,
|
|
name,
|
|
wrapperClassName,
|
|
defaultChecked,
|
|
setChecked,
|
|
...props
|
|
}: CheckboxProps) {
|
|
const finalSize = size || 20;
|
|
|
|
const [internalChecked, setInternalChecked] = React.useState(
|
|
defaultChecked || false
|
|
);
|
|
|
|
const checkMarkRef = React.useRef<HTMLInputElement>();
|
|
|
|
return (
|
|
<div
|
|
{...wrapperProps}
|
|
onClick={(e) => {
|
|
checkMarkRef.current?.click();
|
|
wrapperProps?.onClick?.(e);
|
|
}}
|
|
className={twMerge(
|
|
"flex items-center gap-2",
|
|
wrapperClassName,
|
|
wrapperProps?.className
|
|
)}
|
|
>
|
|
<input
|
|
type="checkbox"
|
|
{...props}
|
|
width={finalSize}
|
|
height={finalSize}
|
|
className={twMerge("hidden")}
|
|
name={name}
|
|
onChange={(e) => {
|
|
setInternalChecked(e.target.checked);
|
|
setChecked?.(e.target.checked);
|
|
}}
|
|
ref={checkMarkRef as any}
|
|
/>
|
|
<div
|
|
className={twMerge(
|
|
"flex items-center justify-center p-[3px] rounded",
|
|
internalChecked
|
|
? "bg-emerald-700 twui-checkbox-checked"
|
|
: "outline-slate-600 dark:outline-white/50 outline-2 outline -outline-offset-2 twui-checkbox-unchecked",
|
|
"twui-checkbox"
|
|
)}
|
|
style={{
|
|
width: finalSize + "px",
|
|
height: finalSize + "px",
|
|
}}
|
|
>
|
|
{internalChecked && <CheckMarkSVG />}
|
|
</div>
|
|
{label && <label>{label}</label>}
|
|
</div>
|
|
);
|
|
}
|