/** @jsxImportSource @emotion/react */ 'use client'; import { Background, Flex, Padding, Text, TouchableOpacity } from '@/@dble_layout'; import onScrollToNextRef from '@/libs/handler/onScrollToRef'; import { fontSize } from '@/libs/themes'; import { CSSObject } from '@emotion/react'; import { InputHTMLAttributes, forwardRef, memo, useCallback, useEffect, useId, useRef, useState } from 'react'; interface Props extends Omit, 'size' | 'type'> { type?: 'text' | 'number' | 'tel' | 'price' | 'password' | 'textarea' | 'select'; autoRaise?: boolean; label: string; error?: boolean; errorMessage?: string; onClear?: () => void; children?: never[]; isStroke?: boolean; fieldColor?: string; renderItem?: (item: unknown, index?: number) => React.ReactElement; options?: unknown[]; focus?: boolean; isFocus?: boolean; } const TextField = memo( forwardRef( ( { type = 'text', autoRaise = true, label, value = '', error, errorMessage, onClear, isStroke = false, fieldColor = '#fff', options = [], renderItem, focus = true, isFocus = false, ...rest }, ref ) => { const stableId = useId(); const fieldRef = useRef(null); const textareaRef = useRef(null); const [isFocused, setIsFocused] = useState<'focus' | 'error' | null>(null); const isError = value !== '' && error; const [textareaHeight, setTextareaHeight] = useState(0); // // events const handleFocus = useCallback(() => { if (fieldRef.current) { setIsFocused('focus'); if (isFocus) onScrollToNextRef(fieldRef); } }, [isFocus]); const handleBlur = useCallback(() => { if (fieldRef.current) setIsFocused(null); }, []); const handleChange = (e: React.ChangeEvent) => { let newValue = e.target.value; if (type === 'tel') { newValue = formatPhoneNumber(newValue) || ''; } if (type === 'price') { newValue = newValue.replace(/[^0-9]/g, ''); newValue = new Intl.NumberFormat('ko-KR').format(Number(newValue)); } if (rest.onChange) { rest.onChange({ ...e, target: { ...e.target, value: newValue } }); } }; // rasize useEffect(() => { const handleRasie = () => { if (value && value !== '' && textareaRef && 'current' in textareaRef && textareaRef.current) { textareaRef.current.style.height = 'auto'; textareaRef.current.style.height = textareaRef.current.scrollHeight + 'px'; setTextareaHeight(textareaRef.current.scrollHeight); } else if (textareaRef.current) { textareaRef.current.style.height = 'auto'; setTextareaHeight(0); } }; if (type === 'textarea' && autoRaise) handleRasie(); }, [type, value, textareaRef, autoRaise]); // // themes const bg = () => { if (isError) return '#f9f2f2'; if (focus && isFocused === 'focus') return '#fff'; return fieldColor; }; const br = () => { if (isError) return '#f09696'; if (focus && isFocused === 'focus') return '#c9ced7'; return isStroke ? '#e5e5e5' : '#eaeaea'; }; const labelColor = () => { if (isError) return '#f56767'; return '#7e7f84'; }; return ( {isError && ( )} {error && errorMessage ? errorMessage : label} {type === 'textarea' && (