@burdenoff/microfe-admin 2026.608.1 → 2026.624.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.
Files changed (80) hide show
  1. package/dist/admin/AdminRoutes.js +14 -10
  2. package/dist/admin/AdminRoutes.js.map +1 -1
  3. package/dist/admin/components/AccessDenied.js +2 -2
  4. package/dist/admin/components/AccessDenied.js.map +1 -1
  5. package/dist/admin/components/ActivityFeed.js +4 -4
  6. package/dist/admin/components/ActivityFeed.js.map +1 -1
  7. package/dist/admin/components/Charts.js +4 -4
  8. package/dist/admin/components/Charts.js.map +1 -1
  9. package/dist/admin/components/ConfirmDialog.js +44 -25
  10. package/dist/admin/components/ConfirmDialog.js.map +1 -1
  11. package/dist/admin/components/DataTable.js +7 -7
  12. package/dist/admin/components/DataTable.js.map +1 -1
  13. package/dist/admin/components/FormSheet.js +7 -7
  14. package/dist/admin/components/FormSheet.js.map +1 -1
  15. package/dist/admin/components/MetricCard.js +4 -4
  16. package/dist/admin/components/MetricCard.js.map +1 -1
  17. package/dist/admin/components/PageLayout.js +3 -3
  18. package/dist/admin/components/PageLayout.js.map +1 -1
  19. package/dist/admin/components/PermissionGuard.js +1 -1
  20. package/dist/admin/components/PermissionGuard.js.map +1 -1
  21. package/dist/admin/components/RowActions.js +2 -2
  22. package/dist/admin/components/RowActions.js.map +1 -1
  23. package/dist/admin/components/TenantMembersPanel.js +15 -15
  24. package/dist/admin/components/TenantMembersPanel.js.map +1 -1
  25. package/dist/admin/components/TenantSsoPanel.js +14 -14
  26. package/dist/admin/components/TenantSsoPanel.js.map +1 -1
  27. package/dist/admin/components/Toast.js +9 -9
  28. package/dist/admin/components/Toast.js.map +1 -1
  29. package/dist/admin/components/forms/SubscriptionForm.js +10 -10
  30. package/dist/admin/components/forms/SubscriptionForm.js.map +1 -1
  31. package/dist/admin/components/forms/TenantForm.js +8 -8
  32. package/dist/admin/components/forms/TenantForm.js.map +1 -1
  33. package/dist/admin/components/forms/TicketForm.js +2 -2
  34. package/dist/admin/components/forms/TicketForm.js.map +1 -1
  35. package/dist/admin/components/forms/UserForm.js +8 -8
  36. package/dist/admin/components/forms/UserForm.js.map +1 -1
  37. package/dist/admin/components/ui.js +16 -16
  38. package/dist/admin/components/ui.js.map +1 -1
  39. package/dist/admin/constants/index.js +8 -8
  40. package/dist/admin/constants/index.js.map +1 -1
  41. package/dist/admin/pages/AuditLogsPage.js +8 -8
  42. package/dist/admin/pages/AuditLogsPage.js.map +1 -1
  43. package/dist/admin/pages/CommunicationsPage.js +2 -2
  44. package/dist/admin/pages/CommunicationsPage.js.map +1 -1
  45. package/dist/admin/pages/ContentPagesPage.js +661 -0
  46. package/dist/admin/pages/ContentPagesPage.js.map +1 -0
  47. package/dist/admin/pages/FeatureFlagsPage.js +4 -4
  48. package/dist/admin/pages/FeatureFlagsPage.js.map +1 -1
  49. package/dist/admin/pages/OrganizationsListPage.js +6 -6
  50. package/dist/admin/pages/OrganizationsListPage.js.map +1 -1
  51. package/dist/admin/pages/ProductsPage.js +7 -7
  52. package/dist/admin/pages/ProductsPage.js.map +1 -1
  53. package/dist/admin/pages/ReferralsPage.js +23 -23
  54. package/dist/admin/pages/ReferralsPage.js.map +1 -1
  55. package/dist/admin/pages/RolesPermissionsPage.js +8 -8
  56. package/dist/admin/pages/RolesPermissionsPage.js.map +1 -1
  57. package/dist/admin/pages/SREPage.js +8 -8
  58. package/dist/admin/pages/SREPage.js.map +1 -1
  59. package/dist/admin/pages/SandboxSettingsPage.js +20 -20
  60. package/dist/admin/pages/SandboxSettingsPage.js.map +1 -1
  61. package/dist/admin/pages/SettingsPage.js +20 -20
  62. package/dist/admin/pages/SettingsPage.js.map +1 -1
  63. package/dist/admin/pages/SyncFailuresPage.js +11 -11
  64. package/dist/admin/pages/SyncFailuresPage.js.map +1 -1
  65. package/dist/admin/pages/TenantDetailPage.js +22 -22
  66. package/dist/admin/pages/TenantDetailPage.js.map +1 -1
  67. package/dist/admin/pages/TenantFormRoutePage.js +2 -2
  68. package/dist/admin/pages/TenantFormRoutePage.js.map +1 -1
  69. package/dist/admin/pages/TenantsListPage.js +5 -5
  70. package/dist/admin/pages/TenantsListPage.js.map +1 -1
  71. package/dist/admin/pages/UsersListPage.js +6 -6
  72. package/dist/admin/pages/UsersListPage.js.map +1 -1
  73. package/dist/admin/pages/WaitlistPage.js +7 -7
  74. package/dist/admin/pages/WaitlistPage.js.map +1 -1
  75. package/dist/admin/pages/WorkflowsPage.js +3 -3
  76. package/dist/admin/pages/WorkflowsPage.js.map +1 -1
  77. package/dist/admin/pages/WorkspacesListPage.js +8 -8
  78. package/dist/admin/pages/WorkspacesListPage.js.map +1 -1
  79. package/dist/admin/pages/index.js +1 -0
  80. package/package.json +1 -1
