Files
core/src/shared/components/Input.js
T

115 lines
4.0 KiB
JavaScript

'use client';
import React from 'react';
const Input = ({
type = 'text',
value,
onChange,
placeholder = '',
label,
error,
required = false,
disabled = false,
className = '',
description,
min,
max,
step,
...props
}) => {
const baseInputClassName = `w-full px-[10px] py-[7px] rounded-lg text-[13px] focus:outline-none transition-all duration-[120ms] ease-out disabled:opacity-50 disabled:cursor-not-allowed bg-white border border-neutral-300 text-neutral-900 placeholder-neutral-400 focus:border-neutral-500 focus:ring-1 focus:ring-neutral-500/20 dark:bg-neutral-900/60 dark:border-neutral-700/50 dark:text-white dark:placeholder-neutral-500 dark:focus:border-neutral-600 dark:focus:ring-neutral-600/20 ${
error ? 'border-red-500/50 dark:border-red-500/50' : ''
} ${className}`;
const handleChange = (e) => {
let newValue = e.target.value;
// Handle number type conversions
if (type === 'number') {
// Convert empty string to 0 for numeric inputs to prevent database errors
if (newValue === '' || newValue === null || newValue === undefined) {
newValue = 0;
} else {
newValue = parseFloat(newValue);
// Handle NaN case
if (isNaN(newValue)) {
newValue = 0;
}
}
}
onChange?.(newValue);
};
// Enhanced color input renderer
const renderColorInput = () => {
return (
<div className="flex gap-2">
<div className="relative">
<input
type="color"
className="absolute inset-0 w-12 h-10 opacity-0 cursor-pointer"
value={value || '#000000'}
onChange={handleChange}
disabled={disabled}
{...props}
/>
<div
className={`w-12 h-10 border rounded-lg cursor-pointer transition-all duration-[120ms] ease-out ${
error ? 'border-red-500/50' : 'border-neutral-300 dark:border-neutral-700/50 dark:hover:border-neutral-600'
} ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`}
style={{ backgroundColor: value || '#000000' }}
></div>
</div>
<input
type="text"
className={`${baseInputClassName} flex-1 min-w-0`}
value={value || ''}
onChange={handleChange}
placeholder={placeholder || 'Enter hex color'}
disabled={disabled}
{...props}
/>
</div>
);
};
return (
<div className="space-y-2">
{label && (
<label className="block text-xs font-medium text-neutral-700 dark:text-white">
{label}
{required && <span className="text-red-500 dark:text-red-400 ml-1">*</span>}
</label>
)}
{type === 'color' ? (
renderColorInput()
) : (
<input
type={type}
value={value}
onChange={handleChange}
placeholder={placeholder}
className={baseInputClassName}
disabled={disabled}
min={min}
max={max}
step={step}
{...props}
/>
)}
{error && (
<p className="text-red-600 dark:text-red-400 text-xs">{error}</p>
)}
{description && !error && (
<p className="text-xs text-neutral-500 dark:text-neutral-400 opacity-75">{description}</p>
)}
</div>
);
};
export default Input;