import React from 'react'; import * as Select from '@ariakit/react/select'; import type { Option } from '~/common'; import { cn } from '~/utils/'; interface DropdownProps { value?: string; label?: string; onChange: (value: string) => void; options: (string | Option | { divider: true })[]; className?: string; sizeClasses?: string; testId?: string; icon?: React.ReactNode; iconOnly?: boolean; renderValue?: (option: Option) => React.ReactNode; ariaLabel?: string; portal?: boolean; } const isDivider = (item: string | Option | { divider: true }): item is { divider: true } => typeof item === 'object' && 'divider' in item; const isOption = (item: string | Option | { divider: true }): item is Option => typeof item === 'object' && 'value' in item && 'label' in item; const Dropdown: React.FC = ({ value: selectedValue, label = '', onChange, options, className = '', sizeClasses, testId = 'dropdown-menu', icon, iconOnly = false, renderValue, ariaLabel, portal = true, }) => { const handleChange = (value: string) => { onChange(value); }; const selectProps = Select.useSelectStore({ value: selectedValue, setValue: handleChange, }); const getOptionObject = (val: string | undefined): Option | undefined => { if (val == null || val === '') { return undefined; } return options .filter((o) => !isDivider(o)) .map((o) => (typeof o === 'string' ? { value: o, label: o } : o)) .find((o) => isOption(o) && o.value === val) as Option | undefined; }; const getOptionLabel = (currentValue: string | undefined) => { if (currentValue == null || currentValue === '') { return ''; } const option = getOptionObject(currentValue); return option ? option.label : currentValue; }; return (
{icon} {!iconOnly && ( {label} {(() => { const matchedOption = getOptionObject(selectedValue); if (matchedOption && renderValue) { return renderValue(matchedOption); } return getOptionLabel(selectedValue); })()} )}
{!iconOnly && }
{options.map((item, index) => { if (isDivider(item)) { return
; } const option = typeof item === 'string' ? { value: item, label: item } : item; if (!isOption(option)) { return null; } return (
{option.icon != null && {option.icon as React.ReactNode}} {option.label} {selectedValue === option.value && ( )}
); })}
); }; export default Dropdown;