139 lines
4.2 KiB
Text
139 lines
4.2 KiB
Text
---
|
|
import "@pagefind/default-ui/css/ui.css";
|
|
import Main from "@/layouts/Main.astro";
|
|
import Layout from "@/layouts/Layout.astro";
|
|
import Header from "@/components/Header.astro";
|
|
import Footer from "@/components/Footer.astro";
|
|
import { SITE } from "@/config";
|
|
|
|
const backUrl = SITE.showBackButton ? `${Astro.url.pathname}` : "/";
|
|
---
|
|
|
|
<Layout title={`Search | ${SITE.title}`}>
|
|
<Header />
|
|
<Main pageTitle="Search" pageDesc="Search any article ...">
|
|
<div id="pagefind-search" transition:persist data-backurl={backUrl}></div>
|
|
</Main>
|
|
<Footer />
|
|
</Layout>
|
|
|
|
<script>
|
|
function initSearch() {
|
|
const pageFindSearch: HTMLElement | null =
|
|
document.querySelector("#pagefind-search");
|
|
|
|
if (!pageFindSearch) return;
|
|
|
|
const params = new URLSearchParams(window.location.search);
|
|
|
|
const onIdle = window.requestIdleCallback || (cb => setTimeout(cb, 1));
|
|
|
|
onIdle(async () => {
|
|
// @ts-expect-error — Missing types for @pagefind/default-ui package.
|
|
const { PagefindUI } = await import("@pagefind/default-ui");
|
|
|
|
// Display warning inn dev mode
|
|
if (import.meta.env.DEV) {
|
|
pageFindSearch.innerHTML = `
|
|
<div class="bg-muted/75 rounded p-4 space-y-4 mb-4">
|
|
<p><strong>DEV mode Warning! </strong>You need to build the project at least once to see the search results during development.</p>
|
|
<code class="block bg-black text-white px-2 py-1 rounded">pnpm run build</code>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Init pagefind ui
|
|
const search = new PagefindUI({
|
|
element: "#pagefind-search",
|
|
showSubResults: true,
|
|
showImages: false,
|
|
processTerm: function (term: string) {
|
|
params.set("q", term); // Update the `q` parameter in the URL
|
|
history.replaceState(history.state, "", "?" + params.toString()); // Push the new URL without reloading
|
|
|
|
const backUrl = pageFindSearch?.dataset?.backurl;
|
|
sessionStorage.setItem("backUrl", backUrl + "?" + params.toString());
|
|
|
|
return term;
|
|
},
|
|
});
|
|
|
|
// If search param exists (eg: search?q=astro), trigger search
|
|
const query = params.get("q");
|
|
if (query) {
|
|
search.triggerSearch(query);
|
|
}
|
|
|
|
// Reset search param if search input is cleared
|
|
const searchInput = document.querySelector(".pagefind-ui__search-input");
|
|
const clearButton = document.querySelector(".pagefind-ui__search-clear");
|
|
searchInput?.addEventListener("input", resetSearchParam);
|
|
clearButton?.addEventListener("click", resetSearchParam);
|
|
|
|
function resetSearchParam(e: Event) {
|
|
if ((e.target as HTMLInputElement)?.value.trim() === "") {
|
|
history.replaceState(history.state, "", window.location.pathname);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
document.addEventListener("astro:after-swap", () => {
|
|
const pagefindSearch = document.querySelector("#pagefind-search");
|
|
|
|
// if pagefind search form already exists, don't initialize search component
|
|
if (pagefindSearch && pagefindSearch.querySelector("form")) return;
|
|
|
|
initSearch();
|
|
});
|
|
initSearch();
|
|
</script>
|
|
|
|
<style is:global>
|
|
#pagefind-search {
|
|
--pagefind-ui-font: var(--font-mono);
|
|
--pagefind-ui-text: var(--foreground);
|
|
--pagefind-ui-background: var(--background);
|
|
--pagefind-ui-border: var(--border);
|
|
--pagefind-ui-primary: var(--accent);
|
|
--pagefind-ui-tag: var(--background);
|
|
--pagefind-ui-border-radius: 0.375rem;
|
|
--pagefind-ui-border-width: 1px;
|
|
--pagefind-ui-image-border-radius: 8px;
|
|
--pagefind-ui-image-box-ratio: 3 / 2;
|
|
|
|
form::before {
|
|
background-color: var(--foreground);
|
|
}
|
|
|
|
input {
|
|
font-weight: 400;
|
|
border: 1px solid var(--border);
|
|
}
|
|
|
|
input:focus-visible {
|
|
outline: 1px solid var(--accent);
|
|
}
|
|
|
|
.pagefind-ui__result-title a {
|
|
color: var(--accent);
|
|
outline-offset: 1px;
|
|
outline-color: var(--accent);
|
|
}
|
|
|
|
.pagefind-ui__result-title a:focus-visible,
|
|
.pagefind-ui__search-clear:focus-visible {
|
|
text-decoration-line: none;
|
|
outline-width: 2px;
|
|
outline-style: dashed;
|
|
}
|
|
|
|
.pagefind-ui__result:last-of-type {
|
|
border-bottom: 0;
|
|
}
|
|
|
|
.pagefind-ui__result-nested .pagefind-ui__result-link:before {
|
|
font-family: system-ui;
|
|
}
|
|
}
|
|
</style>
|