import type { ButtonProps } from '@blueprintjs/core'; import { Button } from '@blueprintjs/core'; import type { SelectProps } from '@blueprintjs/select'; import { Select } from '@blueprintjs/select'; import type { ForwardedRef, ReactNode } from 'react'; import { forwardRef, useEffect } from 'react'; import { useSelect } from 'react-science/ui'; import type { FilterType } from '../utility/filterType.js'; interface ItemOptions { renderItem?: (item: T) => ReactNode; defaultSelectedItem?: T; } interface ItemSelectOptions = SelectDefaultItem> { itemTextKey?: keyof FilterType; itemValueKey?: keyof T; selectedItemValue?: T[keyof T]; placeholder?: string; filterPlaceholder?: string; getSelectedText?: (item: T) => string; } type SelectOptions = SelectDefaultItem> = ItemOptions & ItemSelectOptions; type ReturnedUseSelectOptions = ReturnType; export type Select2Props = SelectDefaultItem> = Omit< SelectProps, keyof Omit< ReturnedUseSelectOptions, 'onItemSelect' | 'value' | 'popoverProps' > > & SelectOptions & { selectedButtonProps?: Omit; } & Pick; function getDefaultSelectedItem< T extends Record = SelectDefaultItem, >(items: T[], itemValueKey?: keyof T, value?: any) { return items.find((item) => itemValueKey && item[itemValueKey] === value); } export interface SelectDefaultItem { label: string; value: any; } function InnerSelect2 = SelectDefaultItem>( props: Select2Props, ref: any, ) { const { items, defaultSelectedItem, itemTextKey = 'label', itemValueKey = 'value', selectedItemValue, onItemSelect, selectedButtonProps, fill, intent, placeholder = '', filterPlaceholder, popoverProps, getSelectedText, ...otherProps } = props; const { value: item, onItemSelect: innerOnItemSelect, setValue, ...defaultSelectProps } = useSelect({ defaultSelectedItem: defaultSelectedItem ?? getDefaultSelectedItem(items, itemValueKey, selectedItemValue), itemTextKey: itemTextKey as keyof FilterType, }); useEffect(() => { const value = defaultSelectedItem ?? getDefaultSelectedItem(items, itemValueKey, selectedItemValue); setValue(value || null); }, [defaultSelectedItem, itemValueKey, items, selectedItemValue, setValue]); const selectedText = item?.[itemTextKey] ? typeof getSelectedText === 'function' ? getSelectedText(item) : String(item[itemTextKey]) : placeholder; return ( ); } export const Select2 = forwardRef(InnerSelect2) as < T extends Record = SelectDefaultItem, >( props: Select2Props & { ref?: ForwardedRef }, ) => ReturnType;