@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,1197 @@
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 "./jsx-runtime-CjozyJt-.js";
4
+ import { E as i, d as a, f as o, l as s, n as c, u as l } from "./ui-DRIo9Krs.js";
5
+ import { n as u, t as d } from "./NewsletterCanvasEditor--B06apn3.js";
6
+ import { n as f, t as ee } from "./export-edition-html-C_hdXQu5.js";
7
+ import { a as te, s as ne } from "./hooks-C377EXJG.js";
8
+ import { n as p } from "./lib-CylJmhlJ.js";
9
+ import { n as m } from "./sonnerHostBridge-CXuCMM3R.js";
10
+ import { i as h, t as g } from "./storage-VDSvnkvR.js";
11
+ import "./src-BWDAOzZO.js";
12
+ import { t as _ } from "./outline-DwDYhYcF.js";
13
+ import { t as v } from "./Page-D3u8IZ2a.js";
14
+ import { r as y } from "./EditionEmail-CyhC8232.js";
15
+ import { t as b } from "./useModuleFeature-DgsFIUpv.js";
16
+ import { t as x } from "./contentAccessService-Cs7tdAo-.js";
17
+ import { t as S } from "./edition-slug-CARO24Bs.js";
18
+ //#region src/components/content-access/ContentAccessControl.tsx
19
+ var C = _(), w = /* @__PURE__ */ e(t()), T = r();
20
+ function E({ contentType: e, entityId: t, status: n, onStatusChange: r, draftValue: o = "draft", publishedValue: c = "published", className: u }) {
21
+ let d = e === "event", f = e === "newsletter_edition", ee = d ? "Registration" : "Who can see this", [te, ne] = (0, w.useState)(!0), [p, m] = (0, w.useState)([]), [h, g] = (0, w.useState)("everyone"), [_, v] = (0, w.useState)(0), [y, b] = (0, w.useState)("minimum"), [S, C] = (0, w.useState)([]), [E, D] = (0, w.useState)(30), [O, k] = (0, w.useState)("idle"), [A, j] = (0, w.useState)(null);
22
+ (0, w.useEffect)(() => {
23
+ let n = !0;
24
+ return (async () => {
25
+ try {
26
+ let [r, i] = await Promise.all([x.listTiers(), x.getPolicy(e, t)]);
27
+ if (!n) return;
28
+ m(r), M(i);
29
+ } catch (e) {
30
+ n && j(e.message);
31
+ } finally {
32
+ n && ne(!1);
33
+ }
34
+ })(), () => {
35
+ n = !1;
36
+ };
37
+ }, [e, t]);
38
+ function M(e) {
39
+ if (!e) {
40
+ g("everyone"), v(0), b("minimum"), C([]);
41
+ return;
42
+ }
43
+ d ? g(e.gated_actions?.includes("register") ? "members" : "everyone") : e.embargo_days ? (g("embargo"), D(e.embargo_days)) : g(e.audience === "members" ? "members" : "everyone"), v(e.min_tier_rank ?? 0), e.allowed_tiers && e.allowed_tiers.length > 0 ? (b("specific"), C(e.allowed_tiers)) : (b("minimum"), C([]));
44
+ }
45
+ let N = (0, w.useMemo)(() => [{
46
+ value: 0,
47
+ label: "Any member"
48
+ }, ...p.map((e) => ({
49
+ value: e.rank,
50
+ label: `${e.display_label} or higher`
51
+ }))], [p]);
52
+ async function P(n) {
53
+ k("saving"), j(null);
54
+ let r = n.tierMode === "specific" ? {
55
+ min_tier_rank: 0,
56
+ allowed_tiers: n.selectedTiers
57
+ } : {
58
+ min_tier_rank: n.tierRank,
59
+ allowed_tiers: null
60
+ };
61
+ try {
62
+ n.mode === "everyone" ? await x.clearPolicy(e, t) : d ? await x.setPolicy({
63
+ content_type: e,
64
+ entity_id: t,
65
+ audience: "public",
66
+ ...r,
67
+ gated_actions: ["register"],
68
+ note: "Members-only registration"
69
+ }) : n.mode === "embargo" ? await x.setPolicy({
70
+ content_type: e,
71
+ entity_id: t,
72
+ audience: "public",
73
+ ...r,
74
+ embargo_days: n.embargoDays
75
+ }) : await x.setPolicy({
76
+ content_type: e,
77
+ entity_id: t,
78
+ audience: "members",
79
+ ...r
80
+ }), k("saved"), setTimeout(() => k((e) => e === "saved" ? "idle" : e), 1500);
81
+ } catch (e) {
82
+ k("error"), j(e.message);
83
+ }
84
+ }
85
+ let F = (e) => {
86
+ let t = {
87
+ mode: h,
88
+ tierRank: _,
89
+ embargoDays: E,
90
+ tierMode: y,
91
+ selectedTiers: S,
92
+ ...e
93
+ };
94
+ g(t.mode), v(t.tierRank), D(t.embargoDays), b(t.tierMode), C(t.selectedTiers), P(t);
95
+ }, I = n != null && n !== c, L = h === "members" || h === "embargo";
96
+ return /* @__PURE__ */ (0, T.jsxs)(i, {
97
+ className: u,
98
+ children: [
99
+ /* @__PURE__ */ (0, T.jsxs)("div", {
100
+ className: "flex items-center justify-between",
101
+ children: [/* @__PURE__ */ (0, T.jsx)("h3", {
102
+ className: "text-sm font-semibold text-[var(--gray-12)]",
103
+ children: "Access"
104
+ }), /* @__PURE__ */ (0, T.jsxs)("span", {
105
+ className: "text-xs text-[var(--gray-a10)]",
106
+ children: [
107
+ O === "saving" && "Saving…",
108
+ O === "saved" && "Saved ✓",
109
+ O === "error" && /* @__PURE__ */ (0, T.jsx)("span", {
110
+ className: "text-[var(--red-9)]",
111
+ children: "Save failed"
112
+ })
113
+ ]
114
+ })]
115
+ }),
116
+ r && /* @__PURE__ */ (0, T.jsxs)("div", {
117
+ className: "mt-3",
118
+ children: [/* @__PURE__ */ (0, T.jsx)("div", {
119
+ className: "text-xs font-medium text-[var(--gray-11)] mb-1",
120
+ children: "Status"
121
+ }), /* @__PURE__ */ (0, T.jsxs)("div", {
122
+ className: "flex flex-col gap-1",
123
+ children: [/* @__PURE__ */ (0, T.jsx)(a, {
124
+ name: `status-${t}`,
125
+ label: "Draft — admin only",
126
+ checked: n !== c,
127
+ onChange: () => r(o)
128
+ }), /* @__PURE__ */ (0, T.jsx)(a, {
129
+ name: `status-${t}`,
130
+ label: "Published",
131
+ checked: n === c,
132
+ onChange: () => r(c)
133
+ })]
134
+ })]
135
+ }),
136
+ I ? /* @__PURE__ */ (0, T.jsxs)("p", {
137
+ className: "mt-3 text-xs text-[var(--gray-a10)]",
138
+ children: [
139
+ "This ",
140
+ e.replace(/_/g, " "),
141
+ " is a draft — visible to admins only. Publish it to apply access rules."
142
+ ]
143
+ }) : /* @__PURE__ */ (0, T.jsxs)("div", {
144
+ className: "mt-3",
145
+ children: [
146
+ /* @__PURE__ */ (0, T.jsx)("div", {
147
+ className: "text-xs font-medium text-[var(--gray-11)] mb-1",
148
+ children: ee
149
+ }),
150
+ /* @__PURE__ */ (0, T.jsxs)("div", {
151
+ className: "flex flex-col gap-1",
152
+ children: [
153
+ /* @__PURE__ */ (0, T.jsx)(a, {
154
+ name: `vis-${t}`,
155
+ label: d ? "Anyone can register" : "Everyone",
156
+ checked: h === "everyone",
157
+ onChange: () => F({ mode: "everyone" })
158
+ }),
159
+ /* @__PURE__ */ (0, T.jsx)(a, {
160
+ name: `vis-${t}`,
161
+ label: "Members only",
162
+ checked: h === "members",
163
+ onChange: () => F({ mode: "members" })
164
+ }),
165
+ f && /* @__PURE__ */ (0, T.jsx)(a, {
166
+ name: `vis-${t}`,
167
+ label: "Members-only for a while, then public",
168
+ checked: h === "embargo",
169
+ onChange: () => F({ mode: "embargo" })
170
+ })
171
+ ]
172
+ }),
173
+ L && /* @__PURE__ */ (0, T.jsxs)("div", {
174
+ className: "mt-2 pl-6 space-y-2",
175
+ children: [/* @__PURE__ */ (0, T.jsx)(s, {
176
+ label: "Tier requirement",
177
+ value: y,
178
+ data: [{
179
+ value: "minimum",
180
+ label: "Minimum tier"
181
+ }, {
182
+ value: "specific",
183
+ label: "Specific tiers"
184
+ }],
185
+ onChange: (e) => F({ tierMode: e.target.value === "specific" ? "specific" : "minimum" })
186
+ }), y === "minimum" ? /* @__PURE__ */ (0, T.jsx)(s, {
187
+ label: "Minimum tier",
188
+ value: _,
189
+ data: N,
190
+ onChange: (e) => F({ tierRank: Number(e.target.value) })
191
+ }) : /* @__PURE__ */ (0, T.jsxs)("div", { children: [
192
+ /* @__PURE__ */ (0, T.jsx)("div", {
193
+ className: "text-xs font-medium text-[var(--gray-11)] mb-1",
194
+ children: "Allowed tiers"
195
+ }),
196
+ p.length === 0 ? /* @__PURE__ */ (0, T.jsx)("p", {
197
+ className: "text-xs text-[var(--gray-a10)]",
198
+ children: "No tiers available."
199
+ }) : /* @__PURE__ */ (0, T.jsx)("div", {
200
+ className: "flex flex-col gap-1",
201
+ children: p.map((e) => /* @__PURE__ */ (0, T.jsxs)("label", {
202
+ className: "flex items-center gap-2 text-sm text-[var(--gray-11)]",
203
+ children: [/* @__PURE__ */ (0, T.jsx)("input", {
204
+ type: "checkbox",
205
+ checked: S.includes(e.tier),
206
+ onChange: (t) => {
207
+ let n = t.target.checked ? [...S, e.tier] : S.filter((t) => t !== e.tier);
208
+ F({ selectedTiers: n });
209
+ }
210
+ }), e.display_label]
211
+ }, e.tier))
212
+ }),
213
+ /* @__PURE__ */ (0, T.jsx)("p", {
214
+ className: "text-xs text-[var(--gray-a10)] mt-1",
215
+ children: "Only members in the checked tiers can access."
216
+ })
217
+ ] })]
218
+ }),
219
+ h === "embargo" && /* @__PURE__ */ (0, T.jsx)("div", {
220
+ className: "mt-2 pl-6",
221
+ children: /* @__PURE__ */ (0, T.jsx)(l, {
222
+ label: "Members-only for (days)",
223
+ type: "number",
224
+ min: 1,
225
+ value: E,
226
+ onChange: (e) => F({ embargoDays: Math.max(1, Number(e.target.value) || 1) })
227
+ })
228
+ })
229
+ ]
230
+ }),
231
+ A && /* @__PURE__ */ (0, T.jsx)("p", {
232
+ className: "mt-2 text-xs text-[var(--red-9)]",
233
+ children: A
234
+ }),
235
+ te && /* @__PURE__ */ (0, T.jsx)("p", {
236
+ className: "mt-2 text-xs text-[var(--gray-a10)]",
237
+ children: "Loading…"
238
+ })
239
+ ]
240
+ });
241
+ }
242
+ //#endregion
243
+ //#region ../../../gatewaze-modules/modules/newsletters/admin/utils/view-online-url.ts
244
+ function D() {
245
+ if (typeof window > "u") return null;
246
+ let e = window.location.hostname.replace("-admin.", "-app.").replace(/^admin\./, "");
247
+ return `${window.location.protocol}//${e}`;
248
+ }
249
+ function O(e, t, n) {
250
+ let r = t?.edition_date?.slice(0, 10);
251
+ if (!r) return null;
252
+ let i = (t?.subject ?? t?.title ?? "").trim(), a = S(r, i);
253
+ if (e?.view_online_target === "external") {
254
+ let t = e.view_online_external_base_url?.trim().replace(/\/+$/, "");
255
+ return t ? `${t}/${a}/` : null;
256
+ }
257
+ let o = e?.slug?.trim();
258
+ if (!o) return null;
259
+ let s = n ?? D();
260
+ return s ? `${s}/newsletters/${o}/${a}` : null;
261
+ }
262
+ //#endregion
263
+ //#region ../../../gatewaze-modules/modules/newsletters/admin/components/EditionSendingTab.tsx
264
+ function k({ editionId: e, editionDate: t, subject: r, collection: i, newsletterSlug: a, editionStatus: o, getRenderedHtml: s }) {
265
+ let c = (0, w.useCallback)(async () => {
266
+ let e = typeof window < "u" ? window.location.protocol : "https:", o = `${e}//${typeof window < "u" ? window.location.hostname.replace("-admin.", "-app.").replace(/^admin\./, "") : "localhost"}`;
267
+ try {
268
+ let { data: t } = await n.from("platform_settings").select("value").eq("key", "domain").maybeSingle(), r = (t?.value)?.trim();
269
+ r && (o = /^https?:\/\//i.test(r) ? r.replace(/\/+$/, "") : `${e}//${r.replace(/\/+$/, "")}`);
270
+ } catch {}
271
+ let c = O({
272
+ slug: a,
273
+ view_online_target: i?.view_online_target,
274
+ view_online_external_base_url: i?.view_online_external_base_url
275
+ }, {
276
+ edition_date: t,
277
+ subject: r
278
+ }, o) ?? `${o}/newsletters`, l = s ? await s() : null;
279
+ return l &&= l.replace(/\{\{web_version\}\}/g, c).replace(/\{%\s*view_in_browser_url\s*%\}/g, c), {
280
+ html: l,
281
+ webVersionUrl: c,
282
+ portalBaseUrl: o
283
+ };
284
+ }, [
285
+ a,
286
+ i?.view_online_target,
287
+ i?.view_online_external_base_url,
288
+ t,
289
+ r,
290
+ s
291
+ ]), l = (0, w.useMemo)(() => {
292
+ let t = a ? `/newsletters/${a}` : void 0, s = e === "new";
293
+ return {
294
+ domainKey: "newsletter",
295
+ title: "Send Newsletter",
296
+ parentId: s ? "" : e,
297
+ sendsTable: "newsletter_sends",
298
+ parentFkColumn: "edition_id",
299
+ logSendIdColumn: "newsletter_send_id",
300
+ tzBreakdownRpc: "newsletter_send_timezone_breakdown",
301
+ sendEndpoint: "newsletter-send",
302
+ canSend: o === "published",
303
+ canSendReason: s ? "Save the edition first" : o === "published" ? void 0 : "This edition is a draft. Publish it before sending — the email’s “View Online” link points at the published page.",
304
+ features: {
305
+ deliveryStrategy: !0,
306
+ excludeSent: !0
307
+ },
308
+ emailDetails: {
309
+ editable: !1,
310
+ editHref: t,
311
+ editLabel: "Edit in settings",
312
+ values: {
313
+ subject: r || "",
314
+ preheader: "",
315
+ fromAddress: i?.from_email || "",
316
+ fromName: i?.from_name || "",
317
+ replyTo: i?.reply_to || ""
318
+ }
319
+ },
320
+ recipients: {
321
+ display: `${i?.list_name || "No list linked"}${i?.subscriber_count == null ? "" : ` (${i.subscriber_count.toLocaleString()})`}`,
322
+ editable: !0,
323
+ editHref: t,
324
+ editLabel: "Edit"
325
+ },
326
+ recipientCount: i?.subscriber_count ?? null,
327
+ async countRecipients(e) {
328
+ if (!i?.list_id) return i?.subscriber_count ?? 0;
329
+ let { data: t, error: r } = await n.rpc("newsletter_recipient_preview_count", {
330
+ p_list_id: i.list_id,
331
+ p_exclude_send_ids: e.length > 0 ? e : null
332
+ });
333
+ if (r) throw r;
334
+ return t ?? 0;
335
+ },
336
+ async previewSchedule(e) {
337
+ if (!i?.list_id || !e.scheduledAt) return [];
338
+ let { data: t, error: r } = await n.rpc("newsletter_preview_send_schedule", {
339
+ p_list_id: i.list_id,
340
+ p_scheduled_at: e.scheduledAt,
341
+ p_target_local: e.targetLocal,
342
+ p_default_timezone: e.defaultTimezone
343
+ });
344
+ if (r) throw r;
345
+ return t || [];
346
+ },
347
+ async createSend(t) {
348
+ let { html: a, webVersionUrl: o, portalBaseUrl: s } = await c(), { data: l, error: u } = await n.from("newsletter_sends").insert({
349
+ edition_id: e,
350
+ collection_id: i?.id ?? null,
351
+ status: t.scheduleType === "scheduled" ? "scheduled" : "sending",
352
+ subject: r || null,
353
+ from_address: i?.from_email || null,
354
+ from_name: i?.from_name || null,
355
+ list_ids: i?.list_id ? [i.list_id] : [],
356
+ schedule_type: t.scheduleType,
357
+ scheduled_at: t.scheduledAt,
358
+ delivery_strategy: t.deliveryStrategy,
359
+ target_local: t.targetLocal,
360
+ default_timezone: t.defaultTimezone,
361
+ adapter_id: "html",
362
+ rendered_html: a,
363
+ exclude_sent_send_ids: t.excludeSentSendIds.length > 0 ? t.excludeSentSendIds : null,
364
+ metadata: {
365
+ web_version_url: o,
366
+ portal_base_url: s
367
+ }
368
+ }).select("id").single();
369
+ if (u) throw u;
370
+ return { id: l.id };
371
+ },
372
+ async rerenderContent(e) {
373
+ let { html: t } = await c();
374
+ if (!t) throw Error("Nothing to render yet");
375
+ let { error: i } = await n.from("newsletter_sends").update({
376
+ rendered_html: t,
377
+ subject: r || null,
378
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
379
+ }).eq("id", e);
380
+ if (i) throw i;
381
+ },
382
+ async sendTest(t) {
383
+ let { html: i } = await c(), a = globalThis.__GATEWAZE_CONFIG__.VITE_API_URL ?? "", { data: { session: o } } = await n.auth.getSession(), s = await fetch(`${a}/api/admin/newsletters/editions/${e}/test-send`, {
384
+ method: "POST",
385
+ headers: {
386
+ "Content-Type": "application/json",
387
+ ...o ? { Authorization: `Bearer ${o.access_token}` } : {}
388
+ },
389
+ body: JSON.stringify({
390
+ recipient_email: t,
391
+ html: i,
392
+ subject: r || "Newsletter"
393
+ })
394
+ });
395
+ if (!s.ok) {
396
+ let e = await s.json().catch(() => null), t = typeof e?.error == "string" ? e.error : e?.error?.message;
397
+ throw Error(t || `Test send failed (${s.status})`);
398
+ }
399
+ }
400
+ };
401
+ }, [
402
+ e,
403
+ o,
404
+ r,
405
+ i,
406
+ a,
407
+ c
408
+ ]);
409
+ return /* @__PURE__ */ (0, T.jsx)(u, { adapter: l });
410
+ }
411
+ //#endregion
412
+ //#region ../../../gatewaze-modules/modules/newsletters/admin/hooks/useEditionPresence.ts
413
+ function A(e) {
414
+ let [t, r] = (0, w.useState)([]);
415
+ return (0, w.useEffect)(() => {
416
+ if (!e || e === "new") {
417
+ r([]);
418
+ return;
419
+ }
420
+ let t = typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID() : `self-${Date.now()}-${Math.floor(Math.random() * 1e9)}`, i = !1, a = n.channel(`edition-presence:${e}`, { config: { presence: { key: t } } });
421
+ return a.on("presence", { event: "sync" }, () => {
422
+ let e = a.presenceState(), n = [];
423
+ for (let [r, i] of Object.entries(e)) {
424
+ if (r === t) continue;
425
+ let e = i?.[0];
426
+ e && n.push({
427
+ id: e.id ?? r,
428
+ name: e.name ?? "A teammate",
429
+ joinedAt: e.joinedAt ?? ""
430
+ });
431
+ }
432
+ i || r(n);
433
+ }), a.subscribe((e) => {
434
+ e === "SUBSCRIBED" && n.auth.getUser().then(({ data: e }) => {
435
+ a.track({
436
+ id: e.user?.id ?? t,
437
+ name: e.user?.email ?? "A teammate",
438
+ joinedAt: (/* @__PURE__ */ new Date()).toISOString()
439
+ });
440
+ });
441
+ }), () => {
442
+ i = !0, n.removeChannel(a);
443
+ };
444
+ }, [e]), t;
445
+ }
446
+ //#endregion
447
+ //#region ../../../gatewaze-modules/modules/newsletters/admin/hooks/useEditionDraft.ts
448
+ var j = "nl-edition-draft:v1:", M = (e) => `${j}${e}`;
449
+ function N() {
450
+ try {
451
+ return typeof localStorage > "u" ? null : localStorage;
452
+ } catch {
453
+ return null;
454
+ }
455
+ }
456
+ function P(e, t, n) {
457
+ let r = N();
458
+ if (!(!r || !e || e === "new")) try {
459
+ r.setItem(M(e), JSON.stringify({
460
+ savedAt: n,
461
+ payload: t
462
+ }));
463
+ } catch {}
464
+ }
465
+ function F(e) {
466
+ let t = N();
467
+ if (!t || !e) return null;
468
+ try {
469
+ let n = t.getItem(M(e));
470
+ if (!n) return null;
471
+ let r = JSON.parse(n);
472
+ return !r || typeof r.savedAt != "number" || !r.payload ? null : r;
473
+ } catch {
474
+ return null;
475
+ }
476
+ }
477
+ function I(e) {
478
+ let t = N();
479
+ if (!(!t || !e)) try {
480
+ t.removeItem(M(e));
481
+ } catch {}
482
+ }
483
+ function L(e) {
484
+ try {
485
+ return JSON.stringify(e);
486
+ } catch {
487
+ return "";
488
+ }
489
+ }
490
+ //#endregion
491
+ //#region ../../../gatewaze-modules/modules/newsletters/admin/pages/editions/[id].tsx
492
+ function R(e) {
493
+ return {
494
+ subject: e.subject ?? "",
495
+ preheader: e.preheader ?? "",
496
+ edition_date: e.edition_date ?? "",
497
+ blocks: e.blocks ?? []
498
+ };
499
+ }
500
+ function z(e) {
501
+ let t = e;
502
+ return t ? t.status === 401 || t.code === "PGRST301" || t.code === "42501" || /jwt (expired|invalid)|not authori[sz]ed|invalid.*(token|claim)|auth session (missing|expired)|401/i.test(t.message || "") : !1;
503
+ }
504
+ function B() {
505
+ let { id: e, tab: t, slug: r } = ne(), [i] = p(), a = te(), s = e === "new", l = b("bulk-emailing"), [u, _] = (0, w.useState)(!0), [x, S] = (0, w.useState)(!1), [D, j] = (0, w.useState)(null), M = (0, w.useRef)(0), N = A(D?.id ?? null), [B, V] = (0, w.useState)(null), [H, U] = (0, w.useState)(!1), W = (0, w.useRef)(""), ae = (0, w.useRef)(!1), [G, oe] = (0, w.useState)([]), [K, se] = (0, w.useState)([]), [q, ce] = (0, w.useState)(null), [J, le] = (0, w.useState)(null), [ue, de] = (0, w.useState)({}), fe = (0, w.useMemo)(() => {
506
+ let e = G.filter((e) => e.render_kind === "react-email" || e.render_kind === "declarative").map((e) => e.component_id || e.block_type || "").filter((e) => e.length > 0);
507
+ if (e.length === 0) return;
508
+ let t = K.map((e) => e.brick_type).filter((e) => typeof e == "string" && e.length > 0);
509
+ return [.../* @__PURE__ */ new Set([...e, ...t])];
510
+ }, [G, K]), Y = (0, w.useRef)(null), [pe, me] = (0, w.useState)(null);
511
+ (0, w.useEffect)(() => {
512
+ function e() {
513
+ let e = Y.current;
514
+ if (!e) return;
515
+ let t = e.getBoundingClientRect().top, n = window.visualViewport?.height ?? window.innerHeight, r = Math.max(320, Math.floor(n - t - 32));
516
+ me((e) => e === r ? e : r);
517
+ }
518
+ e(), window.addEventListener("resize", e), window.visualViewport?.addEventListener("resize", e);
519
+ let t = typeof ResizeObserver < "u" ? new ResizeObserver(e) : null;
520
+ return t && Y.current && t.observe(Y.current), () => {
521
+ window.removeEventListener("resize", e), window.visualViewport?.removeEventListener("resize", e), t?.disconnect();
522
+ };
523
+ }, []);
524
+ let X = [
525
+ "editor",
526
+ "details",
527
+ ...l ? ["sending"] : []
528
+ ].includes(t) ? t : "editor", he = (t) => {
529
+ let n = r ? `/newsletters/${r}/editions` : "/newsletters/editor";
530
+ a(`${n}/${e}/${t}`, { replace: !0 });
531
+ }, Z = (0, w.useCallback)(async (e) => {
532
+ let { data: t } = await n.from("newsletters_template_collections").select("*").eq("id", e).single();
533
+ if (t) {
534
+ let r = { ...t }, i = {
535
+ ...t.metadata || {},
536
+ from_name: t.from_name || null,
537
+ from_email: t.from_email || null
538
+ };
539
+ if (de(i), t.list_id) try {
540
+ let { data: e, error: i } = await n.from("lists").select("name").eq("id", t.list_id).single();
541
+ if (i) console.warn("[newsletter] Failed to load list:", i.message);
542
+ else if (e) {
543
+ r.list_name = e.name;
544
+ let { count: i, error: a } = await n.from("list_subscriptions").select("id", {
545
+ count: "exact",
546
+ head: !0
547
+ }).eq("list_id", t.list_id).eq("subscribed", !0);
548
+ a && console.warn("[newsletter] Failed to count subscribers:", a.message), r.subscriber_count = i || 0;
549
+ }
550
+ } catch (e) {
551
+ console.warn("[newsletter] Lists module may not be installed:", e);
552
+ }
553
+ try {
554
+ let { data: t } = await n.from("templates_wrappers").select("html").eq("library_id", e).eq("key", "default").eq("is_current", !0).maybeSingle();
555
+ r.wrapperTemplate = t?.html ?? null;
556
+ } catch {
557
+ r.wrapperTemplate = null;
558
+ }
559
+ return le(r), t.metadata;
560
+ }
561
+ return null;
562
+ }, []), ge = (0, w.useCallback)(async (e) => {
563
+ try {
564
+ let t = n.from("templates_block_defs").select("id, key, name, description, schema, html, rich_text_template, has_bricks, render_kind, component_id, block_type:key").eq("is_current", !0).order("key"), r = n.from("templates_brick_defs").select("id, block_def_id, key, name, schema, html, rich_text_template, sort_order, brick_type:key, render_kind, component_id, templates_block_defs!inner(library_id)").eq("is_current", !0).order("sort_order");
565
+ e && (t = t.eq("library_id", e), r = r.eq("templates_block_defs.library_id", e));
566
+ let [i, a] = await Promise.all([t, r]);
567
+ if (i.error) throw i.error;
568
+ if (a.error) throw a.error;
569
+ let o = (i.data ?? []).map((e) => ({
570
+ ...e,
571
+ content: {
572
+ html_template: e.html ?? "",
573
+ rich_text_template: e.rich_text_template ?? null,
574
+ has_bricks: e.has_bricks ?? !1,
575
+ schema: e.schema ?? {}
576
+ }
577
+ })), s = (a.data ?? []).map((e) => ({
578
+ ...e,
579
+ content: {
580
+ html_template: e.html ?? "",
581
+ rich_text_template: e.rich_text_template ?? null,
582
+ schema: e.schema ?? {}
583
+ }
584
+ }));
585
+ oe(o), se(s);
586
+ } catch (e) {
587
+ console.error("Error loading templates:", e), m.error("Failed to load templates");
588
+ }
589
+ }, []), _e = (0, w.useCallback)(async () => {
590
+ if (s) {
591
+ let e = i.get("collection");
592
+ if (!e) {
593
+ m.error("Please select a template first"), a(r ? `/newsletters/${r}` : "/newsletters");
594
+ return;
595
+ }
596
+ ce(e);
597
+ let t = await Z(e), n = t && typeof t == "object" ? t.default_edition_template_slug : void 0, o = [];
598
+ if (typeof n == "string" && n.length > 0) try {
599
+ let { ALL_STARTERS: e } = await import("./starter-templates-CFs-QUdF.js"), t = e.find((e) => e.slug === n);
600
+ t && (o = t.blocks.map((e, t) => ({
601
+ id: re(),
602
+ block_template: {
603
+ id: "",
604
+ name: e.type,
605
+ block_type: e.type,
606
+ content: {
607
+ html_template: "",
608
+ schema: {},
609
+ has_bricks: !1
610
+ }
611
+ },
612
+ content: ie({ ...e.props }),
613
+ sort_order: (t + 1) * 1e3,
614
+ bricks: []
615
+ })));
616
+ } catch (e) {
617
+ console.warn("[edition-new] failed to apply default template:", e);
618
+ }
619
+ j({
620
+ id: "new",
621
+ edition_date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
622
+ subject: "",
623
+ preheader: "",
624
+ blocks: o
625
+ }), _(!1);
626
+ return;
627
+ }
628
+ try {
629
+ let { data: t, error: r } = await n.from("newsletters_editions").select("*").eq("id", e).single();
630
+ if (r) throw r;
631
+ M.current = typeof t.version == "number" ? t.version : 0, t.collection_id && (ce(t.collection_id), await Z(t.collection_id));
632
+ let { data: i, error: a } = await n.from("newsletters_edition_blocks").select("*, block_template:templates_block_defs!templates_block_def_id(id, key, name, description, schema, html, rich_text_template, has_bricks, render_kind, component_id, block_type:key)").eq("edition_id", e).is("deleted_at", null).order("sort_order");
633
+ if (a) throw a;
634
+ let o = (i || []).map((e) => e.id), s = [];
635
+ if (o.length > 0) {
636
+ let { data: e, error: t } = await n.from("newsletters_edition_bricks").select("*, brick_template:templates_brick_defs!templates_brick_def_id(id, block_def_id, key, name, schema, html, rich_text_template, sort_order, brick_type:key, render_kind, component_id)").in("block_id", o).is("deleted_at", null).order("sort_order");
637
+ if (t) throw t;
638
+ s = e || [];
639
+ }
640
+ let c = (e) => ({
641
+ ...e,
642
+ content: {
643
+ html_template: e.html ?? "",
644
+ rich_text_template: e.rich_text_template ?? null,
645
+ has_bricks: e.has_bricks ?? !1,
646
+ schema: e.schema ?? {}
647
+ }
648
+ }), l = (e) => ({
649
+ ...e,
650
+ content: {
651
+ html_template: e.html ?? "",
652
+ rich_text_template: e.rich_text_template ?? null,
653
+ schema: e.schema ?? {}
654
+ }
655
+ }), u = `${globalThis.__GATEWAZE_CONFIG__.VITE_SUPABASE_URL ?? ""}/storage/v1/object/public/media`;
656
+ j({
657
+ id: t.id,
658
+ edition_date: t.edition_date,
659
+ subject: t.title || "",
660
+ preheader: t.preheader || "",
661
+ status: t.status,
662
+ blocks: (i || []).map((e) => ({
663
+ id: e.id,
664
+ block_template: e.block_template ? c(e.block_template) : {
665
+ id: "",
666
+ name: e.block_type,
667
+ block_type: e.block_type,
668
+ content: {
669
+ html_template: "",
670
+ schema: {},
671
+ has_bricks: !1
672
+ }
673
+ },
674
+ content: g(e.content || {}, u),
675
+ sort_order: e.sort_order,
676
+ bricks: s.filter((t) => t.block_id === e.id).map((e) => ({
677
+ id: e.id,
678
+ brick_template: e.brick_template ? l(e.brick_template) : e.brick_template,
679
+ content: g(e.content || {}, u),
680
+ sort_order: e.sort_order
681
+ }))
682
+ }))
683
+ });
684
+ } catch (e) {
685
+ console.error("Error loading edition:", e), m.error("Failed to load edition"), a(r ? `/newsletters/${r}` : "/newsletters");
686
+ } finally {
687
+ _(!1);
688
+ }
689
+ }, [
690
+ e,
691
+ s,
692
+ a,
693
+ i,
694
+ Z,
695
+ r
696
+ ]);
697
+ (0, w.useEffect)(() => {
698
+ _e();
699
+ }, [_e]), (0, w.useEffect)(() => {
700
+ q && ge(q);
701
+ }, [q, ge]), (0, w.useEffect)(() => {
702
+ if (u || !D || D.id === "new" || ae.current) return;
703
+ ae.current = !0;
704
+ let e = L(R(D));
705
+ W.current = e;
706
+ let t = F(D.id);
707
+ t && L(t.payload) !== e && V(t);
708
+ }, [u, D]), (0, w.useEffect)(() => {
709
+ if (!D || D.id === "new" || B || L(R(D)) === W.current) return;
710
+ let e = D.id, t = setTimeout(() => P(e, R(D), Date.now()), 800);
711
+ return () => clearTimeout(t);
712
+ }, [D, B]);
713
+ let ve = (0, w.useRef)(!1);
714
+ (0, w.useEffect)(() => {
715
+ s && D && D.id === "new" && q && !x && !ve.current && (ve.current = !0, Q({ silent: !0 }));
716
+ }, [
717
+ s,
718
+ D,
719
+ q,
720
+ x
721
+ ]);
722
+ let Q = async (e) => {
723
+ if (D) {
724
+ S(!0);
725
+ try {
726
+ if (D.id === "new") {
727
+ let { data: t, error: i } = await n.from("newsletters_editions").insert({
728
+ edition_date: D.edition_date,
729
+ title: D.subject || "Untitled",
730
+ preheader: D.preheader || null,
731
+ content_category: J?.content_category || null,
732
+ status: "draft",
733
+ collection_id: q
734
+ }).select();
735
+ if (i) throw i;
736
+ let o = t?.[0];
737
+ if (!o) throw Error("Edition created but not returned — try saving again");
738
+ for (let e of D.blocks) {
739
+ let t = e.block_template.id && e.block_template.id !== "" ? e.block_template.id : null, { data: r, error: i } = await n.from("newsletters_edition_blocks").insert({
740
+ id: e.id,
741
+ edition_id: o.id,
742
+ templates_block_def_id: t,
743
+ block_type: e.block_template.block_type,
744
+ content: h(e.content),
745
+ sort_order: e.sort_order
746
+ }).select();
747
+ if (i) throw i;
748
+ let a = r?.[0];
749
+ if (a) for (let t of e.bricks) {
750
+ let e = t.brick_template.id && t.brick_template.id !== "" ? t.brick_template.id : null, { error: r } = await n.from("newsletters_edition_bricks").insert({
751
+ id: t.id,
752
+ block_id: a.id,
753
+ templates_brick_def_id: e,
754
+ brick_type: t.brick_template.brick_type,
755
+ content: h(t.content),
756
+ sort_order: t.sort_order
757
+ });
758
+ if (r) throw r;
759
+ }
760
+ }
761
+ if (e?.silent) {
762
+ let e = r ? `/newsletters/${r}/editions` : "/newsletters/editor";
763
+ window.history.replaceState(null, "", `${e}/${o.id}/editor`), j((e) => e && {
764
+ ...e,
765
+ id: o.id
766
+ });
767
+ } else {
768
+ m.success("Edition created");
769
+ let e = r ? `/newsletters/${r}/editions` : "/newsletters/editor";
770
+ a(`${e}/${o.id}/editor`, { replace: !0 });
771
+ }
772
+ } else {
773
+ let t = D.blocks.map((e) => ({
774
+ id: e.id,
775
+ block_type: e.block_template.block_type,
776
+ templates_block_def_id: e.block_template.id && e.block_template.id !== "" ? e.block_template.id : null,
777
+ content: h(e.content),
778
+ sort_order: e.sort_order,
779
+ bricks: e.bricks.map((e) => ({
780
+ id: e.id,
781
+ brick_type: e.brick_template.brick_type,
782
+ templates_brick_def_id: e.brick_template.id && e.brick_template.id !== "" ? e.brick_template.id : null,
783
+ content: h(e.content),
784
+ sort_order: e.sort_order
785
+ }))
786
+ })), { data: r, error: i } = await n.rpc("newsletters_save_edition", {
787
+ p_edition_id: D.id,
788
+ p_expected_version: M.current,
789
+ p_title: D.subject || "Untitled",
790
+ p_preheader: D.preheader || null,
791
+ p_content_category: J?.content_category || null,
792
+ p_edition_date: D.edition_date,
793
+ p_blocks: t
794
+ });
795
+ if (i) throw i.code === "55006" || /version_conflict/i.test(i.message || "") ? (m.error("This edition was changed elsewhere since you opened it. Reload to get the latest before saving — your current changes were NOT saved.", { duration: 12e3 }), Error("__edition_version_conflict__")) : z(i) ? (P(D.id, R(D), Date.now()), U(!0), Error("__edition_session_expired__")) : (console.error("Save edition error:", i), i);
796
+ let a = r?.version;
797
+ typeof a == "number" && (M.current = a), W.current = L(R(D)), I(D.id), H && U(!1), e?.silent || m.success("Edition saved");
798
+ }
799
+ } catch (t) {
800
+ if (t?.message === "__edition_version_conflict__") {
801
+ S(!1);
802
+ return;
803
+ }
804
+ if (t?.message === "__edition_session_expired__") {
805
+ S(!1);
806
+ return;
807
+ }
808
+ if (z(t) && D) {
809
+ P(D.id, R(D), Date.now()), U(!0), S(!1);
810
+ return;
811
+ }
812
+ throw console.error("Error saving edition:", t), e?.silent || m.error("Failed to save edition"), t;
813
+ } finally {
814
+ S(!1);
815
+ }
816
+ }
817
+ }, ye = () => {
818
+ !B || !D || (j({
819
+ ...D,
820
+ subject: B.payload.subject,
821
+ preheader: B.payload.preheader,
822
+ edition_date: B.payload.edition_date,
823
+ blocks: B.payload.blocks
824
+ }), V(null), m.success("Restored your unsaved changes — save to sync them to the server."));
825
+ }, be = () => {
826
+ D && I(D.id), V(null);
827
+ }, xe = () => {
828
+ D && P(D.id, R(D), Date.now()), a("/login");
829
+ };
830
+ if (u) return /* @__PURE__ */ (0, T.jsx)(v, {
831
+ title: "Loading...",
832
+ children: /* @__PURE__ */ (0, T.jsx)("div", {
833
+ className: "flex items-center justify-center h-64",
834
+ children: /* @__PURE__ */ (0, T.jsx)(c, {})
835
+ })
836
+ });
837
+ if (!D) return /* @__PURE__ */ (0, T.jsx)(v, {
838
+ title: "Not Found",
839
+ children: /* @__PURE__ */ (0, T.jsx)("div", {
840
+ className: "p-6 text-center text-[var(--gray-9)]",
841
+ children: "Edition not found"
842
+ })
843
+ });
844
+ D.status;
845
+ let $ = "size-4", Se = [
846
+ {
847
+ id: "editor",
848
+ label: "Editor",
849
+ icon: /* @__PURE__ */ (0, T.jsx)(C.PencilSquareIcon, { className: $ })
850
+ },
851
+ {
852
+ id: "details",
853
+ label: "Details",
854
+ icon: /* @__PURE__ */ (0, T.jsx)(C.Cog6ToothIcon, { className: $ })
855
+ },
856
+ ...l ? [{
857
+ id: "sending",
858
+ label: "Sending",
859
+ icon: /* @__PURE__ */ (0, T.jsx)(C.PaperAirplaneIcon, { className: $ })
860
+ }] : []
861
+ ], Ce = [
862
+ {
863
+ id: "details",
864
+ label: "Settings",
865
+ icon: /* @__PURE__ */ (0, T.jsx)(C.Cog6ToothIcon, { className: $ })
866
+ },
867
+ {
868
+ id: "template",
869
+ label: "Template",
870
+ icon: /* @__PURE__ */ (0, T.jsx)(C.RectangleGroupIcon, { className: $ })
871
+ },
872
+ {
873
+ id: "editions",
874
+ label: "Editions",
875
+ icon: /* @__PURE__ */ (0, T.jsx)(C.DocumentTextIcon, { className: $ })
876
+ },
877
+ ...l ? [{
878
+ id: "replies",
879
+ label: "Replies",
880
+ icon: /* @__PURE__ */ (0, T.jsx)(C.ChatBubbleLeftRightIcon, { className: $ })
881
+ }, {
882
+ id: "stats",
883
+ label: "Stats",
884
+ icon: /* @__PURE__ */ (0, T.jsx)(C.ChartBarIcon, { className: $ })
885
+ }] : []
886
+ ], we = new Date(D.edition_date).toLocaleDateString("en-US", {
887
+ year: "numeric",
888
+ month: "short",
889
+ day: "numeric"
890
+ });
891
+ return /* @__PURE__ */ (0, T.jsx)(v, {
892
+ title: D.subject || "Newsletter Edition",
893
+ children: /* @__PURE__ */ (0, T.jsxs)(o, {
894
+ title: J?.name ? `Newsletters: ${J.name}` : "Newsletters",
895
+ tabs: Ce,
896
+ activeTabId: "editions",
897
+ onTabChange: (e) => a(r ? `/newsletters/${r}/${e}` : "/newsletters"),
898
+ breadcrumbs: [{
899
+ label: "Editions",
900
+ to: r ? `/newsletters/${r}/editions` : "/newsletters"
901
+ }, { label: we }],
902
+ onBreadcrumbNavigate: (e) => a(e),
903
+ subTabs: Se,
904
+ activeSubTabId: X,
905
+ onSubTabChange: he,
906
+ children: [
907
+ N.length > 0 && /* @__PURE__ */ (0, T.jsxs)("div", {
908
+ style: {
909
+ display: "flex",
910
+ alignItems: "center",
911
+ gap: 8,
912
+ padding: "6px 14px",
913
+ fontSize: 13,
914
+ background: "#FEF3C7",
915
+ color: "#92400E",
916
+ borderBottom: "1px solid #FDE68A"
917
+ },
918
+ children: [/* @__PURE__ */ (0, T.jsx)("span", {
919
+ "aria-hidden": !0,
920
+ children: "👀"
921
+ }), /* @__PURE__ */ (0, T.jsxs)("span", { children: [N.length === 1 ? `${N[0].name} is also editing this edition` : `${N.length} other people are also editing this edition`, " — your changes are protected, but coordinate to avoid conflicting saves."] })]
922
+ }),
923
+ H && /* @__PURE__ */ (0, T.jsxs)("div", {
924
+ style: {
925
+ display: "flex",
926
+ alignItems: "center",
927
+ gap: 10,
928
+ flexWrap: "wrap",
929
+ padding: "10px 14px",
930
+ fontSize: 13,
931
+ background: "#FEE2E2",
932
+ color: "#991B1B",
933
+ borderBottom: "1px solid #FCA5A5"
934
+ },
935
+ children: [
936
+ /* @__PURE__ */ (0, T.jsx)("span", {
937
+ "aria-hidden": !0,
938
+ children: "⚠️"
939
+ }),
940
+ /* @__PURE__ */ (0, T.jsx)("span", {
941
+ style: { fontWeight: 600 },
942
+ children: "You’ve been signed out."
943
+ }),
944
+ /* @__PURE__ */ (0, T.jsxs)("span", { children: [
945
+ "Your recent changes are saved on this device and will be restored after you sign in again — they were ",
946
+ /* @__PURE__ */ (0, T.jsx)("strong", { children: "not" }),
947
+ " saved to the server."
948
+ ] }),
949
+ /* @__PURE__ */ (0, T.jsx)("button", {
950
+ onClick: xe,
951
+ style: {
952
+ marginLeft: "auto",
953
+ padding: "4px 12px",
954
+ background: "#991B1B",
955
+ color: "#fff",
956
+ border: "none",
957
+ borderRadius: 6,
958
+ fontSize: 13,
959
+ cursor: "pointer"
960
+ },
961
+ children: "Sign in again"
962
+ })
963
+ ]
964
+ }),
965
+ B && !H && /* @__PURE__ */ (0, T.jsxs)("div", {
966
+ style: {
967
+ display: "flex",
968
+ alignItems: "center",
969
+ gap: 10,
970
+ flexWrap: "wrap",
971
+ padding: "10px 14px",
972
+ fontSize: 13,
973
+ background: "#FEF3C7",
974
+ color: "#92400E",
975
+ borderBottom: "1px solid #FDE68A"
976
+ },
977
+ children: [
978
+ /* @__PURE__ */ (0, T.jsx)("span", {
979
+ "aria-hidden": !0,
980
+ children: "💾"
981
+ }),
982
+ /* @__PURE__ */ (0, T.jsxs)("span", { children: [
983
+ "Unsaved changes from ",
984
+ new Date(B.savedAt).toLocaleString(),
985
+ " were found on this device (they never reached the server)."
986
+ ] }),
987
+ /* @__PURE__ */ (0, T.jsxs)("span", {
988
+ style: {
989
+ marginLeft: "auto",
990
+ display: "flex",
991
+ gap: 8
992
+ },
993
+ children: [/* @__PURE__ */ (0, T.jsx)("button", {
994
+ onClick: ye,
995
+ style: {
996
+ padding: "4px 12px",
997
+ background: "#92400E",
998
+ color: "#fff",
999
+ border: "none",
1000
+ borderRadius: 6,
1001
+ fontSize: 13,
1002
+ cursor: "pointer"
1003
+ },
1004
+ children: "Restore"
1005
+ }), /* @__PURE__ */ (0, T.jsx)("button", {
1006
+ onClick: be,
1007
+ style: {
1008
+ padding: "4px 12px",
1009
+ background: "transparent",
1010
+ color: "#92400E",
1011
+ border: "1px solid #92400E",
1012
+ borderRadius: 6,
1013
+ fontSize: 13,
1014
+ cursor: "pointer"
1015
+ },
1016
+ children: "Discard"
1017
+ })]
1018
+ })
1019
+ ]
1020
+ }),
1021
+ X === "editor" && /* @__PURE__ */ (0, T.jsx)("div", {
1022
+ ref: Y,
1023
+ className: "-mx-[calc(var(--margin-x)+1.5rem)] -mt-4 -mb-6",
1024
+ style: {
1025
+ height: pe == null ? "calc(100vh - 240px)" : `${pe}px`,
1026
+ padding: "1rem calc(var(--margin-x) + 1.5rem)",
1027
+ overflow: "hidden",
1028
+ boxSizing: "border-box"
1029
+ },
1030
+ children: /* @__PURE__ */ (0, T.jsx)(d, {
1031
+ edition: D,
1032
+ blockTemplates: G,
1033
+ brickTemplates: K,
1034
+ collectionMetadata: ue,
1035
+ wrapperTemplate: J?.wrapperTemplate ?? null,
1036
+ viewOnlineUrl: O(J, {
1037
+ edition_date: D.edition_date,
1038
+ subject: D.subject,
1039
+ title: D.title
1040
+ }),
1041
+ ...q ? { collectionId: q } : {},
1042
+ ...fe ? { enabledRegistryComponentIds: fe } : {},
1043
+ onChange: j,
1044
+ onSave: Q,
1045
+ onStatusChange: async (e) => {
1046
+ j((t) => t && {
1047
+ ...t,
1048
+ status: e
1049
+ }), !s && D && (await n.from("newsletters_editions").update({
1050
+ status: e,
1051
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
1052
+ }).eq("id", D.id), m.success(`Status changed to ${e}`));
1053
+ },
1054
+ isSaving: x
1055
+ })
1056
+ }),
1057
+ X === "details" && /* @__PURE__ */ (0, T.jsx)("div", {
1058
+ className: "py-2",
1059
+ children: /* @__PURE__ */ (0, T.jsxs)("div", {
1060
+ className: "max-w-2xl space-y-5",
1061
+ children: [
1062
+ /* @__PURE__ */ (0, T.jsxs)("div", { children: [
1063
+ /* @__PURE__ */ (0, T.jsx)("label", {
1064
+ className: "block text-sm font-medium text-[var(--gray-12)] mb-1.5",
1065
+ children: "Edition title / subject"
1066
+ }),
1067
+ /* @__PURE__ */ (0, T.jsx)("input", {
1068
+ type: "text",
1069
+ value: D.subject ?? "",
1070
+ onChange: (e) => j({
1071
+ ...D,
1072
+ subject: e.target.value
1073
+ }),
1074
+ placeholder: "Edition title — also the email subject line",
1075
+ className: "w-full px-3 py-2 border border-[var(--gray-a6)] rounded-md bg-[var(--color-surface)] text-sm text-[var(--gray-12)] focus:outline-none focus:ring-2 focus:ring-[var(--accent-8)]"
1076
+ }),
1077
+ /* @__PURE__ */ (0, T.jsx)("p", {
1078
+ className: "text-xs text-[var(--gray-9)] mt-1",
1079
+ children: "The subject line shown in the recipient's inbox. Also used as the edition's display name in lists."
1080
+ })
1081
+ ] }),
1082
+ /* @__PURE__ */ (0, T.jsxs)("div", { children: [
1083
+ /* @__PURE__ */ (0, T.jsx)("label", {
1084
+ className: "block text-sm font-medium text-[var(--gray-12)] mb-1.5",
1085
+ children: "Edition date"
1086
+ }),
1087
+ /* @__PURE__ */ (0, T.jsx)("input", {
1088
+ type: "date",
1089
+ value: D.edition_date ?? "",
1090
+ onChange: (e) => j({
1091
+ ...D,
1092
+ edition_date: e.target.value
1093
+ }),
1094
+ className: "px-3 py-2 border border-[var(--gray-a6)] rounded-md bg-[var(--color-surface)] text-sm text-[var(--gray-12)] focus:outline-none focus:ring-2 focus:ring-[var(--accent-8)]"
1095
+ }),
1096
+ /* @__PURE__ */ (0, T.jsx)("p", {
1097
+ className: "text-xs text-[var(--gray-9)] mt-1",
1098
+ children: "The date this edition is logically associated with — used for ordering and for the public archive page."
1099
+ })
1100
+ ] }),
1101
+ /* @__PURE__ */ (0, T.jsxs)("div", { children: [
1102
+ /* @__PURE__ */ (0, T.jsx)("label", {
1103
+ className: "block text-sm font-medium text-[var(--gray-12)] mb-1.5",
1104
+ children: "Preheader"
1105
+ }),
1106
+ /* @__PURE__ */ (0, T.jsx)("textarea", {
1107
+ value: D.preheader ?? "",
1108
+ onChange: (e) => j({
1109
+ ...D,
1110
+ preheader: e.target.value
1111
+ }),
1112
+ placeholder: "Preheader — short preview text shown in the inbox next to the subject (recommended ~80 chars)",
1113
+ rows: 3,
1114
+ className: "w-full px-3 py-2 border border-[var(--gray-a6)] rounded-md bg-[var(--color-surface)] text-sm text-[var(--gray-12)] focus:outline-none focus:ring-2 focus:ring-[var(--accent-8)] resize-y"
1115
+ }),
1116
+ /* @__PURE__ */ (0, T.jsx)("p", {
1117
+ className: "text-xs text-[var(--gray-9)] mt-1",
1118
+ children: "The short snippet most email clients show next to or below the subject. Recommended length: ~80 characters."
1119
+ })
1120
+ ] }),
1121
+ D.id && /* @__PURE__ */ (0, T.jsx)(E, {
1122
+ contentType: "newsletter_edition",
1123
+ entityId: D.id
1124
+ }),
1125
+ /* @__PURE__ */ (0, T.jsx)("div", {
1126
+ className: "pt-2",
1127
+ children: /* @__PURE__ */ (0, T.jsx)("button", {
1128
+ type: "button",
1129
+ onClick: () => Q(),
1130
+ disabled: x,
1131
+ className: "px-4 py-2 bg-[var(--accent-9)] hover:bg-[var(--accent-10)] disabled:opacity-50 text-white text-sm font-medium rounded-md transition-colors",
1132
+ children: x ? "Saving…" : "Save details"
1133
+ })
1134
+ })
1135
+ ]
1136
+ })
1137
+ }),
1138
+ X === "sending" && l && /* @__PURE__ */ (0, T.jsx)("div", {
1139
+ className: "py-2",
1140
+ children: /* @__PURE__ */ (0, T.jsx)(k, {
1141
+ editionId: D.id,
1142
+ editionDate: D.edition_date,
1143
+ subject: D.subject || "",
1144
+ collection: J,
1145
+ newsletterSlug: r,
1146
+ editionStatus: D.status,
1147
+ getRenderedHtml: D ? async () => {
1148
+ let e = /* @__PURE__ */ new Map();
1149
+ for (let t of D.blocks) {
1150
+ let n = t.block_template.component_id || t.block_template.block_type, r = t.block_template.render_kind;
1151
+ y.has(n) || r === "react-email" || r === "declarative" ? e.set(t.id, {
1152
+ render_kind: "react-email",
1153
+ component_id: n
1154
+ }) : e.set(t.id, {
1155
+ render_kind: "mustache",
1156
+ mustache_html: t.block_template.content.html_template ?? ""
1157
+ });
1158
+ }
1159
+ return ee({
1160
+ edition: D,
1161
+ format: "email",
1162
+ blockMeta: e,
1163
+ wrapperTemplate: J?.wrapperTemplate ?? null,
1164
+ viewOnlineUrl: O(J, {
1165
+ edition_date: D.edition_date,
1166
+ subject: D.subject,
1167
+ title: D.title
1168
+ }) ?? void 0,
1169
+ registry: f(G, K),
1170
+ pretty: !1,
1171
+ forSend: !0
1172
+ });
1173
+ } : void 0
1174
+ })
1175
+ })
1176
+ ]
1177
+ })
1178
+ });
1179
+ }
1180
+ function re() {
1181
+ if (typeof crypto < "u" && "randomUUID" in crypto) return crypto.randomUUID();
1182
+ let e = "";
1183
+ for (let t = 0; t < 32; t++) e += "0123456789abcdef"[Math.floor(Math.random() * 16)];
1184
+ return `${e.slice(0, 8)}-${e.slice(8, 12)}-4${e.slice(13, 16)}-${e.slice(16, 20)}-${e.slice(20, 32)}`;
1185
+ }
1186
+ function ie(e) {
1187
+ let t = { ...e };
1188
+ return Array.isArray(t.children) && (t.children = t.children.map((e) => ({
1189
+ type: e.type,
1190
+ props: ie({
1191
+ ...e.props,
1192
+ id: re()
1193
+ })
1194
+ }))), t;
1195
+ }
1196
+ //#endregion
1197
+ export { B as default };