Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | 5x 91x 91x 91x 52x 52x 50x 2x 91x 5x 5x 86x 4x 10x 3x 82x 5x | import type { InputHTMLAttributes, ReactNode } from 'react';
import { forwardRef } from 'react';
import type { Control, FieldPath, FieldValues } from 'react-hook-form';
import { Controller } from 'react-hook-form';
import { cn } from '@/lib/utils';
import { Text } from '@/components/text';
export interface BaseCheckboxProps
extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
label?: string | ReactNode;
error?: string;
description?: string;
}
// Enhanced Checkbox props that can work with React Hook Form
export interface CheckboxProps<T extends FieldValues = FieldValues>
extends BaseCheckboxProps {
name?: FieldPath<T>;
control?: Control<T>;
}
const BaseCheckbox = forwardRef<HTMLInputElement, BaseCheckboxProps>(
({ className, label, error, description, id, ...props }, ref) => {
const checkboxId =
id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
const baseStyles = [
'rounded border-gray-300 text-primary focus:ring-primary',
'focus:ring-2 focus:ring-offset-2',
'disabled:cursor-not-allowed disabled:opacity-50',
error ? 'border-red-500' : 'border-gray-300',
];
const renderLabel = () => {
Iif (!label) return null;
if (typeof label === 'string') {
return <span className="text-sm text-muted-foreground">{label}</span>;
}
return label;
};
return (
<div className="flex flex-col space-y-1">
<div className="flex items-center space-x-2">
<input
type="checkbox"
id={checkboxId}
className={cn(baseStyles.join(' '), className)}
ref={ref}
{...props}
/>
{label && (
<label htmlFor={checkboxId} className="text-sm cursor-pointer">
{renderLabel()}
</label>
)}
</div>
{description && (
<Text size="xs" variant="muted" className="ml-6">
{description}
</Text>
)}
{error && (
<Text size="sm" variant="destructive" className="ml-6" as="span">
{error}
</Text>
)}
</div>
);
}
);
BaseCheckbox.displayName = 'BaseCheckbox';
// Smart Checkbox component that works with or without React Hook Form
const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
({ name, control, ...props }, ref) => {
// If control and name are provided, use Controller
if (control && name) {
return (
<Controller
name={name as any}
control={control as any}
render={({
field: { value, onChange, ...field },
fieldState: { error },
}) => (
<BaseCheckbox
{...field}
{...props}
checked={value}
onChange={e => onChange(e.target.checked)}
error={error?.message || props.error}
ref={ref}
/>
)}
/>
);
}
// Otherwise, use as regular checkbox
return <BaseCheckbox {...props} ref={ref} />;
}
);
Checkbox.displayName = 'Checkbox';
export { Checkbox, BaseCheckbox };
|