101 lines
3.3 KiB
JavaScript
101 lines
3.3 KiB
JavaScript
import { Combobox } from "@headlessui/react";
|
|
|
|
import { DropDownItem } from "@shared/nej-react-components/Parts/DropDown";
|
|
import { useEffect, useState } from "react";
|
|
|
|
import tw, { styled } from "twin.macro";
|
|
import "styled-components/macro";
|
|
import { useField } from "@shared/nej-react-components/Parts/Input";
|
|
|
|
export function AutocompleteSelect({ title, titleProps = null, data, nullable = false, ...props }) {
|
|
const [field, meta, helpers] = useField(props);
|
|
|
|
const [query, setQuery] = useState(field.value ?? "");
|
|
const [internalData, setInternalData] = useState([]);
|
|
|
|
useEffect(() => {
|
|
(async () => {
|
|
if (typeof data === "function") {
|
|
//if data is async function await it
|
|
setInternalData(await data(query));
|
|
} else if (Array.isArray(data)) {
|
|
setInternalData(
|
|
query === ""
|
|
? data
|
|
: data.filter((item) => {
|
|
if (typeof item === "string")
|
|
return item.toLowerCase().includes(query.toLowerCase());
|
|
|
|
return item.label.toLowerCase().includes(query.toLowerCase());
|
|
})
|
|
);
|
|
} else {
|
|
console.error("data is not an array or function :c");
|
|
setInternalData([]);
|
|
}
|
|
})();
|
|
}, [query, data]);
|
|
|
|
return (
|
|
<>
|
|
<Combobox
|
|
{...props}
|
|
{...field}
|
|
value={
|
|
field.value
|
|
? internalData?.filter((item) =>
|
|
typeof item === "string"
|
|
? item == field.value
|
|
: item.value === field.value
|
|
)[0]
|
|
: null
|
|
}
|
|
onChange={(value) => {
|
|
console.log(value);
|
|
field.onChange({ target: { value: value, name: field.name } });
|
|
}}
|
|
nullable={nullable}
|
|
>
|
|
<div css={[title && tw`my-1`, tw`relative`]} >
|
|
{title && (
|
|
<label
|
|
{...titleProps}
|
|
css={[
|
|
tw`block text-secondary text-sm font-bold mb-2`,
|
|
titleProps?.css,
|
|
]}
|
|
>
|
|
{title}
|
|
</label>
|
|
)}
|
|
<div tw="relative">
|
|
<Combobox.Input
|
|
tw="bg-primary cursor-pointer appearance-none border-2 border-secondary rounded w-full py-2 px-4 text-primary leading-tight focus:outline-none focus:bg-secondary focus:border-accent transition duration-150 "
|
|
onChange={(event) => setQuery(event.target.value)}
|
|
displayValue={(val) => (typeof val === "string" ? val : val?.label)}
|
|
/>
|
|
<Combobox.Button tw="absolute top-0 right-0 left-0 bottom-0 " />
|
|
</div>
|
|
<Combobox.Options tw="absolute z-10 max-h-60 w-full bg-trinary rounded-xl overflow-y-auto overflow-x-hidden">
|
|
{internalData?.map((val) => (
|
|
<Combobox.Option
|
|
tw=""
|
|
key={typeof val === "string" ? val : val.value}
|
|
value={typeof val === "string" ? val : val.value}
|
|
>
|
|
<DropDownItem>
|
|
{typeof val === "string" ? val : val.label}
|
|
</DropDownItem>
|
|
</Combobox.Option>
|
|
))}
|
|
</Combobox.Options>
|
|
</div>
|
|
</Combobox>
|
|
|
|
{meta?.touched && meta.error ? (
|
|
<div tw="text-[#c23c3c]">{meta.error}</div>
|
|
) : null}
|
|
</>
|
|
);
|
|
}
|