import React, { forwardRef, useMemo, useState } from "react"; import { Controller, FieldValues } from "react-hook-form"; import { Adapt, Button, Dialog, Input, ListItem, ScrollView, Sheet, Text, View, } from "tamagui"; import { FormFieldBaseProps } from "./utility"; import { ErrorMessage } from "./form"; import Icons from "./icons"; export type SelectItem = { label: string; value: string; }; type SelectMultipleProps = React.ComponentPropsWithoutRef & { items?: SelectItem[] | null; value?: string[]; defaultValue?: string[]; onChange?: (value: string[]) => void; placeholder?: string; isCreatable?: boolean; onCreate?: (value: string) => void; }; type SelectMultipleRef = React.ElementRef; const SelectMultiple = forwardRef( (props, ref) => { const { items, value, defaultValue, onChange, placeholder = "Select...", isCreatable = false, onCreate, ...restProps } = props; const [search, setSearch] = useState(""); const itemList = useMemo(() => { if (!items?.length) { return []; } let list = [...items]; const searchText = search.toLowerCase().trim(); if (searchText?.length > 0) { list = list.filter((i) => i.label.toLowerCase().includes(searchText)); } return list.sort((a) => (value?.includes(a.value) ? -1 : 1)); }, [items, search, value]); const onCreateNew = () => { const newItem = search.trim(); onCreate?.(newItem); onItemPress(newItem); setSearch(""); }; const onItemPress = (key: string) => { const curValues = [...(value || [])]; const idx = curValues.indexOf(key); if (idx >= 0) { curValues.splice(idx, 1); onChange?.(curValues); } else { curValues.push(key); onChange?.(curValues); } }; const onEnter = () => { if (itemList.length > 0) { onItemPress(itemList[0].value); setSearch(""); return; } const newItem = search.trim(); if (isCreatable && newItem.length > 0) { return onCreateNew(); } }; return ( {placeholder} ); } ); type SelectMultipleFieldProps = FormFieldBaseProps & SelectMultipleProps; export const SelectMultipleField = ({ form, name, ...props }: SelectMultipleFieldProps) => ( ( <> )} /> ); export const useSelectCreatableItems = (initialItems?: SelectItem[] | null) => { const [items, setItems] = useState([]); const itemsCombined = useMemo(() => { return [...items, ...(initialItems || [])]; }, [items, initialItems]); const addItem = (value: string) => { const idx = itemsCombined.findIndex((i) => i.value === value); if (idx >= 0) { return; } setItems([...items, { label: value, value }]); }; return [itemsCombined, addItem, setItems] as const; }; export default SelectMultiple;