import { t as e } from "./utils-Ct96Mtjw.js";
import { l as t, r as n, t as r, u as i } from "./dialog-DQ6nkP0y.js";
import { createContext as a, forwardRef as o, useCallback as s, useContext as c, useEffect as l, useRef as u, useState as d } from "react";
import { FileText as f, Loader2 as p, Search as m, X as h } from "lucide-react";
import { useNavigate as g } from "react-router-dom";
import { jsx as _, jsxs as v } from "react/jsx-runtime";
import y from "flexsearch";
//#region src/lib/search/runtime/search-engine.ts
var b = 20, x = class {
	index;
	sections = /* @__PURE__ */ new Map();
	initialized = !1;
	constructor() {
		this.index = new y.Index({
			tokenize: "full",
			resolution: 9,
			cache: 100
		});
	}
	init(e) {
		this.clear();
		for (let t of e.sections) this.sections.set(t.id, t), this.index.add(t.id, t.tokens.join(" "));
		this.initialized = !0;
	}
	clear() {
		this.sections.clear(), this.index = new y.Index({
			tokenize: "full",
			resolution: 9,
			cache: 100
		}), this.initialized = !1;
	}
	search(e) {
		if (!this.initialized) return [];
		let { query: t, limit: n = b } = e, r = t.toLowerCase().trim();
		return r ? this.index.search(r, { limit: n }).map((e) => {
			let t = this.sections.get(e);
			return t ? {
				id: t.id,
				pageTitle: t.pageTitle,
				sectionTitle: t.sectionTitle,
				snippet: this.generateSnippet(t.content, r),
				url: t.url,
				score: 1
			} : null;
		}).filter((e) => e !== null) : [];
	}
	generateSnippet(e, t) {
		if (!e) return "";
		let n = e.toLowerCase(), r = t.split(/\s+/).filter(Boolean), i = 0;
		for (let e of r) {
			let t = n.indexOf(e);
			if (t !== -1) {
				i = t;
				break;
			}
		}
		let a = Math.max(0, i - 30), o = Math.min(e.length, a + 150), s = e.slice(a, o);
		return a > 0 && (s = "..." + s), o < e.length && (s += "..."), s;
	}
	isInitialized() {
		return this.initialized;
	}
	getSectionCount() {
		return this.sections.size;
	}
}, S = new x();
//#endregion
//#region src/lib/search/runtime/highlighter.ts
function C(e, t, n = "mark") {
	if (!e || t.length === 0) return e;
	let r = e.toLowerCase(), i = [];
	for (let e of t) {
		let t = e.toLowerCase(), n = 0;
		for (;;) {
			let a = r.indexOf(t, n);
			if (a === -1) break;
			i.push({
				start: a,
				end: a + e.length
			}), n = a + 1;
		}
	}
	if (i.length === 0) return e;
	let a = w(i), o = "", s = 0;
	for (let t of a) o += e.slice(s, t.start), o += `<${n}>`, o += e.slice(t.start, t.end), o += `</${n}>`, s = t.end;
	return o += e.slice(s), o;
}
function w(e) {
	if (e.length === 0) return [];
	let t = [...e].sort((e, t) => e.start - t.start), n = [t[0]];
	for (let e = 1; e < t.length; e++) {
		let r = t[e], i = n[n.length - 1];
		r.start <= i.end ? i.end = Math.max(i.end, r.end) : n.push(r);
	}
	return n;
}
function T(e, t, n = {}) {
	let { maxLength: r = 120, contextBefore: i = 30, contextAfter: a = 80 } = n;
	if (!e) return "";
	if (t.length === 0) return e.slice(0, r) + (e.length > r ? "..." : "");
	let o = e.toLowerCase(), s = -1, c = "";
	for (let e of t) {
		let t = o.indexOf(e.toLowerCase());
		t !== -1 && (s === -1 || t < s) && (s = t, c = e);
	}
	if (s === -1) return e.slice(0, r) + (e.length > r ? "..." : "");
	let l = Math.max(0, s - i), u = Math.min(e.length, s + c.length + a), d = e.slice(l, u);
	return l > 0 && (d = "..." + d), u < e.length && (d += "..."), d;
}
function E(e, t, n = {}) {
	return C(T(e, t, n), t, n.tag || "mark");
}
function D(e) {
	return e.toLowerCase().split(/[\s\-_]+/).filter((e) => e.length > 0);
}
//#endregion
//#region src/components/search/SearchProvider.tsx
var O = a(null);
function k() {
	let e = c(O);
	if (!e) throw Error("useSearch must be used within a SearchProvider");
	return e;
}
function A({ children: e, lang: t = "zh-cn", enabled: n = !0, maxResults: r = 20, enableHotkeys: i = !0 }) {
	let [a, o] = d(!1), [c, f] = d(!1), [p, m] = d(null), [h, g] = d([]), [v, y] = d(""), [b, S] = d(!1), C = u(null), w = u(null), T = u(null), E = u(!1);
	l(() => (C.current = new x(), () => {
		C.current &&= (C.current.clear(), null);
	}), []), l(() => {
		T.current && T.current !== t && (o(!1), T.current = null, g([]), y(""), C.current && C.current.clear());
	}, [t]);
	let D = s(async () => {
		if (!(a && T.current === t || E.current || !n)) {
			E.current = !0, f(!0), m(null);
			try {
				let e = await fetch(`/search-index-${t}.json`);
				if (!e.ok) throw Error(`Failed to load search index: ${e.status}`);
				let n = await e.json();
				C.current && C.current.init(n), T.current = t, o(!0);
			} catch (e) {
				m(e instanceof Error ? e.message : "Failed to load search index");
			} finally {
				f(!1), E.current = !1;
			}
		}
	}, [
		t,
		a,
		n
	]), k = s(async (e) => {
		if (!e.trim()) return g([]), [];
		C.current?.isInitialized() || await D();
		let n = {
			query: e,
			lang: t,
			limit: r
		};
		if (C.current) {
			let e = C.current.search(n);
			return g(e), e;
		}
		return [];
	}, [
		t,
		D,
		r
	]);
	l(() => {
		if (!v.trim()) {
			g([]);
			return;
		}
		return w.current && clearTimeout(w.current), w.current = setTimeout(() => {
			k(v);
		}, 150), () => {
			w.current && clearTimeout(w.current);
		};
	}, [v, k]), l(() => {
		b && !a && !E.current && D();
	}, [
		b,
		a,
		D
	]), l(() => {
		if (!i) return;
		let e = (e) => {
			(e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k" && (e.preventDefault(), S((e) => !e)), e.key === "Escape" && b && S(!1);
		};
		return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
	}, [i, b]);
	let A = {
		isLoaded: a,
		isLoading: c,
		error: p,
		search: k,
		results: h,
		query: v,
		setQuery: y,
		open: b,
		setOpen: S,
		loadIndex: D
	};
	return /* @__PURE__ */ _(O.Provider, {
		value: A,
		children: e
	});
}
//#endregion
//#region src/components/search/SearchInput.tsx
var j = o(({ value: t, onChange: n, onClear: r, className: i, placeholder: a, ...o }, s) => /* @__PURE__ */ v("div", {
	className: "flex items-center gap-3 px-4 py-3 border-b",
	children: [
		/* @__PURE__ */ _(m, { className: "h-5 w-5 shrink-0 text-muted-foreground" }),
		/* @__PURE__ */ _("input", {
			ref: s,
			type: "text",
			value: t,
			onChange: (e) => n(e.target.value),
			placeholder: a || "搜索文档...",
			className: e("flex-1 bg-transparent text-base outline-none placeholder:text-muted-foreground", i),
			...o
		}),
		t && r && /* @__PURE__ */ _("button", {
			type: "button",
			onClick: r,
			className: "p-1 rounded hover:bg-muted transition-colors",
			children: /* @__PURE__ */ _(h, { className: "h-4 w-4 text-muted-foreground" })
		})
	]
}));
j.displayName = "SearchInput";
//#endregion
//#region src/components/search/SearchItem.tsx
var M = o(({ result: t, query: n, isSelected: r, onClick: i, onMouseEnter: a }, o) => {
	let s = D(n), c = E(t.sectionTitle, s, {
		maxLength: 100,
		contextBefore: 0,
		contextAfter: 0
	}), l = E(t.snippet, s, { maxLength: 150 });
	return /* @__PURE__ */ v("div", {
		ref: o,
		onClick: i,
		onMouseEnter: a,
		className: e("flex items-start gap-3 px-4 py-3 cursor-pointer transition-all duration-200 border-l-2 rounded-r-md mx-2", "hover:shadow-sm hover:translate-x-0.5", r ? "bg-accent/80 border-l-primary shadow-md scale-[1.02] translate-x-1" : "hover:bg-muted/50 border-l-transparent"),
		children: [/* @__PURE__ */ _(f, { className: "h-4 w-4 mt-0.5 shrink-0 text-muted-foreground" }), /* @__PURE__ */ v("div", {
			className: "flex-1 min-w-0",
			children: [
				/* @__PURE__ */ _("div", {
					className: "flex items-center gap-2",
					children: /* @__PURE__ */ _("span", {
						className: "font-medium text-sm truncate",
						dangerouslySetInnerHTML: { __html: c }
					})
				}),
				t.pageTitle !== t.sectionTitle && /* @__PURE__ */ _("div", {
					className: "text-xs text-muted-foreground truncate mt-0.5",
					children: t.pageTitle
				}),
				l && /* @__PURE__ */ _("div", {
					className: "text-xs text-muted-foreground mt-1 line-clamp-2",
					dangerouslySetInnerHTML: { __html: l }
				})
			]
		})]
	});
});
M.displayName = "SearchItem";
//#endregion
//#region src/components/search/SearchResults.tsx
function N({ results: e, query: t, onSelect: n }) {
	let [r, i] = d(0), a = u(null), o = u(null);
	l(() => {
		i(0);
	}, [e]), l(() => {
		if (o.current && a.current) {
			let e = a.current, t = o.current, n = e.getBoundingClientRect(), r = t.getBoundingClientRect();
			(r.bottom > n.bottom || r.top < n.top) && t.scrollIntoView({ block: "nearest" });
		}
	}, [r]), l(() => {
		let t = (t) => {
			if (t.key === "ArrowDown") t.preventDefault(), i((t) => Math.min(t + 1, e.length - 1));
			else if (t.key === "ArrowUp") t.preventDefault(), i((e) => Math.max(e - 1, 0));
			else if (t.key === "Enter") {
				t.preventDefault();
				let i = e[r];
				i && n(i.url);
			}
		};
		return document.addEventListener("keydown", t), () => document.removeEventListener("keydown", t);
	}, [
		e,
		r,
		n
	]);
	let s = (e) => {
		n(e.url);
	};
	return /* @__PURE__ */ _("div", {
		ref: a,
		className: "py-2",
		children: e.map((e, n) => /* @__PURE__ */ _(M, {
			result: e,
			query: t,
			isSelected: n === r,
			ref: n === r ? o : null,
			onClick: () => s(e),
			onMouseEnter: () => i(n)
		}, e.id))
	});
}
//#endregion
//#region src/components/search/SearchDialog.tsx
function P({ placeholder: e }) {
	let { open: a, setOpen: o, query: s, setQuery: c, results: d, isLoading: f, error: m, isLoaded: h } = k(), y = g(), b = u(null);
	return l(() => {
		a && b.current && setTimeout(() => b.current?.focus(), 0);
	}, [a]), l(() => {
		a || c("");
	}, [a, c]), /* @__PURE__ */ _(r, {
		open: a,
		onOpenChange: (e) => {
			o(e);
		},
		children: /* @__PURE__ */ v(n, {
			className: "overflow-hidden p-0 shadow-lg max-w-xl top-[15%] translate-y-0",
			showCloseButton: !1,
			children: [
				/* @__PURE__ */ _(i, { children: "搜索文档" }),
				/* @__PURE__ */ _(t, { children: "搜索文档内容" }),
				/* @__PURE__ */ v("div", {
					className: "flex flex-col",
					children: [
						/* @__PURE__ */ _(j, {
							ref: b,
							value: s,
							onChange: c,
							placeholder: e,
							onClear: () => c("")
						}),
						/* @__PURE__ */ v("div", {
							className: "max-h-[60vh] overflow-y-auto border-t",
							children: [
								f && !h && /* @__PURE__ */ _("div", {
									className: "flex items-center justify-center py-12",
									children: /* @__PURE__ */ _(p, { className: "h-6 w-6 animate-spin text-muted-foreground" })
								}),
								m && /* @__PURE__ */ _("div", {
									className: "px-4 py-8 text-center text-sm text-muted-foreground",
									children: m
								}),
								h && !f && !s && /* @__PURE__ */ _("div", {
									className: "px-4 py-8 text-center text-sm text-muted-foreground",
									children: "输入关键词搜索文档"
								}),
								h && s && d.length === 0 && !f && /* @__PURE__ */ v("div", {
									className: "px-4 py-8 text-center text-sm text-muted-foreground",
									children: [
										"未找到 \"",
										s,
										"\" 相关结果"
									]
								}),
								d.length > 0 && /* @__PURE__ */ _(N, {
									results: d,
									query: s,
									onSelect: (e) => {
										y(e), o(!1);
									}
								})
							]
						}),
						/* @__PURE__ */ v("div", {
							className: "flex items-center justify-between border-t px-4 py-2 text-xs text-muted-foreground bg-muted/30",
							children: [/* @__PURE__ */ v("div", {
								className: "flex items-center gap-4",
								children: [/* @__PURE__ */ v("span", {
									className: "flex items-center gap-1",
									children: [/* @__PURE__ */ _("kbd", {
										className: "px-1.5 py-0.5 rounded bg-muted border text-[10px]",
										children: "↵"
									}), "选择"]
								}), /* @__PURE__ */ v("span", {
									className: "flex items-center gap-1",
									children: [/* @__PURE__ */ _("kbd", {
										className: "px-1.5 py-0.5 rounded bg-muted border text-[10px]",
										children: "↑↓"
									}), "导航"]
								})]
							}), /* @__PURE__ */ v("span", {
								className: "flex items-center gap-1",
								children: [/* @__PURE__ */ _("kbd", {
									className: "px-1.5 py-0.5 rounded bg-muted border text-[10px]",
									children: "esc"
								}), "关闭"]
							})]
						})
					]
				})
			]
		})
	});
}
//#endregion
export { A as a, E as c, x as d, S as f, j as i, C as l, N as n, k as o, M as r, T as s, P as t, D as u };
