creacion de componentes dinamicos
This commit is contained in:
1 parent
ae415fef4e
commit
d74aa50845
13 files changed
+1448
No files matched your search
@@ -0,0 +1,111 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { FiCheck, FiMinus } from 'react-icons/fi';
|
||||
|
||||
export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
||||
label?: React.ReactNode;
|
||||
description?: string;
|
||||
errorMessage?: string;
|
||||
indeterminate?: boolean;
|
||||
}
|
||||
|
||||
export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
||||
(
|
||||
{
|
||||
label,
|
||||
description,
|
||||
errorMessage,
|
||||
indeterminate = false,
|
||||
checked,
|
||||
disabled,
|
||||
className = '',
|
||||
id,
|
||||
name,
|
||||
...props
|
||||
},
|
||||
forwardedRef
|
||||
) => {
|
||||
const internalRef = useRef<HTMLInputElement>(null);
|
||||
const resolvedRef = (forwardedRef as React.RefObject<HTMLInputElement>) || internalRef;
|
||||
const checkboxId = id || name || (typeof label === 'string' ? label.toLowerCase().replace(/\s+/g, '-') : undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if (resolvedRef.current) {
|
||||
resolvedRef.current.indeterminate = indeterminate;
|
||||
}
|
||||
}, [indeterminate, resolvedRef]);
|
||||
|
||||
const isChecked = Boolean(checked);
|
||||
|
||||
return (
|
||||
<div className={`flex flex-col space-y-1 ${className}`}>
|
||||
<label
|
||||
htmlFor={checkboxId}
|
||||
className={`inline-flex items-start gap-2.5 select-none cursor-pointer group ${
|
||||
disabled ? 'opacity-50 !cursor-not-allowed' : ''
|
||||
}`}
|
||||
>
|
||||
{/* Custom Styled Box */}
|
||||
<div className="relative flex items-center justify-center mt-0.5 shrink-0">
|
||||
<input
|
||||
ref={resolvedRef}
|
||||
id={checkboxId}
|
||||
name={name}
|
||||
type="checkbox"
|
||||
checked={checked}
|
||||
disabled={disabled}
|
||||
className="peer sr-only"
|
||||
{...props}
|
||||
/>
|
||||
|
||||
<div
|
||||
className={`
|
||||
w-4 h-4 rounded-md flex items-center justify-center transition-all duration-200
|
||||
border
|
||||
peer-focus-visible:ring-2 peer-focus-visible:ring-offset-2
|
||||
peer-focus-visible:ring-cyan-500 peer-focus-visible:ring-offset-white dark:peer-focus-visible:ring-offset-slate-950
|
||||
${
|
||||
isChecked || indeterminate
|
||||
? 'bg-cyan-500 border-cyan-500 text-slate-950 shadow-sm shadow-cyan-500/20'
|
||||
: 'bg-white dark:bg-slate-900 border-slate-300 dark:border-slate-700 text-transparent group-hover:border-slate-400 dark:group-hover:border-slate-500'
|
||||
}
|
||||
${
|
||||
errorMessage
|
||||
? '!border-rose-500 !bg-rose-50 dark:!bg-rose-950/30'
|
||||
: ''
|
||||
}
|
||||
`}
|
||||
>
|
||||
{indeterminate ? (
|
||||
<FiMinus className="text-xs stroke-3" />
|
||||
) : isChecked ? (
|
||||
<FiCheck className="text-xs stroke-3" />
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Label and Sub-description */}
|
||||
{(label || description) && (
|
||||
<div className="flex flex-col text-left">
|
||||
{label && (
|
||||
<span className="text-xs sm:text-sm font-medium text-slate-800 dark:text-slate-200 group-hover:text-slate-950 dark:group-hover:text-white transition-colors">
|
||||
{label}
|
||||
</span>
|
||||
)}
|
||||
{description && (
|
||||
<span className="text-xs text-slate-500 dark:text-slate-400">
|
||||
{description}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</label>
|
||||
|
||||
{errorMessage && (
|
||||
<p className="text-xs text-rose-600 dark:text-rose-400 pl-6.5">{errorMessage}</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Checkbox.displayName = 'Checkbox';
|
||||
Reference in new issue
Block a user