@openrails/contentkit-ui 0.90.0 → 0.90.1
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 +80 -0
- package/dist/client/browser-search-history.d.ts +24 -0
- package/dist/client/browser-search-history.js +92 -0
- package/dist/client/browser-search-history.js.map +1 -0
- package/dist/client/discovery.d.ts +5 -2
- package/dist/client/discovery.js +14 -22
- package/dist/client/discovery.js.map +1 -1
- package/dist/client.js +14 -14
- package/dist/components/admin/content-admin.d.ts +28 -0
- package/dist/components/admin/content-admin.js +191 -0
- package/dist/components/admin/content-admin.js.map +1 -0
- package/dist/components/content/index.d.ts +1 -0
- package/dist/components/content/reader-settings.d.ts +19 -0
- package/dist/components/content/reader-settings.js +95 -0
- package/dist/components/content/reader-settings.js.map +1 -0
- package/dist/components/content/search.d.ts +2 -0
- package/dist/components/content/search.js +334 -137
- package/dist/components/content/search.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +18 -16
- package/dist/locales/admin/de.js +10 -0
- package/dist/locales/admin/de.js.map +1 -1
- package/dist/locales/admin/en.d.ts +10 -0
- package/dist/locales/admin/en.js +10 -0
- package/dist/locales/admin/en.js.map +1 -1
- package/dist/locales/admin/es.js +10 -0
- package/dist/locales/admin/es.js.map +1 -1
- package/dist/locales/admin/ja.js +10 -0
- package/dist/locales/admin/ja.js.map +1 -1
- package/dist/locales/admin/ko.js +10 -0
- package/dist/locales/admin/ko.js.map +1 -1
- package/dist/locales/admin/zh.js +10 -0
- package/dist/locales/admin/zh.js.map +1 -1
- package/dist/locales/discovery/de.js +9 -0
- package/dist/locales/discovery/de.js.map +1 -1
- package/dist/locales/discovery/en.d.ts +9 -0
- package/dist/locales/discovery/en.js +9 -0
- package/dist/locales/discovery/en.js.map +1 -1
- package/dist/locales/discovery/es.js +9 -0
- package/dist/locales/discovery/es.js.map +1 -1
- package/dist/locales/discovery/ja.js +9 -0
- package/dist/locales/discovery/ja.js.map +1 -1
- package/dist/locales/discovery/ko.js +9 -0
- package/dist/locales/discovery/ko.js.map +1 -1
- package/dist/locales/discovery/zh.js +9 -0
- package/dist/locales/discovery/zh.js.map +1 -1
- package/dist/locales/en.d.ts +19 -0
- package/dist/react/discovery.d.ts +1 -1
- package/dist/react/discovery.js +145 -92
- package/dist/react/discovery.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/ui/dialog.js +16 -10
- package/dist/ui/dialog.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,160 +5,357 @@ 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, useId as l, useMemo as u,
|
|
9
|
-
import { Fragment as
|
|
10
|
-
import { cn as
|
|
11
|
-
import { Cancel01Icon as
|
|
12
|
-
import { HugeiconsIcon as
|
|
8
|
+
import { useContext as c, useEffect as ee, useId as te, useLayoutEffect as l, useMemo as u, useRef as d, useState as f } from "react";
|
|
9
|
+
import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
10
|
+
import { cn as g } from "cn";
|
|
11
|
+
import { Cancel01Icon as _, Clock01Icon as v, File01Icon as y, Folder01Icon as b, Image01Icon as x, Search01Icon as S, TagsIcon as C, UserIcon as w } from "@hugeicons/core-free-icons";
|
|
12
|
+
import { HugeiconsIcon as T } from "@hugeicons/react";
|
|
13
|
+
import { createPortal as E } from "react-dom";
|
|
13
14
|
//#region src/components/content/search.tsx
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
15
|
+
var D = {
|
|
16
|
+
artist: {
|
|
17
|
+
icon: w,
|
|
18
|
+
color: "text-blue-500 dark:text-blue-400"
|
|
19
|
+
},
|
|
20
|
+
series: {
|
|
21
|
+
icon: b,
|
|
22
|
+
color: "text-yellow-600 dark:text-yellow-400"
|
|
23
|
+
},
|
|
24
|
+
gallery: {
|
|
25
|
+
icon: x,
|
|
26
|
+
color: "text-green-600 dark:text-green-400"
|
|
27
|
+
},
|
|
28
|
+
post: {
|
|
29
|
+
icon: y,
|
|
30
|
+
color: "text-purple-500 dark:text-purple-400"
|
|
31
|
+
},
|
|
32
|
+
blog: {
|
|
33
|
+
icon: y,
|
|
34
|
+
color: "text-purple-500 dark:text-purple-400"
|
|
35
|
+
},
|
|
36
|
+
poll: {
|
|
37
|
+
icon: y,
|
|
38
|
+
color: "text-purple-500 dark:text-purple-400"
|
|
39
|
+
},
|
|
40
|
+
character: {
|
|
41
|
+
icon: w,
|
|
42
|
+
color: "text-purple-500 dark:text-purple-400"
|
|
43
|
+
},
|
|
44
|
+
tag: {
|
|
45
|
+
icon: C,
|
|
46
|
+
color: "text-orange-500 dark:text-orange-400"
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
function O(e, t, n, r) {
|
|
50
|
+
let [i, a] = f(0);
|
|
51
|
+
return l(() => {
|
|
52
|
+
if (!e || !t || !n.current) return;
|
|
53
|
+
let i = n.current.closest("header, [role=\"banner\"]") ?? r.current ?? n.current, o = n.current.ownerDocument.defaultView;
|
|
54
|
+
if (!o) return;
|
|
55
|
+
let s = () => a(Math.max(0, Math.min(o.innerHeight, i.getBoundingClientRect().bottom)));
|
|
56
|
+
s();
|
|
57
|
+
let c = typeof ResizeObserver > "u" ? void 0 : new ResizeObserver(s);
|
|
58
|
+
return c?.observe(i), o.addEventListener("resize", s), o.addEventListener("scroll", s, !0), o.visualViewport?.addEventListener("resize", s), o.visualViewport?.addEventListener("scroll", s), () => {
|
|
59
|
+
c?.disconnect(), o.removeEventListener("resize", s), o.removeEventListener("scroll", s, !0), o.visualViewport?.removeEventListener("resize", s), o.visualViewport?.removeEventListener("scroll", s);
|
|
60
|
+
};
|
|
61
|
+
}, [
|
|
62
|
+
e,
|
|
63
|
+
t,
|
|
64
|
+
n,
|
|
65
|
+
r
|
|
66
|
+
]), i;
|
|
67
|
+
}
|
|
68
|
+
function k({ kind: e }) {
|
|
69
|
+
let t = D[e];
|
|
70
|
+
return /* @__PURE__ */ m(T, {
|
|
71
|
+
icon: t?.icon ?? S,
|
|
72
|
+
strokeWidth: 2,
|
|
73
|
+
className: g("size-4 shrink-0", t?.color ?? "text-muted-foreground"),
|
|
74
|
+
"data-search-kind": e,
|
|
75
|
+
"aria-hidden": !0
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function A({ value: e, formatter: t }) {
|
|
79
|
+
return !e || Number.isNaN(Date.parse(e)) ? null : /* @__PURE__ */ m("time", {
|
|
80
|
+
dateTime: e,
|
|
81
|
+
className: "shrink-0 text-xs text-muted-foreground",
|
|
82
|
+
children: t.format(new Date(e))
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
function j(l) {
|
|
86
|
+
let { t: y, error: b, language: x } = t(), C = te(), w = c(r)?.navigate, [D, j] = f(l.defaultValue ?? ""), [M, N] = f(!1), [P, F] = f(-1), I = d(null), L = d(null), R = d(null), z = l.presentation === "header", B = O(M, z, I, R), V = u(() => new Intl.DateTimeFormat(x, { dateStyle: "short" }), [x]), H = !D.trim(), U = o(D, {
|
|
87
|
+
kind: l.kind,
|
|
88
|
+
group_kinds: l.groupKinds,
|
|
89
|
+
client: l.client
|
|
90
|
+
}), W = a({
|
|
91
|
+
enabled: l.recent !== !1 && M && H,
|
|
92
|
+
client: l.client
|
|
93
|
+
}), ne = u(() => H ? W.searches.map((e) => ({
|
|
23
94
|
type: "recent",
|
|
24
|
-
query: e.query
|
|
25
|
-
|
|
95
|
+
query: e.query,
|
|
96
|
+
searchedAt: e.searched_at
|
|
97
|
+
})) : [...U.contents.map((e) => ({
|
|
26
98
|
type: "content",
|
|
27
99
|
card: e
|
|
28
|
-
})), ...
|
|
100
|
+
})), ...U.groups.map((e) => ({
|
|
29
101
|
type: "group",
|
|
30
102
|
group: e
|
|
31
103
|
}))], [
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
]),
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
T(e.target.value), D(!0), k(-1);
|
|
72
|
-
},
|
|
73
|
-
onFocus: () => {
|
|
74
|
-
D(!0), j(!0);
|
|
104
|
+
H,
|
|
105
|
+
W.searches,
|
|
106
|
+
U.contents,
|
|
107
|
+
U.groups
|
|
108
|
+
]), G = H || U.query === D.trim(), K = G ? ne : [], q = K[P], re = H ? W.loading : !G || U.loading, J = H && l.recent !== !1, ie = H ? !z && J && !W.error ? "contents.noRecentSearches" : "contents.searchHint" : "contents.noResults";
|
|
109
|
+
ee(() => {
|
|
110
|
+
if (!M) return;
|
|
111
|
+
let e = (e) => {
|
|
112
|
+
!I.current?.contains(e.target) && !L.current?.contains(e.target) && N(!1);
|
|
113
|
+
};
|
|
114
|
+
return document.addEventListener("pointerdown", e), () => document.removeEventListener("pointerdown", e);
|
|
115
|
+
}, [M]);
|
|
116
|
+
let Y = () => {
|
|
117
|
+
N(!0);
|
|
118
|
+
}, X = (e) => {
|
|
119
|
+
N(!1), e && l.onSearch(e);
|
|
120
|
+
}, Z = (e) => {
|
|
121
|
+
if (e.type === "recent") return j(e.query), X(e.query);
|
|
122
|
+
let t = l.href ? l.href(e.type === "content" ? e.card : e.group) : e.type === "content" ? e.card.path : e.group.path;
|
|
123
|
+
N(!1), t && (w ? w(t) : location.assign(t));
|
|
124
|
+
}, Q = (e) => {
|
|
125
|
+
e.key === "Escape" && (e.preventDefault(), R.current?.focus(), N(!1), F(-1));
|
|
126
|
+
}, $ = /* @__PURE__ */ h(p, { children: [
|
|
127
|
+
J && /* @__PURE__ */ h("div", {
|
|
128
|
+
className: g("flex items-center justify-between gap-2 text-muted-foreground", z ? "mb-4 text-base font-semibold" : "px-2 py-1 text-xs"),
|
|
129
|
+
children: [/* @__PURE__ */ h("span", {
|
|
130
|
+
id: `${C}-recent`,
|
|
131
|
+
className: "flex items-center gap-2",
|
|
132
|
+
children: [z && /* @__PURE__ */ m(T, {
|
|
133
|
+
icon: v,
|
|
134
|
+
strokeWidth: 2,
|
|
135
|
+
className: "size-5",
|
|
136
|
+
"aria-hidden": !0
|
|
137
|
+
}), y("contents.recentSearches")]
|
|
138
|
+
}), K.length > 0 && /* @__PURE__ */ m("button", {
|
|
139
|
+
type: "button",
|
|
140
|
+
className: "rounded px-1 hover:text-foreground",
|
|
141
|
+
onMouseDown: (e) => {
|
|
142
|
+
e.preventDefault();
|
|
75
143
|
},
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (e.key === "Escape") return D(!1);
|
|
79
|
-
I && (e.key === "ArrowDown" ? (e.preventDefault(), k((e) => Math.min(F.length - 1, e + 1))) : e.key === "ArrowUp" && (e.preventDefault(), k((e) => Math.max(-1, e - 1))));
|
|
80
|
-
}
|
|
144
|
+
onClick: () => void W.clear(),
|
|
145
|
+
children: y(z ? "contents.clearAllRecent" : "contents.clearRecent")
|
|
81
146
|
})]
|
|
82
|
-
}),
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
"data-ckui": "suggestion",
|
|
107
|
-
"data-type": t.type,
|
|
108
|
-
className: h("flex cursor-pointer items-center gap-2 px-2 py-1.5", n === O && "bg-accent text-accent-foreground"),
|
|
109
|
-
onMouseEnter: () => k(n),
|
|
110
|
-
onMouseDown: (e) => {
|
|
111
|
-
e.preventDefault(), R(t);
|
|
112
|
-
},
|
|
113
|
-
children: t.type === "content" ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", {
|
|
114
|
-
className: "h-10 w-8 shrink-0 overflow-hidden rounded bg-muted",
|
|
115
|
-
children: /* @__PURE__ */ p(e, {
|
|
116
|
-
outputs: t.card.cover,
|
|
117
|
-
alt: "",
|
|
118
|
-
fit: "cover",
|
|
119
|
-
className: "size-full"
|
|
120
|
-
})
|
|
121
|
-
}), /* @__PURE__ */ p("span", {
|
|
122
|
-
className: "min-w-0 truncate",
|
|
123
|
-
children: t.card.title || t.card.code
|
|
124
|
-
})] }) : t.type === "group" ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", {
|
|
147
|
+
}),
|
|
148
|
+
/* @__PURE__ */ m("ul", {
|
|
149
|
+
id: `${C}-list`,
|
|
150
|
+
role: "listbox",
|
|
151
|
+
"aria-label": y(H ? "contents.recentSearches" : "contents.suggestions"),
|
|
152
|
+
className: g("grid", z && "gap-2"),
|
|
153
|
+
children: K.map((t, n) => /* @__PURE__ */ m("li", {
|
|
154
|
+
id: `${C}-${n}`,
|
|
155
|
+
role: "option",
|
|
156
|
+
"aria-selected": n === P,
|
|
157
|
+
"data-ckui": "suggestion",
|
|
158
|
+
"data-type": t.type,
|
|
159
|
+
className: g("flex cursor-pointer items-center", z ? 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 === P && "bg-accent text-accent-foreground"),
|
|
160
|
+
onMouseEnter: () => F(n),
|
|
161
|
+
onMouseDown: (e) => {
|
|
162
|
+
e.preventDefault(), Z(t);
|
|
163
|
+
},
|
|
164
|
+
children: z && t.type !== "recent" ? /* @__PURE__ */ h(p, { children: [
|
|
165
|
+
/* @__PURE__ */ m(k, { kind: t.type === "content" ? t.card.kind : t.group.kind }),
|
|
166
|
+
/* @__PURE__ */ m("span", {
|
|
167
|
+
className: "sr-only",
|
|
168
|
+
children: s(l.labels, t.type === "content" ? t.card.kind : t.group.kind)
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ m("span", {
|
|
125
171
|
className: "min-w-0 flex-1 truncate",
|
|
126
|
-
children: t.group.name || t.group.slug
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
172
|
+
children: t.type === "content" ? t.card.title || t.card.code : t.group.name || t.group.slug
|
|
173
|
+
})
|
|
174
|
+
] }) : t.type === "content" ? /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m("span", {
|
|
175
|
+
className: "h-10 w-8 shrink-0 overflow-hidden rounded bg-muted",
|
|
176
|
+
children: /* @__PURE__ */ m(e, {
|
|
177
|
+
outputs: t.card.cover,
|
|
178
|
+
alt: "",
|
|
179
|
+
fit: "cover",
|
|
180
|
+
className: "size-full"
|
|
181
|
+
})
|
|
182
|
+
}), /* @__PURE__ */ m("span", {
|
|
183
|
+
className: "min-w-0 truncate",
|
|
184
|
+
children: t.card.title || t.card.code
|
|
185
|
+
})] }) : t.type === "group" ? /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m("span", {
|
|
186
|
+
className: "min-w-0 flex-1 truncate",
|
|
187
|
+
children: t.group.name || t.group.slug
|
|
188
|
+
}), /* @__PURE__ */ m("span", {
|
|
189
|
+
className: "text-xs text-muted-foreground",
|
|
190
|
+
children: s(l.labels, t.group.kind)
|
|
191
|
+
})] }) : /* @__PURE__ */ h(p, { children: [
|
|
192
|
+
/* @__PURE__ */ m(T, {
|
|
193
|
+
icon: z ? S : v,
|
|
194
|
+
strokeWidth: 2,
|
|
195
|
+
className: "size-4 shrink-0 text-muted-foreground",
|
|
196
|
+
"aria-hidden": !0
|
|
197
|
+
}),
|
|
198
|
+
/* @__PURE__ */ m("span", {
|
|
199
|
+
className: "min-w-0 flex-1 truncate",
|
|
200
|
+
children: t.query
|
|
201
|
+
}),
|
|
202
|
+
z && /* @__PURE__ */ m(A, {
|
|
203
|
+
value: t.searchedAt,
|
|
204
|
+
formatter: V
|
|
205
|
+
}),
|
|
206
|
+
/* @__PURE__ */ m("button", {
|
|
207
|
+
type: "button",
|
|
208
|
+
className: "rounded p-0.5 text-muted-foreground hover:text-foreground",
|
|
209
|
+
"aria-label": y("contents.removeRecent", { q: t.query }),
|
|
210
|
+
onMouseDown: (e) => {
|
|
211
|
+
e.preventDefault(), e.stopPropagation();
|
|
212
|
+
},
|
|
213
|
+
onClick: () => void W.clear(t.query),
|
|
214
|
+
children: /* @__PURE__ */ m(T, {
|
|
132
215
|
icon: _,
|
|
133
216
|
strokeWidth: 2,
|
|
134
|
-
className: "size-
|
|
217
|
+
className: "size-3.5",
|
|
135
218
|
"aria-hidden": !0
|
|
136
|
-
}),
|
|
137
|
-
/* @__PURE__ */ p("span", {
|
|
138
|
-
className: "min-w-0 flex-1 truncate",
|
|
139
|
-
children: t.query
|
|
140
|
-
}),
|
|
141
|
-
/* @__PURE__ */ p("button", {
|
|
142
|
-
type: "button",
|
|
143
|
-
className: "rounded p-0.5 text-muted-foreground hover:text-foreground",
|
|
144
|
-
"aria-label": x("contents.removeRecent", { q: t.query }),
|
|
145
|
-
onMouseDown: (e) => {
|
|
146
|
-
e.preventDefault(), e.stopPropagation(), P.clear(t.query);
|
|
147
|
-
},
|
|
148
|
-
children: /* @__PURE__ */ p(y, {
|
|
149
|
-
icon: g,
|
|
150
|
-
strokeWidth: 2,
|
|
151
|
-
className: "size-3.5",
|
|
152
|
-
"aria-hidden": !0
|
|
153
|
-
})
|
|
154
219
|
})
|
|
155
|
-
|
|
156
|
-
|
|
220
|
+
})
|
|
221
|
+
] })
|
|
222
|
+
}, t.type === "content" ? `c:${t.card.id}` : t.type === "group" ? `g:${t.group.id}` : `r:${t.query}`))
|
|
223
|
+
}),
|
|
224
|
+
re ? /* @__PURE__ */ m("div", {
|
|
225
|
+
role: "status",
|
|
226
|
+
className: g("text-muted-foreground", z ? "flex justify-center py-4" : "px-3 py-2"),
|
|
227
|
+
children: z ? /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m("span", {
|
|
228
|
+
className: "size-6 animate-spin rounded-full border-2 border-muted border-t-foreground motion-reduce:animate-none",
|
|
229
|
+
"aria-hidden": !0
|
|
230
|
+
}), /* @__PURE__ */ m("span", {
|
|
231
|
+
className: "sr-only",
|
|
232
|
+
children: y("contents.loading")
|
|
233
|
+
})] }) : y("contents.loading")
|
|
234
|
+
}) : !H && U.error ? /* @__PURE__ */ m("p", {
|
|
235
|
+
role: "alert",
|
|
236
|
+
className: g("px-3 py-2 text-destructive", z && "text-center"),
|
|
237
|
+
children: b(U.error)
|
|
238
|
+
}) : K.length === 0 && /* @__PURE__ */ h("div", {
|
|
239
|
+
role: "status",
|
|
240
|
+
className: g("text-muted-foreground", z ? "flex flex-col items-center gap-2 py-8 text-center" : "px-3 py-2"),
|
|
241
|
+
children: [z && /* @__PURE__ */ m(T, {
|
|
242
|
+
icon: S,
|
|
243
|
+
strokeWidth: 2,
|
|
244
|
+
className: "size-8",
|
|
245
|
+
"aria-hidden": !0
|
|
246
|
+
}), /* @__PURE__ */ m("p", { children: y(ie, { q: D.trim() }) })]
|
|
247
|
+
})
|
|
248
|
+
] });
|
|
249
|
+
return /* @__PURE__ */ h(n, {
|
|
250
|
+
ref: I,
|
|
251
|
+
appearance: l.appearance,
|
|
252
|
+
className: g("relative text-sm", l.className),
|
|
253
|
+
"data-ckui": "search-box",
|
|
254
|
+
onBlur: (e) => {
|
|
255
|
+
!e.currentTarget.contains(e.relatedTarget) && !L.current?.contains(e.relatedTarget) && N(!1);
|
|
256
|
+
},
|
|
257
|
+
children: [/* @__PURE__ */ h("form", {
|
|
258
|
+
role: "search",
|
|
259
|
+
className: "relative",
|
|
260
|
+
onSubmit: (e) => {
|
|
261
|
+
if (e.preventDefault(), M && q) return Z(q);
|
|
262
|
+
X(D.trim());
|
|
263
|
+
},
|
|
264
|
+
children: [
|
|
265
|
+
z ? /* @__PURE__ */ m("button", {
|
|
266
|
+
type: "submit",
|
|
267
|
+
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",
|
|
268
|
+
"aria-label": y("contents.search"),
|
|
269
|
+
children: /* @__PURE__ */ m(T, {
|
|
270
|
+
icon: S,
|
|
271
|
+
strokeWidth: 2,
|
|
272
|
+
className: "size-4",
|
|
273
|
+
"aria-hidden": !0
|
|
274
|
+
})
|
|
275
|
+
}) : /* @__PURE__ */ m(T, {
|
|
276
|
+
icon: S,
|
|
277
|
+
strokeWidth: 2,
|
|
278
|
+
className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground",
|
|
279
|
+
"aria-hidden": !0
|
|
280
|
+
}),
|
|
281
|
+
/* @__PURE__ */ m(i, {
|
|
282
|
+
ref: R,
|
|
283
|
+
type: z ? "text" : "search",
|
|
284
|
+
role: "combobox",
|
|
285
|
+
"aria-label": y("contents.search"),
|
|
286
|
+
"aria-expanded": M,
|
|
287
|
+
"aria-controls": `${C}-list`,
|
|
288
|
+
"aria-activedescendant": M && q ? `${C}-${P}` : void 0,
|
|
289
|
+
"aria-autocomplete": "list",
|
|
290
|
+
autoComplete: "off",
|
|
291
|
+
className: g("h-9 ps-8", z && "rounded-full border-border/50 bg-foreground/10 pe-9 text-base shadow-none md:text-base"),
|
|
292
|
+
value: D,
|
|
293
|
+
placeholder: l.placeholder ?? y("contents.searchPlaceholder"),
|
|
294
|
+
onChange: (e) => {
|
|
295
|
+
j(e.target.value), N(!0), F(-1);
|
|
296
|
+
},
|
|
297
|
+
onFocus: Y,
|
|
298
|
+
onClick: Y,
|
|
299
|
+
onKeyDown: (e) => {
|
|
300
|
+
if (e.key === "Escape") {
|
|
301
|
+
e.preventDefault(), N(!1), F(-1);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
e.key === "ArrowDown" ? (e.preventDefault(), Y(), F((e) => M ? Math.min(K.length - 1, e + 1) : 0)) : e.key === "ArrowUp" && M && (e.preventDefault(), F((e) => Math.max(-1, e - 1)));
|
|
305
|
+
}
|
|
306
|
+
}),
|
|
307
|
+
z && (D || M) && /* @__PURE__ */ m("button", {
|
|
308
|
+
type: "button",
|
|
309
|
+
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",
|
|
310
|
+
"aria-label": y(D ? "contents.clearSearch" : "common.close"),
|
|
311
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
312
|
+
onClick: () => {
|
|
313
|
+
R.current?.focus(), F(-1), D ? (j(""), N(!0)) : N(!1);
|
|
314
|
+
},
|
|
315
|
+
children: /* @__PURE__ */ m(T, {
|
|
316
|
+
icon: _,
|
|
317
|
+
strokeWidth: 2,
|
|
318
|
+
className: "size-4",
|
|
319
|
+
"aria-hidden": !0
|
|
320
|
+
})
|
|
321
|
+
})
|
|
322
|
+
]
|
|
323
|
+
}), M && (z ? E(/* @__PURE__ */ h(n, {
|
|
324
|
+
appearance: l.appearance,
|
|
325
|
+
className: "fixed inset-x-0 bottom-0 z-[70] text-sm",
|
|
326
|
+
style: { top: B },
|
|
327
|
+
"data-ckui": "search-layer",
|
|
328
|
+
children: [/* @__PURE__ */ m("div", {
|
|
329
|
+
className: "absolute inset-0 bg-black/30 backdrop-blur-sm",
|
|
330
|
+
"data-ckui": "search-backdrop",
|
|
331
|
+
"aria-hidden": !0
|
|
332
|
+
}), /* @__PURE__ */ m("div", {
|
|
333
|
+
ref: L,
|
|
334
|
+
className: "relative w-full origin-top animate-in fade-in-0 slide-in-from-top-2 bg-background pt-1.5 text-foreground shadow-lg duration-200 ease-out motion-reduce:animate-none",
|
|
335
|
+
"data-ckui": "search-panel",
|
|
336
|
+
onKeyDown: Q,
|
|
337
|
+
children: /* @__PURE__ */ m("div", {
|
|
338
|
+
className: "mx-auto w-full max-w-[71rem] px-4 pt-5 md:px-[10%]",
|
|
339
|
+
children: /* @__PURE__ */ m("div", {
|
|
340
|
+
className: "[--search-max-height:70vh] overflow-y-auto pb-7 md:[--search-max-height:60vh]",
|
|
341
|
+
style: { maxHeight: `min(var(--search-max-height), calc(100dvh - ${B}px - 1.875rem))` },
|
|
342
|
+
children: /* @__PURE__ */ m("div", {
|
|
343
|
+
className: H ? "px-4 py-4" : "px-4",
|
|
344
|
+
children: $
|
|
345
|
+
})
|
|
346
|
+
})
|
|
347
|
+
})
|
|
157
348
|
})]
|
|
158
|
-
})
|
|
349
|
+
}), document.body) : /* @__PURE__ */ m("div", {
|
|
350
|
+
ref: L,
|
|
351
|
+
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
|
+
"data-ckui": "search-panel",
|
|
353
|
+
onKeyDown: Q,
|
|
354
|
+
children: $
|
|
355
|
+
}))]
|
|
159
356
|
});
|
|
160
357
|
}
|
|
161
358
|
//#endregion
|
|
162
|
-
export {
|
|
359
|
+
export { j as SearchBox };
|
|
163
360
|
|
|
164
361
|
//# sourceMappingURL=search.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","names":[],"sources":["../../../src/components/content/search.tsx"],"sourcesContent":["import { Cancel01Icon, Clock01Icon, Search01Icon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useContext, useId, useMemo, useState } from \"react\";\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 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\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 } = 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 [touched, setTouched] = useState(false);\n const empty = !text.trim();\n const found = useTypeahead(text, { kind: p.kind, group_kinds: p.groupKinds, client: p.client });\n const recent = useRecentSearches({ enabled: p.recent !== false && touched, 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.groups.map((group) => ({ type: \"group\" as const, group }))],\n [empty, recent.searches, found.contents, found.groups],\n );\n const shown = open && items.length > 0 && (empty || found.query === text.trim());\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 return (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"relative text-sm\", p.className)} data-ckui=\"search-box\">\n <form\n role=\"search\"\n onSubmit={(e) => {\n e.preventDefault();\n if (shown && active >= 0) return go(items[active]!);\n search(text.trim());\n }}\n >\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 type=\"search\"\n role=\"combobox\"\n aria-label={t(\"contents.search\")}\n aria-expanded={shown}\n aria-controls={`${id}-list`}\n aria-activedescendant={shown && active >= 0 ? `${id}-${active}` : undefined}\n aria-autocomplete=\"list\"\n autoComplete=\"off\"\n className=\"h-9 ps-8\"\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={() => {\n setOpen(true);\n setTouched(true);\n }}\n onBlur={() => setOpen(false)}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") return setOpen(false);\n if (!shown) return;\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActive((a) => Math.min(items.length - 1, a + 1));\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActive((a) => Math.max(-1, a - 1));\n }\n }}\n />\n </form>\n {shown && (\n <div 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\">\n {empty && (\n <div className=\"flex items-center justify-between gap-2 px-2 py-1 text-xs text-muted-foreground\">\n <span id={`${id}-recent`}>{t(\"contents.recentSearches\")}</span>\n <button\n type=\"button\"\n className=\"rounded px-1 hover:text-foreground\"\n onMouseDown={(e) => {\n e.preventDefault();\n void recent.clear();\n }}\n >\n {t(\"contents.clearRecent\")}\n </button>\n </div>\n )}\n <ul id={`${id}-list`} role=\"listbox\" aria-label={empty ? t(\"contents.recentSearches\") : t(\"contents.suggestions\")} className=\"grid\">\n {items.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 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 {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={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 void recent.clear(s.query);\n }}\n >\n <HugeiconsIcon icon={Cancel01Icon} strokeWidth={2} className=\"size-3.5\" aria-hidden />\n </button>\n </>\n )}\n </li>\n ))}\n </ul>\n </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 /** The reader's recent searches while the box is empty. Default true. */\n recent?: boolean;\n /** Header-wide dropdown under the nearest header/banner; 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; searchedAt?: 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 useHeaderTop(open: boolean, enabled: boolean, root: RefObject<HTMLDivElement | null>, input: RefObject<HTMLInputElement | null>): number {\n const [top, setTop] = useState(0);\n useLayoutEffect(() => {\n if (!open || !enabled || !root.current) return;\n const anchor = root.current.closest('header, [role=\"banner\"]') ?? input.current ?? root.current;\n const view = root.current.ownerDocument.defaultView;\n if (!view) return;\n const measure = () => setTop(Math.max(0, Math.min(view.innerHeight, anchor.getBoundingClientRect().bottom)));\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 top;\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\nfunction SearchDate({ value, formatter }: { value?: string; formatter: Intl.DateTimeFormat }) {\n if (!value || Number.isNaN(Date.parse(value))) return null;\n return <time dateTime={value} className=\"shrink-0 text-xs text-muted-foreground\">{formatter.format(new Date(value))}</time>;\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, language } = 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 top = useHeaderTop(open, header, root, input);\n const dates = useMemo(() => new Intl.DateTimeFormat(language, { dateStyle: \"short\" }), [language]);\n const empty = !text.trim();\n const found = useTypeahead(text, { kind: p.kind, group_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, searchedAt: r.searched_at }))\n : [...found.contents.map((card) => ({ type: \"content\" as const, card })), ...found.groups.map((group) => ({ type: \"group\" as const, group }))],\n [empty, recent.searches, found.contents, found.groups],\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 {header && <SearchDate value={s.searchedAt} formatter={dates} />}\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} className=\"relative w-full origin-top animate-in fade-in-0 slide-in-from-top-2 bg-background pt-1.5 text-foreground shadow-lg duration-200 ease-out motion-reduce:animate-none\" data-ckui=\"search-panel\" onKeyDown={panelKeyDown}>\n <div className=\"mx-auto w-full max-w-[71rem] px-4 pt-5 md:px-[10%]\">\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 className={empty ? \"px-4 py-4\" : \"px-4\"}>{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/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export { MediaReadinessNotice, type MediaReadinessNoticeProps } from './componen
|
|
|
21
21
|
export * from './components/social/index.js';
|
|
22
22
|
export * from './components/groups/index.js';
|
|
23
23
|
export * from './components/content/index.js';
|
|
24
|
+
export { ContentAdmin, type ContentAdminProps, type ContentAdminSection } from './components/admin/content-admin.js';
|
|
24
25
|
export { UserCommentStanding, useUserCommentStandingAccess, type UserCommentStandingProps } from './components/admin/user-comment-standing.js';
|
|
25
26
|
export { PollManager, pollState, usePollManagerAccess, type PollManagerProps } from './components/admin/poll-manager.js';
|
|
26
27
|
export { ContentEditor, ContentManager, contentStatus, useContentManagerAccess, type BodyEditorProps, type ContentEditorProps, type ContentManagerProps, type ContentStatus } from './components/admin/content-manager.js';
|