diff --git a/src/components/search.svelte b/src/components/search.svelte index 8559ec6..d625110 100644 --- a/src/components/search.svelte +++ b/src/components/search.svelte @@ -2,12 +2,9 @@ import { cn } from "@/utils/cn"; import { onMount } from "svelte"; - import { page } from "$app/state"; - import { goto } from "$app/navigation"; - + import { addParams } from "@/utils/searchParams"; import SearchIcon from "@lucide/svelte/icons/search"; import CommandIcon from "@lucide/svelte/icons/command"; - import { SvelteURLSearchParams } from "svelte/reactivity"; interface Props { searchValue: string; @@ -19,19 +16,12 @@ let inputElement: HTMLInputElement; const onInput = (event: Event) => { - const param = "search"; const value = (event.target as HTMLInputElement).value; onSearch(value); - const params = new SvelteURLSearchParams(page.url.searchParams); - if (value) { - params.set(param, value); - } else { - params.delete(param); - } - goto(`?${params.toString()}`, { - keepFocus: true, - noScroll: true, - replaceState: true, + addParams({ + params: { + search: value, + }, }); }; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 1f680ae..86e30f1 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -3,6 +3,7 @@ import type { PageProps } from "./$types"; import { cn } from "@/utils/cn"; + import { deleteParam } from "@/utils/searchParams"; import { svgsData } from "@/data"; import { searchWithFuse } from "@/utils/searchWithFuse"; @@ -12,11 +13,12 @@ import SvgCard from "@/components/svgs/svgCard.svelte"; import SortSvgs from "@/components/svgs/sortSvgs.svelte"; import Container from "@/components/container.svelte"; + import SearchXIcon from "@lucide/svelte/icons/search-x"; import PageCard from "@/components/pageCard.svelte"; - import PageHeader from "@/components/pageHeader.svelte"; import FolderIcon from "@lucide/svelte/icons/folder"; - import FolderSearchIcon from "@lucide/svelte/icons/folder-search"; + import PageHeader from "@/components/pageHeader.svelte"; + import Button from "@/components/ui/button/button.svelte"; // SSR Data: let { data }: PageProps = $props(); @@ -60,6 +62,13 @@ searchSvgs(); }; + const handleClearSearch = () => { + searchTerm = ""; + filteredSvgs = sorted ? alphabeticallySorted : latestSorted; + deleteParam("search"); + updateDisplaySvgs(); + }; + $effect(() => { updateDisplaySvgs(); }); @@ -87,7 +96,14 @@ logos

{:else} - +

{filteredSvgs.length} logos diff --git a/src/routes/directory/[category]/+page.svelte b/src/routes/directory/[category]/+page.svelte index 6e84561..d0900de 100644 --- a/src/routes/directory/[category]/+page.svelte +++ b/src/routes/directory/[category]/+page.svelte @@ -3,7 +3,6 @@ import type { PageProps } from "./$types"; import { page } from "$app/state"; - import { goto } from "$app/navigation"; import { SvelteURLSearchParams } from "svelte/reactivity"; import { cn } from "@/utils/cn"; @@ -14,68 +13,70 @@ import Search from "@/components/search.svelte"; import SvgCard from "@/components/svgs/svgCard.svelte"; import Container from "@/components/container.svelte"; + import SearchXIcon from "@lucide/svelte/icons/search-x"; import PageCard from "@/components/pageCard.svelte"; import PageHeader from "@/components/pageHeader.svelte"; import FolderIcon from "@lucide/svelte/icons/folder-open"; import ArrowLeftIcon from "@lucide/svelte/icons/arrow-left"; - import { buttonVariants } from "@/components/ui/button"; + import { Button, buttonVariants } from "@/components/ui/button"; + import SortSvgs from "@/components/svgs/sortSvgs.svelte"; + import { deleteParam } from "@/utils/searchParams"; // SSR Data: let { data }: PageProps = $props(); const directoryData = $derived(data); // States: + let maxDisplay = 30; let searchTerm = $state(data.searchTerm || ""); - let filteredSvgs = $derived(data.filteredSvgs); + let filteredSvgs = $derived(data.initialSvgs); + let sorted = $state(data.sorted); + let displaySvgs = $state([]); + let showAll = $state(false); + + const updateDisplaySvgs = () => { + displaySvgs = showAll ? filteredSvgs : filteredSvgs.slice(0, maxDisplay); + }; const searchSvgs = () => { if (!searchTerm) { - filteredSvgs = data.svgs; + filteredSvgs = sorted ? data.alphabeticallySorted : data.latestSorted; + updateDisplaySvgs(); return; } if (searchTerm.length < 3) { - filteredSvgs = data.svgs.filter((svg: iSVG) => + filteredSvgs = ( + sorted ? data.alphabeticallySorted : data.latestSorted + ).filter((svg: iSVG) => svg.title.toLowerCase().includes(searchTerm.toLowerCase()), ); } else { - filteredSvgs = searchWithFuse(data.svgs) + filteredSvgs = searchWithFuse(filteredSvgs) .search(searchTerm) .map((result) => result.item); } + updateDisplaySvgs(); }; const handleSearch = (value: string) => { searchTerm = value; - - const params = new SvelteURLSearchParams(page.url.searchParams); - if (value) { - params.set("search", value); - } else { - params.delete("search"); - } - - goto(`?${params.toString()}`, { - keepFocus: true, - noScroll: true, - replaceState: true, - }); - searchSvgs(); }; - const formatCategory = (category: string) => - category.charAt(0).toUpperCase() + category.slice(1); + const handleClearSearch = () => { + searchTerm = ""; + deleteParam("search"); + updateDisplaySvgs(); + }; $effect(() => { - filteredSvgs = data.svgs.filter((svg: iSVG) => - svg.title.toLowerCase().includes(searchTerm.toLowerCase()), - ); + updateDisplaySvgs(); }); - {formatCategory(directoryData.category)} SVG logos - Svgl + {directoryData.category} SVG logos - Svgl - + - + {#if searchTerm} + + {:else} + + {/if}

- {formatCategory(directoryData.category)} + {directoryData.category}

- {#if !searchTerm}

- {data.svgs.length} SVGs + {data.initialSvgs.length} SVGs

{:else}

@@ -117,6 +123,14 @@

{/if} + { + sorted = value; + searchSvgs(); + }} + /> diff --git a/src/utils/searchParams.ts b/src/utils/searchParams.ts new file mode 100644 index 0000000..9ae5f44 --- /dev/null +++ b/src/utils/searchParams.ts @@ -0,0 +1,35 @@ +import { page } from "$app/state"; +import { goto } from "$app/navigation"; +import { SvelteURLSearchParams } from "svelte/reactivity"; + +interface SearchParams { + params: Record; +} + +const addParams = ({ params }: SearchParams) => { + const searchParams = new SvelteURLSearchParams(page.url.searchParams); + Object.entries(params).forEach(([key, value]) => { + if (value) { + searchParams.set(key, value); + } else { + searchParams.delete(key); + } + }); + goto(`?${searchParams.toString()}`, { + keepFocus: true, + noScroll: true, + replaceState: true, + }); +}; + +const deleteParam = (key: string) => { + const params = new SvelteURLSearchParams(page.url.searchParams); + params.delete(key); + goto(`?${params.toString()}`, { + keepFocus: true, + noScroll: true, + replaceState: true, + }); +}; + +export { addParams, deleteParam };