Files
pulsenode/components/widgets/search/Widget.tsx
T

69 lines
2.4 KiB
TypeScript
Raw Normal View History

2026-08-17 13:49:55 +02:00
"use client";
import { useState, type FormEvent } from "react";
import type { SearchEngine, Widget } from "@/lib/config/schema";
import { WidgetCard } from "@/components/widgets/WidgetCard";
2026-08-17 13:49:55 +02:00
type SearchWidget = Extract<Widget, { type: "search" }>;
const ENGINE_URLS: Record<string, string> = {
duckduckgo: "https://duckduckgo.com/?q=",
google: "https://www.google.com/search?q=",
bing: "https://www.bing.com/search?q=",
};
const ENGINE_LABEL: Record<string, string> = {
duckduckgo: "DuckDuckGo",
google: "Google",
bing: "Bing",
};
2026-08-17 13:49:55 +02:00
export function SearchWidget({ widget }: { widget: SearchWidget }) {
const [engine, setEngine] = useState(widget.defaultEngine ?? widget.engines[0]);
const [query, setQuery] = useState("");
function handleSubmit(event: FormEvent) {
event.preventDefault();
const trimmed = query.trim();
if (!trimmed) return;
window.open(`${ENGINE_URLS[engine]}${encodeURIComponent(trimmed)}`, "_blank", "noreferrer");
}
return (
<WidgetCard span={4}>
<form onSubmit={handleSubmit} className="flex flex-1 flex-col justify-center gap-2">
<div className="text-[10px] tracking-[0.1em] text-accent uppercase">Search</div>
<input
value={query}
onChange={(event) => setQuery(event.target.value)}
placeholder="Search the web…"
autoComplete="off"
className="min-h-9 w-full rounded-md border border-border bg-bg px-2.5 py-1.5 text-sm text-fg outline-none placeholder:text-fg-muted focus-visible:border-accent"
/>
{widget.engines.length > 1 && (
<div className="inline-flex self-start overflow-hidden rounded-md border border-border">
{widget.engines.map((option) => (
<label
key={option}
className={`cursor-pointer px-2.5 py-1 text-[12px] first:border-l-0 [&+label]:border-l [&+label]:border-border ${
option === engine ? "text-accent shadow-[inset_0_0_0_1px_var(--pn-accent)]" : "text-fg-muted"
}`}
>
<input
type="radio"
name="engine"
value={option}
checked={option === engine}
onChange={() => setEngine(option as SearchEngine)}
className="sr-only"
/>
{ENGINE_LABEL[option] ?? option}
</label>
))}
</div>
)}
</form>
</WidgetCard>
2026-08-17 13:49:55 +02:00
);
}