157 lines
4.6 KiB
JavaScript
157 lines
4.6 KiB
JavaScript
import React, {
|
|
useCallback,
|
|
useEffect,
|
|
useState,
|
|
} from 'react';
|
|
|
|
import classNames from 'classnames';
|
|
|
|
import Spotlight from '@enact/spotlight';
|
|
import Spottable from '@enact/spotlight/Spottable';
|
|
|
|
import iconDownArrow
|
|
from '../../../../assets/images/btn/btn-dropdown-nor@3x.png';
|
|
import styles from './CustomDropDown.new.module.less';
|
|
|
|
const SpottableDiv = Spottable('div');
|
|
|
|
const CustomDropDown = ({
|
|
className,
|
|
options = [],
|
|
selectedIndex = 0,
|
|
onSelect,
|
|
spotlightId,
|
|
placeholder = 'Select option',
|
|
onSpotlightUp,
|
|
disabled = false,
|
|
}) => {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
|
|
// 옵션을 표준화 (문자열 또는 객체 처리)
|
|
const normalizeOption = (option) => {
|
|
if (typeof option === 'string') {
|
|
return { label: option, disabled: false, imageUrl: null };
|
|
}
|
|
return { ...option, imageUrl: option.imageUrl || null };
|
|
};
|
|
|
|
const normalizedOptions = options.map(normalizeOption);
|
|
|
|
const handleToggle = useCallback(() => {
|
|
const newIsOpen = !isOpen;
|
|
setIsOpen(newIsOpen);
|
|
|
|
if (!newIsOpen) {
|
|
setTimeout(() => {
|
|
if (spotlightId) {
|
|
Spotlight.focus(spotlightId);
|
|
}
|
|
}, 50);
|
|
}
|
|
}, [isOpen, spotlightId]);
|
|
|
|
const handleOptionSelect = useCallback(
|
|
(index, optionDisabled) => {
|
|
// disabled된 옵션은 선택 불가
|
|
if (optionDisabled) {
|
|
return;
|
|
}
|
|
|
|
setIsOpen(false);
|
|
if (onSelect) {
|
|
onSelect({ selected: index });
|
|
}
|
|
setTimeout(() => {
|
|
if (spotlightId) {
|
|
Spotlight.focus(spotlightId);
|
|
}
|
|
}, 50);
|
|
},
|
|
[onSelect, spotlightId]
|
|
);
|
|
|
|
const selectedOption = normalizedOptions[selectedIndex];
|
|
const selectedLabel = selectedOption?.label || placeholder;
|
|
const selectedId = selectedOption?.prodOptCdCval ? selectedOption?.prodOptCdCval : null;
|
|
const selectedImage = selectedOption?.imageUrl;
|
|
|
|
return (
|
|
<div className={`${styles.custom_dropdown} ${className || ''}`}>
|
|
<SpottableDiv
|
|
className={`${styles.custom_dropdown__button} ${
|
|
isOpen ? styles.custom_dropdown__button_expanded : ''
|
|
}`}
|
|
onClick={handleToggle}
|
|
spotlightId={spotlightId}
|
|
onSpotlightUp={onSpotlightUp}
|
|
spotlightDisabled={disabled}
|
|
>
|
|
<div className={styles.custom_dropdown__content}>
|
|
{selectedImage && (
|
|
<img
|
|
src={selectedImage}
|
|
alt=""
|
|
className={styles.custom_dropdown__image}
|
|
/>
|
|
)}
|
|
<div className={styles.custom_dropdown__text}>{selectedLabel} {selectedId ? `ID : ${selectedId}` : ''}</div>
|
|
</div>
|
|
<div className={styles.custom_dropdown__icon}>
|
|
<img src={iconDownArrow} alt="dropdown arrow" />
|
|
</div>
|
|
</SpottableDiv>
|
|
|
|
{isOpen && (
|
|
<div className={styles.custom_dropdown__list}>
|
|
{normalizedOptions
|
|
.slice()
|
|
.reverse()
|
|
.map((option, reverseIndex) => {
|
|
const originalIndex = normalizedOptions.length - 1 - reverseIndex;
|
|
const isOptionDisabled = option.disabled;
|
|
return (
|
|
<SpottableDiv
|
|
key={originalIndex}
|
|
className={classNames(
|
|
styles.custom_dropdown__option,
|
|
originalIndex === selectedIndex
|
|
? styles.custom_dropdown__option_selected
|
|
: '',
|
|
isOptionDisabled
|
|
? styles.custom_dropdown__option_disabled
|
|
: ''
|
|
)}
|
|
onClick={() =>
|
|
handleOptionSelect(originalIndex, isOptionDisabled)
|
|
}
|
|
spotlightDisabled={isOptionDisabled}
|
|
>
|
|
{option.imageUrl && (
|
|
<img
|
|
src={option.imageUrl}
|
|
className={styles.custom_dropdown__image}
|
|
/>
|
|
)}
|
|
<span className={styles.custom_dropdown__optname}>
|
|
{option.label} {option.prodOptCdCval ? `ID : ${option.prodOptCdCval}` : ''}
|
|
</span>
|
|
{isOptionDisabled ? (
|
|
<span className={styles.custom_dropdown__lasttxt}>
|
|
SOLD OUT
|
|
</span>
|
|
) : (
|
|
<span className={styles.custom_dropdown__lasttxt}>
|
|
{option.price}
|
|
</span>
|
|
)}
|
|
</SpottableDiv>
|
|
);
|
|
})}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default CustomDropDown;
|