@@ -0,0 +1,661 @@
1
+ import { useToast as e } from "../components/Toast.js";
2
+ import { useAdminPermissions as t } from "../hooks/useAdminPermissions.js";
3
+ import { Badge as n, Button as r, EmptyState as i, Input as a } from "../components/ui.js";
4
+ import { PageLayout as ee } from "../components/PageLayout.js";
5
+ import { formatDate as te } from "../utils/formatters.js";
6
+ import { DataTable as ne, Pagination as re } from "../components/DataTable.js";
7
+ import { FormRow as o, FormSection as s, FormSheet as ie, FormSheetFooter as ae } from "../components/FormSheet.js";
8
+ import { DeleteConfirmDialog as oe } from "../components/ConfirmDialog.js";
9
+ import { RowActions as se, createRowActions as ce } from "../components/RowActions.js";
10
+ import { PermissionGuard as le } from "../components/PermissionGuard.js";
11
+ import "../components/index.js";
12
+ import { useCallback as c, useEffect as l, useRef as ue, useState as u } from "react";
13
+ import { FileText as de, Plus as fe, Search as pe } from "lucide-react";
14
+ import { jsx as d, jsxs as f } from "react/jsx-runtime";
15
+ import { gql as p } from "@apollo/client";
16
+ import { useApolloClient as me } from "@apollo/client/react";
17
+ //#region src/admin/pages/ContentPagesPage.tsx
18
+ var m = 20, h = [
19
+ {
20
+ value: "blog",
21
+ label: "Blog",
22
+ category: "Blog"
23
+ },
24
+ {
25
+ value: "case-study",
26
+ label: "Case Study",
27
+ category: "Case Study"
28
+ },
29
+ {
30
+ value: "changelog",
31
+ label: "Changelog",
32
+ category: "Changelog"
33
+ }
34
+ ], he = {
35
+ blog: "default",
36
+ "case-study": "secondary",
37
+ changelog: "outline"
38
+ }, g = p`
39
+ query AdminContentListProducts($limit: Int, $offset: Int) {
40
+ platformProducts(limit: $limit, offset: $offset) {
41
+ items {
42
+ id
43
+ name
44
+ slug
45
+ }
46
+ }
47
+ }
48
+ `, ge = p`
49
+ query AdminContentPages(
50
+ $productId: String
51
+ $filter: ContentPageFilterInput
52
+ $limit: Int
53
+ $offset: Int
54
+ ) {
55
+ contentPages(productId: $productId, filter: $filter, limit: $limit, offset: $offset) {
56
+ items {
57
+ id
58
+ productId
59
+ slug
60
+ title
61
+ content
62
+ contentFormat
63
+ tags
64
+ category
65
+ excerpt
66
+ thumbnail
67
+ author
68
+ publishedAt
69
+ readingTime
70
+ featured
71
+ isPublished
72
+ visibility
73
+ updatedAt
74
+ }
75
+ total
76
+ }
77
+ }
78
+ `, _e = p`
79
+ mutation AdminCreateContentPage($input: CreateContentPageInput!) {
80
+ createContentPage(input: $input) {
81
+ id
82
+ slug
83
+ }
84
+ }
85
+ `, ve = p`
86
+ mutation AdminUpdateContentPage($id: ID!, $input: UpdateContentPageInput!) {
87
+ updateContentPage(id: $id, input: $input) {
88
+ id
89
+ slug
90
+ }
91
+ }
92
+ `, ye = p`
93
+ mutation AdminDeleteContentPage($id: ID!) {
94
+ deleteContentPage(id: $id)
95
+ }
96
+ `, _ = {
97
+ productId: "",
98
+ type: "blog",
99
+ slug: "",
100
+ title: "",
101
+ excerpt: "",
102
+ content: "",
103
+ author: "",
104
+ publishedAt: "",
105
+ thumbnail: "",
106
+ readingTime: "",
107
+ featured: !1,
108
+ isPublished: !0
109
+ };
110
+ function v(e) {
111
+ return e.includes("changelog") ? "changelog" : e.includes("case-study") ? "case-study" : "blog";
112
+ }
113
+ var y = "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:opacity-50";
114
+ function b() {
115
+ let { canViewProducts: p, canManageProducts: b, isLoading: x } = t(), S = me(), C = e(), [w, be] = u([]), [T, E] = u(""), [D, xe] = u(""), [O, Se] = u(""), [k, A] = u(""), [j, M] = u(1), N = ue(0);
116
+ l(() => {
117
+ let e = setTimeout(() => {
118
+ A(O), M(1);
119
+ }, 300);
120
+ return () => clearTimeout(e);
121
+ }, [O]);
122
+ let [P, Ce] = u([]), [F, we] = u(0), [Te, I] = u(!1), [L, R] = u(null), [Ee, z] = u(!1), [B, V] = u(null), [H, U] = u(_), [De, W] = u(!1), [G, K] = u(null), [q, J] = u(!1), Y = x || !p;
123
+ l(() => {
124
+ if (Y) return;
125
+ let e = !0;
126
+ return S.query({
127
+ query: g,
128
+ variables: {
129
+ limit: 100,
130
+ offset: 0
131
+ },
132
+ fetchPolicy: "network-only"
133
+ }).then((t) => {
134
+ if (!e) return;
135
+ let n = t.data?.platformProducts?.items ?? [];
136
+ be(n), E((e) => e || n[0]?.id || "");
137
+ }).catch((t) => {
138
+ e && R(t instanceof Error ? t.message : "Failed to load products");
139
+ }), () => {
140
+ e = !1;
141
+ };
142
+ }, [S, Y]);
143
+ let X = c(async () => {
144
+ if (Y || !T) return;
145
+ let e = ++N.current;
146
+ I(!0);
147
+ try {
148
+ let t = await S.query({
149
+ query: ge,
150
+ variables: {
151
+ productId: T,
152
+ filter: {
153
+ ...k ? { search: k } : {},
154
+ ...D ? { tag: D } : {}
155
+ },
156
+ limit: m,
157
+ offset: (j - 1) * m
158
+ },
159
+ fetchPolicy: "network-only"
160
+ });
161
+ if (e !== N.current) return;
162
+ Ce(t.data?.contentPages?.items ?? []), we(t.data?.contentPages?.total ?? 0), R(null);
163
+ } catch (t) {
164
+ if (e !== N.current) return;
165
+ R(t instanceof Error ? t.message : "Failed to load content pages");
166
+ } finally {
167
+ e === N.current && I(!1);
168
+ }
169
+ }, [
170
+ S,
171
+ Y,
172
+ T,
173
+ k,
174
+ D,
175
+ j
176
+ ]);
177
+ l(() => {
178
+ X();
179
+ }, [X]);
180
+ let Z = Math.ceil(F / m), Oe = c(() => {
181
+ V(null), U({
182
+ ..._,
183
+ productId: T,
184
+ type: D || "blog"
185
+ }), z(!0);
186
+ }, [T, D]), ke = c((e) => {
187
+ V(e), U({
188
+ productId: e.productId ?? "",
189
+ type: v(e.tags),
190
+ slug: e.slug,
191
+ title: e.title,
192
+ excerpt: e.excerpt ?? "",
193
+ content: e.content,
194
+ author: e.author ?? "",
195
+ publishedAt: e.publishedAt ? e.publishedAt.slice(0, 10) : "",
196
+ thumbnail: e.thumbnail ?? "",
197
+ readingTime: e.readingTime == null ? "" : String(e.readingTime),
198
+ featured: e.featured,
199
+ isPublished: e.isPublished
200
+ }), z(!0);
201
+ }, []), Ae = c(async () => {
202
+ let e = [
203
+ !H.title.trim() && "Title",
204
+ !H.slug.trim() && "Slug",
205
+ !H.content.trim() && "Content"
206
+ ].filter(Boolean);
207
+ if (e.length) {
208
+ C.error(`${e.join(", ")} ${e.length > 1 ? "are" : "is"} required`);
209
+ return;
210
+ }
211
+ let t = H.thumbnail.trim();
212
+ if (t && !/^(https?:\/\/|\/\/|\/)/i.test(t)) {
213
+ C.error("Thumbnail must be an http(s) URL or an absolute path");
214
+ return;
215
+ }
216
+ W(!0);
217
+ let n = h.find((e) => e.value === H.type), r = B ? null : void 0, i = {
218
+ title: H.title.trim(),
219
+ content: H.content,
220
+ contentFormat: "markdown",
221
+ excerpt: H.excerpt.trim() || r,
222
+ author: H.author.trim() || r,
223
+ publishedAt: H.publishedAt ? new Date(H.publishedAt).toISOString() : r,
224
+ thumbnail: H.thumbnail.trim() || r,
225
+ readingTime: H.readingTime === "" ? r : Number(H.readingTime),
226
+ featured: H.featured,
227
+ isPublished: H.isPublished
228
+ };
229
+ try {
230
+ B ? (await S.mutate({
231
+ mutation: ve,
232
+ variables: {
233
+ id: B.id,
234
+ input: i
235
+ }
236
+ }), C.success("Content page updated")) : (await S.mutate({
237
+ mutation: _e,
238
+ variables: { input: {
239
+ ...i,
240
+ visibility: "PUBLIC",
241
+ tags: [H.type],
242
+ category: n.category,
243
+ productId: H.productId || void 0,
244
+ slug: H.slug.trim().replace(/-+/g, "-").replace(/^-+|-+$/g, "")
245
+ } }
246
+ }), C.success("Content page created")), z(!1), await X();
247
+ } catch (e) {
248
+ C.error(e instanceof Error ? e.message : "Failed to save content page");
249
+ } finally {
250
+ W(!1);
251
+ }
252
+ }, [
253
+ H,
254
+ B,
255
+ S,
256
+ C,
257
+ X
258
+ ]), je = c(async () => {
259
+ if (!(!G || q)) {
260
+ J(!0);
261
+ try {
262
+ await S.mutate({
263
+ mutation: ye,
264
+ variables: { id: G.id }
265
+ }), C.success("Content page deleted"), K(null), P.length === 1 && j > 1 ? M((e) => e - 1) : await X();
266
+ } catch (e) {
267
+ C.error(e instanceof Error ? e.message : "Failed to delete content page");
268
+ } finally {
269
+ J(!1);
270
+ }
271
+ }
272
+ }, [
273
+ G,
274
+ q,
275
+ S,
276
+ C,
277
+ X,
278
+ P.length,
279
+ j
280
+ ]), Me = [
281
+ {
282
+ key: "title",
283
+ header: "Title",
284
+ render: (e) => /* @__PURE__ */ f("div", {
285
+ className: "min-w-0",
286
+ children: [/* @__PURE__ */ d("div", {
287
+ className: "font-medium text-foreground",
288
+ children: e.title
289
+ }), /* @__PURE__ */ d("div", {
290
+ className: "truncate text-xs text-muted-foreground",
291
+ children: e.slug
292
+ })]
293
+ })
294
+ },
295
+ {
296
+ key: "type",
297
+ header: "Type",
298
+ width: "120px",
299
+ render: (e) => {
300
+ let t = h.find((t) => e.tags.includes(t.value));
301
+ return /* @__PURE__ */ d(n, {
302
+ variant: t ? he[t.value] : "outline",
303
+ className: "text-xs capitalize",
304
+ children: t?.label ?? "Other"
305
+ });
306
+ }
307
+ },
308
+ {
309
+ key: "status",
310
+ header: "Status",
311
+ width: "110px",
312
+ render: (e) => /* @__PURE__ */ f("div", {
313
+ className: "flex items-center gap-1",
314
+ children: [/* @__PURE__ */ d(n, {
315
+ variant: e.isPublished ? "default" : "outline",
316
+ className: "text-xs",
317
+ children: e.isPublished ? "Published" : "Draft"
318
+ }), e.featured && /* @__PURE__ */ d(n, {
319
+ variant: "secondary",
320
+ className: "text-xs",
321
+ children: "Featured"
322
+ })]
323
+ })
324
+ },
325
+ {
326
+ key: "updatedAt",
327
+ header: "Updated",
328
+ width: "110px",
329
+ render: (e) => te(e.updatedAt)
330
+ },
331
+ {
332
+ key: "actions",
333
+ header: "",
334
+ width: "60px",
335
+ align: "right",
336
+ render: (e) => /* @__PURE__ */ d(se, { actions: ce({
337
+ onEdit: b ? () => ke(e) : void 0,
338
+ onDelete: b ? () => K(e) : void 0
339
+ }) })
340
+ }
341
+ ], Q = "content-page-form", $ = !!B && !h.some((e) => B.tags.includes(e.value));
342
+ return /* @__PURE__ */ f(le, {
343
+ allowed: p,
344
+ isLoading: x,
345
+ pageTitle: "Content",
346
+ denyMessage: "You don't have permission to manage content pages.",
347
+ children: [
348
+ /* @__PURE__ */ d(ee, {
349
+ title: "Content",
350
+ description: `Blog posts, case studies, and changelog entries${F ? ` · ${F} total` : ""}`,
351
+ actions: /* @__PURE__ */ f(r, {
352
+ onClick: Oe,
353
+ disabled: !b || !T,
354
+ children: [/* @__PURE__ */ d(fe, { className: "mr-2 h-4 w-4" }), "New Content"]
355
+ }),
356
+ children: /* @__PURE__ */ f("div", {
357
+ className: "space-y-4",
358
+ children: [
359
+ /* @__PURE__ */ f("div", {
360
+ className: "flex flex-wrap items-center gap-3",
361
+ children: [
362
+ /* @__PURE__ */ f("select", {
363
+ "aria-label": "Filter by product",
364
+ className: `${y} max-w-xs`,
365
+ value: T,
366
+ onChange: (e) => {
367
+ M(1), E(e.target.value);
368
+ },
369
+ children: [w.length === 0 && /* @__PURE__ */ d("option", {
370
+ value: "",
371
+ children: "Loading products…"
372
+ }), w.map((e) => /* @__PURE__ */ d("option", {
373
+ value: e.id,
374
+ children: e.name
375
+ }, e.id))]
376
+ }),
377
+ /* @__PURE__ */ f("select", {
378
+ "aria-label": "Filter by content type",
379
+ className: `${y} max-w-[180px]`,
380
+ value: D,
381
+ onChange: (e) => {
382
+ M(1), xe(e.target.value);
383
+ },
384
+ children: [/* @__PURE__ */ d("option", {
385
+ value: "",
386
+ children: "All types"
387
+ }), h.map((e) => /* @__PURE__ */ d("option", {
388
+ value: e.value,
389
+ children: e.label
390
+ }, e.value))]
391
+ }),
392
+ /* @__PURE__ */ f("div", {
393
+ className: "relative max-w-sm flex-1",
394
+ children: [/* @__PURE__ */ d(pe, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), /* @__PURE__ */ d(a, {
395
+ placeholder: "Search content...",
396
+ value: O,
397
+ onChange: (e) => Se(e.target.value),
398
+ className: "pl-9"
399
+ })]
400
+ })
401
+ ]
402
+ }),
403
+ L && /* @__PURE__ */ d("div", {
404
+ className: "rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive",
405
+ children: L
406
+ }),
407
+ /* @__PURE__ */ d(ne, {
408
+ columns: Me,
409
+ data: P,
410
+ keyExtractor: (e) => e.id,
411
+ loading: Te,
412
+ emptyState: /* @__PURE__ */ d(i, {
413
+ icon: /* @__PURE__ */ d(de, { className: "h-8 w-8" }),
414
+ title: "No content yet",
415
+ description: "Create a blog post, case study, or changelog entry to get started."
416
+ })
417
+ }),
418
+ F > m && /* @__PURE__ */ d(re, {
419
+ page: j,
420
+ totalPages: Z,
421
+ totalItems: F,
422
+ pageSize: m,
423
+ onPageChange: M
424
+ })
425
+ ]
426
+ })
427
+ }),
428
+ /* @__PURE__ */ d(ie, {
429
+ open: Ee,
430
+ onClose: () => z(!1),
431
+ title: B ? "Edit content" : "New content",
432
+ footer: /* @__PURE__ */ d(ae, {
433
+ formId: Q,
434
+ isSubmitting: De,
435
+ submitLabel: B ? "Save changes" : "Create",
436
+ onCancel: () => z(!1)
437
+ }),
438
+ children: /* @__PURE__ */ f("form", {
439
+ id: Q,
440
+ onSubmit: (e) => {
441
+ e.preventDefault(), Ae();
442
+ },
443
+ className: "space-y-6",
444
+ children: [
445
+ /* @__PURE__ */ f(s, {
446
+ title: "Basics",
447
+ children: [
448
+ /* @__PURE__ */ f(o, {
449
+ cols: 2,
450
+ children: [/* @__PURE__ */ f("label", {
451
+ className: "space-y-1.5",
452
+ children: [/* @__PURE__ */ d("span", {
453
+ className: "text-sm font-medium",
454
+ children: "Type"
455
+ }), /* @__PURE__ */ f("select", {
456
+ className: y,
457
+ value: $ ? "__other" : H.type,
458
+ disabled: !!B,
459
+ onChange: (e) => U((t) => ({
460
+ ...t,
461
+ type: e.target.value
462
+ })),
463
+ children: [$ && /* @__PURE__ */ d("option", {
464
+ value: "__other",
465
+ children: "Other"
466
+ }), h.map((e) => /* @__PURE__ */ d("option", {
467
+ value: e.value,
468
+ children: e.label
469
+ }, e.value))]
470
+ })]
471
+ }), /* @__PURE__ */ f("label", {
472
+ className: "space-y-1.5",
473
+ children: [/* @__PURE__ */ d("span", {
474
+ className: "text-sm font-medium",
475
+ children: "Product"
476
+ }), /* @__PURE__ */ d("select", {
477
+ className: y,
478
+ value: H.productId,
479
+ disabled: !!B,
480
+ onChange: (e) => U((t) => ({
481
+ ...t,
482
+ productId: e.target.value
483
+ })),
484
+ children: w.map((e) => /* @__PURE__ */ d("option", {
485
+ value: e.id,
486
+ children: e.name
487
+ }, e.id))
488
+ })]
489
+ })]
490
+ }),
491
+ /* @__PURE__ */ f(o, {
492
+ cols: 2,
493
+ children: [/* @__PURE__ */ f("label", {
494
+ className: "space-y-1.5",
495
+ children: [/* @__PURE__ */ d("span", {
496
+ className: "text-sm font-medium",
497
+ children: "Title"
498
+ }), /* @__PURE__ */ d(a, {
499
+ value: H.title,
500
+ onChange: (e) => U((t) => ({
501
+ ...t,
502
+ title: e.target.value
503
+ })),
504
+ placeholder: "A clear, descriptive title"
505
+ })]
506
+ }), /* @__PURE__ */ f("label", {
507
+ className: "space-y-1.5",
508
+ children: [/* @__PURE__ */ d("span", {
509
+ className: "text-sm font-medium",
510
+ children: "Slug"
511
+ }), /* @__PURE__ */ d(a, {
512
+ value: H.slug,
513
+ disabled: !!B,
514
+ onChange: (e) => U((t) => ({
515
+ ...t,
516
+ slug: e.target.value.toLowerCase().replace(/[^a-z0-9-]+/g, "-")
517
+ })),
518
+ placeholder: "url-friendly-slug"
519
+ })]
520
+ })]
521
+ }),
522
+ /* @__PURE__ */ f("label", {
523
+ className: "block space-y-1.5",
524
+ children: [/* @__PURE__ */ d("span", {
525
+ className: "text-sm font-medium",
526
+ children: "Excerpt"
527
+ }), /* @__PURE__ */ d("textarea", {
528
+ className: `${y} h-16 py-2`,
529
+ value: H.excerpt,
530
+ onChange: (e) => U((t) => ({
531
+ ...t,
532
+ excerpt: e.target.value
533
+ })),
534
+ placeholder: "Short summary shown in cards and previews"
535
+ })]
536
+ })
537
+ ]
538
+ }),
539
+ /* @__PURE__ */ d(s, {
540
+ title: "Content",
541
+ description: "Markdown supported (headings, lists, links, bold).",
542
+ children: /* @__PURE__ */ d("textarea", {
543
+ "aria-label": "Content",
544
+ className: `${y} h-64 py-2 font-mono text-xs`,
545
+ value: H.content,
546
+ onChange: (e) => U((t) => ({
547
+ ...t,
548
+ content: e.target.value
549
+ })),
550
+ placeholder: "## Heading\n\nWrite your content in markdown..."
551
+ })
552
+ }),
553
+ /* @__PURE__ */ f(s, {
554
+ title: "Meta",
555
+ children: [
556
+ /* @__PURE__ */ f(o, {
557
+ cols: 3,
558
+ children: [
559
+ /* @__PURE__ */ f("label", {
560
+ className: "space-y-1.5",
561
+ children: [/* @__PURE__ */ d("span", {
562
+ className: "text-sm font-medium",
563
+ children: "Author"
564
+ }), /* @__PURE__ */ d(a, {
565
+ value: H.author,
566
+ onChange: (e) => U((t) => ({
567
+ ...t,
568
+ author: e.target.value
569
+ })),
570
+ placeholder: "The Team"
571
+ })]
572
+ }),
573
+ /* @__PURE__ */ f("label", {
574
+ className: "space-y-1.5",
575
+ children: [/* @__PURE__ */ d("span", {
576
+ className: "text-sm font-medium",
577
+ children: "Published date"
578
+ }), /* @__PURE__ */ d(a, {
579
+ type: "date",
580
+ value: H.publishedAt,
581
+ onChange: (e) => U((t) => ({
582
+ ...t,
583
+ publishedAt: e.target.value
584
+ }))
585
+ })]
586
+ }),
587
+ /* @__PURE__ */ f("label", {
588
+ className: "space-y-1.5",
589
+ children: [/* @__PURE__ */ d("span", {
590
+ className: "text-sm font-medium",
591
+ children: "Reading time (min)"
592
+ }), /* @__PURE__ */ d(a, {
593
+ type: "number",
594
+ min: 0,
595
+ value: H.readingTime,
596
+ onChange: (e) => U((t) => ({
597
+ ...t,
598
+ readingTime: e.target.value
599
+ }))
600
+ })]
601
+ })
602
+ ]
603
+ }),
604
+ /* @__PURE__ */ f("label", {
605
+ className: "block space-y-1.5",
606
+ children: [/* @__PURE__ */ d("span", {
607
+ className: "text-sm font-medium",
608
+ children: "Thumbnail URL"
609
+ }), /* @__PURE__ */ d(a, {
610
+ value: H.thumbnail,
611
+ onChange: (e) => U((t) => ({
612
+ ...t,
613
+ thumbnail: e.target.value
614
+ })),
615
+ placeholder: "https://…/image.png"
616
+ })]
617
+ }),
618
+ /* @__PURE__ */ f("div", {
619
+ className: "flex items-center gap-6 pt-1",
620
+ children: [/* @__PURE__ */ f("label", {
621
+ className: "flex items-center gap-2 text-sm",
622
+ children: [/* @__PURE__ */ d("input", {
623
+ type: "checkbox",
624
+ checked: H.featured,
625
+ onChange: (e) => U((t) => ({
626
+ ...t,
627
+ featured: e.target.checked
628
+ }))
629
+ }), "Featured"]
630
+ }), /* @__PURE__ */ f("label", {
631
+ className: "flex items-center gap-2 text-sm",
632
+ children: [/* @__PURE__ */ d("input", {
633
+ type: "checkbox",
634
+ checked: H.isPublished,
635
+ onChange: (e) => U((t) => ({
636
+ ...t,
637
+ isPublished: e.target.checked
638
+ }))
639
+ }), "Published"]
640
+ })]
641
+ })
642
+ ]
643
+ })
644
+ ]
645
+ })
646
+ }),
647
+ /* @__PURE__ */ d(oe, {
648
+ open: !!G,
649
+ onClose: () => K(null),
650
+ onConfirm: je,
651
+ itemName: G?.title ?? "this content page",
652
+ itemType: "content page",
653
+ loading: q
654
+ })
655
+ ]
656
+ });
657
+ }
658
+ //#endregion
659
+ export { b as ContentPagesPage };
660
+
661
+ //# sourceMappingURL=ContentPagesPage.js.map