react-vite-themes
Version:
A test/experimental React theme system created for learning purposes. Features atomic design components, SCSS variables, and dark/light theme support. Not intended for production use.
67 lines (66 loc) • 3.38 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React, { forwardRef, useState } from 'react';
import { Icon } from '../Icon';
export const Input = forwardRef(({ as = 'input', className = '', size = 'md', leftIcon, leftIconSize = 'sm', rightIcon, rightIconSize = 'sm', isRounded = false, showDateIcon = true, dateFormat = 'YYYY-MM-DD', minDate, maxDate, useCustomCalendar = false, showPasswordToggle = false, onChange, type, ...props }, ref) => {
const Component = as;
// Password toggle state
const [showPassword, setShowPassword] = useState(false);
// Determine if this is a password input
const isPasswordInput = type === 'password';
const shouldShowPasswordToggle = isPasswordInput && showPasswordToggle;
// Determine the effective type (password or text for toggle)
const effectiveType = shouldShowPasswordToggle && showPassword ? 'text' : type;
const sizeClasses = {
sm: 'input-sm',
md: 'input-md',
lg: 'input-lg'
};
// Auto-add calendar icon for date inputs if showDateIcon is true
const isDateInput = type === 'date';
const shouldShowDateIcon = isDateInput && showDateIcon && !leftIcon;
const effectiveLeftIcon = shouldShowDateIcon ? 'calendar' : leftIcon;
// Determine effective right icon (password toggle takes precedence)
const effectiveRightIcon = shouldShowPasswordToggle
? (showPassword ? 'eye-off' : 'eye')
: rightIcon;
const inputClasses = [
'input',
sizeClasses[size || 'md'],
effectiveLeftIcon ? 'input-with-left-icon' : '',
effectiveRightIcon ? 'input-with-right-icon' : '',
isRounded ? 'input-rounded' : '',
isDateInput ? 'input-date' : '',
className
].filter(Boolean).join(' ');
// Helper function to render icon
const renderIcon = (icon, iconSize) => {
if (typeof icon === 'string') {
return _jsx(Icon, { name: icon, size: iconSize });
}
return icon;
};
// Handle file input state
const handleChange = (event) => {
if (type === 'file' && event.target instanceof HTMLInputElement) {
const files = event.target.files;
const hasFiles = files && files.length > 0;
// Add or remove the has-files class
if (hasFiles) {
event.target.classList.add('has-files');
}
else {
event.target.classList.remove('has-files');
}
}
// Call the original onChange if provided
if (onChange) {
onChange(event);
}
};
// Handle password toggle
const handlePasswordToggle = () => {
setShowPassword(!showPassword);
};
return (_jsxs("div", { className: "input-wrapper", children: [effectiveLeftIcon && (_jsx("div", { className: "input-left-icon", children: renderIcon(effectiveLeftIcon, leftIconSize) })), _jsx(Component, { ref: ref, className: inputClasses, type: effectiveType, onChange: handleChange, min: minDate, max: maxDate, ...props }), effectiveRightIcon && (_jsx("div", { className: `input-right-icon ${shouldShowPasswordToggle ? 'input-password-toggle' : ''}`, onClick: shouldShowPasswordToggle ? handlePasswordToggle : undefined, children: renderIcon(effectiveRightIcon, rightIconSize) }))] }));
});
Input.displayName = 'Input';