@gatewaze/admin-embed 0.1.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.
Files changed (96) hide show
  1. package/README.md +42 -0
  2. package/dist/AiSkillsPicker-dbFhcanE.js +373 -0
  3. package/dist/ContentAccessPage-D0HRqPFc.js +264 -0
  4. package/dist/DataTable-fe6yRVpF.js +1984 -0
  5. package/dist/DetailPageHeader-D_v7924k.js +69 -0
  6. package/dist/EditionEmail-CyhC8232.js +8382 -0
  7. package/dist/GuideContent-DBXKCu7r.js +7580 -0
  8. package/dist/HostMediaTab-BsIBEQ1v.js +440 -0
  9. package/dist/InboxPage-C8ivCKdx.js +1112 -0
  10. package/dist/NewsletterCanvasEditor--B06apn3.js +11453 -0
  11. package/dist/NewsletterSetupWizard-BqV6-fa5.js +347 -0
  12. package/dist/NewsletterSignup-DRVZIpOs.js +224 -0
  13. package/dist/Page-D3u8IZ2a.js +14 -0
  14. package/dist/Toaster-Cde0i6IA.js +18 -0
  15. package/dist/Tooltip-CqxUlW1d.js +746 -0
  16. package/dist/_collectionSlug_-B3UN6M-Q.js +308 -0
  17. package/dist/_collection_-Qz4k_Qjl.js +139 -0
  18. package/dist/_edition_-DQXwkI_-.js +301 -0
  19. package/dist/_id_-CtT7rT9f.js +257 -0
  20. package/dist/_id_-CzScE4Qn.js +1197 -0
  21. package/dist/_virtual_gatewaze-modules-BeloWlOa.js +991 -0
  22. package/dist/admin-B0Mmrh_O.js +1239 -0
  23. package/dist/admin-CcfoK6vD.js +17 -0
  24. package/dist/admin-embed.js +21844 -0
  25. package/dist/admin.css +2 -0
  26. package/dist/block-editor-vXBShAue.js +226 -0
  27. package/dist/brand-DklYwIeA.js +11 -0
  28. package/dist/brick-editor-CmBitMMK.js +225 -0
  29. package/dist/broadcastService-CBqXNt_N.js +190 -0
  30. package/dist/classnames-uWIYaD6z.js +44 -0
  31. package/dist/contentAccessService-Cs7tdAo-.js +59 -0
  32. package/dist/context-jzuubYRz.js +5 -0
  33. package/dist/createSafeContext-P1pK0sAN.js +17 -0
  34. package/dist/detail-B8SVFJJr.js +26285 -0
  35. package/dist/detail-uFBxRbLF.js +2966 -0
  36. package/dist/dist-DTrOExw8.js +38806 -0
  37. package/dist/edition-slug-CARO24Bs.js +7 -0
  38. package/dist/export-edition-html-C_hdXQu5.js +18893 -0
  39. package/dist/floating-ui.dom-Cyv879E9.js +987 -0
  40. package/dist/hooks-C377EXJG.js +2974 -0
  41. package/dist/img/mlops-logo.png +0 -0
  42. package/dist/img/mlops-logo2.png +0 -0
  43. package/dist/index.d.ts +105 -0
  44. package/dist/jsx-runtime-CjozyJt-.js +180 -0
  45. package/dist/lib-CylJmhlJ.js +828 -0
  46. package/dist/list-C0cz0aQz.js +451 -0
  47. package/dist/list-CIVgIGsU.js +166 -0
  48. package/dist/logo/mlops-alt.png +0 -0
  49. package/dist/logo/mlops-logo.png +0 -0
  50. package/dist/new-r4KWpqa6.js +80 -0
  51. package/dist/outline-DwDYhYcF.js +6538 -0
  52. package/dist/pages-Ersfxcz7.js +216 -0
  53. package/dist/preview/12627f.jpg +0 -0
  54. package/dist/preview/af009d.jpg +0 -0
  55. package/dist/public-api-LD11kMxh.js +238 -0
  56. package/dist/react-DB2tPNit.js +933 -0
  57. package/dist/react-dom-giQNVXng.js +267 -0
  58. package/dist/registry-4XrV9iNG.js +7 -0
  59. package/dist/render-BtUWfMUt.js +59634 -0
  60. package/dist/resolvePeopleByEmail-hivX2l07.js +828 -0
  61. package/dist/runtime-config.js +10 -0
  62. package/dist/sends-BkPO6PG2.js +182 -0
  63. package/dist/server.browser-Pj3QUa7k.js +15227 -0
  64. package/dist/shim-BCerG8nb.js +6681 -0
  65. package/dist/sonnerHostBridge-CXuCMM3R.js +665 -0
  66. package/dist/src-BWDAOzZO.js +799 -0
  67. package/dist/starter-templates-CFs-QUdF.js +3077 -0
  68. package/dist/storage-VDSvnkvR.js +39 -0
  69. package/dist/templateParser-BQ2IsJ6c.js +49 -0
  70. package/dist/templates-rjQjWsRr.js +253 -0
  71. package/dist/theme/gatewaze/android-icon-144x144.png +0 -0
  72. package/dist/theme/gatewaze/android-icon-192x192.png +0 -0
  73. package/dist/theme/gatewaze/android-icon-36x36.png +0 -0
  74. package/dist/theme/gatewaze/android-icon-48x48.png +0 -0
  75. package/dist/theme/gatewaze/android-icon-72x72.png +0 -0
  76. package/dist/theme/gatewaze/android-icon-96x96.png +0 -0
  77. package/dist/theme/gatewaze/favicon-144x144.png +0 -0
  78. package/dist/theme/gatewaze/favicon-16x16.png +0 -0
  79. package/dist/theme/gatewaze/favicon-192x192.png +0 -0
  80. package/dist/theme/gatewaze/favicon-32x32.png +0 -0
  81. package/dist/theme/gatewaze/favicon-96x96.png +0 -0
  82. package/dist/theme/gatewaze/favicon.ico +0 -0
  83. package/dist/theme/gatewaze/gatewaze-icon-512.png +0 -0
  84. package/dist/theme/gatewaze/gatewaze-logo-black.svg +24 -0
  85. package/dist/theme/gatewaze/gatewaze-logo-white.svg +20 -0
  86. package/dist/theme/gatewaze/gatewaze-poweredby-black.svg +25 -0
  87. package/dist/theme/gatewaze/gatewaze-poweredby-white.svg +25 -0
  88. package/dist/theme/gatewaze/logo_black.svg +24 -0
  89. package/dist/theme/gatewaze/logo_white.svg +20 -0
  90. package/dist/theme-D6odw5nx.js +586 -0
  91. package/dist/ui-DRIo9Krs.js +9747 -0
  92. package/dist/upload-DMNfZ6FX.js +505 -0
  93. package/dist/useModuleFeature-DgsFIUpv.js +8 -0
  94. package/dist/utils-BcVvIjaY.js +36 -0
  95. package/dist/with-selector-B8eSdVx_.js +100 -0
  96. package/package.json +33 -0
