"use client";
import { type ButtonHTMLAttributes, forwardRef, useState } from "react";
import { cn } from "@/lib/utils";
export type SwitchSize = "sm" | "md";
export interface SwitchProps
extends Omit, "onChange" | "value" | "defaultValue"> {
/** Controlled on state. */
checked?: boolean;
/** Starting state when uncontrolled. Default false. */
defaultChecked?: boolean;
/** Called with the next state each time the switch is toggled. */
onCheckedChange?: (checked: boolean) => void;
/** Track size. Default "md". */
size?: SwitchSize;
}
const SIZES: Record = {
sm: { track: "h-5 w-9", thumb: "h-4 w-4 group-data-[state=on]:translate-x-4" },
md: { track: "h-6 w-11", thumb: "h-5 w-5 group-data-[state=on]:translate-x-5" },
};
/**
* An on and off switch. Put it inside a label and the whole row becomes the
* tap target, with no dead space between the text and the track.
*/
export const Switch = forwardRef(function Switch(
{ checked, defaultChecked = false, onCheckedChange, size = "md", className, onClick, ...props },
ref,
) {
const [uncontrolled, setUncontrolled] = useState(defaultChecked);
const isControlled = checked !== undefined;
const on = isControlled ? checked : uncontrolled;
return (
);
});