From 1503406b6f7f9b3d078da965a9c47ab308926c6e Mon Sep 17 00:00:00 2001 From: "focp212@naver.com" Date: Tue, 11 Nov 2025 13:44:35 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=20=EB=82=B4?= =?UTF-8?q?=EC=9A=A9=20=EC=88=98=EC=A0=95=EB=B0=8F=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shared/configs/config.development.ts | 2 +- src/shared/configs/config.production.ts | 2 +- src/shared/configs/index.ts | 2 +- src/shared/constants/common.ts | 5 +- src/shared/constants/environment.ts | 14 -- src/shared/constants/form.ts | 55 ------ src/shared/constants/local-storage.ts | 1 - src/shared/lib/error.ts | 3 +- src/shared/lib/hooks/index.tsx | 1 - .../lib/hooks/use-request-notification.ts | 13 -- src/shared/lib/hooks/use-router-listener.ts | 20 --- .../lib/hooks/use-select-bottom-sheet.tsx | 50 ------ src/shared/ui/reset-button/index.tsx | 26 --- src/shared/ui/selects/select-template.tsx | 80 --------- src/shared/ui/selects/select.tsx | 71 -------- src/shared/ui/text-input/clear-button.tsx | 23 --- src/shared/ui/text-input/description.tsx | 9 - src/shared/ui/text-input/error-container.tsx | 8 - src/shared/ui/text-input/error-item.tsx | 10 -- src/shared/ui/text-input/error-message.tsx | 25 --- .../ui/text-input/external-error-display.tsx | 25 --- src/shared/ui/text-input/text-field.tsx | 166 ------------------ .../ui/text-input/text-input-container.tsx | 26 --- src/shared/ui/text-input/text-input.tsx | 117 ------------ src/shared/ui/text-input/text-label.tsx | 33 ---- 25 files changed, 8 insertions(+), 779 deletions(-) delete mode 100644 src/shared/constants/environment.ts delete mode 100644 src/shared/constants/form.ts delete mode 100644 src/shared/lib/hooks/use-request-notification.ts delete mode 100644 src/shared/lib/hooks/use-router-listener.ts delete mode 100644 src/shared/lib/hooks/use-select-bottom-sheet.tsx delete mode 100644 src/shared/ui/reset-button/index.tsx delete mode 100644 src/shared/ui/selects/select-template.tsx delete mode 100644 src/shared/ui/selects/select.tsx delete mode 100644 src/shared/ui/text-input/clear-button.tsx delete mode 100644 src/shared/ui/text-input/description.tsx delete mode 100644 src/shared/ui/text-input/error-container.tsx delete mode 100644 src/shared/ui/text-input/error-item.tsx delete mode 100644 src/shared/ui/text-input/error-message.tsx delete mode 100644 src/shared/ui/text-input/external-error-display.tsx delete mode 100644 src/shared/ui/text-input/text-field.tsx delete mode 100644 src/shared/ui/text-input/text-input-container.tsx delete mode 100644 src/shared/ui/text-input/text-input.tsx delete mode 100644 src/shared/ui/text-input/text-label.tsx diff --git a/src/shared/configs/config.development.ts b/src/shared/configs/config.development.ts index b8f89c6..3690fc5 100644 --- a/src/shared/configs/config.development.ts +++ b/src/shared/configs/config.development.ts @@ -1,4 +1,4 @@ -import { RELEASE_VERSION } from '@/shared/constants/environment'; +import { RELEASE_VERSION } from '@/shared/constants/common'; import { ConfigMap } from './types'; /** * development diff --git a/src/shared/configs/config.production.ts b/src/shared/configs/config.production.ts index ba8196f..5a99507 100644 --- a/src/shared/configs/config.production.ts +++ b/src/shared/configs/config.production.ts @@ -1,4 +1,4 @@ -import { RELEASE_VERSION } from '@/shared/constants/environment'; +import { RELEASE_VERSION } from '@/shared/constants/common'; import { ConfigMap } from './types'; /** diff --git a/src/shared/configs/index.ts b/src/shared/configs/index.ts index 43a54dd..84f8999 100644 --- a/src/shared/configs/index.ts +++ b/src/shared/configs/index.ts @@ -1,5 +1,5 @@ import { Env } from './types'; -import { RELEASE_VERSION } from '@/shared/constants/environment'; +import { RELEASE_VERSION } from '@/shared/constants/common'; import { PRODUCTION_CONFIG_MAP } from './config.production'; import { DEVELOPMENT_CONFIG_MAP } from './config.development'; diff --git a/src/shared/constants/common.ts b/src/shared/constants/common.ts index 11d71b5..7cd4dab 100644 --- a/src/shared/constants/common.ts +++ b/src/shared/constants/common.ts @@ -1 +1,4 @@ -export const IMAGE_ROOT = '/images'; \ No newline at end of file +import packageInfo from '../../../package.json'; + +export const IMAGE_ROOT = '/images'; +export const RELEASE_VERSION = packageInfo.version; \ No newline at end of file diff --git a/src/shared/constants/environment.ts b/src/shared/constants/environment.ts deleted file mode 100644 index 1dab0be..0000000 --- a/src/shared/constants/environment.ts +++ /dev/null @@ -1,14 +0,0 @@ -import packageInfo from '../../../package.json'; - -// 어플리케이션 running environment (development, production, test) -export const IS_LOCAL = import.meta.env.VITE_APP_ENV === 'local'; -export const IS_TEST = import.meta.env.VITE_APP_ENV === 'test'; -export const IS_DEV = import.meta.env.VITE_APP_ENV === 'development'; -export const IS_PROD = import.meta.env.VITE_APP_ENV === 'production'; -export const IS_STORYBOOK = !!import.meta.env.STORYBOOK; - -export const IS_DEV_PHASE = IS_LOCAL || IS_DEV; - -export const IS_MOCK_PHASE = import.meta.env.VITE_APP_ENV === 'mock'; - -export const RELEASE_VERSION = packageInfo.version; diff --git a/src/shared/constants/form.ts b/src/shared/constants/form.ts deleted file mode 100644 index f1f7680..0000000 --- a/src/shared/constants/form.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { FieldValues, RegisterOptions } from 'react-hook-form'; - -export const createFormOptions = (overrides?: Partial>>) => { - const defaultOptions: Partial>> = { - NAME: { - required: '이름을 입력해 주세요.', - pattern: { value: /^[가-힣]{2,}$/, message: '이름을 두 글자 이상 입력해 주세요.' }, - }, - BIRTH: { - minLength: { value: 8, message: '생년월일을 8자리로 입력해 주세요.' }, - pattern: { - value: /^\d{4}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$/, - message: '생년월일 형식에 맞게 입력해 주세요.', - }, - validate: { - isBeforeToday: (value: string | null | undefined) => { - if (!value) return '생년월일을 입력해 주세요.'; - const birthDate = new Date( - Number(value.slice(0, 4)), - Number(value.slice(4, 6)) - 1, - Number(value.slice(6, 8)), - ); - const today = new Date(); - today.setHours(0, 0, 0, 0); - return birthDate < today || '오늘 이전 날짜로 입력해 주세요.'; - }, - }, - required: '생년월일을 입력해 주세요.', - }, - CARRIER: { - required: '', - }, - PHONE: { - required: '휴대폰 번호를 입력해 주세요.', - pattern: { value: /^01[016789][0-9]{7,8}$/, message: '올바르지 않은 휴대폰 형식입니다.' }, - }, - BANK_ACCOUNT: { - required: '계좌번호를 입력해 주세요.', - pattern: { value: /^[0-9]+$/, message: '숫자만 입력 가능합니다.' }, - }, - BANK_CODE: { - required: '은행을 선택해 주세요.', - }, - ALIAS_NM: { - required: true, - pattern: { value: /^[0-9]+$/, message: '숫자만 입력 가능합니다.' }, - }, - }; - return { - ...defaultOptions, - ...overrides, - }; -}; - -export const MAX_INPUT_NUMBER = 999999999999999; diff --git a/src/shared/constants/local-storage.ts b/src/shared/constants/local-storage.ts index 7eced1c..0d2df6a 100644 --- a/src/shared/constants/local-storage.ts +++ b/src/shared/constants/local-storage.ts @@ -14,5 +14,4 @@ export enum StorageKeys { DeviceId = 'DEVICE_ID', AppVersion = 'APP_VERSION', LogOut = 'LOGOUT', - }; diff --git a/src/shared/lib/error.ts b/src/shared/lib/error.ts index 4e80f00..95d1abe 100644 --- a/src/shared/lib/error.ts +++ b/src/shared/lib/error.ts @@ -1,11 +1,10 @@ import axios from 'axios'; import { NiceAxiosError } from '@/shared/@types/error'; -import { IS_MOCK_PHASE } from '@/shared/constants/environment'; // CBDCAxiosError가 아니라면 상위 Error Boundary로 위임 export const checkIsAxiosError = (error: Error): error is NiceAxiosError => axios.isAxiosError(error); export const checkIsKickOutError = (error: NiceAxiosError) => { const status = error.response?.status.toString(); - return !IS_MOCK_PHASE && (status === '401' || status === '403'); + return status === '401' || status === '403'; }; diff --git a/src/shared/lib/hooks/index.tsx b/src/shared/lib/hooks/index.tsx index 67a5fe1..ebb84ab 100644 --- a/src/shared/lib/hooks/index.tsx +++ b/src/shared/lib/hooks/index.tsx @@ -1,5 +1,4 @@ export * from './use-navigate'; export * from './use-fix-scroll-view-safari'; export * from './use-navigate'; -export * from './use-router-listener'; export * from './use-keyboard-aware'; diff --git a/src/shared/lib/hooks/use-request-notification.ts b/src/shared/lib/hooks/use-request-notification.ts deleted file mode 100644 index 77de283..0000000 --- a/src/shared/lib/hooks/use-request-notification.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useEffect } from 'react'; - -import { NativeFunction } from '@/shared/constants/native-function'; - -export const useRequestNotification = () => { - useEffect(() => { - window.webViewBridge.send(NativeFunction.RequestNotification, { - success: async () => { - // console.log('res', res); - }, - }); - }, []); -}; diff --git a/src/shared/lib/hooks/use-router-listener.ts b/src/shared/lib/hooks/use-router-listener.ts deleted file mode 100644 index 4364541..0000000 --- a/src/shared/lib/hooks/use-router-listener.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { RouterState } from '@remix-run/router'; -import { useEffect } from 'react'; -import { NavigationType } from 'react-router'; - -import { router } from '@/shared/configs/router'; - -type IRouterListener = (state: RouterState) => void; - -export const useRouterListener = (callback: IRouterListener, actionType?: NavigationType) => { - useEffect(() => { - const unsubscribe = router.subscribe((state: any) => { - if (actionType && state.historyAction !== actionType) return; - if (!actionType || state.historyAction === actionType) { - callback?.(state); - } - }); - - return unsubscribe; - }, [callback, actionType]); -}; diff --git a/src/shared/lib/hooks/use-select-bottom-sheet.tsx b/src/shared/lib/hooks/use-select-bottom-sheet.tsx deleted file mode 100644 index c5d1634..0000000 --- a/src/shared/lib/hooks/use-select-bottom-sheet.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { overlay } from 'overlay-kit'; -import { BottomSheet } from '@/shared/ui/bottom-sheets/bottom-sheet'; -import { - SelectTemplate, - ElementType, - RadioChangeProps, - SelectTemplateProps, -} from '@/shared/ui/selects/select-template'; -import { JSX } from 'react/jsx-runtime'; - -export interface SelectBottomSheetProps extends SelectTemplateProps { - title?: string | JSX.Element; - description?: string | JSX.Element; - onClose?: () => void; -} - -export const useSelectBottomSheet = () => { - const openSelectBottomSheet = (selectBottomSheet: SelectBottomSheetProps) => { - const { - values = [], - labels = [], - valueKey = undefined, - selectedLabel = '', - selectedValue = '', - title = '', - description = '', - } = selectBottomSheet; - - const handleRadioChange = ({ event, label, value }: RadioChangeProps>) => { - selectBottomSheet?.onRadioChange?.({ event, label, value }); - }; - - overlay.open(({ isOpen, close, unmount }) => { - return ( - - - - ); - }); - }; - - return { openSelectBottomSheet, closeBottomSheet: overlay.closeAll }; -}; diff --git a/src/shared/ui/reset-button/index.tsx b/src/shared/ui/reset-button/index.tsx deleted file mode 100644 index decdd3d..0000000 --- a/src/shared/ui/reset-button/index.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import clsx from 'clsx'; -import { motion, useAnimation } from 'framer-motion'; - -interface RefreshButtonProps { - onClick: () => void; - children?: React.ReactNode; -} -export const RefreshButton = ({ onClick, children }: RefreshButtonProps) => { - const controls = useAnimation(); - const handleReset = async () => { - controls.start({ - rotate: 360, - transition: { duration: 0.4 }, - }); - controls.set({ rotate: 0 }); - onClick?.(); - }; - return ( - - ); -}; diff --git a/src/shared/ui/selects/select-template.tsx b/src/shared/ui/selects/select-template.tsx deleted file mode 100644 index 4a86219..0000000 --- a/src/shared/ui/selects/select-template.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import clsx from 'clsx'; -import { useEffect, useRef } from 'react'; - -export type ElementType = T extends (infer U)[] ? U : never; - -export interface RadioChangeProps { - event: React.ChangeEvent; - label?: string; - value: ValueType; -} -export interface SelectTemplateProps { - values?: ValueType[]; - valueKey?: keyof ValueType; - labels?: string[]; - selectedLabel?: string; - selectedValue?: string; - onRadioChange?: ({ event, label, value }: RadioChangeProps) => void; -} - -export const SelectTemplate = ({ - values = [], - valueKey, - labels = [], - selectedLabel, - selectedValue, - onRadioChange, -}: SelectTemplateProps) => { - const refs = useRef<(HTMLLabelElement | null)[]>([]); - - const handleRadioChange = ({ event, label, value }: RadioChangeProps>) => { - onRadioChange?.({ event, label, value }); - }; - - useEffect(() => { - const scrollIntoView = (array: any[], selected: string | undefined) => { - const index = array?.indexOf(selected ?? ''); - if (index !== -1 && refs.current[index]) { - refs.current[index]?.scrollIntoView({ behavior: 'smooth', block: 'center' }); - } - }; - scrollIntoView(labels, selectedLabel); - scrollIntoView(values, selectedValue); - }, [selectedLabel, labels, selectedValue, values]); - - return ( -
- {values?.map((value, index) => { - return ( - - ); - })} -
- ); -}; diff --git a/src/shared/ui/selects/select.tsx b/src/shared/ui/selects/select.tsx deleted file mode 100644 index e25cc61..0000000 --- a/src/shared/ui/selects/select.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -import { ElementType, Fragment, useEffect, useState } from 'react'; -import { RegisterOptions, useFormContext, UseFormRegister } from 'react-hook-form'; - -import { BottomSheet } from '~/shared/ui/bottom-sheets/bottom-sheet'; -import { SelectTemplate, RadioChangeProps } from '~/shared/ui/selects/select-template'; -import { TextInput } from '~/shared/ui/text-input/text-input'; - -interface SelectProps { - placeholder: string; - labels: string[]; - values: string[]; - name: string; - option?: RegisterOptions; - readOnly?: boolean; - onClick?: () => void; - register: UseFormRegister; - classStr?: string; -} - -export const Select = ({ placeholder, register, name, option, labels, values, classStr }: SelectProps) => { - const [isOpenBottomSheet, setIsOpenBottomSheet] = useState(false); - - const handleCloseBottomSheet = () => { - setIsOpenBottomSheet(false); - if ((!value || value?.length < 0) && option?.required) { - setError(name, { type: 'required', message: option?.required.toString() ?? null }); - } - }; - - const { setValue, clearErrors, watch, getValues, setError } = useFormContext(); - const value = watch(name); - - const defaultValue = getValues(name); - const selectedValue = watch(name, defaultValue); - const selectedLabel = labels[values.indexOf(selectedValue)]; - - const onInputClick = (event: React.MouseEvent) => { - event.preventDefault(); - setIsOpenBottomSheet(true); - }; - - const onRadioChange = ({ event }: RadioChangeProps>) => { - setValue(name, event.target.value); - setIsOpenBottomSheet(false); - clearErrors(name); - }; - - useEffect(() => { - if (value?.length > 0) { - setValue(name, selectedValue); - } - }, []); - - return ( - - - - - - - ); -}; diff --git a/src/shared/ui/text-input/clear-button.tsx b/src/shared/ui/text-input/clear-button.tsx deleted file mode 100644 index 1078de2..0000000 --- a/src/shared/ui/text-input/clear-button.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import clsx from 'clsx'; - -interface ClearButtonProps { - isShow: boolean; - isError: boolean; - isActiveWithoutError: boolean; - onClick: (() => void) | undefined; -} -export const ClearButton = ({ isShow, isError, isActiveWithoutError, onClick }: ClearButtonProps) => { - return ( - - ); -}; diff --git a/src/shared/ui/text-input/description.tsx b/src/shared/ui/text-input/description.tsx deleted file mode 100644 index 6f6cce2..0000000 --- a/src/shared/ui/text-input/description.tsx +++ /dev/null @@ -1,9 +0,0 @@ -interface DescriptionProps { - description?: string | React.ReactNode; -} -export const Description = ({ description }: DescriptionProps) => { - if (!description) { - return <>; - } - return

{description}

; -}; diff --git a/src/shared/ui/text-input/error-container.tsx b/src/shared/ui/text-input/error-container.tsx deleted file mode 100644 index 67b9e55..0000000 --- a/src/shared/ui/text-input/error-container.tsx +++ /dev/null @@ -1,8 +0,0 @@ -interface ErrorContainerProps { - isErrorPaddingPresent?: boolean; - children: React.ReactNode; -} - -export const ErrorContainer = ({ isErrorPaddingPresent, children }: ErrorContainerProps) => { - return
{children}
; -}; diff --git a/src/shared/ui/text-input/error-item.tsx b/src/shared/ui/text-input/error-item.tsx deleted file mode 100644 index a6482e2..0000000 --- a/src/shared/ui/text-input/error-item.tsx +++ /dev/null @@ -1,10 +0,0 @@ -interface ErrorItemProps { - message: string; -} -export const ErrorItem = ({ message }: ErrorItemProps) => { - return ( -
- {message} -
- ); -}; diff --git a/src/shared/ui/text-input/error-message.tsx b/src/shared/ui/text-input/error-message.tsx deleted file mode 100644 index b4b288b..0000000 --- a/src/shared/ui/text-input/error-message.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useFormContext } from 'react-hook-form'; - -import { ErrorContainer } from './error-container'; -import { ErrorItem } from './error-item'; - -interface ErrorMessageProps { - name: string; - isErrorPaddingPresent?: boolean; - isShowError: boolean; -} - -export const ErrorMessage = ({ isShowError, name, isErrorPaddingPresent = true }: ErrorMessageProps) => { - const { - formState: { errors }, - } = useFormContext(); - - if (!isShowError) { - return <>; - } - return ( - - {errors[name] && } - - ); -}; diff --git a/src/shared/ui/text-input/external-error-display.tsx b/src/shared/ui/text-input/external-error-display.tsx deleted file mode 100644 index f0dc7c9..0000000 --- a/src/shared/ui/text-input/external-error-display.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useFormContext } from 'react-hook-form'; - -import { ErrorContainer } from './error-container'; -import { ErrorItem } from './error-item'; - -interface ExternalErrorDisplayProps { - isErrorPaddingPresent?: boolean; - isShowAll?: boolean; -} -export const ExternalErrorDisplay = ({ - isErrorPaddingPresent = true, - isShowAll = false, -}: ExternalErrorDisplayProps) => { - const { - formState: { errors }, - } = useFormContext(); - - return ( - - {( - Object.keys(errors)?.map((key) => ) - ) } - - ); -}; diff --git a/src/shared/ui/text-input/text-field.tsx b/src/shared/ui/text-input/text-field.tsx deleted file mode 100644 index c08f89c..0000000 --- a/src/shared/ui/text-input/text-field.tsx +++ /dev/null @@ -1,166 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -import { forwardRef, startTransition, useCallback, useMemo, useRef } from 'react'; -import { useFormContext, UseFormRegister } from 'react-hook-form'; - -export type TextFieldProps = { - placeholder?: string; - inputMode?: 'text' | 'search' | 'email' | 'tel' | 'url' | 'none' | 'numeric' | 'decimal'; - readOnly?: boolean; - selectLabel?: string; - onInputFocus?: (event: React.FocusEvent) => void; - onInputBlur?: (event: React.FocusEvent) => void; - onInputChange?: (event: React.ChangeEvent) => void; - isFocused: boolean; - setIsFocused: React.Dispatch>; - suffix?: string; - prefix?: string; - textFieldId: string; -} & ReturnType>; - -export const TextField = forwardRef(function TextField( - { - name, - placeholder, - inputMode = 'text', - onBlur, - disabled, - readOnly, - onInputFocus, - onInputBlur, - selectLabel, - onChange, - onInputChange, - maxLength, - isFocused, - setIsFocused, - suffix, - prefix, - textFieldId, - }, - ref, -) { - const textRef = useRef(null); - - const { - setValue, - formState: { errors }, - watch, - trigger, - } = useFormContext(); - - const value = watch(name); - const hasValue = useMemo(() => value?.length > 0, [value]); - const isFocusedAndNoValue = useMemo(() => isFocused && !hasValue, [isFocused, hasValue]); - - const handleBlur = useCallback( - (event: React.FocusEvent) => { - if (readOnly) return; - startTransition(() => { - setIsFocused(false); - onBlur(event); - onInputBlur?.(event); - if (prefix || suffix) { - trigger(name); - } - }); - }, - [setIsFocused, onBlur, onInputBlur], - ); - - const handleFocus = useCallback( - (event: React.FocusEvent) => { - if (readOnly) return; - setIsFocused(true); - onInputFocus?.(event); - }, - [setIsFocused, onInputFocus], - ); - - const handleChange = useCallback( - (event: React.ChangeEvent) => { - startTransition(() => { - // if maxLength is set, do not allow input more than maxLength - if (maxLength && event.target.value?.length > maxLength) { - setValue(name, event.target.value.substring(0, maxLength)); - return; - } - if (prefix || suffix) { - const inputValue = event.target.value; - const numberPart = inputValue.replace(/[^\d]/g, ''); - const formattedNumber = Number(numberPart).toLocaleString('ko-KR'); - setValue(name, numberPart); - - setTimeout(() => { - const cursorPosition = (prefix ? prefix.length : 0) + formattedNumber.length; - textRef.current?.setSelectionRange(cursorPosition, cursorPosition); - }, 0); - } - - onChange(event); - onInputChange?.(event); - }); - }, - [maxLength, setValue, name, onChange, onInputChange], - ); - - if (selectLabel) { - return ( - <> - - - - ); - } - - const isNotNullValue = value !== null && value !== undefined && value !== ''; - - if (prefix || suffix) { - return ( - <> - - - - ); - } - - return ( - - ); -}); diff --git a/src/shared/ui/text-input/text-input-container.tsx b/src/shared/ui/text-input/text-input-container.tsx deleted file mode 100644 index be05ff9..0000000 --- a/src/shared/ui/text-input/text-input-container.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import clsx from 'clsx'; - -interface TextInputContainerProps { - children: React.ReactNode; - isError: boolean; - disabled?: boolean; - isActiveWithoutError: boolean; - labelClassStr?: string; -} - -export const TextInputContainer = ({ - children, - isError, - disabled, - isActiveWithoutError, - labelClassStr, -}: TextInputContainerProps) => { - const containerClassNames = clsx(`relative border-b h-9 block border-[#000]/[.56]`, { - [labelClassStr as string]: labelClassStr, - 'border-gray-300': disabled, - 'border-[#ff0000]': isError, - 'border-[#2196f3]': isActiveWithoutError, - }); - - return
{children}
; -}; diff --git a/src/shared/ui/text-input/text-input.tsx b/src/shared/ui/text-input/text-input.tsx deleted file mode 100644 index b3fb443..0000000 --- a/src/shared/ui/text-input/text-input.tsx +++ /dev/null @@ -1,117 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -import clsx from 'clsx'; -import { forwardRef, useDeferredValue, useMemo, useState } from 'react'; -import { useFormContext, UseFormRegister } from 'react-hook-form'; - -import { ClearButton } from './clear-button'; -import { Description } from './description'; -import { ErrorMessage } from './error-message'; -import { TextField, TextFieldProps } from './text-field'; -import { TextInputContainer } from './text-input-container'; -import { TextLabel } from './text-label'; - -type TextInputProps = { - label?: string | React.ReactNode; - description?: string | React.ReactNode; - selectMode?: boolean; - isOpenBottomSheet?: boolean; - classStr?: string; - labelClassStr?: string; - isErrorPaddingPresent?: boolean; - isShowError?: boolean; - onClick?: (event: React.MouseEvent) => void; -} & Omit & - ReturnType>; - -export const TextInput = forwardRef(function TextInput(props, ref) { - const { - name, - label, - description, - disabled, - onClick, - selectMode, - isOpenBottomSheet, - classStr, - labelClassStr, - isErrorPaddingPresent = true, - isShowError = true, - } = props; - const textFieldId = useMemo(() => `text-input-${name}`, [name]); - - const { - setFocus, - setValue, - watch, - formState: { errors }, - clearErrors, - } = useFormContext(); - const value = watch(name); - const [isFocused, setIsFocused] = useState(false); - - // selectMode true일 때는, input Focus 상태를 isOpenBottomSheet 상태로 처리 - const isSelecting = useMemo(() => !!selectMode && !!isOpenBottomSheet, [selectMode, isOpenBottomSheet]); - const deferredIsFocused = useDeferredValue(isFocused || isSelecting); - - const hasValue = useMemo(() => !!value && String(value)?.length > 0, [value]); - - const isActiveWithoutError = useMemo( - () => deferredIsFocused && hasValue && !errors[name], - [hasValue, deferredIsFocused, errors[name]], - ); - - const handleContainerClick = (event: React.MouseEvent) => { - onClick?.(event); - }; - - // handle clear button - const handleClickClearButton = () => { - setValue(name, ''); - clearErrors(name); - setFocus(name); - }; - - return ( - <> -
- - - - - - - -
- - - ); -}); diff --git a/src/shared/ui/text-input/text-label.tsx b/src/shared/ui/text-input/text-label.tsx deleted file mode 100644 index 4a5b049..0000000 --- a/src/shared/ui/text-input/text-label.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import clsx from 'clsx'; -import { ReactNode } from 'react'; - -interface TextLabelProps { - label: ReactNode; - textFieldId: string; - isError: boolean; - hasValue: boolean; - isFocused: boolean; - isActiveWithoutError: boolean; -} - -export const TextLabel = ({ - label, - textFieldId, - isError, - isFocused, - hasValue, - isActiveWithoutError, -}: TextLabelProps) => { - const labelClassNames = clsx('absolute left-0 transition-all duration-200 h-9 leading-9', { - 'top-[-17px] text-[12px] leading-[12px]': isFocused || hasValue, - 'top-1/2 text-[16px] mt-[-18px] text-black/[.6] ': !isFocused && !hasValue, - 'text-[#ff0000] ': isError, - 'text-[#2196f3] ': isActiveWithoutError, - }); - - return ( - - ); -};