import React, {ComponentPropsWithoutRef, ReactNode, useId} from 'react'; import clsx from 'clsx'; import {useController} from 'react-hook-form'; import {mergeProps, useObjectRef} from '@react-aria/utils'; import {InputSize} from '../input-field/input-size'; import {getInputFieldClassNames} from '../input-field/get-input-field-class-names'; import {AutoFocusProps, useAutoFocus} from '../../focus/use-auto-focus'; interface SwitchProps extends AutoFocusProps, Omit, 'size'> { size?: InputSize; className?: string; description?: ReactNode; invalid?: boolean; errorMessage?: string; } export const Switch = React.forwardRef( (props, ref) => { const { children, size = 'sm', description, className, invalid, autoFocus, errorMessage, ...domProps } = props; const inputRef = useObjectRef(ref); useAutoFocus({autoFocus}, inputRef); const style = getSizeClassName(size); const fieldClassNames = getInputFieldClassNames(props); const descriptionId = useId(); return (
{description && !errorMessage && (
{description}
)} {errorMessage && (
{errorMessage}
)}
); } ); interface FormSwitchProps extends SwitchProps { name: string; } export function FormSwitch(props: FormSwitchProps) { const { field: {onChange, onBlur, value = false, ref}, fieldState: {invalid, error}, } = useController({ name: props.name, }); const formProps: Partial = { onChange: e => { if (e.target.value && e.target.value !== 'on') { onChange(e.target.checked ? e.target.value : false); } else { onChange(e); } }, onBlur, checked: !!value, invalid, errorMessage: error?.message, name: props.name, }; return ; } function getSizeClassName(size: InputSize): string { switch (size) { case 'xl': return 'w-68 h-36 before:w-28 before:h-28 checked:before:translate-x-36'; case 'lg': return 'w-56 h-30 before:w-22 before:h-22 checked:before:translate-x-30'; case 'md': return 'w-46 h-24 before:w-18 before:h-18 checked:before:translate-x-24'; case 'xs': return 'w-30 h-16 before:w-12 before:h-12 checked:before:translate-x-16'; default: return 'w-38 h-20 before:w-14 before:h-14 checked:before:translate-x-20'; } }