OneLauncher-Cracked/desktop/src/ui/components/base/Dropdown.tsx
2024-06-18 00:18:19 +02:00

81 lines
2.2 KiB
TypeScript

import { Index, type JSX, type ParentProps, children, createSignal, splitProps } from 'solid-js';
import { ChevronDownIcon } from '@untitled-theme/icons-solid';
import Popup from '../overlay/Popup';
import Button from './Button';
import styles from './Dropdown.module.scss';
export type DropdownProps = Omit<JSX.HTMLAttributes<HTMLDivElement>, 'onChange'> & {
onChange?: (selected: number) => any;
text?: string;
selected?: number;
};
function Dropdown(props: DropdownProps) {
const [split, rest] = splitProps(props, ['children', 'class', 'text', 'onChange', 'selected']);
const [visible, setVisible] = createSignal(false);
// eslint-disable-next-line solid/reactivity -- todo
const [selected, setSelected] = createSignal<number>(split.selected || 0);
let ref!: HTMLDivElement;
const items = () => children(() => split.children).toArray();
function select(index: number) {
setSelected(index);
setVisible(false);
if (split.onChange)
split.onChange(selected());
}
return (
<div ref={ref} class={`${styles.dropdown} ${split.class}`} {...rest}>
<Button
class="h-full w-full"
buttonStyle="secondary"
onClick={() => setVisible(true)}
iconRight={<ChevronDownIcon />}
>
<div
class="flex-1 flex flex-row items-center text-nowrap gap-1 h-full overflow-hidden"
>
<span>{split.text}</span>
{items()[selected()]}
</div>
</Button>
<Popup
mount={ref}
visible={visible}
setVisible={setVisible}
ref={ref => ref.classList.add('mt-1', 'w-full')}
>
<div class="bg-secondary rounded-lg border border-gray-05 p-1 shadow-md shadow-black/30">
<div class="flex flex-col gap-2">
<Index each={items()}>
{(item, index) => (
<div onClick={() => select(index)}>
<div class="hover:bg-gray-05 p-2 rounded-lg flex flex-row gap-2 justify-between items-center">
{item()}
<div class={styles.selected! + (selected() === index ? ` ${styles.visible}` : '')} />
</div>
</div>
)}
</Index>
</div>
</div>
</Popup>
</div>
);
}
Dropdown.Row = function (props: ParentProps) {
return (
<div class={styles.row}>
{props.children}
</div>
);
};
export default Dropdown;