feat: refactor replacing types & moving search item to DropdownMenu component + add multiselect functionality
This commit is contained in:
@@ -1,57 +1,43 @@
|
||||
<script lang="ts">
|
||||
// This component (Checkbox) is implemented in a parallel Pull Request, so it may not be available in the current branch
|
||||
// import Checkbox from "./Checkbox.svelte";
|
||||
import SearchIcon from "../../../svgs/SearchIcon.svelte";
|
||||
import type {
|
||||
DropdownItemModel,
|
||||
DropdownItemPosition,
|
||||
DropdownVariant,
|
||||
} from "./dropdown.types";
|
||||
|
||||
let {
|
||||
position = "middle",
|
||||
id,
|
||||
label,
|
||||
position,
|
||||
variant,
|
||||
selectedIds = $bindable<string[]>([]),
|
||||
...item
|
||||
} = $props<
|
||||
DropdownItemModel & {
|
||||
position?: DropdownItemPosition;
|
||||
variant: DropdownVariant;
|
||||
selectedIds?: string[];
|
||||
}
|
||||
>();
|
||||
} = $props<{
|
||||
id: string;
|
||||
label: string;
|
||||
position?: DropdownItemPosition;
|
||||
variant: DropdownVariant;
|
||||
selectedIds?: string[];
|
||||
}>();
|
||||
|
||||
let positionClass =
|
||||
position === "start" ? "rounded-t-lg" : position === "end" ? "rounded-b-lg" : "";
|
||||
</script>
|
||||
|
||||
{#if item.type === "search"}
|
||||
<div class="border-grey rounded-t-lg border bg-white p-4">
|
||||
<div
|
||||
class="border-secondary group relative flex items-center justify-between rounded-3xl border bg-white p-4"
|
||||
>
|
||||
<input
|
||||
class="max-h-6 w-full max-w-72 border-0 bg-white p-0 text-base/6 font-normal text-black ring-0 placeholder:opacity-48"
|
||||
type="text"
|
||||
placeholder="Search..."
|
||||
/>
|
||||
<SearchIcon class="absolute right-4" width={"32"} height={"32"} />
|
||||
</div>
|
||||
</div>
|
||||
{:else if variant === "multiselect"}
|
||||
{#if variant === "multiselect"}
|
||||
<div
|
||||
class="border-grey hover:bg-soft-purple hover:border-variant1 cursor-pointer border bg-white p-4 text-start {positionClass}"
|
||||
>
|
||||
<label class="flex cursor-pointer justify-between">
|
||||
<span class="text-base text-black">{item.label}</span>
|
||||
<span class="text-base text-black">{label}</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selectedIds.includes(item.id)}
|
||||
checked={selectedIds.includes(id)}
|
||||
onchange={(e) => {
|
||||
if (e.currentTarget.checked) {
|
||||
selectedIds = [...selectedIds, item.id];
|
||||
selectedIds = [...selectedIds, id];
|
||||
} else {
|
||||
selectedIds = selectedIds.filter((id: string) => id !== item.id);
|
||||
selectedIds = selectedIds.filter((x: string) => x !== id);
|
||||
}
|
||||
}}
|
||||
class="text-primary border-secondary mt-1 size-5 shrink-0 rounded-sm border ring-0"
|
||||
@@ -62,6 +48,6 @@
|
||||
<div
|
||||
class="border-grey hover:bg-soft-purple hover:border-variant1 cursor-pointer border bg-white p-4 text-start {positionClass}"
|
||||
>
|
||||
<button class="w-full cursor-pointer text-base text-black">{item.label}</button>
|
||||
<button class="w-full cursor-pointer text-base text-black">{label}</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -1,49 +1,46 @@
|
||||
<script lang="ts">
|
||||
import SearchIcon from "../../../svgs/SearchIcon.svelte";
|
||||
import DropdownItem from "./DropdownItem.svelte";
|
||||
import type {
|
||||
DropdownVariant,
|
||||
DropdownBasicItem,
|
||||
DropdownMultiSelectItem,
|
||||
DropdownItemModel,
|
||||
} from "./dropdown.types";
|
||||
import type { DropdownItemPosition, DropdownItemType, DropdownVariant } from "./dropdown.types";
|
||||
|
||||
let {
|
||||
variant,
|
||||
items,
|
||||
hasSearch = false,
|
||||
selectedIds = $bindable<string[]>([]),
|
||||
} = $props<
|
||||
| {
|
||||
variant: "basic";
|
||||
items: DropdownBasicItem[];
|
||||
hasSearch?: boolean;
|
||||
}
|
||||
| {
|
||||
variant: "multiselect";
|
||||
items: DropdownMultiSelectItem[];
|
||||
hasSearch?: boolean;
|
||||
selectedIds?: string[];
|
||||
}
|
||||
>();
|
||||
} = $props<{
|
||||
variant: DropdownVariant;
|
||||
items: DropdownItemType[];
|
||||
hasSearch?: boolean;
|
||||
selectedIds?: string[];
|
||||
}>();
|
||||
|
||||
const renderedItems = $derived<DropdownItemModel[]>([
|
||||
...(hasSearch ? [{ id: "search", type: "search" } as const] : []),
|
||||
...items.map((item: DropdownBasicItem | DropdownMultiSelectItem) => ({
|
||||
...item,
|
||||
type: variant,
|
||||
})),
|
||||
]);
|
||||
const renderedItems = $derived<DropdownItemType[]>(items);
|
||||
|
||||
function getPosition(index: number, length: number) {
|
||||
if (index === 0 && hasSearch) return "middle";
|
||||
function getPosition(index: number, length: number): DropdownItemPosition {
|
||||
if (index === 0 && !hasSearch) return "start";
|
||||
if (index === length - 1) return "end";
|
||||
return "start";
|
||||
return "middle";
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="flex w-full max-w-[416px] flex-col self-center rounded-lg bg-transparent shadow-[0_35px_10px_0_rgba(0,0,0,0),0_22px_9px_0_rgba(0,0,0,0.01),0_13px_8px_0_rgba(0,0,0,0.05),0_6px_6px_0_rgba(0,0,0,0.09),0_1px_3px_0_rgba(0,0,0,0.1)]"
|
||||
>
|
||||
{#if hasSearch}
|
||||
<div class="border-grey rounded-t-lg border bg-white p-4">
|
||||
<div
|
||||
class="border-secondary group relative flex items-center justify-between rounded-3xl border bg-white p-4"
|
||||
>
|
||||
<input
|
||||
class="max-h-6 w-full max-w-72 border-0 bg-white p-0 text-base/6 font-normal text-black ring-0 placeholder:opacity-48"
|
||||
type="text"
|
||||
placeholder="Search..."
|
||||
/>
|
||||
<SearchIcon class="absolute right-4" width={"32"} height={"32"} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#each renderedItems as item, index}
|
||||
<DropdownItem
|
||||
{...item}
|
||||
|
||||
@@ -2,17 +2,7 @@ export type DropdownVariant = "basic" | "multiselect";
|
||||
|
||||
export type DropdownItemPosition = "start" | "middle" | "end";
|
||||
|
||||
export type DropdownBasicItem = {
|
||||
export type DropdownItemType = {
|
||||
id: string;
|
||||
label: string;
|
||||
};
|
||||
|
||||
export type DropdownMultiSelectItem = {
|
||||
id: string;
|
||||
label: string;
|
||||
};
|
||||
|
||||
export type DropdownItemModel =
|
||||
| { id: string; type: "search" }
|
||||
| ({ type: "basic" } & DropdownBasicItem)
|
||||
| ({ type: "multiselect" } & DropdownMultiSelectItem);
|
||||
|
||||
Reference in New Issue
Block a user