@@ -0,0 +1,1112 @@
1
+ import { c as e, t } from "./react-DB2tPNit.js";
2
+ import { d as n } from "./shim-BCerG8nb.js";
3
+ import { t as r } from "./_virtual_gatewaze-modules-BeloWlOa.js";
4
+ import { t as i } from "./jsx-runtime-CjozyJt-.js";
5
+ import { D as a, E as o, O as s, f as c, r as l } from "./ui-DRIo9Krs.js";
6
+ import { n as u } from "./context-jzuubYRz.js";
7
+ import { t as d } from "./Page-D3u8IZ2a.js";
8
+ //#region src/hooks/useModuleSlots.ts
9
+ var f = /* @__PURE__ */ e(t()), p = 500;
10
+ function m(e, t) {
11
+ let n = u(), i = t?.enabledModuleIds.join(","), a = t?.enabledFeatures.join(",");
12
+ return (0, f.useMemo)(() => {
13
+ let i = t ? (e) => t.enabledModuleIds.includes(e) : n.isModuleEnabled, a = t ? (e) => t.enabledFeatures.includes(e) : n.isFeatureEnabled, o = [];
14
+ for (let t of r) {
15
+ if (!t.adminSlots || !i(t.id)) continue;
16
+ let n = t.__identity?.firstParty ?? !0;
17
+ for (let r of t.adminSlots) {
18
+ if (r.slotName !== e || r.requiredFeature && !a(r.requiredFeature)) continue;
19
+ let i = r.meta?.tabId ?? r.slotName, s = r.order ?? 100, c = n ? s : Math.max(p, s);
20
+ o.push({
21
+ moduleId: t.id,
22
+ registration: r,
23
+ scopedId: `${t.id}:${i}`,
24
+ effectiveOrder: c
25
+ });
26
+ }
27
+ }
28
+ return o.sort((e, t) => e.effectiveOrder - t.effectiveOrder), o;
29
+ }, [
30
+ e,
31
+ n.isModuleEnabled,
32
+ n.isFeatureEnabled,
33
+ i,
34
+ a
35
+ ]);
36
+ }
37
+ //#endregion
38
+ //#region ../../../gatewaze-modules/modules/content-platform/admin/utils/inboxService.ts
39
+ var h = () => l();
40
+ async function g(e, t) {
41
+ let { data: { session: r } } = await n.auth.getSession(), i = r?.access_token ? { Authorization: `Bearer ${r.access_token}` } : {}, a = await fetch(`${h()}${e}`, {
42
+ credentials: "include",
43
+ headers: {
44
+ "Content-Type": "application/json",
45
+ ...i,
46
+ ...t?.headers ?? {}
47
+ },
48
+ ...t
49
+ });
50
+ if (!a.ok) {
51
+ let e = await a.json().catch(() => ({}));
52
+ throw Object.assign(Error(e?.error?.message ?? a.statusText), {
53
+ code: e?.error?.code ?? `http_${a.status}`,
54
+ status: a.status
55
+ });
56
+ }
57
+ return a.json();
58
+ }
59
+ function _(e) {
60
+ let t = new URLSearchParams();
61
+ return e.cursor && t.set("cursor", e.cursor), e.limit && t.set("limit", String(e.limit)), e.content_type?.length && t.set("content_type", e.content_type.join(",")), e.source_kind?.length && t.set("source_kind", e.source_kind.join(",")), e.time && t.set("time", e.time), e.publish_state?.length && t.set("publish_state", e.publish_state.join(",")), e.category?.length && t.set("category", e.category.join(",")), e.member_only && t.set("member_only", "true"), e.search && t.set("search", e.search), e.sort && t.set("sort", e.sort), e.assigned_to && t.set("assigned_to", e.assigned_to), t.toString();
62
+ }
63
+ var v = {
64
+ async list(e = {}) {
65
+ return await g(`/admin/inbox/list?${_(e)}`);
66
+ },
67
+ async bulk(e, t, n = {}) {
68
+ return (await g("/admin/inbox/bulk", {
69
+ method: "POST",
70
+ body: JSON.stringify({
71
+ action: e,
72
+ selection: {
73
+ mode: "ids",
74
+ items: t
75
+ },
76
+ params: n
77
+ })
78
+ })).data;
79
+ },
80
+ async explain(e) {
81
+ return (await g(`/admin/inbox/explain/${e}`)).data;
82
+ }
83
+ }, y = i(), b = {
84
+ published: "green",
85
+ pending_review: "amber",
86
+ auto_suppressed: "gray",
87
+ rejected: "red",
88
+ unpublished: "gray",
89
+ draft: "blue"
90
+ }, x = {
91
+ scraper: "Scraper",
92
+ ai_discovery: "AI discovery",
93
+ admin_ui: "Manual",
94
+ api: "API",
95
+ mcp: "MCP",
96
+ user_submission: "User",
97
+ import: "Import",
98
+ unknown: "Unknown"
99
+ };
100
+ function S(e) {
101
+ let t = Math.max(0, Math.floor((Date.now() - new Date(e).getTime()) / 1e3));
102
+ if (t < 60) return `${t}s`;
103
+ let n = Math.floor(t / 60);
104
+ if (n < 60) return `${n}m`;
105
+ let r = Math.floor(n / 60);
106
+ return r < 24 ? `${r}h` : `${Math.floor(r / 24)}d`;
107
+ }
108
+ function C({ row: e, selected: t, onToggleSelect: n, onOpenDrawer: r, onSourceFilter: i }) {
109
+ return x[e.source.kind] ?? e.source.kind, /* @__PURE__ */ (0, y.jsxs)("tr", {
110
+ className: "border-b border-[var(--gray-a4)] hover:bg-[var(--gray-a3)] cursor-pointer",
111
+ onClick: r,
112
+ children: [
113
+ /* @__PURE__ */ (0, y.jsx)("td", {
114
+ className: "px-3 py-2 w-10",
115
+ onClick: (e) => e.stopPropagation(),
116
+ children: /* @__PURE__ */ (0, y.jsx)("input", {
117
+ type: "checkbox",
118
+ checked: t,
119
+ onChange: n
120
+ })
121
+ }),
122
+ /* @__PURE__ */ (0, y.jsx)("td", {
123
+ className: "px-3 py-2",
124
+ children: /* @__PURE__ */ (0, y.jsx)(s, {
125
+ variant: "soft",
126
+ color: "blue",
127
+ className: "capitalize",
128
+ children: e.content_type
129
+ })
130
+ }),
131
+ /* @__PURE__ */ (0, y.jsx)("td", {
132
+ className: "px-3 py-2 max-w-[420px]",
133
+ children: /* @__PURE__ */ (0, y.jsxs)("div", {
134
+ className: "flex items-start gap-3",
135
+ children: [e.thumbnail_url && /* @__PURE__ */ (0, y.jsx)("img", {
136
+ src: e.thumbnail_url,
137
+ alt: "",
138
+ className: "w-12 h-12 object-cover rounded flex-shrink-0",
139
+ onError: (e) => {
140
+ e.currentTarget.style.display = "none";
141
+ }
142
+ }), /* @__PURE__ */ (0, y.jsxs)("div", {
143
+ className: "min-w-0 flex-1",
144
+ children: [/* @__PURE__ */ (0, y.jsxs)("div", {
145
+ className: "font-medium text-sm truncate flex items-center gap-1.5",
146
+ title: e.title ?? "",
147
+ children: [/* @__PURE__ */ (0, y.jsx)("span", {
148
+ className: "truncate min-w-0",
149
+ children: e.title ?? /* @__PURE__ */ (0, y.jsx)("span", {
150
+ className: "text-[var(--gray-10)] italic",
151
+ children: "untitled"
152
+ })
153
+ }), e.source_url && /* @__PURE__ */ (0, y.jsx)("a", {
154
+ href: e.source_url,
155
+ target: "_blank",
156
+ rel: "noopener noreferrer",
157
+ onClick: (e) => e.stopPropagation(),
158
+ className: "text-[var(--gray-10)] hover:text-[var(--accent-9)] flex-shrink-0",
159
+ title: `Open source: ${e.source_url}`,
160
+ children: "↗"
161
+ })]
162
+ }), e.subtitle && /* @__PURE__ */ (0, y.jsx)("div", {
163
+ className: "text-xs text-[var(--gray-11)] truncate",
164
+ title: e.subtitle,
165
+ children: e.subtitle
166
+ })]
167
+ })]
168
+ })
169
+ }),
170
+ /* @__PURE__ */ (0, y.jsx)("td", {
171
+ className: "px-3 py-2 max-w-[260px]",
172
+ children: e.matched_rules && e.matched_rules.length > 0 ? /* @__PURE__ */ (0, y.jsxs)("div", {
173
+ className: "flex flex-wrap gap-1",
174
+ children: [e.matched_rules.slice(0, 3).map((e) => /* @__PURE__ */ (0, y.jsx)(s, {
175
+ variant: "soft",
176
+ color: e.kind === "membership" ? "green" : "blue",
177
+ title: e.name,
178
+ children: e.name.length > 28 ? e.name.slice(0, 25) + "…" : e.name
179
+ }, e.id)), e.matched_rules.length > 3 && /* @__PURE__ */ (0, y.jsxs)("span", {
180
+ className: "text-xs text-[var(--gray-10)] self-center",
181
+ children: ["+", e.matched_rules.length - 3]
182
+ })]
183
+ }) : /* @__PURE__ */ (0, y.jsx)("span", {
184
+ className: "text-xs text-[var(--gray-10)] italic",
185
+ children: "no match"
186
+ })
187
+ }),
188
+ /* @__PURE__ */ (0, y.jsx)("td", {
189
+ className: "px-3 py-2",
190
+ children: e.category && /* @__PURE__ */ (0, y.jsx)(s, {
191
+ variant: "soft",
192
+ color: e.category === "members" ? "green" : "gray",
193
+ children: e.category
194
+ })
195
+ }),
196
+ /* @__PURE__ */ (0, y.jsx)("td", {
197
+ className: "px-3 py-2",
198
+ children: e.publish_state && /* @__PURE__ */ (0, y.jsx)(s, {
199
+ variant: "soft",
200
+ color: b[e.publish_state] ?? "gray",
201
+ children: e.publish_state.replace(/_/g, " ")
202
+ })
203
+ }),
204
+ /* @__PURE__ */ (0, y.jsx)("td", {
205
+ className: "px-3 py-2 text-xs text-[var(--gray-11)] whitespace-nowrap",
206
+ children: S(e.submitted_at)
207
+ })
208
+ ]
209
+ });
210
+ }
211
+ //#endregion
212
+ //#region src/components/shared/SideDrawer.tsx
213
+ function w({ open: e, onClose: t, title: n, subtitle: r, width: i = 640, children: a, onPrev: o, onNext: s, position: c, className: l = "" }) {
214
+ if ((0, f.useEffect)(() => {
215
+ if (!e) return;
216
+ let n = (e) => {
217
+ e.key === "Escape" ? t() : e.key === "ArrowLeft" && o ? o() : e.key === "ArrowRight" && s && s();
218
+ };
219
+ return window.addEventListener("keydown", n), () => window.removeEventListener("keydown", n);
220
+ }, [
221
+ e,
222
+ t,
223
+ o,
224
+ s
225
+ ]), !e) return null;
226
+ let u = { width: typeof i == "number" ? `${i}px` : i };
227
+ return /* @__PURE__ */ (0, y.jsx)("div", {
228
+ className: "fixed inset-0 z-50 bg-black/40 flex justify-end",
229
+ onClick: t,
230
+ children: /* @__PURE__ */ (0, y.jsxs)("div", {
231
+ style: u,
232
+ className: `h-full bg-white dark:bg-[var(--gray-1)] text-[var(--gray-12)] shadow-2xl border-l border-[var(--gray-a4)] relative animate-[drawerSlideIn_0.2s_ease-out] flex flex-col ${l}`,
233
+ onClick: (e) => e.stopPropagation(),
234
+ children: [
235
+ (n || r) && /* @__PURE__ */ (0, y.jsxs)("div", {
236
+ className: "flex items-start justify-between gap-4 p-6 pb-4 border-b border-[var(--gray-a4)]",
237
+ children: [/* @__PURE__ */ (0, y.jsxs)("div", {
238
+ className: "flex-1 min-w-0",
239
+ children: [n && (typeof n == "string" ? /* @__PURE__ */ (0, y.jsx)("h2", {
240
+ className: "text-xl font-semibold truncate",
241
+ children: n
242
+ }) : n), r && /* @__PURE__ */ (0, y.jsx)("div", {
243
+ className: "text-sm text-[var(--gray-11)] mt-1",
244
+ children: r
245
+ })]
246
+ }), /* @__PURE__ */ (0, y.jsx)("button", {
247
+ onClick: t,
248
+ className: "text-[var(--gray-11)] hover:text-[var(--gray-12)] flex-shrink-0 text-xl leading-none",
249
+ "aria-label": "Close",
250
+ children: "×"
251
+ })]
252
+ }),
253
+ !n && !r && /* @__PURE__ */ (0, y.jsx)("button", {
254
+ onClick: t,
255
+ className: "absolute top-4 right-4 text-[var(--gray-11)] hover:text-[var(--gray-12)] text-xl leading-none z-10",
256
+ "aria-label": "Close",
257
+ children: "×"
258
+ }),
259
+ /* @__PURE__ */ (0, y.jsx)("div", {
260
+ className: "flex-1 overflow-y-auto",
261
+ children: a
262
+ }),
263
+ (o || s) && /* @__PURE__ */ (0, y.jsxs)("div", {
264
+ className: "sticky bottom-0 left-0 right-0 px-6 py-3 bg-white dark:bg-[var(--gray-1)] border-t border-[var(--gray-a4)] flex items-center justify-between",
265
+ children: [
266
+ /* @__PURE__ */ (0, y.jsx)("button", {
267
+ onClick: o,
268
+ disabled: !o,
269
+ className: "px-3 py-1.5 rounded-md text-sm font-medium bg-[var(--gray-a3)] hover:bg-[var(--gray-a5)] text-[var(--gray-12)] disabled:opacity-40 disabled:cursor-not-allowed",
270
+ children: "← Previous"
271
+ }),
272
+ c && /* @__PURE__ */ (0, y.jsxs)("span", {
273
+ className: "text-xs text-[var(--gray-11)] tabular-nums",
274
+ children: [
275
+ c.current + 1,
276
+ " of ",
277
+ c.total
278
+ ]
279
+ }),
280
+ /* @__PURE__ */ (0, y.jsx)("button", {
281
+ onClick: s,
282
+ disabled: !s,
283
+ className: "px-3 py-1.5 rounded-md text-sm font-medium bg-[var(--gray-a3)] hover:bg-[var(--gray-a5)] text-[var(--gray-12)] disabled:opacity-40 disabled:cursor-not-allowed",
284
+ children: "Next →"
285
+ })
286
+ ]
287
+ })
288
+ ]
289
+ })
290
+ });
291
+ }
292
+ //#endregion
293
+ //#region ../../../gatewaze-modules/modules/content-platform/admin/components/InboxDrawer.tsx
294
+ function T({ row: e, onClose: t, onActed: n, onPrev: r, onNext: i, position: c }) {
295
+ let [l, u] = (0, f.useState)(null), [d, p] = (0, f.useState)(!0), [m, h] = (0, f.useState)(!1), [g, _] = (0, f.useState)(null), [b, x] = (0, f.useState)(""), [S, C] = (0, f.useState)(!1);
296
+ (0, f.useEffect)(() => {
297
+ let t = !0;
298
+ return p(!0), v.explain(e.triage_item_id).then((e) => {
299
+ t && u(e);
300
+ }).catch((e) => {
301
+ t && _(e.message);
302
+ }).finally(() => {
303
+ t && p(!1);
304
+ }), () => {
305
+ t = !1;
306
+ };
307
+ }, [e.triage_item_id]);
308
+ let T = async (t, r = {}) => {
309
+ h(!0), _(null);
310
+ try {
311
+ let i = await v.bulk(t, [{
312
+ triage_item_id: e.triage_item_id,
313
+ lifecycle_key: e.lifecycle_key
314
+ }], r);
315
+ if (i.failed > 0) {
316
+ let e = i.errors[0];
317
+ _(`${e.code}: ${e.message}`);
318
+ return;
319
+ }
320
+ n();
321
+ } catch (e) {
322
+ _(e.message ?? String(e));
323
+ } finally {
324
+ h(!1);
325
+ }
326
+ }, E = (() => {
327
+ switch (e.publish_state) {
328
+ case "pending_review": return [{
329
+ label: "Approve",
330
+ color: "green",
331
+ variant: "solid",
332
+ onClick: () => T("approve")
333
+ }, {
334
+ label: "Reject",
335
+ color: "red",
336
+ variant: "soft",
337
+ onClick: () => C(!0),
338
+ requiresReason: !0
339
+ }];
340
+ case "auto_suppressed": return [{
341
+ label: "Approve & publish",
342
+ color: "green",
343
+ variant: "solid",
344
+ onClick: () => T("set_state", { target_state: "published" })
345
+ }, {
346
+ label: "Reject",
347
+ color: "red",
348
+ variant: "soft",
349
+ onClick: () => C(!0),
350
+ requiresReason: !0
351
+ }];
352
+ case "published": return [{
353
+ label: "Unpublish",
354
+ color: "amber",
355
+ variant: "soft",
356
+ onClick: () => T("set_state", { target_state: "unpublished" })
357
+ }, {
358
+ label: "Reject",
359
+ color: "red",
360
+ variant: "soft",
361
+ onClick: () => C(!0),
362
+ requiresReason: !0
363
+ }];
364
+ case "unpublished": return [{
365
+ label: "Republish",
366
+ color: "green",
367
+ variant: "solid",
368
+ onClick: () => T("set_state", { target_state: "published" })
369
+ }];
370
+ case "rejected": return [{
371
+ label: "Reopen for review",
372
+ color: "blue",
373
+ variant: "soft",
374
+ onClick: () => T("set_state", { target_state: "pending_review" })
375
+ }];
376
+ case "draft": return [{
377
+ label: "Submit for review",
378
+ color: "blue",
379
+ variant: "soft",
380
+ onClick: () => T("set_state", { target_state: "pending_review" })
381
+ }, {
382
+ label: "Publish",
383
+ color: "green",
384
+ variant: "solid",
385
+ onClick: () => T("set_state", { target_state: "published" })
386
+ }];
387
+ default: return [{
388
+ label: "Approve",
389
+ color: "green",
390
+ variant: "solid",
391
+ onClick: () => T("approve")
392
+ }, {
393
+ label: "Reject",
394
+ color: "red",
395
+ variant: "soft",
396
+ onClick: () => C(!0),
397
+ requiresReason: !0
398
+ }];
399
+ }
400
+ })();
401
+ return l?.matched_rules.find((e) => e.metadata?.kind === "membership"), /* @__PURE__ */ (0, y.jsx)(w, {
402
+ open: !0,
403
+ onClose: t,
404
+ onPrev: r,
405
+ onNext: i,
406
+ position: c,
407
+ title: /* @__PURE__ */ (0, y.jsxs)("div", { children: [
408
+ /* @__PURE__ */ (0, y.jsxs)("div", {
409
+ className: "flex items-center gap-2 mb-1",
410
+ children: [
411
+ /* @__PURE__ */ (0, y.jsx)(s, {
412
+ variant: "soft",
413
+ color: "blue",
414
+ className: "capitalize",
415
+ children: e.content_type
416
+ }),
417
+ e.publish_state && /* @__PURE__ */ (0, y.jsx)(s, {
418
+ variant: "soft",
419
+ color: "amber",
420
+ children: e.publish_state.replace(/_/g, " ")
421
+ }),
422
+ e.category && /* @__PURE__ */ (0, y.jsx)(s, {
423
+ variant: "soft",
424
+ color: e.category === "members" ? "green" : "gray",
425
+ children: e.category
426
+ })
427
+ ]
428
+ }),
429
+ /* @__PURE__ */ (0, y.jsx)("h2", {
430
+ className: "text-xl font-semibold truncate",
431
+ children: e.title ?? /* @__PURE__ */ (0, y.jsx)("span", {
432
+ className: "italic text-[var(--gray-10)]",
433
+ children: "untitled"
434
+ })
435
+ }),
436
+ e.subtitle && /* @__PURE__ */ (0, y.jsx)("p", {
437
+ className: "text-sm text-[var(--gray-11)] mt-1",
438
+ children: e.subtitle
439
+ })
440
+ ] }),
441
+ children: /* @__PURE__ */ (0, y.jsxs)("div", {
442
+ className: "p-6",
443
+ children: [
444
+ /* @__PURE__ */ (0, y.jsxs)("div", {
445
+ className: "flex items-start gap-4 mb-4",
446
+ children: [e.thumbnail_url && /* @__PURE__ */ (0, y.jsx)("img", {
447
+ src: e.thumbnail_url,
448
+ alt: "",
449
+ className: "w-80 h-auto max-h-80 object-contain rounded-lg bg-[var(--gray-a3)] flex-shrink-0",
450
+ onError: (e) => {
451
+ e.currentTarget.style.display = "none";
452
+ }
453
+ }), /* @__PURE__ */ (0, y.jsxs)("div", {
454
+ className: "flex-1 min-w-0 flex flex-col gap-2",
455
+ children: [E.map((e, t) => /* @__PURE__ */ (0, y.jsx)(a, {
456
+ variant: e.variant ?? "solid",
457
+ color: e.color,
458
+ onClick: e.onClick,
459
+ disabled: m,
460
+ children: m && t === 0 ? "Working…" : e.label
461
+ }, t)), e.source_url && /* @__PURE__ */ (0, y.jsx)("a", {
462
+ href: e.source_url,
463
+ target: "_blank",
464
+ rel: "noopener noreferrer",
465
+ className: "inline-flex items-center justify-center gap-1 px-3 py-1.5 rounded-md text-sm font-medium bg-[var(--gray-a3)] hover:bg-[var(--gray-a5)] text-[var(--gray-12)]",
466
+ children: "View event ↗"
467
+ })]
468
+ })]
469
+ }),
470
+ e.source_url && /* @__PURE__ */ (0, y.jsx)(o, {
471
+ className: "p-3 mb-4 text-xs text-[var(--gray-11)]",
472
+ children: /* @__PURE__ */ (0, y.jsx)("span", {
473
+ className: "break-all",
474
+ title: e.source_url,
475
+ children: e.source_url
476
+ })
477
+ }),
478
+ S && /* @__PURE__ */ (0, y.jsxs)(o, {
479
+ className: "p-3 mb-4 border border-red-500/30",
480
+ children: [
481
+ /* @__PURE__ */ (0, y.jsx)("label", {
482
+ className: "block text-xs font-medium mb-1",
483
+ children: "Rejection reason"
484
+ }),
485
+ /* @__PURE__ */ (0, y.jsx)("textarea", {
486
+ value: b,
487
+ onChange: (e) => x(e.target.value),
488
+ rows: 2,
489
+ className: "w-full px-2 py-1 text-sm border border-[var(--gray-a6)] rounded bg-[var(--color-surface)]"
490
+ }),
491
+ /* @__PURE__ */ (0, y.jsxs)("div", {
492
+ className: "flex gap-2 mt-2",
493
+ children: [/* @__PURE__ */ (0, y.jsx)(a, {
494
+ size: "1",
495
+ color: "red",
496
+ onClick: () => T("set_state", {
497
+ target_state: "rejected",
498
+ reason: b
499
+ }),
500
+ disabled: !b.trim() || m,
501
+ children: "Confirm reject"
502
+ }), /* @__PURE__ */ (0, y.jsx)(a, {
503
+ size: "1",
504
+ variant: "outline",
505
+ onClick: () => C(!1),
506
+ children: "Cancel"
507
+ })]
508
+ })
509
+ ]
510
+ }),
511
+ g && /* @__PURE__ */ (0, y.jsx)("div", {
512
+ className: "p-3 mb-4 bg-red-500/10 border border-red-500/30 rounded-md text-sm text-red-600",
513
+ children: g
514
+ }),
515
+ d ? /* @__PURE__ */ (0, y.jsx)("div", {
516
+ className: "text-sm text-[var(--gray-11)]",
517
+ children: "Loading explanation…"
518
+ }) : l && /* @__PURE__ */ (0, y.jsxs)("div", {
519
+ className: "space-y-4",
520
+ children: [/* @__PURE__ */ (0, y.jsxs)(o, {
521
+ className: "p-3",
522
+ children: [/* @__PURE__ */ (0, y.jsx)("h3", {
523
+ className: "text-sm font-semibold mb-2",
524
+ children: "Why is this here?"
525
+ }), /* @__PURE__ */ (0, y.jsxs)("ul", {
526
+ className: "text-xs text-[var(--gray-11)] space-y-2",
527
+ children: [
528
+ /* @__PURE__ */ (0, y.jsxs)("li", { children: [
529
+ /* @__PURE__ */ (0, y.jsx)("strong", { children: "Source:" }),
530
+ " ",
531
+ l.source?.source_kind ?? "unknown",
532
+ l.source?.source_ref && ` · ${l.source.source_ref}`
533
+ ] }),
534
+ l.matched_rules.filter((e) => e.metadata?.kind === "membership").length > 0 && /* @__PURE__ */ (0, y.jsxs)("li", { children: [/* @__PURE__ */ (0, y.jsxs)("strong", { children: [
535
+ "Member match",
536
+ l.matched_rules.filter((e) => e.metadata?.kind === "membership").length > 1 ? "es" : "",
537
+ ":"
538
+ ] }), /* @__PURE__ */ (0, y.jsx)("ul", {
539
+ className: "mt-1 ml-2 space-y-0.5",
540
+ children: l.matched_rules.filter((e) => e.metadata?.kind === "membership").map((e) => /* @__PURE__ */ (0, y.jsxs)("li", {
541
+ className: "flex items-center gap-1.5 flex-wrap",
542
+ children: [
543
+ /* @__PURE__ */ (0, y.jsx)(s, {
544
+ variant: "soft",
545
+ color: "green",
546
+ size: "1",
547
+ children: e.name.replace(/^Member: /, "")
548
+ }),
549
+ e.metadata?.tier && /* @__PURE__ */ (0, y.jsxs)("span", {
550
+ className: "text-[var(--gray-10)]",
551
+ children: ["tier: ", String(e.metadata.tier)]
552
+ }),
553
+ /* @__PURE__ */ (0, y.jsxs)("span", {
554
+ className: "text-[var(--gray-10)]",
555
+ children: ["— matched on ", /* @__PURE__ */ (0, y.jsx)("code", { children: e.pattern })]
556
+ })
557
+ ]
558
+ }, e.id))
559
+ })] }),
560
+ l.matched_rules.filter((e) => e.metadata?.kind !== "membership").length > 0 && /* @__PURE__ */ (0, y.jsxs)("li", { children: [/* @__PURE__ */ (0, y.jsxs)("strong", { children: [
561
+ "Keyword match",
562
+ l.matched_rules.filter((e) => e.metadata?.kind !== "membership").length > 1 ? "es" : "",
563
+ ":"
564
+ ] }), /* @__PURE__ */ (0, y.jsx)("ul", {
565
+ className: "mt-1 ml-2 space-y-0.5",
566
+ children: l.matched_rules.filter((e) => e.metadata?.kind !== "membership").map((e) => /* @__PURE__ */ (0, y.jsxs)("li", {
567
+ className: "flex items-center gap-1.5 flex-wrap",
568
+ children: [/* @__PURE__ */ (0, y.jsx)(s, {
569
+ variant: "soft",
570
+ color: "blue",
571
+ size: "1",
572
+ children: e.name
573
+ }), /* @__PURE__ */ (0, y.jsxs)("span", {
574
+ className: "text-[var(--gray-10)]",
575
+ children: ["— matched on ", /* @__PURE__ */ (0, y.jsx)("code", { children: e.pattern })]
576
+ })]
577
+ }, e.id))
578
+ })] }),
579
+ l.matched_rules.length === 0 && /* @__PURE__ */ (0, y.jsxs)("li", { children: [
580
+ /* @__PURE__ */ (0, y.jsx)("strong", { children: "No keyword or member rule matched." }),
581
+ " ",
582
+ "Category defaults to ",
583
+ /* @__PURE__ */ (0, y.jsx)("code", { children: e.category ?? "community" }),
584
+ "."
585
+ ] }),
586
+ l.keyword_verdict && /* @__PURE__ */ (0, y.jsxs)("li", {
587
+ className: "text-[var(--gray-10)]",
588
+ children: [
589
+ /* @__PURE__ */ (0, y.jsx)("strong", { children: "Verdict:" }),
590
+ " is_visible=",
591
+ String(l.keyword_verdict.is_visible),
592
+ ",",
593
+ " ",
594
+ "evaluated ",
595
+ new Date(l.keyword_verdict.evaluated_at).toLocaleString()
596
+ ]
597
+ })
598
+ ]
599
+ })]
600
+ }), l.state_history.length > 0 && /* @__PURE__ */ (0, y.jsxs)(o, {
601
+ className: "p-3",
602
+ children: [/* @__PURE__ */ (0, y.jsx)("h3", {
603
+ className: "text-sm font-semibold mb-2",
604
+ children: "State history"
605
+ }), /* @__PURE__ */ (0, y.jsx)("ul", {
606
+ className: "text-xs text-[var(--gray-11)] space-y-1",
607
+ children: l.state_history.slice(0, 10).map((e, t) => /* @__PURE__ */ (0, y.jsxs)("li", {
608
+ className: "flex items-center gap-2",
609
+ children: [
610
+ /* @__PURE__ */ (0, y.jsx)("span", {
611
+ className: "text-[var(--gray-10)] tabular-nums",
612
+ children: new Date(e.occurred_at).toLocaleString()
613
+ }),
614
+ /* @__PURE__ */ (0, y.jsxs)("span", { children: [
615
+ e.from_state ?? "∅",
616
+ " → ",
617
+ /* @__PURE__ */ (0, y.jsx)("strong", { children: e.to_state })
618
+ ] }),
619
+ /* @__PURE__ */ (0, y.jsxs)("span", {
620
+ className: "text-[var(--gray-10)]",
621
+ children: ["by ", e.actor]
622
+ })
623
+ ]
624
+ }, t))
625
+ })]
626
+ })]
627
+ })
628
+ ]
629
+ })
630
+ });
631
+ }
632
+ //#endregion
633
+ //#region ../../../gatewaze-modules/modules/content-platform/admin/pages/InboxPage.tsx
634
+ var E = "px-3 py-1.5 border border-[var(--gray-a6)] rounded-md bg-[var(--color-surface)] text-sm focus:outline-none focus:ring-2 focus:ring-[var(--accent-8)]", D = [
635
+ "pending_review",
636
+ "auto_suppressed",
637
+ "rejected",
638
+ "published",
639
+ "unpublished",
640
+ "draft"
641
+ ], O = [
642
+ "scraper",
643
+ "ai_discovery",
644
+ "admin_ui",
645
+ "api",
646
+ "mcp",
647
+ "user_submission",
648
+ "import"
649
+ ];
650
+ function k() {
651
+ let [e, t] = (0, f.useState)([]), [r, i] = (0, f.useState)(!0), [s, l] = (0, f.useState)(null), [u, p] = (0, f.useState)({
652
+ publish_state: ["pending_review", "auto_suppressed"],
653
+ time: "upcoming"
654
+ }), [h, g] = (0, f.useState)(""), [_, b] = (0, f.useState)(/* @__PURE__ */ new Set()), [x, S] = (0, f.useState)(null), [w, k] = (0, f.useState)(!1), [A, j] = (0, f.useState)(null), [M, N] = (0, f.useState)(null), [P, F] = (0, f.useState)(null), [I, L] = (0, f.useState)(!1), R = (0, f.useCallback)(async () => {
655
+ i(!0), l(null);
656
+ try {
657
+ let e = await v.list({
658
+ ...u,
659
+ search: h.trim() || void 0,
660
+ limit: 50
661
+ });
662
+ t(e.data), F(e.page.next_cursor), N(e.page.estimated_total), b(/* @__PURE__ */ new Set());
663
+ } catch (e) {
664
+ l(e.message ?? String(e));
665
+ } finally {
666
+ i(!1);
667
+ }
668
+ }, [u, h]), z = (0, f.useCallback)(async () => {
669
+ if (!(!P || I)) {
670
+ L(!0);
671
+ try {
672
+ let e = await v.list({
673
+ ...u,
674
+ search: h.trim() || void 0,
675
+ limit: 50,
676
+ cursor: P
677
+ });
678
+ t((t) => [...t, ...e.data]), F(e.page.next_cursor), e.page.estimated_total != null && N(e.page.estimated_total);
679
+ } catch (e) {
680
+ l(e.message ?? String(e));
681
+ } finally {
682
+ L(!1);
683
+ }
684
+ }
685
+ }, [
686
+ P,
687
+ I,
688
+ u,
689
+ h
690
+ ]);
691
+ (0, f.useEffect)(() => {
692
+ R();
693
+ }, [R]);
694
+ let B = (0, f.useRef)(null);
695
+ (0, f.useEffect)(() => {
696
+ let e = B.current;
697
+ if (!e) return;
698
+ let t = new IntersectionObserver((e) => {
699
+ e[0]?.isIntersecting && z();
700
+ }, { rootMargin: "200px" });
701
+ return t.observe(e), () => t.disconnect();
702
+ }, [z]);
703
+ let V = (e, t) => {
704
+ p((n) => {
705
+ let r = { ...n };
706
+ return t == null || Array.isArray(t) && t.length === 0 ? delete r[e] : r[e] = t, r;
707
+ });
708
+ }, H = (0, f.useCallback)((e) => {
709
+ b((t) => {
710
+ let n = new Set(t);
711
+ return n.has(e) ? n.delete(e) : n.add(e), n;
712
+ });
713
+ }, []), U = () => {
714
+ _.size === e.length ? b(/* @__PURE__ */ new Set()) : b(new Set(e.map((e) => e.triage_item_id)));
715
+ }, W = (0, f.useMemo)(() => e.filter((e) => _.has(e.triage_item_id)).map((e) => ({
716
+ triage_item_id: e.triage_item_id,
717
+ lifecycle_key: e.lifecycle_key
718
+ })), [e, _]), G = async (e, t = {}) => {
719
+ if (W.length !== 0) {
720
+ if (e === "reject") {
721
+ let e = prompt("Rejection reason?");
722
+ if (!e) return;
723
+ t = { reason: e };
724
+ }
725
+ if (confirm(`${e} ${W.length} item(s)?`)) {
726
+ k(!0), j(null);
727
+ try {
728
+ let n = await v.bulk(e, W, t);
729
+ j(`${e}: ${n.processed} processed, ${n.failed} failed`), await R();
730
+ } catch (e) {
731
+ j(`Error: ${e.message ?? String(e)}`);
732
+ } finally {
733
+ k(!1);
734
+ }
735
+ }
736
+ }
737
+ }, [K, q] = (0, f.useState)({
738
+ pending_review: 0,
739
+ auto_suppressed: 0,
740
+ rejected: 0
741
+ }), [J, Y] = (0, f.useState)(0);
742
+ (0, f.useEffect)(() => {
743
+ let e = !0, t = (/* @__PURE__ */ new Date(Date.now() - 6048e5)).toISOString();
744
+ return n.from("content_keyword_rules").select("id", {
745
+ count: "exact",
746
+ head: !0
747
+ }).gte("created_at", t).eq("is_active", !0).then(({ count: t }) => {
748
+ e && Y(t ?? 0);
749
+ }), () => {
750
+ e = !1;
751
+ };
752
+ }, []), (0, f.useEffect)(() => {
753
+ let e = !0;
754
+ return Promise.all([
755
+ v.list({
756
+ ...u,
757
+ publish_state: ["pending_review"],
758
+ limit: 1
759
+ }).then((e) => e.page.estimated_total ?? 0),
760
+ v.list({
761
+ ...u,
762
+ publish_state: ["auto_suppressed"],
763
+ limit: 1
764
+ }).then((e) => e.page.estimated_total ?? 0),
765
+ v.list({
766
+ ...u,
767
+ publish_state: ["rejected"],
768
+ limit: 1
769
+ }).then((e) => e.page.estimated_total ?? 0)
770
+ ]).then(([t, n, r]) => {
771
+ e && q({
772
+ pending_review: t,
773
+ auto_suppressed: n,
774
+ rejected: r
775
+ });
776
+ }).catch(() => {}), () => {
777
+ e = !1;
778
+ };
779
+ }, [
780
+ u.content_type,
781
+ u.source_kind,
782
+ u.member_only
783
+ ]);
784
+ let X = m("content-platform:inbox-tab"), Z = (0, f.useMemo)(() => [{
785
+ id: "triage",
786
+ label: "Triage",
787
+ component: null
788
+ }, ...X.map((e) => ({
789
+ id: e.registration.meta?.tabId ?? e.moduleId,
790
+ label: e.registration.meta?.label ?? e.moduleId,
791
+ component: (0, f.lazy)(e.registration.component)
792
+ }))], [X]), [Q, ee] = (0, f.useState)("triage"), $ = Z.find((e) => e.id === Q)?.component ?? null;
793
+ return /* @__PURE__ */ (0, y.jsx)(d, {
794
+ title: "Inbox",
795
+ children: /* @__PURE__ */ (0, y.jsxs)(c, {
796
+ title: "Inbox",
797
+ tabs: Z.map((e) => ({
798
+ id: e.id,
799
+ label: e.label
800
+ })),
801
+ activeTabId: Q,
802
+ onTabChange: ee,
803
+ children: [$ && Q !== "triage" ? /* @__PURE__ */ (0, y.jsx)(f.Suspense, {
804
+ fallback: /* @__PURE__ */ (0, y.jsx)("div", {
805
+ className: "p-8 text-center text-sm text-[var(--gray-11)]",
806
+ children: "Loading…"
807
+ }),
808
+ children: /* @__PURE__ */ (0, y.jsx)($, {})
809
+ }) : /* @__PURE__ */ (0, y.jsxs)(y.Fragment, { children: [
810
+ K.rejected > 0 && J > 0 && /* @__PURE__ */ (0, y.jsx)(o, {
811
+ className: "p-3 mb-4 border-l-4 border-l-amber-500 bg-amber-50 dark:bg-amber-950/20",
812
+ children: /* @__PURE__ */ (0, y.jsxs)("div", {
813
+ className: "flex items-center justify-between gap-3",
814
+ children: [/* @__PURE__ */ (0, y.jsxs)("div", {
815
+ className: "text-sm text-[var(--gray-12)]",
816
+ children: [
817
+ /* @__PURE__ */ (0, y.jsx)("strong", { children: J }),
818
+ " keyword rule",
819
+ J === 1 ? "" : "s",
820
+ " added in the last 7 days.",
821
+ " ",
822
+ /* @__PURE__ */ (0, y.jsx)("strong", { children: K.rejected }),
823
+ " rejected item",
824
+ K.rejected === 1 ? "" : "s",
825
+ " may now match. Worth re-reviewing."
826
+ ]
827
+ }), /* @__PURE__ */ (0, y.jsx)(a, {
828
+ size: "2",
829
+ variant: "soft",
830
+ onClick: () => V("publish_state", ["rejected"]),
831
+ children: "Review rejected"
832
+ })]
833
+ })
834
+ }),
835
+ /* @__PURE__ */ (0, y.jsxs)("div", {
836
+ className: "grid grid-cols-3 gap-3 mb-4",
837
+ children: [
838
+ /* @__PURE__ */ (0, y.jsxs)(o, {
839
+ className: "p-3 cursor-pointer",
840
+ onClick: () => V("publish_state", ["pending_review"]),
841
+ children: [/* @__PURE__ */ (0, y.jsx)("div", {
842
+ className: "text-xs text-[var(--gray-11)]",
843
+ children: "Pending review"
844
+ }), /* @__PURE__ */ (0, y.jsx)("div", {
845
+ className: "text-2xl font-semibold text-amber-600",
846
+ children: K.pending_review
847
+ })]
848
+ }),
849
+ /* @__PURE__ */ (0, y.jsxs)(o, {
850
+ className: "p-3 cursor-pointer",
851
+ onClick: () => V("publish_state", ["auto_suppressed"]),
852
+ children: [/* @__PURE__ */ (0, y.jsx)("div", {
853
+ className: "text-xs text-[var(--gray-11)]",
854
+ children: "Auto-suppressed"
855
+ }), /* @__PURE__ */ (0, y.jsx)("div", {
856
+ className: "text-2xl font-semibold text-gray-600",
857
+ children: K.auto_suppressed
858
+ })]
859
+ }),
860
+ /* @__PURE__ */ (0, y.jsxs)(o, {
861
+ className: "p-3 cursor-pointer",
862
+ onClick: () => V("publish_state", ["rejected"]),
863
+ children: [/* @__PURE__ */ (0, y.jsx)("div", {
864
+ className: "text-xs text-[var(--gray-11)]",
865
+ children: "Rejected"
866
+ }), /* @__PURE__ */ (0, y.jsx)("div", {
867
+ className: "text-2xl font-semibold text-red-600",
868
+ children: K.rejected
869
+ })]
870
+ })
871
+ ]
872
+ }),
873
+ /* @__PURE__ */ (0, y.jsxs)("div", {
874
+ className: "flex flex-wrap gap-2 mb-4 items-center",
875
+ children: [
876
+ /* @__PURE__ */ (0, y.jsx)("input", {
877
+ className: E,
878
+ placeholder: "Search title…",
879
+ value: h,
880
+ onChange: (e) => g(e.target.value),
881
+ onKeyDown: (e) => e.key === "Enter" && R(),
882
+ style: { minWidth: 220 }
883
+ }),
884
+ /* @__PURE__ */ (0, y.jsxs)("select", {
885
+ className: E,
886
+ value: (u.content_type ?? [""])[0] ?? "",
887
+ onChange: (e) => V("content_type", e.target.value ? [e.target.value] : void 0),
888
+ children: [
889
+ /* @__PURE__ */ (0, y.jsx)("option", {
890
+ value: "",
891
+ children: "All types"
892
+ }),
893
+ /* @__PURE__ */ (0, y.jsx)("option", {
894
+ value: "event",
895
+ children: "event"
896
+ }),
897
+ /* @__PURE__ */ (0, y.jsx)("option", {
898
+ value: "content_item",
899
+ children: "content_item"
900
+ }),
901
+ /* @__PURE__ */ (0, y.jsx)("option", {
902
+ value: "blog",
903
+ children: "blog"
904
+ }),
905
+ /* @__PURE__ */ (0, y.jsx)("option", {
906
+ value: "newsletter",
907
+ children: "newsletter"
908
+ }),
909
+ /* @__PURE__ */ (0, y.jsx)("option", {
910
+ value: "podcast",
911
+ children: "podcast"
912
+ })
913
+ ]
914
+ }),
915
+ /* @__PURE__ */ (0, y.jsxs)("select", {
916
+ className: E,
917
+ value: (u.source_kind ?? [""])[0] ?? "",
918
+ onChange: (e) => V("source_kind", e.target.value ? [e.target.value] : void 0),
919
+ children: [/* @__PURE__ */ (0, y.jsx)("option", {
920
+ value: "",
921
+ children: "All sources"
922
+ }), O.map((e) => /* @__PURE__ */ (0, y.jsx)("option", {
923
+ value: e,
924
+ children: e
925
+ }, e))]
926
+ }),
927
+ /* @__PURE__ */ (0, y.jsxs)("select", {
928
+ className: E,
929
+ value: (u.publish_state ?? [""])[0] ?? "",
930
+ onChange: (e) => V("publish_state", e.target.value ? [e.target.value] : void 0),
931
+ children: [/* @__PURE__ */ (0, y.jsx)("option", {
932
+ value: "",
933
+ children: "Pending review (default)"
934
+ }), D.map((e) => /* @__PURE__ */ (0, y.jsx)("option", {
935
+ value: e,
936
+ children: e.replace(/_/g, " ")
937
+ }, e))]
938
+ }),
939
+ /* @__PURE__ */ (0, y.jsxs)("select", {
940
+ className: E,
941
+ value: u.time ?? "upcoming",
942
+ onChange: (e) => V("time", e.target.value),
943
+ children: [
944
+ /* @__PURE__ */ (0, y.jsx)("option", {
945
+ value: "upcoming",
946
+ children: "Upcoming events (default)"
947
+ }),
948
+ /* @__PURE__ */ (0, y.jsx)("option", {
949
+ value: "past",
950
+ children: "Past events"
951
+ }),
952
+ /* @__PURE__ */ (0, y.jsx)("option", {
953
+ value: "all",
954
+ children: "All dates"
955
+ })
956
+ ]
957
+ }),
958
+ /* @__PURE__ */ (0, y.jsxs)("label", {
959
+ className: "flex items-center gap-1 text-sm",
960
+ children: [/* @__PURE__ */ (0, y.jsx)("input", {
961
+ type: "checkbox",
962
+ checked: !!u.member_only,
963
+ onChange: (e) => V("member_only", e.target.checked || void 0)
964
+ }), "Member only"]
965
+ }),
966
+ /* @__PURE__ */ (0, y.jsx)(a, {
967
+ size: "1",
968
+ variant: "ghost",
969
+ onClick: () => {
970
+ p({
971
+ publish_state: ["pending_review", "auto_suppressed"],
972
+ time: "upcoming"
973
+ }), g("");
974
+ },
975
+ children: "Reset"
976
+ })
977
+ ]
978
+ }),
979
+ _.size > 0 && /* @__PURE__ */ (0, y.jsxs)(o, {
980
+ className: "p-3 mb-4 bg-[var(--accent-a3)] flex items-center justify-between",
981
+ children: [/* @__PURE__ */ (0, y.jsxs)("div", {
982
+ className: "text-sm",
983
+ children: [
984
+ /* @__PURE__ */ (0, y.jsx)("strong", { children: _.size }),
985
+ " selected",
986
+ _.size === e.length && M && M > e.length && /* @__PURE__ */ (0, y.jsxs)("span", {
987
+ className: "ml-2 text-xs text-[var(--gray-11)]",
988
+ children: [
989
+ "(page only — estimated ",
990
+ M,
991
+ " match the filter)"
992
+ ]
993
+ })
994
+ ]
995
+ }), /* @__PURE__ */ (0, y.jsxs)("div", {
996
+ className: "flex gap-2",
997
+ children: [
998
+ /* @__PURE__ */ (0, y.jsx)(a, {
999
+ size: "1",
1000
+ onClick: () => G("approve"),
1001
+ disabled: w,
1002
+ children: "Approve"
1003
+ }),
1004
+ /* @__PURE__ */ (0, y.jsx)(a, {
1005
+ size: "1",
1006
+ variant: "soft",
1007
+ color: "red",
1008
+ onClick: () => G("reject"),
1009
+ disabled: w,
1010
+ children: "Reject"
1011
+ }),
1012
+ /* @__PURE__ */ (0, y.jsx)(a, {
1013
+ size: "1",
1014
+ variant: "ghost",
1015
+ onClick: () => b(/* @__PURE__ */ new Set()),
1016
+ children: "Clear"
1017
+ })
1018
+ ]
1019
+ })]
1020
+ }),
1021
+ A && /* @__PURE__ */ (0, y.jsx)("div", {
1022
+ className: "p-2 mb-4 bg-[var(--accent-a3)] text-sm rounded",
1023
+ children: A
1024
+ }),
1025
+ /* @__PURE__ */ (0, y.jsx)(o, { children: r ? /* @__PURE__ */ (0, y.jsx)("div", {
1026
+ className: "p-8 text-center text-sm text-[var(--gray-11)]",
1027
+ children: "Loading…"
1028
+ }) : s ? /* @__PURE__ */ (0, y.jsx)("div", {
1029
+ className: "p-8 text-center text-sm text-red-600",
1030
+ children: s
1031
+ }) : e.length === 0 ? /* @__PURE__ */ (0, y.jsx)("div", {
1032
+ className: "p-8 text-center text-sm text-[var(--gray-11)]",
1033
+ children: "Nothing to triage. New content will appear here as scrapers, AI discovery, and submissions arrive."
1034
+ }) : /* @__PURE__ */ (0, y.jsxs)("div", {
1035
+ className: "overflow-x-auto",
1036
+ children: [/* @__PURE__ */ (0, y.jsxs)("table", {
1037
+ className: "w-full",
1038
+ children: [/* @__PURE__ */ (0, y.jsx)("thead", {
1039
+ className: "border-b border-[var(--gray-a4)]",
1040
+ children: /* @__PURE__ */ (0, y.jsxs)("tr", {
1041
+ className: "text-left text-xs text-[var(--gray-11)]",
1042
+ children: [
1043
+ /* @__PURE__ */ (0, y.jsx)("th", {
1044
+ className: "px-3 py-2 w-10",
1045
+ children: /* @__PURE__ */ (0, y.jsx)("input", {
1046
+ type: "checkbox",
1047
+ checked: _.size === e.length && e.length > 0,
1048
+ onChange: U
1049
+ })
1050
+ }),
1051
+ /* @__PURE__ */ (0, y.jsx)("th", {
1052
+ className: "px-3 py-2",
1053
+ children: "Type"
1054
+ }),
1055
+ /* @__PURE__ */ (0, y.jsx)("th", {
1056
+ className: "px-3 py-2",
1057
+ children: "Title"
1058
+ }),
1059
+ /* @__PURE__ */ (0, y.jsx)("th", {
1060
+ className: "px-3 py-2",
1061
+ children: "Matched"
1062
+ }),
1063
+ /* @__PURE__ */ (0, y.jsx)("th", {
1064
+ className: "px-3 py-2",
1065
+ children: "Category"
1066
+ }),
1067
+ /* @__PURE__ */ (0, y.jsx)("th", {
1068
+ className: "px-3 py-2",
1069
+ children: "Status"
1070
+ }),
1071
+ /* @__PURE__ */ (0, y.jsx)("th", {
1072
+ className: "px-3 py-2",
1073
+ children: "Age"
1074
+ })
1075
+ ]
1076
+ })
1077
+ }), /* @__PURE__ */ (0, y.jsx)("tbody", { children: e.map((e) => /* @__PURE__ */ (0, y.jsx)(C, {
1078
+ row: e,
1079
+ selected: _.has(e.triage_item_id),
1080
+ onToggleSelect: () => H(e.triage_item_id),
1081
+ onOpenDrawer: () => S(e),
1082
+ onSourceFilter: (e) => V("source_kind", [e])
1083
+ }, e.triage_item_id)) })]
1084
+ }), /* @__PURE__ */ (0, y.jsx)("div", {
1085
+ ref: B,
1086
+ className: "px-3 py-3 text-center text-xs text-[var(--gray-11)]",
1087
+ children: I ? "Loading more…" : P ? `Loaded ${e.length} of ${M ?? "?"}…` : e.length === (M ?? e.length) ? `All ${e.length} loaded` : ""
1088
+ })]
1089
+ }) })
1090
+ ] }), x && (() => {
1091
+ let t = e.findIndex((e) => e.triage_item_id === x.triage_item_id), n = t > 0 ? e[t - 1] : null, r = t >= 0 && t < e.length - 1 ? e[t + 1] : null, i = M ?? e.length;
1092
+ return /* @__PURE__ */ (0, y.jsx)(T, {
1093
+ row: x,
1094
+ onClose: () => S(null),
1095
+ onActed: () => {
1096
+ r ? (S(r), R()) : P ? (z().then(() => {}), S(null)) : (S(null), R());
1097
+ },
1098
+ onPrev: n ? () => S(n) : void 0,
1099
+ onNext: r ? () => S(r) : P ? async () => {
1100
+ await z();
1101
+ } : void 0,
1102
+ position: t >= 0 ? {
1103
+ current: t,
1104
+ total: i
1105
+ } : void 0
1106
+ });
1107
+ })()]
1108
+ })
1109
+ });
1110
+ }
1111
+ //#endregion
1112
+ export { k as default };