/*! ratio-ui · design system for knowledge sharing · https://github.com/losol/ratio-ui · (c) 2026 Losol AS · MPL-2.0 */
"use client";
import { Search } from "../../icons/index.js";
import { Kbd } from "../Kbd/Kbd.js";
import "../Kbd/index.js";
import { useCallback, useEffect, useRef, useState } from "react";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
//#region src/core/CommandPalette/CommandPalette.tsx
var SHORTCUT_KEYS = {
	"cmd+k": "k",
	"cmd+j": "j",
	"cmd+p": "p"
};
/**
* Command palette with trigger button, search input, keyboard navigation,
* and result list. Implements the combobox + listbox ARIA pattern.
*
* Register a global keyboard shortcut (default Cmd+K) to open.
*/
function CommandPalette({ items, onSelect, onQueryChange, placeholder = "Search...", shortcut = "cmd+k", shortcutHint = "⌘K", emptyMessage = "No results for “{query}”", className = "" }) {
	const [isOpen, setIsOpen] = useState(false);
	const [query, setQuery] = useState("");
	const [activeIndex, setActiveIndex] = useState(0);
	const inputRef = useRef(null);
	const dialogRef = useRef(null);
	const previousFocusRef = useRef(null);
	const open = useCallback(() => setIsOpen(true), []);
	const close = useCallback(() => setIsOpen(false), []);
	useEffect(() => {
		const key = SHORTCUT_KEYS[shortcut];
		if (!key) return;
		const handler = (e) => {
			if ((e.metaKey || e.ctrlKey) && e.key === key) {
				e.preventDefault();
				setIsOpen((prev) => !prev);
			}
		};
		document.addEventListener("keydown", handler);
		return () => document.removeEventListener("keydown", handler);
	}, [shortcut]);
	useEffect(() => {
		if (isOpen) {
			previousFocusRef.current = document.activeElement;
			requestAnimationFrame(() => inputRef.current?.focus());
			const trapFocus = (e) => {
				if (e.key !== "Tab") return;
				const dialog = dialogRef.current;
				if (!dialog) return;
				const focusable = dialog.querySelectorAll("input, button, [tabindex]:not([tabindex=\"-1\"])");
				if (focusable.length === 0) return;
				const first = focusable[0];
				const last = focusable[focusable.length - 1];
				if (e.shiftKey && document.activeElement === first) {
					e.preventDefault();
					last.focus();
				} else if (!e.shiftKey && document.activeElement === last) {
					e.preventDefault();
					first.focus();
				}
			};
			document.addEventListener("keydown", trapFocus);
			return () => document.removeEventListener("keydown", trapFocus);
		} else {
			setQuery("");
			setActiveIndex(0);
			previousFocusRef.current?.focus();
		}
	}, [isOpen]);
	const handleQueryChange = useCallback((value) => {
		setQuery(value);
		setActiveIndex(0);
		onQueryChange(value);
	}, [onQueryChange]);
	const handleSelect = useCallback((item) => {
		onSelect(item);
		close();
	}, [onSelect, close]);
	const handleKeyDown = (e) => {
		if (e.key === "Escape") {
			close();
			return;
		}
		if (items.length === 0) return;
		if (e.key === "ArrowDown") {
			e.preventDefault();
			setActiveIndex((i) => Math.min(i + 1, items.length - 1));
		} else if (e.key === "ArrowUp") {
			e.preventDefault();
			setActiveIndex((i) => Math.max(i - 1, 0));
		} else if (e.key === "Enter" && items[activeIndex]) {
			e.preventDefault();
			handleSelect(items[activeIndex]);
		}
	};
	return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("button", {
		type: "button",
		onClick: open,
		className: `flex items-center gap-2 rounded-lg border border-border-1 px-3 py-1.5 text-sm text-(--text-subtle) transition-colors hover:border-border-2 hover:text-(--text) ${className}`,
		"aria-label": placeholder,
		children: [
			/* @__PURE__ */ jsx(Search, {
				"aria-hidden": "true",
				className: "h-4 w-4"
			}),
			/* @__PURE__ */ jsx("span", {
				className: "hidden sm:inline",
				children: placeholder
			}),
			shortcutHint && /* @__PURE__ */ jsx(Kbd, {
				className: "hidden sm:inline-flex",
				children: shortcutHint
			})
		]
	}), isOpen && /* @__PURE__ */ jsx("div", {
		className: "fixed inset-0 z-50 flex items-start justify-center pt-[20vh] bg-black/50",
		onClick: (e) => {
			if (e.target === e.currentTarget) close();
		},
		onKeyDown: (e) => {
			if (e.key === "Escape") close();
		},
		role: "presentation",
		children: /* @__PURE__ */ jsxs("div", {
			ref: dialogRef,
			"aria-label": placeholder,
			"aria-modal": "true",
			className: "w-full max-w-lg rounded-xl bg-card shadow-2xl",
			role: "dialog",
			children: [
				/* @__PURE__ */ jsxs("div", {
					className: "flex items-center border-b border-border-1 px-4",
					children: [
						/* @__PURE__ */ jsx(Search, {
							"aria-hidden": "true",
							className: "mr-3 h-5 w-5 text-(--text-subtle)"
						}),
						/* @__PURE__ */ jsx("input", {
							ref: inputRef,
							"aria-activedescendant": items.length > 0 ? `command-palette-option-${activeIndex}` : void 0,
							"aria-autocomplete": "list",
							"aria-controls": "command-palette-results",
							"aria-expanded": items.length > 0,
							className: "w-full bg-transparent py-4 text-base text-(--text) outline-none placeholder:text-(--text-subtle)",
							onChange: (e) => handleQueryChange(e.target.value),
							onKeyDown: handleKeyDown,
							placeholder,
							role: "combobox",
							type: "search",
							value: query
						}),
						/* @__PURE__ */ jsx(Kbd, {
							className: "ml-2",
							children: "esc"
						})
					]
				}),
				items.length > 0 && /* @__PURE__ */ jsx("ul", {
					className: "max-h-80 overflow-y-auto p-2",
					id: "command-palette-results",
					role: "listbox",
					children: items.map((item, i) => /* @__PURE__ */ jsxs("li", {
						id: `command-palette-option-${i}`,
						"aria-selected": i === activeIndex,
						className: `cursor-pointer rounded-lg px-4 py-3 ${i === activeIndex ? "bg-primary-50 dark:bg-primary-900/30" : "hover:bg-card-hover/50"}`,
						onClick: () => handleSelect(item),
						role: "option",
						children: [/* @__PURE__ */ jsx("div", {
							className: "text-sm font-medium text-(--text)",
							children: item.title
						}), item.descriptionHtml && /* @__PURE__ */ jsx("div", {
							className: "mt-1 line-clamp-2 text-xs text-(--text-subtle)",
							dangerouslySetInnerHTML: { __html: item.descriptionHtml }
						})]
					}, item.id))
				}),
				query && items.length === 0 && /* @__PURE__ */ jsx("div", {
					className: "px-4 py-8 text-center text-sm text-(--text-subtle)",
					children: emptyMessage.replace("{query}", query)
				})
			]
		})
	})] });
}
//#endregion
export { CommandPalette };

//# sourceMappingURL=CommandPalette.js.map