@openrails/contentkit-ui 0.100.1 → 0.101.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -860,11 +860,27 @@ access revision current; signed-out viewers do not fetch an inbox.
|
|
|
860
860
|
including loading and empty states. Set `presentation="header"` for a portal
|
|
861
861
|
panel directly below the input, matching its width and following it on resize
|
|
862
862
|
or scroll: a dimmed backdrop, text rows with colored type icons, and no
|
|
863
|
-
thumbnails. Recent
|
|
863
|
+
thumbnails. Recent searches omit dates. The panel
|
|
864
864
|
slides downward when opened and honors reduced motion. Its mobile/desktop
|
|
865
865
|
scroll limit is 70vh/60vh. The default inline
|
|
866
|
-
presentation is unchanged. Both presentations
|
|
867
|
-
|
|
866
|
+
presentation is unchanged. Both presentations show prefix-matching recent
|
|
867
|
+
queries first (newest first), then matching entities, then content titles. A
|
|
868
|
+
recent query remains selectable while network suggestions debounce or load.
|
|
869
|
+
Guest history persists in localStorage across tabs; account history comes from
|
|
870
|
+
the server, fetched on opening rather than on every keystroke. `recent={false}`
|
|
871
|
+
omits history. Only completed searches are recorded.
|
|
872
|
+
|
|
873
|
+
`GET /v1/typeahead` matches the beginning of a title, entity name or direct
|
|
874
|
+
alias, using the keyword index's case/accent/whitespace normalization. It does
|
|
875
|
+
not expand associated entities, contextual keywords, interior words or typos:
|
|
876
|
+
Inazuma can suggest that artist, but not Business Question merely because
|
|
877
|
+
Inazuma created it. Full `GET /v1/search` retains broader keyword and typo
|
|
878
|
+
matching. Visibility, tenant, language and version eligibility still apply.
|
|
879
|
+
The host owns search-page navigation and suggestion links.
|
|
880
|
+
|
|
881
|
+
Core migration `0010_name_prefix_index` adds the name-only prefix index; apply
|
|
882
|
+
normal ContentKit migrations before serving the new core. Original keyword
|
|
883
|
+
indexes and full-search behavior remain in place.
|
|
868
884
|
`ReaderSettings` combines language selection and content filters in one dialog:
|
|
869
885
|
|
|
870
886
|
```tsx
|
|
@@ -14,7 +14,7 @@ export interface SearchBoxProps {
|
|
|
14
14
|
/** A suggestion's link; default its canonical path. */
|
|
15
15
|
href?: (item: Card | GroupCard) => string | undefined;
|
|
16
16
|
labels?: Labels;
|
|
17
|
-
/**
|
|
17
|
+
/** Recent searches first, prefix-filtered while typing. Default true. */
|
|
18
18
|
recent?: boolean;
|
|
19
19
|
/** A portal dropdown anchored to the header field; default stays inline. */
|
|
20
20
|
presentation?: "inline" | "header";
|
|
@@ -23,7 +23,7 @@ export interface SearchBoxProps {
|
|
|
23
23
|
appearance?: ContentKitUiAppearance;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* Recent query prefixes first, followed by entity and title prefixes. Enter
|
|
27
|
+
* searches, or opens the chosen suggestion; full search can match more deeply.
|
|
28
28
|
*/
|
|
29
29
|
export declare function SearchBox(p: SearchBoxProps): import('react').JSX.Element;
|
|
@@ -5,54 +5,54 @@ import { ContentKitContext as r } from "../../react/context.js";
|
|
|
5
5
|
import { Input as i } from "../../ui/input.js";
|
|
6
6
|
import { useRecentSearches as a, useTypeahead as o } from "../../react/discovery.js";
|
|
7
7
|
import { labelOf as s } from "../groups/parts.js";
|
|
8
|
-
import { useContext as c, useEffect as
|
|
9
|
-
import { Fragment as
|
|
10
|
-
import { cn as
|
|
11
|
-
import { Cancel01Icon as
|
|
12
|
-
import { HugeiconsIcon as
|
|
13
|
-
import { createPortal as
|
|
8
|
+
import { useContext as c, useEffect as ee, useId as te, useLayoutEffect as l, useMemo as ne, useRef as u, useState as d } from "react";
|
|
9
|
+
import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
10
|
+
import { cn as h } from "cn";
|
|
11
|
+
import { Cancel01Icon as g, Clock01Icon as _, File01Icon as v, Folder01Icon as y, Image01Icon as b, Search01Icon as x, TagsIcon as S, UserIcon as C } from "@hugeicons/core-free-icons";
|
|
12
|
+
import { HugeiconsIcon as w } from "@hugeicons/react";
|
|
13
|
+
import { createPortal as re } from "react-dom";
|
|
14
14
|
//#region src/components/content/search.tsx
|
|
15
|
-
var E = {
|
|
15
|
+
var T = (e) => e.type === "content" ? `c:${e.card.id}` : e.type === "group" ? `g:${e.group.id}` : `r:${e.query}`, E = (e) => e.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").normalize("NFC").toLowerCase().trim().replace(/\s+/g, " "), D = {
|
|
16
16
|
artist: {
|
|
17
|
-
icon:
|
|
17
|
+
icon: C,
|
|
18
18
|
color: "text-blue-500 dark:text-blue-400"
|
|
19
19
|
},
|
|
20
20
|
series: {
|
|
21
|
-
icon:
|
|
21
|
+
icon: y,
|
|
22
22
|
color: "text-yellow-600 dark:text-yellow-400"
|
|
23
23
|
},
|
|
24
24
|
gallery: {
|
|
25
|
-
icon:
|
|
25
|
+
icon: b,
|
|
26
26
|
color: "text-green-600 dark:text-green-400"
|
|
27
27
|
},
|
|
28
28
|
post: {
|
|
29
|
-
icon:
|
|
29
|
+
icon: v,
|
|
30
30
|
color: "text-purple-500 dark:text-purple-400"
|
|
31
31
|
},
|
|
32
32
|
blog: {
|
|
33
|
-
icon:
|
|
33
|
+
icon: v,
|
|
34
34
|
color: "text-purple-500 dark:text-purple-400"
|
|
35
35
|
},
|
|
36
36
|
poll: {
|
|
37
|
-
icon:
|
|
37
|
+
icon: v,
|
|
38
38
|
color: "text-purple-500 dark:text-purple-400"
|
|
39
39
|
},
|
|
40
40
|
character: {
|
|
41
|
-
icon:
|
|
41
|
+
icon: C,
|
|
42
42
|
color: "text-purple-500 dark:text-purple-400"
|
|
43
43
|
},
|
|
44
44
|
tag: {
|
|
45
|
-
icon:
|
|
45
|
+
icon: S,
|
|
46
46
|
color: "text-orange-500 dark:text-orange-400"
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
|
-
function
|
|
50
|
-
let [i, a] =
|
|
49
|
+
function O(e, t, n, r) {
|
|
50
|
+
let [i, a] = d({
|
|
51
51
|
top: 0,
|
|
52
52
|
left: 0,
|
|
53
53
|
width: 0
|
|
54
54
|
});
|
|
55
|
-
return
|
|
55
|
+
return l(() => {
|
|
56
56
|
if (!e || !t || !n.current) return;
|
|
57
57
|
let i = r.current ?? n.current, o = n.current.ownerDocument.defaultView;
|
|
58
58
|
if (!o) return;
|
|
@@ -76,40 +76,46 @@ function D(e, t, n, r) {
|
|
|
76
76
|
r
|
|
77
77
|
]), i;
|
|
78
78
|
}
|
|
79
|
-
function
|
|
80
|
-
let t =
|
|
81
|
-
return /* @__PURE__ */
|
|
82
|
-
icon: t?.icon ??
|
|
79
|
+
function ie({ kind: e }) {
|
|
80
|
+
let t = D[e];
|
|
81
|
+
return /* @__PURE__ */ p(w, {
|
|
82
|
+
icon: t?.icon ?? x,
|
|
83
83
|
strokeWidth: 2,
|
|
84
|
-
className:
|
|
84
|
+
className: h("size-4 shrink-0", t?.color ?? "text-muted-foreground"),
|
|
85
85
|
"data-search-kind": e,
|
|
86
86
|
"aria-hidden": !0
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
|
-
function k(
|
|
90
|
-
let { t:
|
|
91
|
-
kind:
|
|
92
|
-
entity_kinds:
|
|
93
|
-
client:
|
|
89
|
+
function k(l) {
|
|
90
|
+
let { t: v, error: y } = t(), b = te(), S = c(r)?.navigate, [C, D] = d(l.defaultValue ?? ""), [k, A] = d(!1), [j, M] = d(), N = u(null), P = u(null), F = u(null), I = l.presentation === "header", L = O(k, I, N, F), { top: R } = L, z = !C.trim(), B = o(C, {
|
|
91
|
+
kind: l.kind,
|
|
92
|
+
entity_kinds: l.groupKinds,
|
|
93
|
+
client: l.client
|
|
94
94
|
}), V = a({
|
|
95
|
-
enabled:
|
|
96
|
-
client:
|
|
97
|
-
}), H =
|
|
95
|
+
enabled: l.recent !== !1 && k,
|
|
96
|
+
client: l.client
|
|
97
|
+
}), H = E(C), U = B.query === C.trim(), W = ne(() => [...l.recent === !1 ? [] : V.searches.filter((e) => E(e.query).startsWith(H)).map((e) => ({
|
|
98
98
|
type: "recent",
|
|
99
99
|
query: e.query
|
|
100
|
-
}))
|
|
101
|
-
type: "content",
|
|
102
|
-
card: e
|
|
103
|
-
})), ...B.entities.map((e) => ({
|
|
100
|
+
})), ...!z && U ? [...B.entities.map((e) => ({
|
|
104
101
|
type: "group",
|
|
105
102
|
group: e
|
|
106
|
-
}))
|
|
103
|
+
})), ...B.contents.map((e) => ({
|
|
104
|
+
type: "content",
|
|
105
|
+
card: e
|
|
106
|
+
}))] : []], [
|
|
107
|
+
l.recent,
|
|
108
|
+
H,
|
|
107
109
|
z,
|
|
110
|
+
U,
|
|
108
111
|
V.searches,
|
|
109
112
|
B.contents,
|
|
110
113
|
B.entities
|
|
111
|
-
]),
|
|
112
|
-
|
|
114
|
+
]), G = j === null ? Math.min(0, W.length - 1) : W.findIndex((e) => T(e) === j), K = W[G], q = (e) => {
|
|
115
|
+
let t = W[e];
|
|
116
|
+
M(t ? T(t) : e >= 0 ? null : void 0);
|
|
117
|
+
}, ae = V.loading || !z && (!U || B.loading), J = z && l.recent !== !1, oe = z ? !I && J && !V.error ? "contents.noRecentSearches" : "contents.searchHint" : "contents.noResults";
|
|
118
|
+
ee(() => {
|
|
113
119
|
if (!k) return;
|
|
114
120
|
let e = (e) => {
|
|
115
121
|
!N.current?.contains(e.target) && !P.current?.contains(e.target) && A(!1);
|
|
@@ -119,216 +125,216 @@ function k(u) {
|
|
|
119
125
|
let Y = () => {
|
|
120
126
|
A(!0);
|
|
121
127
|
}, X = (e) => {
|
|
122
|
-
A(!1), e &&
|
|
128
|
+
A(!1), e && l.onSearch(e);
|
|
123
129
|
}, Z = (e) => {
|
|
124
|
-
if (e.type === "recent") return
|
|
125
|
-
let t =
|
|
126
|
-
A(!1), t && (
|
|
130
|
+
if (e.type === "recent") return D(e.query), X(e.query);
|
|
131
|
+
let t = l.href ? l.href(e.type === "content" ? e.card : e.group) : e.type === "content" ? e.card.path : e.group.path;
|
|
132
|
+
A(!1), t && (S ? S(t) : location.assign(t));
|
|
127
133
|
}, Q = (e) => {
|
|
128
|
-
e.key === "Escape" && (e.preventDefault(), F.current?.focus(), A(!1), M(
|
|
129
|
-
}, $ = /* @__PURE__ */
|
|
130
|
-
|
|
131
|
-
className:
|
|
132
|
-
children: [/* @__PURE__ */
|
|
133
|
-
id: `${
|
|
134
|
+
e.key === "Escape" && (e.preventDefault(), F.current?.focus(), A(!1), M(void 0));
|
|
135
|
+
}, $ = /* @__PURE__ */ m(f, { children: [
|
|
136
|
+
J && /* @__PURE__ */ m("div", {
|
|
137
|
+
className: h("flex items-center justify-between gap-2 text-muted-foreground", I ? "mb-4 text-base font-semibold" : "px-2 py-1 text-xs"),
|
|
138
|
+
children: [/* @__PURE__ */ m("span", {
|
|
139
|
+
id: `${b}-recent`,
|
|
134
140
|
className: "flex items-center gap-2",
|
|
135
|
-
children: [I && /* @__PURE__ */
|
|
136
|
-
icon:
|
|
141
|
+
children: [I && /* @__PURE__ */ p(w, {
|
|
142
|
+
icon: _,
|
|
137
143
|
strokeWidth: 2,
|
|
138
144
|
className: "size-5",
|
|
139
145
|
"aria-hidden": !0
|
|
140
|
-
}),
|
|
141
|
-
}), W.length > 0 && /* @__PURE__ */
|
|
146
|
+
}), v("contents.recentSearches")]
|
|
147
|
+
}), W.length > 0 && /* @__PURE__ */ p("button", {
|
|
142
148
|
type: "button",
|
|
143
149
|
className: "rounded px-1 hover:text-foreground",
|
|
144
150
|
onMouseDown: (e) => {
|
|
145
151
|
e.preventDefault();
|
|
146
152
|
},
|
|
147
153
|
onClick: () => void V.clear(),
|
|
148
|
-
children:
|
|
154
|
+
children: v(I ? "contents.clearAllRecent" : "contents.clearRecent")
|
|
149
155
|
})]
|
|
150
156
|
}),
|
|
151
|
-
/* @__PURE__ */
|
|
152
|
-
id: `${
|
|
157
|
+
/* @__PURE__ */ p("ul", {
|
|
158
|
+
id: `${b}-list`,
|
|
153
159
|
role: "listbox",
|
|
154
|
-
"aria-label":
|
|
155
|
-
className:
|
|
156
|
-
children: W.map((t, n) => /* @__PURE__ */
|
|
157
|
-
id: `${
|
|
160
|
+
"aria-label": v(z ? "contents.recentSearches" : "contents.suggestions"),
|
|
161
|
+
className: h("grid", I && "gap-2"),
|
|
162
|
+
children: W.map((t, n) => /* @__PURE__ */ p("li", {
|
|
163
|
+
id: `${b}-${n}`,
|
|
158
164
|
role: "option",
|
|
159
|
-
"aria-selected": n ===
|
|
165
|
+
"aria-selected": n === G,
|
|
160
166
|
"data-ckui": "suggestion",
|
|
161
167
|
"data-type": t.type,
|
|
162
|
-
className:
|
|
163
|
-
onMouseEnter: () => M(
|
|
168
|
+
className: h("flex cursor-pointer items-center", I ? t.type === "recent" ? "gap-2 rounded-md p-3 text-base hover:bg-foreground/10" : "gap-3 rounded-md px-4 py-1 text-base font-medium hover:bg-foreground/10" : "gap-2 px-2 py-1.5", n === G && "bg-accent text-accent-foreground"),
|
|
169
|
+
onMouseEnter: () => M(T(t)),
|
|
164
170
|
onMouseDown: (e) => {
|
|
165
171
|
e.preventDefault(), Z(t);
|
|
166
172
|
},
|
|
167
|
-
children: I && t.type !== "recent" ? /* @__PURE__ */
|
|
168
|
-
/* @__PURE__ */
|
|
169
|
-
/* @__PURE__ */
|
|
173
|
+
children: I && t.type !== "recent" ? /* @__PURE__ */ m(f, { children: [
|
|
174
|
+
/* @__PURE__ */ p(ie, { kind: t.type === "content" ? t.card.kind : t.group.kind }),
|
|
175
|
+
/* @__PURE__ */ p("span", {
|
|
170
176
|
className: "sr-only",
|
|
171
|
-
children: s(
|
|
177
|
+
children: s(l.labels, t.type === "content" ? t.card.kind : t.group.kind)
|
|
172
178
|
}),
|
|
173
|
-
/* @__PURE__ */
|
|
179
|
+
/* @__PURE__ */ p("span", {
|
|
174
180
|
className: "min-w-0 flex-1 truncate",
|
|
175
181
|
children: t.type === "content" ? t.card.title || t.card.code : t.group.name || t.group.slug
|
|
176
182
|
})
|
|
177
|
-
] }) : t.type === "content" ? /* @__PURE__ */
|
|
183
|
+
] }) : t.type === "content" ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", {
|
|
178
184
|
className: "h-10 w-8 shrink-0 overflow-hidden rounded bg-muted",
|
|
179
|
-
children: /* @__PURE__ */
|
|
185
|
+
children: /* @__PURE__ */ p(e, {
|
|
180
186
|
outputs: t.card.cover,
|
|
181
187
|
alt: "",
|
|
182
188
|
fit: "cover",
|
|
183
189
|
className: "size-full"
|
|
184
190
|
})
|
|
185
|
-
}), /* @__PURE__ */
|
|
191
|
+
}), /* @__PURE__ */ p("span", {
|
|
186
192
|
className: "min-w-0 truncate",
|
|
187
193
|
children: t.card.title || t.card.code
|
|
188
|
-
})] }) : t.type === "group" ? /* @__PURE__ */
|
|
194
|
+
})] }) : t.type === "group" ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", {
|
|
189
195
|
className: "min-w-0 flex-1 truncate",
|
|
190
196
|
children: t.group.name || t.group.slug
|
|
191
|
-
}), /* @__PURE__ */
|
|
197
|
+
}), /* @__PURE__ */ p("span", {
|
|
192
198
|
className: "text-xs text-muted-foreground",
|
|
193
|
-
children: s(
|
|
194
|
-
})] }) : /* @__PURE__ */
|
|
195
|
-
/* @__PURE__ */
|
|
196
|
-
icon: I ?
|
|
199
|
+
children: s(l.labels, t.group.kind)
|
|
200
|
+
})] }) : /* @__PURE__ */ m(f, { children: [
|
|
201
|
+
/* @__PURE__ */ p(w, {
|
|
202
|
+
icon: I ? x : _,
|
|
197
203
|
strokeWidth: 2,
|
|
198
204
|
className: "size-4 shrink-0 text-muted-foreground",
|
|
199
205
|
"aria-hidden": !0
|
|
200
206
|
}),
|
|
201
|
-
/* @__PURE__ */
|
|
207
|
+
/* @__PURE__ */ p("span", {
|
|
202
208
|
className: "min-w-0 flex-1 truncate",
|
|
203
209
|
children: t.query
|
|
204
210
|
}),
|
|
205
|
-
/* @__PURE__ */
|
|
211
|
+
/* @__PURE__ */ p("button", {
|
|
206
212
|
type: "button",
|
|
207
213
|
className: "rounded p-0.5 text-muted-foreground hover:text-foreground",
|
|
208
|
-
"aria-label":
|
|
214
|
+
"aria-label": v("contents.removeRecent", { q: t.query }),
|
|
209
215
|
onMouseDown: (e) => {
|
|
210
216
|
e.preventDefault(), e.stopPropagation();
|
|
211
217
|
},
|
|
212
218
|
onClick: () => void V.clear(t.query),
|
|
213
|
-
children: /* @__PURE__ */
|
|
214
|
-
icon:
|
|
219
|
+
children: /* @__PURE__ */ p(w, {
|
|
220
|
+
icon: g,
|
|
215
221
|
strokeWidth: 2,
|
|
216
222
|
className: "size-3.5",
|
|
217
223
|
"aria-hidden": !0
|
|
218
224
|
})
|
|
219
225
|
})
|
|
220
226
|
] })
|
|
221
|
-
}, t
|
|
227
|
+
}, T(t)))
|
|
222
228
|
}),
|
|
223
|
-
|
|
229
|
+
ae ? /* @__PURE__ */ p("div", {
|
|
224
230
|
role: "status",
|
|
225
|
-
className:
|
|
226
|
-
children: I ? /* @__PURE__ */
|
|
231
|
+
className: h("text-muted-foreground", I ? "flex justify-center py-4" : "px-3 py-2"),
|
|
232
|
+
children: I ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", {
|
|
227
233
|
className: "size-6 animate-spin rounded-full border-2 border-muted border-t-foreground motion-reduce:animate-none",
|
|
228
234
|
"aria-hidden": !0
|
|
229
|
-
}), /* @__PURE__ */
|
|
235
|
+
}), /* @__PURE__ */ p("span", {
|
|
230
236
|
className: "sr-only",
|
|
231
|
-
children:
|
|
232
|
-
})] }) :
|
|
233
|
-
}) : !z && B.error ? /* @__PURE__ */
|
|
237
|
+
children: v("contents.loading")
|
|
238
|
+
})] }) : v("contents.loading")
|
|
239
|
+
}) : !z && B.error ? /* @__PURE__ */ p("p", {
|
|
234
240
|
role: "alert",
|
|
235
|
-
className:
|
|
236
|
-
children:
|
|
237
|
-
}) : W.length === 0 && /* @__PURE__ */
|
|
241
|
+
className: h("px-3 py-2 text-destructive", I && "text-center"),
|
|
242
|
+
children: y(B.error)
|
|
243
|
+
}) : W.length === 0 && /* @__PURE__ */ m("div", {
|
|
238
244
|
role: "status",
|
|
239
|
-
className:
|
|
240
|
-
children: [I && /* @__PURE__ */
|
|
241
|
-
icon:
|
|
245
|
+
className: h("text-muted-foreground", I ? "flex flex-col items-center gap-2 py-8 text-center" : "px-3 py-2"),
|
|
246
|
+
children: [I && /* @__PURE__ */ p(w, {
|
|
247
|
+
icon: x,
|
|
242
248
|
strokeWidth: 2,
|
|
243
249
|
className: "size-8",
|
|
244
250
|
"aria-hidden": !0
|
|
245
|
-
}), /* @__PURE__ */
|
|
251
|
+
}), /* @__PURE__ */ p("p", { children: v(oe, { q: C.trim() }) })]
|
|
246
252
|
})
|
|
247
253
|
] });
|
|
248
|
-
return /* @__PURE__ */
|
|
254
|
+
return /* @__PURE__ */ m(n, {
|
|
249
255
|
ref: N,
|
|
250
|
-
appearance:
|
|
251
|
-
className:
|
|
256
|
+
appearance: l.appearance,
|
|
257
|
+
className: h("relative text-sm", l.className),
|
|
252
258
|
"data-ckui": "search-box",
|
|
253
259
|
onBlur: (e) => {
|
|
254
260
|
!e.currentTarget.contains(e.relatedTarget) && !P.current?.contains(e.relatedTarget) && A(!1);
|
|
255
261
|
},
|
|
256
|
-
children: [/* @__PURE__ */
|
|
262
|
+
children: [/* @__PURE__ */ m("form", {
|
|
257
263
|
role: "search",
|
|
258
264
|
className: "relative",
|
|
259
265
|
onSubmit: (e) => {
|
|
260
|
-
if (e.preventDefault(), k &&
|
|
261
|
-
X(
|
|
266
|
+
if (e.preventDefault(), k && K) return Z(K);
|
|
267
|
+
X(C.trim());
|
|
262
268
|
},
|
|
263
269
|
children: [
|
|
264
|
-
I ? /* @__PURE__ */
|
|
270
|
+
I ? /* @__PURE__ */ p("button", {
|
|
265
271
|
type: "submit",
|
|
266
272
|
className: "absolute top-1/2 left-2.5 -translate-y-1/2 rounded text-muted-foreground hover:text-foreground focus-visible:outline-2 focus-visible:outline-ring",
|
|
267
|
-
"aria-label":
|
|
268
|
-
children: /* @__PURE__ */
|
|
269
|
-
icon:
|
|
273
|
+
"aria-label": v("contents.search"),
|
|
274
|
+
children: /* @__PURE__ */ p(w, {
|
|
275
|
+
icon: x,
|
|
270
276
|
strokeWidth: 2,
|
|
271
277
|
className: "size-4",
|
|
272
278
|
"aria-hidden": !0
|
|
273
279
|
})
|
|
274
|
-
}) : /* @__PURE__ */
|
|
275
|
-
icon:
|
|
280
|
+
}) : /* @__PURE__ */ p(w, {
|
|
281
|
+
icon: x,
|
|
276
282
|
strokeWidth: 2,
|
|
277
283
|
className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground",
|
|
278
284
|
"aria-hidden": !0
|
|
279
285
|
}),
|
|
280
|
-
/* @__PURE__ */
|
|
286
|
+
/* @__PURE__ */ p(i, {
|
|
281
287
|
ref: F,
|
|
282
288
|
type: I ? "text" : "search",
|
|
283
289
|
role: "combobox",
|
|
284
|
-
"aria-label":
|
|
290
|
+
"aria-label": v("contents.search"),
|
|
285
291
|
"aria-expanded": k,
|
|
286
|
-
"aria-controls": `${
|
|
287
|
-
"aria-activedescendant": k &&
|
|
292
|
+
"aria-controls": `${b}-list`,
|
|
293
|
+
"aria-activedescendant": k && K ? `${b}-${G}` : void 0,
|
|
288
294
|
"aria-autocomplete": "list",
|
|
289
295
|
autoComplete: "off",
|
|
290
|
-
className:
|
|
291
|
-
value:
|
|
292
|
-
placeholder:
|
|
296
|
+
className: h("h-9 ps-8", I && "rounded-full border-border/50 bg-foreground/10 pe-9 text-base shadow-none md:text-base"),
|
|
297
|
+
value: C,
|
|
298
|
+
placeholder: l.placeholder ?? v("contents.searchPlaceholder"),
|
|
293
299
|
onChange: (e) => {
|
|
294
|
-
|
|
300
|
+
D(e.target.value), A(!0), M(void 0);
|
|
295
301
|
},
|
|
296
302
|
onFocus: Y,
|
|
297
303
|
onClick: Y,
|
|
298
304
|
onKeyDown: (e) => {
|
|
299
305
|
if (e.key === "Escape") {
|
|
300
|
-
e.preventDefault(), A(!1), M(
|
|
306
|
+
e.preventDefault(), A(!1), M(void 0);
|
|
301
307
|
return;
|
|
302
308
|
}
|
|
303
|
-
e.key === "ArrowDown" ? (e.preventDefault(), Y(),
|
|
309
|
+
e.key === "ArrowDown" ? (e.preventDefault(), Y(), q(k ? Math.min(W.length - 1, G + 1) : 0)) : e.key === "ArrowUp" && k && (e.preventDefault(), q(Math.max(-1, G - 1)));
|
|
304
310
|
}
|
|
305
311
|
}),
|
|
306
|
-
I && (
|
|
312
|
+
I && (C || k) && /* @__PURE__ */ p("button", {
|
|
307
313
|
type: "button",
|
|
308
314
|
className: "absolute top-1/2 right-2.5 -translate-y-1/2 rounded p-0.5 text-muted-foreground hover:text-foreground focus-visible:outline-2 focus-visible:outline-ring",
|
|
309
|
-
"aria-label":
|
|
315
|
+
"aria-label": v(C ? "contents.clearSearch" : "common.close"),
|
|
310
316
|
onMouseDown: (e) => e.preventDefault(),
|
|
311
317
|
onClick: () => {
|
|
312
|
-
F.current?.focus(), M(
|
|
318
|
+
F.current?.focus(), M(void 0), C ? (D(""), A(!0)) : A(!1);
|
|
313
319
|
},
|
|
314
|
-
children: /* @__PURE__ */
|
|
315
|
-
icon:
|
|
320
|
+
children: /* @__PURE__ */ p(w, {
|
|
321
|
+
icon: g,
|
|
316
322
|
strokeWidth: 2,
|
|
317
323
|
className: "size-4",
|
|
318
324
|
"aria-hidden": !0
|
|
319
325
|
})
|
|
320
326
|
})
|
|
321
327
|
]
|
|
322
|
-
}), k && (I ?
|
|
323
|
-
appearance:
|
|
328
|
+
}), k && (I ? re(/* @__PURE__ */ m(n, {
|
|
329
|
+
appearance: l.appearance,
|
|
324
330
|
className: "fixed inset-x-0 bottom-0 z-[70] text-sm",
|
|
325
331
|
style: { top: R },
|
|
326
332
|
"data-ckui": "search-layer",
|
|
327
|
-
children: [/* @__PURE__ */
|
|
333
|
+
children: [/* @__PURE__ */ p("div", {
|
|
328
334
|
className: "absolute inset-0 bg-black/30 backdrop-blur-sm",
|
|
329
335
|
"data-ckui": "search-backdrop",
|
|
330
336
|
"aria-hidden": !0
|
|
331
|
-
}), /* @__PURE__ */
|
|
337
|
+
}), /* @__PURE__ */ p("div", {
|
|
332
338
|
ref: P,
|
|
333
339
|
style: {
|
|
334
340
|
width: L.width,
|
|
@@ -337,16 +343,16 @@ function k(u) {
|
|
|
337
343
|
className: "relative origin-top animate-[search-expand_300ms_ease-out] rounded-lg border border-border bg-background text-foreground shadow-lg transition-none motion-reduce:animate-none",
|
|
338
344
|
"data-ckui": "search-panel",
|
|
339
345
|
onKeyDown: Q,
|
|
340
|
-
children: /* @__PURE__ */
|
|
346
|
+
children: /* @__PURE__ */ p("div", {
|
|
341
347
|
className: "w-full px-3 pt-3",
|
|
342
|
-
children: /* @__PURE__ */
|
|
348
|
+
children: /* @__PURE__ */ p("div", {
|
|
343
349
|
className: "[--search-max-height:70vh] overflow-y-auto pb-7 md:[--search-max-height:60vh]",
|
|
344
350
|
style: { maxHeight: `min(var(--search-max-height), calc(100dvh - ${R}px - 1.875rem))` },
|
|
345
|
-
children: /* @__PURE__ */
|
|
351
|
+
children: /* @__PURE__ */ p("div", { children: $ })
|
|
346
352
|
})
|
|
347
353
|
})
|
|
348
354
|
})]
|
|
349
|
-
}), document.body) : /* @__PURE__ */
|
|
355
|
+
}), document.body) : /* @__PURE__ */ p("div", {
|
|
350
356
|
ref: P,
|
|
351
357
|
className: "absolute top-full z-20 mt-1 grid max-h-96 w-full overflow-auto rounded-md border border-border bg-popover py-1 text-popover-foreground shadow-md",
|
|
352
358
|
"data-ckui": "search-panel",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","names":[],"sources":["../../../src/components/content/search.tsx"],"sourcesContent":["import { Cancel01Icon, Clock01Icon, File01Icon, Folder01Icon, Image01Icon, Search01Icon, TagsIcon, UserIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon, type IconSvgElement } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, type RefObject, type KeyboardEvent } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { Card, GroupCard } from \"../../client/generated/wire.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext } from \"../../react/context.js\";\nimport { useRecentSearches, useTypeahead } from \"../../react/discovery.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Input } from \"#ckui/ui/input\";\nimport { RenditionImg } from \"../rendition-img.js\";\nimport { labelOf, type Labels } from \"../groups/parts.js\";\n\nexport interface SearchBoxProps {\n /** Submits the text: the host shows its search page. */\n onSearch: (q: string) => void;\n /** Suggest contents of this kind only. */\n kind?: string;\n /** The group kinds suggested; every kind with a page by default. */\n groupKinds?: readonly string[];\n defaultValue?: string;\n placeholder?: string;\n /** A suggestion's link; default its canonical path. */\n href?: (item: Card | GroupCard) => string | undefined;\n labels?: Labels;\n /** The reader's recent searches while the box is empty. Default true. */\n recent?: boolean;\n /** A portal dropdown anchored to the header field; default stays inline. */\n presentation?: \"inline\" | \"header\";\n client?: ContentKitClient;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\ntype Suggestion = { type: \"content\"; card: Card } | { type: \"group\"; group: GroupCard } | { type: \"recent\"; query: string };\n\nconst TYPE_ICONS: Record<string, { icon: IconSvgElement; color: string }> = {\n artist: { icon: UserIcon, color: \"text-blue-500 dark:text-blue-400\" },\n series: { icon: Folder01Icon, color: \"text-yellow-600 dark:text-yellow-400\" },\n gallery: { icon: Image01Icon, color: \"text-green-600 dark:text-green-400\" },\n post: { icon: File01Icon, color: \"text-purple-500 dark:text-purple-400\" },\n blog: { icon: File01Icon, color: \"text-purple-500 dark:text-purple-400\" },\n poll: { icon: File01Icon, color: \"text-purple-500 dark:text-purple-400\" },\n character: { icon: UserIcon, color: \"text-purple-500 dark:text-purple-400\" },\n tag: { icon: TagsIcon, color: \"text-orange-500 dark:text-orange-400\" },\n};\n\nfunction useHeaderAnchor(open: boolean, enabled: boolean, root: RefObject<HTMLDivElement | null>, input: RefObject<HTMLInputElement | null>) {\n const [position, setPosition] = useState({ top: 0, left: 0, width: 0 });\n useLayoutEffect(() => {\n if (!open || !enabled || !root.current) return;\n const anchor = input.current ?? root.current;\n const view = root.current.ownerDocument.defaultView;\n if (!view) return;\n const measure = () => {\n const rect = anchor.getBoundingClientRect();\n setPosition({ top: Math.max(0, Math.min(view.innerHeight, rect.bottom + 4)), left: rect.left, width: rect.width });\n };\n measure();\n const observer = typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(measure);\n observer?.observe(anchor);\n view.addEventListener(\"resize\", measure);\n view.addEventListener(\"scroll\", measure, true);\n view.visualViewport?.addEventListener(\"resize\", measure);\n view.visualViewport?.addEventListener(\"scroll\", measure);\n return () => {\n observer?.disconnect();\n view.removeEventListener(\"resize\", measure);\n view.removeEventListener(\"scroll\", measure, true);\n view.visualViewport?.removeEventListener(\"resize\", measure);\n view.visualViewport?.removeEventListener(\"scroll\", measure);\n };\n }, [open, enabled, root, input]);\n return position;\n}\n\nfunction SearchTypeIcon({ kind }: { kind: string }) {\n const type = TYPE_ICONS[kind];\n return <HugeiconsIcon icon={type?.icon ?? Search01Icon} strokeWidth={2} className={cn(\"size-4 shrink-0\", type?.color ?? \"text-muted-foreground\")} data-search-kind={kind} aria-hidden />;\n}\n\n/**\n * A search field suggesting contents and groups as the reader types, and\n * recent searches while it is empty; Enter searches, or opens the suggestion chosen.\n */\nexport function SearchBox(p: SearchBoxProps) {\n const { t, error } = useMessages();\n const id = useId();\n const navigate = useContext(ContentKitContext)?.navigate;\n const [text, setText] = useState(p.defaultValue ?? \"\");\n const [open, setOpen] = useState(false);\n const [active, setActive] = useState(-1);\n const root = useRef<HTMLDivElement>(null);\n const panel = useRef<HTMLDivElement>(null);\n const input = useRef<HTMLInputElement>(null);\n const header = p.presentation === \"header\";\n const anchor = useHeaderAnchor(open, header, root, input);\n const { top } = anchor;\n const empty = !text.trim();\n const found = useTypeahead(text, { kind: p.kind, entity_kinds: p.groupKinds, client: p.client });\n const recent = useRecentSearches({ enabled: p.recent !== false && open && empty, client: p.client });\n const items = useMemo<Suggestion[]>(\n () =>\n empty\n ? recent.searches.map((r) => ({ type: \"recent\" as const, query: r.query }))\n : [...found.contents.map((card) => ({ type: \"content\" as const, card })), ...found.entities.map((group) => ({ type: \"group\" as const, group }))],\n [empty, recent.searches, found.contents, found.entities],\n );\n const current = empty || found.query === text.trim();\n const visible = current ? items : [];\n const selected = visible[active];\n const loading = empty ? recent.loading : !current || found.loading;\n const showRecent = empty && p.recent !== false;\n const emptyMessage = empty ? !header && showRecent && !recent.error ? \"contents.noRecentSearches\" : \"contents.searchHint\" : \"contents.noResults\";\n useEffect(() => {\n if (!open) return;\n const outside = (event: PointerEvent) => {\n if (!root.current?.contains(event.target as Node) && !panel.current?.contains(event.target as Node)) setOpen(false);\n };\n document.addEventListener(\"pointerdown\", outside);\n return () => document.removeEventListener(\"pointerdown\", outside);\n }, [open]);\n const reveal = () => {\n setOpen(true);\n };\n const search = (q: string) => {\n setOpen(false);\n if (q) p.onSearch(q);\n };\n const go = (s: Suggestion) => {\n if (s.type === \"recent\") {\n setText(s.query);\n return search(s.query);\n }\n const url = p.href ? p.href(s.type === \"content\" ? s.card : s.group) : s.type === \"content\" ? s.card.path : s.group.path;\n setOpen(false);\n if (!url) return;\n if (navigate) navigate(url);\n else location.assign(url);\n };\n const panelKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n event.preventDefault();\n input.current?.focus();\n setOpen(false);\n setActive(-1);\n };\n const results = (<>\n {showRecent && (\n <div className={cn(\"flex items-center justify-between gap-2 text-muted-foreground\", header ? \"mb-4 text-base font-semibold\" : \"px-2 py-1 text-xs\")}>\n <span id={`${id}-recent`} className=\"flex items-center gap-2\">{header && <HugeiconsIcon icon={Clock01Icon} strokeWidth={2} className=\"size-5\" aria-hidden />}{t(\"contents.recentSearches\")}</span>\n {visible.length > 0 && <button\n type=\"button\"\n className=\"rounded px-1 hover:text-foreground\"\n onMouseDown={(e) => {\n e.preventDefault();\n }}\n onClick={() => void recent.clear()}\n >\n {t(header ? \"contents.clearAllRecent\" : \"contents.clearRecent\")}\n </button>}\n </div>\n )}\n <ul id={`${id}-list`} role=\"listbox\" aria-label={empty ? t(\"contents.recentSearches\") : t(\"contents.suggestions\")} className={cn(\"grid\", header && \"gap-2\")}>\n {visible.map((s, i) => (\n <li\n key={s.type === \"content\" ? `c:${s.card.id}` : s.type === \"group\" ? `g:${s.group.id}` : `r:${s.query}`}\n id={`${id}-${i}`}\n role=\"option\"\n aria-selected={i === active}\n data-ckui=\"suggestion\"\n data-type={s.type}\n className={cn(\"flex cursor-pointer items-center\", header ? s.type === \"recent\" ? \"gap-2 rounded-md p-3 text-base hover:bg-foreground/10\" : \"gap-3 rounded-md px-4 py-1 text-base font-medium hover:bg-foreground/10\" : \"gap-2 px-2 py-1.5\", i === active && \"bg-accent text-accent-foreground\")}\n onMouseEnter={() => setActive(i)}\n onMouseDown={(e) => {\n e.preventDefault();\n go(s);\n }}\n >\n {header && s.type !== \"recent\" ? (\n <>\n <SearchTypeIcon kind={s.type === \"content\" ? s.card.kind : s.group.kind} />\n <span className=\"sr-only\">{labelOf(p.labels, s.type === \"content\" ? s.card.kind : s.group.kind)}</span>\n <span className=\"min-w-0 flex-1 truncate\">{s.type === \"content\" ? s.card.title || s.card.code : s.group.name || s.group.slug}</span>\n </>\n ) : s.type === \"content\" ? (\n <>\n <span className=\"h-10 w-8 shrink-0 overflow-hidden rounded bg-muted\">\n <RenditionImg outputs={s.card.cover} alt=\"\" fit=\"cover\" className=\"size-full\" />\n </span>\n <span className=\"min-w-0 truncate\">{s.card.title || s.card.code}</span>\n </>\n ) : s.type === \"group\" ? (\n <>\n <span className=\"min-w-0 flex-1 truncate\">{s.group.name || s.group.slug}</span>\n <span className=\"text-xs text-muted-foreground\">{labelOf(p.labels, s.group.kind)}</span>\n </>\n ) : (\n <>\n <HugeiconsIcon icon={header ? Search01Icon : Clock01Icon} strokeWidth={2} className=\"size-4 shrink-0 text-muted-foreground\" aria-hidden />\n <span className=\"min-w-0 flex-1 truncate\">{s.query}</span>\n <button\n type=\"button\"\n className=\"rounded p-0.5 text-muted-foreground hover:text-foreground\"\n aria-label={t(\"contents.removeRecent\", { q: s.query })}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n onClick={() => void recent.clear(s.query)}\n >\n <HugeiconsIcon icon={Cancel01Icon} strokeWidth={2} className=\"size-3.5\" aria-hidden />\n </button>\n </>\n )}\n </li>\n ))}\n </ul>\n {loading ? <div role=\"status\" className={cn(\"text-muted-foreground\", header ? \"flex justify-center py-4\" : \"px-3 py-2\")}>{header ? <><span className=\"size-6 animate-spin rounded-full border-2 border-muted border-t-foreground motion-reduce:animate-none\" aria-hidden /><span className=\"sr-only\">{t(\"contents.loading\")}</span></> : t(\"contents.loading\")}</div>\n : !empty && found.error ? <p role=\"alert\" className={cn(\"px-3 py-2 text-destructive\", header && \"text-center\")}>{error(found.error)}</p>\n : visible.length === 0 && <div role=\"status\" className={cn(\"text-muted-foreground\", header ? \"flex flex-col items-center gap-2 py-8 text-center\" : \"px-3 py-2\")}>{header && <HugeiconsIcon icon={Search01Icon} strokeWidth={2} className=\"size-8\" aria-hidden />}<p>{t(emptyMessage, { q: text.trim() })}</p></div>}\n </>);\n return (\n <ContentKitUiRoot ref={root} appearance={p.appearance} className={cn(\"relative text-sm\", p.className)} data-ckui=\"search-box\" onBlur={(event) => { if (!event.currentTarget.contains(event.relatedTarget) && !panel.current?.contains(event.relatedTarget)) setOpen(false); }}>\n <form\n role=\"search\"\n className=\"relative\"\n onSubmit={(e) => {\n e.preventDefault();\n if (open && selected) return go(selected);\n search(text.trim());\n }}\n >\n {header ? <button type=\"submit\" className=\"absolute top-1/2 left-2.5 -translate-y-1/2 rounded text-muted-foreground hover:text-foreground focus-visible:outline-2 focus-visible:outline-ring\" aria-label={t(\"contents.search\")}><HugeiconsIcon icon={Search01Icon} strokeWidth={2} className=\"size-4\" aria-hidden /></button>\n : <HugeiconsIcon icon={Search01Icon} strokeWidth={2} className=\"pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground\" aria-hidden />}\n <Input\n ref={input}\n type={header ? \"text\" : \"search\"}\n role=\"combobox\"\n aria-label={t(\"contents.search\")}\n aria-expanded={open}\n aria-controls={`${id}-list`}\n aria-activedescendant={open && selected ? `${id}-${active}` : undefined}\n aria-autocomplete=\"list\"\n autoComplete=\"off\"\n className={cn(\"h-9 ps-8\", header && \"rounded-full border-border/50 bg-foreground/10 pe-9 text-base shadow-none md:text-base\")}\n value={text}\n placeholder={p.placeholder ?? t(\"contents.searchPlaceholder\")}\n onChange={(e) => {\n setText(e.target.value);\n setOpen(true);\n setActive(-1);\n }}\n onFocus={reveal}\n onClick={reveal}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n setOpen(false);\n setActive(-1);\n return;\n }\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n reveal();\n setActive((a) => open ? Math.min(visible.length - 1, a + 1) : 0);\n } else if (e.key === \"ArrowUp\" && open) {\n e.preventDefault();\n setActive((a) => Math.max(-1, a - 1));\n }\n }}\n />\n {header && (text || open) && (\n <button\n type=\"button\"\n className=\"absolute top-1/2 right-2.5 -translate-y-1/2 rounded p-0.5 text-muted-foreground hover:text-foreground focus-visible:outline-2 focus-visible:outline-ring\"\n aria-label={text ? t(\"contents.clearSearch\") : t(\"common.close\")}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n input.current?.focus();\n setActive(-1);\n if (text) { setText(\"\"); setOpen(true); }\n else setOpen(false);\n }}\n ><HugeiconsIcon icon={Cancel01Icon} strokeWidth={2} className=\"size-4\" aria-hidden /></button>\n )}\n </form>\n {open && (header ? createPortal(\n <ContentKitUiRoot appearance={p.appearance} className=\"fixed inset-x-0 bottom-0 z-[70] text-sm\" style={{ top }} data-ckui=\"search-layer\">\n <div className=\"absolute inset-0 bg-black/30 backdrop-blur-sm\" data-ckui=\"search-backdrop\" aria-hidden />\n <div ref={panel} style={{ width: anchor.width, marginLeft: anchor.left }} className=\"relative origin-top animate-[search-expand_300ms_ease-out] rounded-lg border border-border bg-background text-foreground shadow-lg transition-none motion-reduce:animate-none\" data-ckui=\"search-panel\" onKeyDown={panelKeyDown}>\n <div className=\"w-full px-3 pt-3\">\n <div className=\"[--search-max-height:70vh] overflow-y-auto pb-7 md:[--search-max-height:60vh]\" style={{ maxHeight: `min(var(--search-max-height), calc(100dvh - ${top}px - 1.875rem))` }}>\n <div>{results}</div>\n </div>\n </div>\n </div>\n </ContentKitUiRoot>, document.body,\n ) : <div ref={panel} className=\"absolute top-full z-20 mt-1 grid max-h-96 w-full overflow-auto rounded-md border border-border bg-popover py-1 text-popover-foreground shadow-md\" data-ckui=\"search-panel\" onKeyDown={panelKeyDown}>{results}</div>)}\n\n </ContentKitUiRoot>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"search.js","names":[],"sources":["../../../src/components/content/search.tsx"],"sourcesContent":["import { Cancel01Icon, Clock01Icon, File01Icon, Folder01Icon, Image01Icon, Search01Icon, TagsIcon, UserIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon, type IconSvgElement } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, type RefObject, type KeyboardEvent } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { Card, GroupCard } from \"../../client/generated/wire.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext } from \"../../react/context.js\";\nimport { useRecentSearches, useTypeahead } from \"../../react/discovery.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Input } from \"#ckui/ui/input\";\nimport { RenditionImg } from \"../rendition-img.js\";\nimport { labelOf, type Labels } from \"../groups/parts.js\";\n\nexport interface SearchBoxProps {\n /** Submits the text: the host shows its search page. */\n onSearch: (q: string) => void;\n /** Suggest contents of this kind only. */\n kind?: string;\n /** The group kinds suggested; every kind with a page by default. */\n groupKinds?: readonly string[];\n defaultValue?: string;\n placeholder?: string;\n /** A suggestion's link; default its canonical path. */\n href?: (item: Card | GroupCard) => string | undefined;\n labels?: Labels;\n /** Recent searches first, prefix-filtered while typing. Default true. */\n recent?: boolean;\n /** A portal dropdown anchored to the header field; default stays inline. */\n presentation?: \"inline\" | \"header\";\n client?: ContentKitClient;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\ntype Suggestion = { type: \"content\"; card: Card } | { type: \"group\"; group: GroupCard } | { type: \"recent\"; query: string };\nconst suggestionKey = (s: Suggestion) => s.type === \"content\" ? `c:${s.card.id}` : s.type === \"group\" ? `g:${s.group.id}` : `r:${s.query}`;\n\n// Match the keyword index's case, Latin accent and whitespace normalization.\nconst prefixText = (text: string) => text.normalize(\"NFKD\").replace(/[\\u0300-\\u036f]/g, \"\").normalize(\"NFC\").toLowerCase().trim().replace(/\\s+/g, \" \");\n\nconst TYPE_ICONS: Record<string, { icon: IconSvgElement; color: string }> = {\n artist: { icon: UserIcon, color: \"text-blue-500 dark:text-blue-400\" },\n series: { icon: Folder01Icon, color: \"text-yellow-600 dark:text-yellow-400\" },\n gallery: { icon: Image01Icon, color: \"text-green-600 dark:text-green-400\" },\n post: { icon: File01Icon, color: \"text-purple-500 dark:text-purple-400\" },\n blog: { icon: File01Icon, color: \"text-purple-500 dark:text-purple-400\" },\n poll: { icon: File01Icon, color: \"text-purple-500 dark:text-purple-400\" },\n character: { icon: UserIcon, color: \"text-purple-500 dark:text-purple-400\" },\n tag: { icon: TagsIcon, color: \"text-orange-500 dark:text-orange-400\" },\n};\n\nfunction useHeaderAnchor(open: boolean, enabled: boolean, root: RefObject<HTMLDivElement | null>, input: RefObject<HTMLInputElement | null>) {\n const [position, setPosition] = useState({ top: 0, left: 0, width: 0 });\n useLayoutEffect(() => {\n if (!open || !enabled || !root.current) return;\n const anchor = input.current ?? root.current;\n const view = root.current.ownerDocument.defaultView;\n if (!view) return;\n const measure = () => {\n const rect = anchor.getBoundingClientRect();\n setPosition({ top: Math.max(0, Math.min(view.innerHeight, rect.bottom + 4)), left: rect.left, width: rect.width });\n };\n measure();\n const observer = typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(measure);\n observer?.observe(anchor);\n view.addEventListener(\"resize\", measure);\n view.addEventListener(\"scroll\", measure, true);\n view.visualViewport?.addEventListener(\"resize\", measure);\n view.visualViewport?.addEventListener(\"scroll\", measure);\n return () => {\n observer?.disconnect();\n view.removeEventListener(\"resize\", measure);\n view.removeEventListener(\"scroll\", measure, true);\n view.visualViewport?.removeEventListener(\"resize\", measure);\n view.visualViewport?.removeEventListener(\"scroll\", measure);\n };\n }, [open, enabled, root, input]);\n return position;\n}\n\nfunction SearchTypeIcon({ kind }: { kind: string }) {\n const type = TYPE_ICONS[kind];\n return <HugeiconsIcon icon={type?.icon ?? Search01Icon} strokeWidth={2} className={cn(\"size-4 shrink-0\", type?.color ?? \"text-muted-foreground\")} data-search-kind={kind} aria-hidden />;\n}\n\n/**\n * Recent query prefixes first, followed by entity and title prefixes. Enter\n * searches, or opens the chosen suggestion; full search can match more deeply.\n */\nexport function SearchBox(p: SearchBoxProps) {\n const { t, error } = useMessages();\n const id = useId();\n const navigate = useContext(ContentKitContext)?.navigate;\n const [text, setText] = useState(p.defaultValue ?? \"\");\n const [open, setOpen] = useState(false);\n // null requests the first result when opening an as-yet-unloaded panel.\n const [active, setActive] = useState<string | null>();\n const root = useRef<HTMLDivElement>(null);\n const panel = useRef<HTMLDivElement>(null);\n const input = useRef<HTMLInputElement>(null);\n const header = p.presentation === \"header\";\n const anchor = useHeaderAnchor(open, header, root, input);\n const { top } = anchor;\n const empty = !text.trim();\n const found = useTypeahead(text, { kind: p.kind, entity_kinds: p.groupKinds, client: p.client });\n const recent = useRecentSearches({ enabled: p.recent !== false && open, client: p.client });\n const prefix = prefixText(text);\n const current = found.query === text.trim();\n const visible = useMemo<Suggestion[]>(\n () => [\n ...(p.recent === false ? [] : recent.searches.filter((r) => prefixText(r.query).startsWith(prefix)).map((r) => ({ type: \"recent\" as const, query: r.query }))),\n ...(!empty && current ? [\n ...found.entities.map((group) => ({ type: \"group\" as const, group })),\n ...found.contents.map((card) => ({ type: \"content\" as const, card })),\n ] : []),\n ],\n [p.recent, prefix, empty, current, recent.searches, found.contents, found.entities],\n );\n // History and live suggestions can arrive independently. Track identity so\n // prepending history never changes what Enter will open.\n const activeIndex = active === null ? Math.min(0, visible.length - 1) : visible.findIndex((s) => suggestionKey(s) === active);\n const selected = visible[activeIndex];\n const activate = (index: number) => {\n const suggestion = visible[index];\n setActive(suggestion ? suggestionKey(suggestion) : index >= 0 ? null : undefined);\n };\n const loading = recent.loading || (!empty && (!current || found.loading));\n const showRecent = empty && p.recent !== false;\n const emptyMessage = empty ? !header && showRecent && !recent.error ? \"contents.noRecentSearches\" : \"contents.searchHint\" : \"contents.noResults\";\n useEffect(() => {\n if (!open) return;\n const outside = (event: PointerEvent) => {\n if (!root.current?.contains(event.target as Node) && !panel.current?.contains(event.target as Node)) setOpen(false);\n };\n document.addEventListener(\"pointerdown\", outside);\n return () => document.removeEventListener(\"pointerdown\", outside);\n }, [open]);\n const reveal = () => {\n setOpen(true);\n };\n const search = (q: string) => {\n setOpen(false);\n if (q) p.onSearch(q);\n };\n const go = (s: Suggestion) => {\n if (s.type === \"recent\") {\n setText(s.query);\n return search(s.query);\n }\n const url = p.href ? p.href(s.type === \"content\" ? s.card : s.group) : s.type === \"content\" ? s.card.path : s.group.path;\n setOpen(false);\n if (!url) return;\n if (navigate) navigate(url);\n else location.assign(url);\n };\n const panelKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n event.preventDefault();\n input.current?.focus();\n setOpen(false);\n setActive(undefined);\n };\n const results = (<>\n {showRecent && (\n <div className={cn(\"flex items-center justify-between gap-2 text-muted-foreground\", header ? \"mb-4 text-base font-semibold\" : \"px-2 py-1 text-xs\")}>\n <span id={`${id}-recent`} className=\"flex items-center gap-2\">{header && <HugeiconsIcon icon={Clock01Icon} strokeWidth={2} className=\"size-5\" aria-hidden />}{t(\"contents.recentSearches\")}</span>\n {visible.length > 0 && <button\n type=\"button\"\n className=\"rounded px-1 hover:text-foreground\"\n onMouseDown={(e) => {\n e.preventDefault();\n }}\n onClick={() => void recent.clear()}\n >\n {t(header ? \"contents.clearAllRecent\" : \"contents.clearRecent\")}\n </button>}\n </div>\n )}\n <ul id={`${id}-list`} role=\"listbox\" aria-label={empty ? t(\"contents.recentSearches\") : t(\"contents.suggestions\")} className={cn(\"grid\", header && \"gap-2\")}>\n {visible.map((s, i) => (\n <li\n key={suggestionKey(s)}\n id={`${id}-${i}`}\n role=\"option\"\n aria-selected={i === activeIndex}\n data-ckui=\"suggestion\"\n data-type={s.type}\n className={cn(\"flex cursor-pointer items-center\", header ? s.type === \"recent\" ? \"gap-2 rounded-md p-3 text-base hover:bg-foreground/10\" : \"gap-3 rounded-md px-4 py-1 text-base font-medium hover:bg-foreground/10\" : \"gap-2 px-2 py-1.5\", i === activeIndex && \"bg-accent text-accent-foreground\")}\n onMouseEnter={() => setActive(suggestionKey(s))}\n onMouseDown={(e) => {\n e.preventDefault();\n go(s);\n }}\n >\n {header && s.type !== \"recent\" ? (\n <>\n <SearchTypeIcon kind={s.type === \"content\" ? s.card.kind : s.group.kind} />\n <span className=\"sr-only\">{labelOf(p.labels, s.type === \"content\" ? s.card.kind : s.group.kind)}</span>\n <span className=\"min-w-0 flex-1 truncate\">{s.type === \"content\" ? s.card.title || s.card.code : s.group.name || s.group.slug}</span>\n </>\n ) : s.type === \"content\" ? (\n <>\n <span className=\"h-10 w-8 shrink-0 overflow-hidden rounded bg-muted\">\n <RenditionImg outputs={s.card.cover} alt=\"\" fit=\"cover\" className=\"size-full\" />\n </span>\n <span className=\"min-w-0 truncate\">{s.card.title || s.card.code}</span>\n </>\n ) : s.type === \"group\" ? (\n <>\n <span className=\"min-w-0 flex-1 truncate\">{s.group.name || s.group.slug}</span>\n <span className=\"text-xs text-muted-foreground\">{labelOf(p.labels, s.group.kind)}</span>\n </>\n ) : (\n <>\n <HugeiconsIcon icon={header ? Search01Icon : Clock01Icon} strokeWidth={2} className=\"size-4 shrink-0 text-muted-foreground\" aria-hidden />\n <span className=\"min-w-0 flex-1 truncate\">{s.query}</span>\n <button\n type=\"button\"\n className=\"rounded p-0.5 text-muted-foreground hover:text-foreground\"\n aria-label={t(\"contents.removeRecent\", { q: s.query })}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n onClick={() => void recent.clear(s.query)}\n >\n <HugeiconsIcon icon={Cancel01Icon} strokeWidth={2} className=\"size-3.5\" aria-hidden />\n </button>\n </>\n )}\n </li>\n ))}\n </ul>\n {loading ? <div role=\"status\" className={cn(\"text-muted-foreground\", header ? \"flex justify-center py-4\" : \"px-3 py-2\")}>{header ? <><span className=\"size-6 animate-spin rounded-full border-2 border-muted border-t-foreground motion-reduce:animate-none\" aria-hidden /><span className=\"sr-only\">{t(\"contents.loading\")}</span></> : t(\"contents.loading\")}</div>\n : !empty && found.error ? <p role=\"alert\" className={cn(\"px-3 py-2 text-destructive\", header && \"text-center\")}>{error(found.error)}</p>\n : visible.length === 0 && <div role=\"status\" className={cn(\"text-muted-foreground\", header ? \"flex flex-col items-center gap-2 py-8 text-center\" : \"px-3 py-2\")}>{header && <HugeiconsIcon icon={Search01Icon} strokeWidth={2} className=\"size-8\" aria-hidden />}<p>{t(emptyMessage, { q: text.trim() })}</p></div>}\n </>);\n return (\n <ContentKitUiRoot ref={root} appearance={p.appearance} className={cn(\"relative text-sm\", p.className)} data-ckui=\"search-box\" onBlur={(event) => { if (!event.currentTarget.contains(event.relatedTarget) && !panel.current?.contains(event.relatedTarget)) setOpen(false); }}>\n <form\n role=\"search\"\n className=\"relative\"\n onSubmit={(e) => {\n e.preventDefault();\n if (open && selected) return go(selected);\n search(text.trim());\n }}\n >\n {header ? <button type=\"submit\" className=\"absolute top-1/2 left-2.5 -translate-y-1/2 rounded text-muted-foreground hover:text-foreground focus-visible:outline-2 focus-visible:outline-ring\" aria-label={t(\"contents.search\")}><HugeiconsIcon icon={Search01Icon} strokeWidth={2} className=\"size-4\" aria-hidden /></button>\n : <HugeiconsIcon icon={Search01Icon} strokeWidth={2} className=\"pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground\" aria-hidden />}\n <Input\n ref={input}\n type={header ? \"text\" : \"search\"}\n role=\"combobox\"\n aria-label={t(\"contents.search\")}\n aria-expanded={open}\n aria-controls={`${id}-list`}\n aria-activedescendant={open && selected ? `${id}-${activeIndex}` : undefined}\n aria-autocomplete=\"list\"\n autoComplete=\"off\"\n className={cn(\"h-9 ps-8\", header && \"rounded-full border-border/50 bg-foreground/10 pe-9 text-base shadow-none md:text-base\")}\n value={text}\n placeholder={p.placeholder ?? t(\"contents.searchPlaceholder\")}\n onChange={(e) => {\n setText(e.target.value);\n setOpen(true);\n setActive(undefined);\n }}\n onFocus={reveal}\n onClick={reveal}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n setOpen(false);\n setActive(undefined);\n return;\n }\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n reveal();\n activate(open ? Math.min(visible.length - 1, activeIndex + 1) : 0);\n } else if (e.key === \"ArrowUp\" && open) {\n e.preventDefault();\n activate(Math.max(-1, activeIndex - 1));\n }\n }}\n />\n {header && (text || open) && (\n <button\n type=\"button\"\n className=\"absolute top-1/2 right-2.5 -translate-y-1/2 rounded p-0.5 text-muted-foreground hover:text-foreground focus-visible:outline-2 focus-visible:outline-ring\"\n aria-label={text ? t(\"contents.clearSearch\") : t(\"common.close\")}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n input.current?.focus();\n setActive(undefined);\n if (text) { setText(\"\"); setOpen(true); }\n else setOpen(false);\n }}\n ><HugeiconsIcon icon={Cancel01Icon} strokeWidth={2} className=\"size-4\" aria-hidden /></button>\n )}\n </form>\n {open && (header ? createPortal(\n <ContentKitUiRoot appearance={p.appearance} className=\"fixed inset-x-0 bottom-0 z-[70] text-sm\" style={{ top }} data-ckui=\"search-layer\">\n <div className=\"absolute inset-0 bg-black/30 backdrop-blur-sm\" data-ckui=\"search-backdrop\" aria-hidden />\n <div ref={panel} style={{ width: anchor.width, marginLeft: anchor.left }} className=\"relative origin-top animate-[search-expand_300ms_ease-out] rounded-lg border border-border bg-background text-foreground shadow-lg transition-none motion-reduce:animate-none\" data-ckui=\"search-panel\" onKeyDown={panelKeyDown}>\n <div className=\"w-full px-3 pt-3\">\n <div className=\"[--search-max-height:70vh] overflow-y-auto pb-7 md:[--search-max-height:60vh]\" style={{ maxHeight: `min(var(--search-max-height), calc(100dvh - ${top}px - 1.875rem))` }}>\n <div>{results}</div>\n </div>\n </div>\n </div>\n </ContentKitUiRoot>, document.body,\n ) : <div ref={panel} className=\"absolute top-full z-20 mt-1 grid max-h-96 w-full overflow-auto rounded-md border border-border bg-popover py-1 text-popover-foreground shadow-md\" data-ckui=\"search-panel\" onKeyDown={panelKeyDown}>{results}</div>)}\n\n </ContentKitUiRoot>\n );\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED