Skip to content

Instantly share code, notes, and snippets.

@gabrielpetersson
Last active November 5, 2022 20:37
Show Gist options
  • Save gabrielpetersson/fe73719e6c989649ab68eea74bf88c4e to your computer and use it in GitHub Desktop.
Save gabrielpetersson/fe73719e6c989649ab68eea74bf88c4e to your computer and use it in GitHub Desktop.
type EnumInputProps =
| {
isMultiSelect: true;
options: EnumOption[];
selected: EnumOption[];
onChange: (value: string[]) => void;
}
| {
isMultiSelect: false;
options: EnumOption[];
selected: EnumOption | null;
onChange: (value: string | null) => void;
};
const EnumMultiInput: FC<EnumInputProps> = ({
options,
isMultiSelect,
selected,
onChange,
}) => {
const [query, setQuery] = useState("");
const [open, setOpen] = useState(false);
const filteredOptions =
query !== ""
? options.filter((option) => option.value.includes(query))
: options;
const { x, y, reference, floating, strategy, context } = useFloating({
open: open,
onOpenChange: setOpen,
middleware: [
size({
apply({ rects, elements }) {
Object.assign(elements.floating.style, {
width: `${rects.reference.width}px`,
});
},
}),
],
placement: "bottom-start",
});
const { getReferenceProps, getFloatingProps } = useInteractions([
useClick(context),
useDismiss(context),
]);
const displaySelected = (() => {
if (selected == null) {
return [];
}
return Array.isArray(selected) ? selected : [selected];
})();
const selected2 = (() => {
if (Array.isArray(selected)) {
return selected.map((s) => s.value);
}
return selected?.value ?? null;
})();
return (
<>
<Box style={thirdBoxStyle} ref={reference} {...getReferenceProps()}>
<div
className={
"align-start mw-[100%] dl-scrollbar flex w-[100%] min-w-0 max-w-[100%] cursor-pointer overflow-x-auto pl-[8px]"
}
>
{displaySelected.length !== 0
? displaySelected.map((option, i) => (
<React.Fragment key={i}>
<Pill {...option} />
<Spacer width={6} />
</React.Fragment>
))
: "Select a value"}
</div>
</Box>
{open && (
<div
ref={floating}
className={clsx("flex flex-col overflow-hidden rounded shadow-sm")}
style={{
position: strategy,
top: y ?? 0,
left: x ?? 0,
}}
{...getFloatingProps()}
>
<Combobox
value={selected2}
// eslint-disable-next-line no-undefined
multiple={isMultiSelect ? true : (undefined as any)}
onChange={(v) => {
onChange(v as any);
if (!isMultiSelect) {
setOpen(false);
setQuery("");
}
}}
>
<Combobox.Input
autoFocus
placeholder={"Find an option..."}
// value={query}
displayValue={() => {
return query;
}}
onChange={(event) => {
setQuery(event.target.value);
}}
className={
"h-[28px] flex-shrink-0 border-none bg-dl-black pl-[10px] align-middle text-12 text-white placeholder-dl-gray-3 outline-none"
}
/>
<Combobox.Options
static
className={
"dl-scrollbar flex max-w-[240px] flex-col overflow-y-auto overflow-x-hidden rounded bg-dl-black"
}
>
{filteredOptions.map((option) => (
<Combobox.Option
key={option.value}
value={option.value}
className={
"box-border flex cursor-pointer justify-between py-[5px] pr-[10px] pl-[8px] ui-active:bg-dl-dark-gray-1"
}
>
{({ selected }) => (
<>
<div className={"min-w-0"}>
<Pill {...option} />
</div>
{selected && (
<div className="ml-[8px] flex-shrink-0">
<Icon icon={"check"} color={"white"} size={16} />
</div>
)}
</>
)}
</Combobox.Option>
))}
</Combobox.Options>
</Combobox>
</div>
)}
</>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment