import React from 'react';
import { useButton } from '@react-native-aria/button';
import { ComboBoxState, useComboBoxState } from '@react-stately/combobox';
import { useComboBox } from '@react-native-aria/combobox';
import { useListBox, useOption } from '@react-native-aria/listbox';
import { ScrollView, findNodeHandle, Platform } from 'react-native';
import { Item } from '@react-stately/collections';
import Box from '../../primitives/Box';
import { Pressable } from '../../primitives/Pressable';
import Text from '../../primitives/Text';
import { extractInObject } from '../../../theme/tools';
import { ITypeaheadProps, IComboBoxProps, layoutPropsList } from './types';
import { Input } from '../../primitives/Input';
import { useThemeProps } from '../../../hooks';
export const Typeahead = React.forwardRef(
(
{
onSelectedItemChange,
options,
renderItem,
getOptionLabel,
getOptionKey,
onChange,
numberOfItems,
...rest
}: ITypeaheadProps,
ref?: any
) => {
return (
{(item: any) => {
if (typeof item !== 'string' && getOptionLabel === undefined) {
throw new Error('Please use getOptionLabel prop');
}
if (item.id === undefined && getOptionKey === undefined) {
throw new Error('Please use getOptionKey prop');
}
const optionLabel = getOptionLabel ? getOptionLabel(item) : item;
const optionKey = getOptionKey
? getOptionKey(item)
: item.id !== undefined
? item.id
: optionLabel;
return (
-
{renderItem ? (
renderItem(item)
) : (
{optionLabel}
)}
);
}}
);
}
);
const ComboBoxImplementation = React.forwardRef(
(props: IComboBoxProps, ref?: any) => {
const [layoutProps] = extractInObject(props, layoutPropsList);
let state = useComboBoxState(props);
let triggerRef = React.useRef(null);
let inputRef = React.useRef(null);
let listBoxRef = React.useRef(null);
let popoverRef = React.useRef(null);
let {
buttonProps: triggerProps,
inputProps,
listBoxProps,
labelProps,
} = useComboBox(
{
...props,
inputRef,
buttonRef: triggerRef,
listBoxRef,
popoverRef,
menuTrigger: 'input',
},
state
);
const toggleIconSetter = () => {
if (typeof props.toggleIcon === 'function')
return props.toggleIcon({
isOpen: state.isOpen,
});
return props.toggleIcon;
};
let { buttonProps } = useButton(triggerProps);
return (
{props.label && (
{props.label}
)}
{toggleIconSetter()}
}
/>
{state.isOpen && (
)}
);
}
);
type IListBoxProps = {
popoverRef: any;
listBoxRef: any;
state: ComboBoxState;
dropdownHeight: number;
label: string;
};
function ListBoxPopup(props: IListBoxProps) {
let { popoverRef, listBoxRef, state, dropdownHeight, label } = props;
let { listBoxProps } = useListBox(
{
label,
autoFocus: state.focusStrategy,
disallowEmptySelection: true,
},
state,
listBoxRef
);
return (
{
if (Platform.OS === 'web') {
listBoxRef.current = findNodeHandle(node);
} else {
listBoxRef.current = node;
}
}}
>
{[...state.collection].map((item) => (
))}
);
}
function Option({ item, state }: { item: any; state: ComboBoxState }) {
const searchItemStyle = useThemeProps('TypeAheadSearchItem', {});
let ref = React.useRef(null);
let isDisabled = state.disabledKeys.has(item.key);
let isSelected = state.selectionManager.isSelected(item.key);
let isFocused = state.selectionManager.focusedKey === item.key;
let { optionProps } = useOption(
{
key: item.key,
isDisabled,
isSelected,
shouldFocusOnHover: true,
shouldUseVirtualFocus: true,
},
state,
ref
);
let backgroundColor = searchItemStyle.backgroundColor;
let opacity = 1;
if (isSelected) {
backgroundColor = searchItemStyle._focus.backgroundColor;
} else if (isFocused) {
backgroundColor = searchItemStyle._focus.backgroundColor;
} else if (isDisabled) {
opacity = 0.6;
backgroundColor = searchItemStyle._disabled.backgroundColor;
}
return (
{item.rendered}
);
}