@@ -5,7 +5,7 @@ import { motion, AnimatePresence } from 'framer-motion';
55import cn from '@lib/cn' ;
66import useOutsideClick from '@hooks/useOutsideClick' ;
77import ChevronIcon from '@assets/svg/chevron' ;
8- import { DropdownProps } from '@/types/dropdownTypes' ;
8+ import { DropdownProps , DropdownOption } from '@/types/dropdownTypes' ;
99// import CheckIcon from '@assets/svg/check';
1010
1111/**
@@ -28,6 +28,7 @@ import { DropdownProps } from '@/types/dropdownTypes';
2828 */
2929export default function Dropdown < T extends string > ( {
3030 options,
31+ optionData,
3132 value,
3233 onChange,
3334 placeholder,
@@ -47,22 +48,34 @@ export default function Dropdown<T extends string>({
4748 const dropdownRef = useRef < HTMLDivElement > ( null ) ;
4849 const buttonRef = useRef < HTMLButtonElement > ( null ) ;
4950
51+ // optionData가 제공되면 우선 사용, 없으면 options 사용
52+ const useOptionData = ! ! optionData ;
53+ const finalOptions = useOptionData
54+ ? optionData !
55+ : options . map ( opt => ( { value : opt , label : opt } ) ) ;
56+
5057 // 내/외부 상태 관리 판별
5158 const isControlled = value !== undefined ;
5259 const selectedValue = isControlled ? value : internalValue ;
5360
61+ // 선택된 값에 해당하는 표시 텍스트 찾기
62+ const displayValue = useOptionData
63+ ? finalOptions . find ( opt => opt . value === selectedValue ) ?. label || ''
64+ : selectedValue ;
65+
5466 // 외부 클릭 감지
5567 useOutsideClick ( dropdownRef , ( ) => {
5668 setIsOpen ( false ) ;
5769 setFocusedIndex ( - 1 ) ;
5870 } ) ;
5971
6072 // 값 선택 핸들러
61- const handleSelect = ( option : T ) => {
73+ const handleSelect = ( optionData : DropdownOption ) => {
74+ const selectedValue = optionData . value as T ;
6275 if ( ! isControlled ) {
63- setInternalValue ( option ) ;
76+ setInternalValue ( selectedValue ) ;
6477 }
65- onChange ?.( option ) ;
78+ onChange ?.( selectedValue ) ;
6679 setIsOpen ( false ) ;
6780 setFocusedIndex ( - 1 ) ;
6881 buttonRef . current ?. focus ( ) ;
@@ -77,7 +90,7 @@ export default function Dropdown<T extends string>({
7790 case ' ' :
7891 e . preventDefault ( ) ;
7992 if ( isOpen && focusedIndex >= 0 ) {
80- handleSelect ( options [ focusedIndex ] ) ;
93+ handleSelect ( finalOptions [ focusedIndex ] ) ;
8194 } else {
8295 setIsOpen ( ! isOpen ) ;
8396 }
@@ -88,7 +101,7 @@ export default function Dropdown<T extends string>({
88101 if ( ! isOpen ) {
89102 setIsOpen ( true ) ;
90103 } else {
91- setFocusedIndex ( ( prev ) => ( prev < options . length - 1 ? prev + 1 : 0 ) ) ;
104+ setFocusedIndex ( ( prev ) => ( prev < finalOptions . length - 1 ? prev + 1 : 0 ) ) ;
92105 }
93106 break ;
94107
@@ -97,7 +110,7 @@ export default function Dropdown<T extends string>({
97110 if ( ! isOpen ) {
98111 setIsOpen ( true ) ;
99112 } else {
100- setFocusedIndex ( ( prev ) => ( prev > 0 ? prev - 1 : options . length - 1 ) ) ;
113+ setFocusedIndex ( ( prev ) => ( prev > 0 ? prev - 1 : finalOptions . length - 1 ) ) ;
101114 }
102115 break ;
103116
@@ -149,7 +162,7 @@ export default function Dropdown<T extends string>({
149162 truncateText && 'flex-1 truncate text-left' ,
150163 ) }
151164 >
152- { selectedValue || placeholder }
165+ { displayValue || placeholder }
153166 </ span >
154167 < ChevronIcon
155168 size = { 24 }
@@ -179,13 +192,13 @@ export default function Dropdown<T extends string>({
179192 listboxClassName ,
180193 ) }
181194 >
182- { options . map ( ( option , index ) => {
183- const isSelected = option === selectedValue ;
195+ { finalOptions . map ( ( optionItem , index ) => {
196+ const isSelected = optionItem . value === selectedValue ;
184197 const isFocused = index === focusedIndex ;
185198
186199 return (
187200 < li
188- key = { option }
201+ key = { ` ${ optionItem . value } - ${ index } ` }
189202 id = { `dropdown-option-${ index } ` }
190203 role = 'option'
191204 aria-selected = { isSelected }
@@ -198,7 +211,7 @@ export default function Dropdown<T extends string>({
198211 : 'hover:bg-gray-100' ,
199212 optionClassName ,
200213 ) }
201- onClick = { ( ) => handleSelect ( option ) }
214+ onClick = { ( ) => handleSelect ( optionItem ) }
202215 onMouseEnter = { ( ) => setFocusedIndex ( index ) }
203216 >
204217 { /* 아이콘 영역 */ }
@@ -211,7 +224,7 @@ export default function Dropdown<T extends string>({
211224 />
212225 )}
213226 </div> */ }
214- < span > { option } </ span >
227+ < span > { optionItem . label } </ span >
215228 </ li >
216229 ) ;
217230 } ) }
0 commit comments