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