@templatical/editor
Advanced tools
| import { $ as e, A as t, H as n, J as r, M as i, N as a, P as o, V as s, Z as c, _ as l, b as u, ct as d, f, g as p, h as m, it as h, j as g, l as _, m as v, n as y, ot as b, p as x, s as S, st as C, u as w, v as T, x as E, y as D, z as ee } from "./draggable-BwWMFq33.js"; | ||
| import { $t as O, A as k, At as A, Dt as j, E as M, En as N, Et as P, Ft as F, Ht as I, It as te, Nt as ne, Qt as L, Rt as re, S as R, Ut as z, Vt as B, Z as ie, Zt as V, _ as H, _t as U, b as W, c as G, d as K, f as q, g as J, h as Y, in as X, l as ae, m as oe, p as se, pn as Z, pt as ce, rt as le, s as ue, st as de, tt as Q, u as fe, ut as pe, v as me, vt as he, x as ge, xn as _e, y as ve, zn as ye } from "./features-D-2kVhHY.js"; | ||
| import { C as be, S as xe } from "./icons-fZoyKV_s.js"; | ||
| import { a as Se, c as Ce, i as we, l as Te, n as Ee, o as De, r as Oe, s as ke, t as Ae } from "./styles-CVUvPdKD.js"; | ||
| import { d as $ } from "./styleConstants-lGobwiLH.js"; | ||
| //#region src/cloud/composables/useSnapshotPreview.ts | ||
| function je(t) { | ||
| let { authManager: n, editor: i, history: a, conditionPreview: o, autoSave: s, onError: l } = t, u = e(null), d = c(null), p = c(null), m = !1; | ||
| r(() => { | ||
| m = !0; | ||
| }); | ||
| let h = f(() => d.value !== null), g = f(() => u.value?.snapshots.value ?? []), _ = f(() => u.value?.isLoading.value ?? !1), v = f(() => u.value?.isRestoring.value ?? !1); | ||
| function y() { | ||
| i.state.template?.id && !u.value && (u.value = q({ | ||
| authManager: n, | ||
| templateId: i.state.template.id, | ||
| onRestore: b, | ||
| onError: l | ||
| }), u.value.loadSnapshots()); | ||
| } | ||
| function b(e) { | ||
| i.setContent(e.content, !1), a.clear(), o.reset(); | ||
| } | ||
| async function x(e) { | ||
| if (!m) { | ||
| if (d.value) { | ||
| d.value = e, i.setContent(e.content, !1); | ||
| return; | ||
| } | ||
| i.state.isDirty && i.hasTemplate() && (await i.createSnapshot(), m) || (p.value = structuredClone(i.content.value), s?.pause(), d.value = e, i.setContent(e.content, !1)); | ||
| } | ||
| } | ||
| async function S() { | ||
| if (!(!d.value || !u.value)) try { | ||
| if (await u.value.restoreSnapshot(d.value.id), m || (await u.value.loadSnapshots(), m)) return; | ||
| } finally { | ||
| m || (d.value = null, p.value = null, s?.resume()); | ||
| } | ||
| } | ||
| function C() { | ||
| !d.value || !p.value || (i.setContent(p.value, !1), d.value = null, p.value = null, s?.resume()); | ||
| } | ||
| async function w() { | ||
| m || u.value && await u.value.loadSnapshots(); | ||
| } | ||
| return { | ||
| snapshotHistoryInstance: u, | ||
| previewingSnapshot: d, | ||
| contentBeforePreview: p, | ||
| isPreviewingSnapshot: h, | ||
| snapshotHistorySnapshots: g, | ||
| snapshotHistoryIsLoading: _, | ||
| snapshotHistoryIsRestoring: v, | ||
| initSnapshotHistory: y, | ||
| handleRestore: b, | ||
| handleSnapshotNavigate: x, | ||
| confirmRestoreSnapshot: S, | ||
| cancelPreview: C, | ||
| loadSnapshotHistory: w | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudPanelState.ts | ||
| function Me() { | ||
| let e = c(null), t = f({ | ||
| get: () => e.value === "ai-chat", | ||
| set: (t) => e.value = t ? "ai-chat" : null | ||
| }), n = f({ | ||
| get: () => e.value === "scoring", | ||
| set: (t) => e.value = t ? "scoring" : null | ||
| }), r = f({ | ||
| get: () => e.value === "design-reference", | ||
| set: (t) => e.value = t ? "design-reference" : null | ||
| }), i = f({ | ||
| get: () => e.value === "comments", | ||
| set: (t) => e.value = t ? "comments" : null | ||
| }), a = c(!1), o = c(!1), s = c(void 0), l = c(!1), u = c(null), d = f(() => e.value !== null), p = f(() => { | ||
| let t = e.value; | ||
| return t === "ai-chat" || t === "design-reference" || t === "scoring" ? t : null; | ||
| }), m = f(() => l.value || e.value === "ai-chat" || e.value === "design-reference" || e.value === "scoring"); | ||
| function h() { | ||
| l.value = !l.value; | ||
| } | ||
| function g(t) { | ||
| l.value = !1, e.value = e.value === t ? null : t; | ||
| } | ||
| return X(u, () => { | ||
| l.value = !1; | ||
| }), { | ||
| activePanel: e, | ||
| aiChatOpen: t, | ||
| scoringPanelOpen: n, | ||
| designReferenceOpen: r, | ||
| commentsOpen: i, | ||
| testEmailModalOpen: a, | ||
| mediaLibraryOpen: o, | ||
| mediaLibraryAccept: s, | ||
| aiMenuOpen: l, | ||
| aiMenuRef: u, | ||
| rightPanelOpen: d, | ||
| activeAiFeature: p, | ||
| aiButtonActive: m, | ||
| toggleAiMenu: h, | ||
| handleAiFeatureSelect: g | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCollabUndoWarning.ts | ||
| function Ne(e) { | ||
| let { isCollaborationEnabled: t, getCollaboratorCount: n, canUndo: r } = e, i = c(!1), a = c(!1), { start: o } = Z(() => { | ||
| a.value = !1; | ||
| }, ye, { immediate: !1 }); | ||
| function s() { | ||
| i.value || !t.value || n() === 0 || !r.value || (i.value = !0, a.value = !0, o()); | ||
| } | ||
| return { | ||
| collabUndoWarningVisible: a, | ||
| showCollabUndoWarning: s | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudFeatureFlags.ts | ||
| function Pe(e) { | ||
| let { planConfigInstance: t, aiConfig: n, editor: r } = e, i = f(() => t.hasFeature("ai_generation") && n.hasAnyMenuFeature.value), a = f(() => t.hasFeature("test_email")), o = f(() => !!r.state.template?.id), s = f(() => t.hasFeature("white_label")), l = f(() => t.config.value?.limits.max_templates ?? null), u = f(() => t.config.value?.template_count ?? 0), d = c(!1), p = c("idle"), m = c(""), { start: h } = Z(() => { | ||
| p.value = "idle"; | ||
| }, 3e3, { immediate: !1 }); | ||
| return { | ||
| canUseAiGeneration: i, | ||
| canSendTestEmail: a, | ||
| hasTemplateSaved: o, | ||
| isWhiteLabeled: s, | ||
| templateLimit: l, | ||
| templateCount: u, | ||
| isSaveExporting: d, | ||
| saveStatus: p, | ||
| saveErrorMessage: m, | ||
| startSaveStatusClear: h | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudMediaLibrary.ts | ||
| function Fe(e) { | ||
| let { onRequestMedia: t, mediaLibraryOpen: n, mediaLibraryAccept: i } = e, a = null; | ||
| async function o() { | ||
| if (t) { | ||
| let e = await t({ accept: ["images"] }); | ||
| return e ? { | ||
| url: e.url, | ||
| alt: e.alt_text || void 0 | ||
| } : null; | ||
| } | ||
| return a &&= (a(null), null), i.value = ["images"], n.value = !0, new Promise((e) => { | ||
| a = (t) => { | ||
| e(t); | ||
| }; | ||
| }); | ||
| } | ||
| function s(e) { | ||
| n.value = !1, a?.({ | ||
| url: e.url, | ||
| alt: e.alt_text || void 0 | ||
| }), a = null; | ||
| } | ||
| function c() { | ||
| n.value = !1, a?.(null), a = null; | ||
| } | ||
| return r(() => { | ||
| a &&= (a(null), null); | ||
| }), { | ||
| handleRequestMedia: o, | ||
| handleMediaSelect: s, | ||
| handleMediaLibraryClose: c | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudInitialization.ts | ||
| function Ie(e) { | ||
| let { config: t, translations: n, fontsManager: r, emit: i, getCommentsSidebar: o } = e, s = c(!0), l = c(!1), u = c(null), d = !1, p = { value: null }, m = null, h = null, g = new M({ | ||
| ...t.auth, | ||
| onError: t.onError | ||
| }), _ = ae({ | ||
| authManager: g, | ||
| onError: t.onError | ||
| }), v = c(/* @__PURE__ */ new Map()), y = ge({ | ||
| authManager: g, | ||
| defaultFontFamily: t.fonts?.defaultFont, | ||
| templateDefaults: t.templateDefaults, | ||
| onError: t.onError, | ||
| lockedBlocks: v | ||
| }), b = oe({ | ||
| authManager: g, | ||
| onError: t.onError | ||
| }); | ||
| t.mcp?.enabled && ue({ | ||
| editor: y, | ||
| channel: b.channel, | ||
| onOperation: t.mcp.onOperation | ||
| }); | ||
| let x = null; | ||
| t.collaboration?.enabled && (x = J({ | ||
| authManager: g, | ||
| editor: y, | ||
| channel: b.channel, | ||
| onError: t.onError, | ||
| onCollaboratorJoined: t.collaboration.onCollaboratorJoined, | ||
| onCollaboratorLeft: t.collaboration.onCollaboratorLeft, | ||
| onBlockLocked: t.collaboration.onBlockLocked, | ||
| onBlockUnlocked: t.collaboration.onBlockUnlocked | ||
| }), ee(() => x.lockedBlocks.value, (e) => { | ||
| v.value = e; | ||
| }, { immediate: !0 }), Y(y, x)); | ||
| let S = f(() => !!t.collaboration?.enabled && _.hasFeature("collaboration")), C = k({ | ||
| editor: y, | ||
| config: { | ||
| uiTheme: t.uiTheme, | ||
| theme: void 0, | ||
| blockDefaults: t.blockDefaults, | ||
| customBlocks: [], | ||
| mergeTags: t.mergeTags, | ||
| displayConditions: t.displayConditions, | ||
| onRequestMedia: null, | ||
| lint: Te(t), | ||
| onSave: () => { | ||
| p.value?.().catch((e) => { | ||
| t.onError?.(e); | ||
| }); | ||
| } | ||
| }, | ||
| translations: n, | ||
| fontsManager: r, | ||
| historyOptions: x ? { isRemoteOperation: () => x._isProcessingRemoteOperation() } : void 0, | ||
| autoSaveOptions: { | ||
| onChange: async () => { | ||
| y.hasTemplate() && (await y.createSnapshot(), m?.snapshotHistoryInstance.value?.loadSnapshots()); | ||
| }, | ||
| debounce: t.autoSaveDebounce ?? 5e3, | ||
| enabled: () => t.autoSave !== !1 && _.hasFeature("auto_save") | ||
| }, | ||
| themeExtraStyles: () => ({ "--tpl-drop-text": `"${n.canvas.dropHere}"` }), | ||
| keyboardOptions: { onBeforeUndo: () => h?.showCollabUndoWarning() }, | ||
| editorRoot: e.editorRoot, | ||
| containerEl: e.containerEl | ||
| }), w = Ne({ | ||
| isCollaborationEnabled: S, | ||
| getCollaboratorCount: () => x?.collaborators.value.length ?? 0, | ||
| canUndo: C.history.canUndo | ||
| }); | ||
| h = w; | ||
| let T = je({ | ||
| authManager: g, | ||
| editor: y, | ||
| history: C.history, | ||
| conditionPreview: C.conditionPreview, | ||
| autoSave: C.autoSave, | ||
| onError: t.onError | ||
| }); | ||
| m = T; | ||
| let E = Me(), D = W(t.ai), A = Pe({ | ||
| planConfigInstance: _, | ||
| aiConfig: D, | ||
| editor: y | ||
| }), j = Fe({ | ||
| onRequestMedia: t.onRequestMedia, | ||
| mediaLibraryOpen: E.mediaLibraryOpen, | ||
| mediaLibraryAccept: E.mediaLibraryAccept | ||
| }); | ||
| ie({ | ||
| onBlockMove: y.moveBlock, | ||
| onBlockAdd: y.addBlock | ||
| }); | ||
| let N = fe({ | ||
| authManager: g, | ||
| getFontsConfig: () => t.fonts, | ||
| canUseCustomFonts: () => _.hasFeature("custom_fonts") | ||
| }), P = K({ | ||
| authManager: g, | ||
| getTemplateId: () => y.state.template?.id ?? null, | ||
| save: () => y.save(), | ||
| exportHtml: (e) => N.exportHtml(e), | ||
| onError: t.onError, | ||
| isAuthReady: l, | ||
| onBeforeTestEmail: t.onBeforeTestEmail | ||
| }), F = me({ | ||
| authManager: g, | ||
| getTemplateId: () => y.state.template?.id ?? null, | ||
| getSocketId: () => b.getSocketId(), | ||
| onComment: t.onComment, | ||
| onError: t.onError, | ||
| isAuthReady: l, | ||
| hasCommentingFeature: () => t.commenting !== !1 && _.hasFeature("commenting") | ||
| }); | ||
| H({ | ||
| comments: F, | ||
| channel: b.channel | ||
| }); | ||
| let I = se({ | ||
| authManager: g, | ||
| onError: t.onError | ||
| }), R = c(!1), U = c(null), q = c(!1), X = ve({ | ||
| authManager: g, | ||
| getTemplateId: () => y.state.template?.id ?? null | ||
| }); | ||
| function Z(e) { | ||
| E.commentsOpen.value = !0, queueMicrotask(() => { | ||
| o()?.filterByBlock(e); | ||
| }); | ||
| } | ||
| a(V, j.handleRequestMedia), a(re, g), a(te, D), a(z, F), a(L, I), a(O, X), a(B, { | ||
| plan: _, | ||
| ai: D, | ||
| comments: { | ||
| getBlockCount: (e) => F.commentCountByBlock.value.get(e) ?? 0, | ||
| openForBlock: Z | ||
| }, | ||
| savedModules: { | ||
| openSaveDialog: (e) => { | ||
| U.value = e ?? null, R.value = !0; | ||
| }, | ||
| openBrowser: () => { | ||
| q.value = !0; | ||
| }, | ||
| moduleCount: f(() => I.modules.value.length) | ||
| } | ||
| }); | ||
| function ce(e) { | ||
| _.hasFeature("theme_customization") && (C.themeOverrides.value = e); | ||
| } | ||
| function le(e) { | ||
| y.setUiTheme(e); | ||
| } | ||
| async function de() { | ||
| s.value = !0, u.value = null; | ||
| try { | ||
| if (await g.initialize(), d) return; | ||
| l.value = !0; | ||
| let e = await G({ authManager: g }); | ||
| if (d) return; | ||
| if (!e.api.ok) throw Error("Health check failed: API is not reachable"); | ||
| if (!e.auth.ok) throw Error(`Health check failed: authentication error${e.auth.error ? ` - ${e.auth.error}` : ""}`); | ||
| if (e.websocket.ok || ne.warn("WebSocket health check failed:", e.websocket.error ?? "unknown error", "-- real-time features will be disabled."), await _.fetchConfig(), d) return; | ||
| r.setCustomFontsEnabled(_.hasFeature("custom_fonts")), t.customBlocks?.length && _.hasFeature("custom_blocks") && C.registerCustomBlocks(t.customBlocks), t.theme && _.hasFeature("theme_customization") && (C.themeOverrides.value = t.theme), t.modules !== !1 && _.hasFeature("saved_modules") && I.loadModules(), i("ready"); | ||
| } catch (e) { | ||
| if (d) return; | ||
| let n = e instanceof Error ? e : Error("Initialization failed", { cause: e }); | ||
| u.value = n, t.onError?.(n); | ||
| } finally { | ||
| d || (s.value = !1); | ||
| } | ||
| } | ||
| function Q() { | ||
| d = !0, r.cleanupFontLinks(), b.disconnect(), C.destroy(), t.onUnmount?.(); | ||
| } | ||
| return { | ||
| isInitializing: s, | ||
| isAuthReady: l, | ||
| initError: u, | ||
| isDestroyed: () => d, | ||
| authManager: g, | ||
| planConfigInstance: _, | ||
| websocket: b, | ||
| collaboration: x, | ||
| isCollaborationEnabled: S, | ||
| editor: y, | ||
| core: C, | ||
| aiConfig: D, | ||
| featureFlags: A, | ||
| mediaLib: j, | ||
| exporter: N, | ||
| testEmail: P, | ||
| commentsInstance: F, | ||
| savedModulesHeadless: I, | ||
| scoringInstance: X, | ||
| panelState: E, | ||
| snapshotPreview: T, | ||
| collabWarning: w, | ||
| showSaveModuleDialog: R, | ||
| showModuleBrowserModal: q, | ||
| saveModulePreSelectedBlockId: U, | ||
| onSaveHook: p, | ||
| initialize: de, | ||
| destroy: Q, | ||
| setThemeOverrides: ce, | ||
| setUiTheme: le, | ||
| openCommentsForBlock: Z | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/utils/preRenderCustomBlocks.ts | ||
| async function Le(e, t) { | ||
| let n = async (e) => { | ||
| if (N(e)) { | ||
| let n = e; | ||
| try { | ||
| n.renderedHtml = await t.renderCustomBlock(n); | ||
| } catch { | ||
| n.renderedHtml = `<!-- Custom block render error: ${n.customType} -->`; | ||
| } | ||
| } | ||
| if (e.type === "section" && "children" in e) { | ||
| let t = e; | ||
| for (let e of t.children) for (let t of e) await n(t); | ||
| } | ||
| }; | ||
| for (let t of e.blocks) await n(t); | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudLifecycle.ts | ||
| function Re(e) { | ||
| let { config: t, editor: n, websocket: r, planConfigInstance: i, snapshotPreview: a, core: o, exporter: s, featureFlags: c, isDestroyed: l } = e; | ||
| function u() { | ||
| return R(i.config.value.websocket); | ||
| } | ||
| async function d(e) { | ||
| let i = await n.create(e); | ||
| return l() ? i : (t.onCreate?.(i), a.initSnapshotHistory(), r.connect(i.id, u()), i); | ||
| } | ||
| async function f(e) { | ||
| let i = await n.load(e); | ||
| return l() ? i : (t.onLoad?.(i), a.initSnapshotHistory(), r.connect(i.id, u()), i); | ||
| } | ||
| async function p() { | ||
| c.isSaveExporting.value = !0, c.saveStatus.value = "idle"; | ||
| try { | ||
| if (await Le(n.content.value, o.registry), l()) throw Error("Component unmounted during save"); | ||
| let e = await n.save(); | ||
| if (l()) throw Error("Component unmounted during save"); | ||
| a.initSnapshotHistory(), a.snapshotHistoryInstance.value?.loadSnapshots(); | ||
| let r = await s.exportHtml(e.id); | ||
| if (l()) throw Error("Component unmounted during save"); | ||
| let i = { | ||
| templateId: e.id, | ||
| html: r.html, | ||
| mjml: r.mjml, | ||
| content: e.content | ||
| }; | ||
| return t.onSave?.(i), c.saveStatus.value = "saved", c.startSaveStatusClear(), i; | ||
| } catch (e) { | ||
| throw l() || (c.saveStatus.value = "error", c.saveErrorMessage.value = e instanceof Error ? e.message : "Save failed"), e; | ||
| } finally { | ||
| l() || (c.isSaveExporting.value = !1); | ||
| } | ||
| } | ||
| return { | ||
| createTemplate: d, | ||
| loadTemplate: f, | ||
| saveTemplate: p | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudSaveGate.ts | ||
| function ze(e) { | ||
| let t = c(!1), n = null, r = f(() => e.planConfig.value?.accessibility?.blockOnError === !0), i = f(() => r.value ? e.issues.value.filter((e) => e.severity === "error") : []), a = f(() => i.value.length > 0); | ||
| async function o(e) { | ||
| return a.value ? (n = e, t.value = !0, !1) : (await e(), !0); | ||
| } | ||
| async function s() { | ||
| let e = n; | ||
| n = null, t.value = !1, e && await e(); | ||
| } | ||
| function l() { | ||
| n = null, t.value = !1; | ||
| } | ||
| return { | ||
| shouldBlock: a, | ||
| blockingIssues: i, | ||
| modalOpen: t, | ||
| tryRunSave: o, | ||
| confirmAndSave: s, | ||
| cancel: l | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/components/CloudSaveGateModal.vue?vue&type=script&setup=true&lang.ts | ||
| var Be = ["aria-label"], Ve = { class: "tpl:flex tpl:max-h-[80vh] tpl:w-full tpl:max-w-md tpl:flex-col tpl:gap-4 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)] tpl:p-5 tpl:shadow-[var(--tpl-shadow-md)]" }, He = { class: "tpl:flex tpl:items-center tpl:gap-2" }, Ue = { class: "tpl:m-0 tpl:text-base tpl:font-semibold tpl:text-[var(--tpl-text)]" }, We = { class: "tpl:m-0 tpl:text-sm tpl:text-[var(--tpl-text-muted)]" }, Ge = { class: "tpl:m-0 tpl:flex tpl:max-h-64 tpl:list-none tpl:flex-col tpl:gap-1.5 tpl:overflow-y-auto tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-2" }, Ke = { class: "tpl:text-xs tpl:text-[var(--tpl-text)]" }, qe = { class: "tpl:font-mono tpl:text-[10px] tpl:text-[var(--tpl-text-dim)]" }, Je = { class: "tpl:flex tpl:justify-end tpl:gap-2" }, Ye = /* @__PURE__ */ E({ | ||
| __name: "CloudSaveGateModal", | ||
| props: { | ||
| open: { type: Boolean }, | ||
| issues: {} | ||
| }, | ||
| emits: ["cancel", "confirm"], | ||
| setup(e, { emit: t }) { | ||
| let n = t, { t: r } = Q(); | ||
| return (t, a) => (i(), v(y, { | ||
| "enter-active-class": "tpl:transition-opacity tpl:duration-150", | ||
| "leave-active-class": "tpl:transition-opacity tpl:duration-150", | ||
| "enter-from-class": "tpl:opacity-0", | ||
| "leave-to-class": "tpl:opacity-0" | ||
| }, { | ||
| default: s(() => [e.open ? (i(), p("div", { | ||
| key: 0, | ||
| role: "dialog", | ||
| "aria-modal": "true", | ||
| "aria-label": h(r).saveGate.title, | ||
| class: "tpl:fixed tpl:inset-0 tpl:z-50 tpl:flex tpl:items-center tpl:justify-center tpl:bg-black/40 tpl:p-6", | ||
| onClick: a[2] ||= _((e) => n("cancel"), ["self"]) | ||
| }, [x("div", Ve, [ | ||
| x("header", He, [D(h(de), { | ||
| size: 18, | ||
| "stroke-width": 2, | ||
| class: "tpl:text-[var(--tpl-warning)]" | ||
| }), x("h2", Ue, d(h(r).saveGate.title), 1)]), | ||
| x("p", We, d(h(r).saveGate.body), 1), | ||
| x("ul", Ge, [(i(!0), p(w, null, o(e.issues, (e) => (i(), p("li", { | ||
| key: `${e.ruleId}-${e.blockId ?? "template"}`, | ||
| class: "tpl:flex tpl:flex-col tpl:gap-0.5 tpl:rounded tpl:px-2 tpl:py-1.5" | ||
| }, [x("span", Ke, d(e.message), 1), x("span", qe, d(e.ruleId), 1)]))), 128))]), | ||
| x("footer", Je, [x("button", { | ||
| type: "button", | ||
| class: "tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)]", | ||
| onClick: a[0] ||= (e) => n("cancel") | ||
| }, d(h(r).saveGate.cancel), 1), x("button", { | ||
| type: "button", | ||
| class: "tpl:rounded-md tpl:bg-[var(--tpl-danger)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:text-white", | ||
| onClick: a[1] ||= (e) => n("confirm") | ||
| }, d(h(r).saveGate.confirm), 1)]) | ||
| ])], 8, Be)) : m("", !0)]), | ||
| _: 1 | ||
| })); | ||
| } | ||
| }), Xe = { | ||
| class: "tpl-header tpl:absolute tpl:top-0 tpl:right-0 tpl:left-0 tpl:z-50 tpl:grid tpl:h-14 tpl:grid-cols-[1fr_auto_1fr] tpl:items-center tpl:px-4", | ||
| style: { | ||
| "background-color": "color-mix(in srgb, var(--tpl-bg) 80%, transparent)", | ||
| "backdrop-filter": "blur(12px)", | ||
| "-webkit-backdrop-filter": "blur(12px)", | ||
| "box-shadow": "var(--tpl-shadow-md)", | ||
| "border-bottom": "1px solid var(--tpl-border)" | ||
| } | ||
| }, Ze = { class: "tpl-header-left tpl:flex tpl:min-w-[200px] tpl:items-center tpl:gap-3" }, Qe = { | ||
| key: 0, | ||
| class: "tpl:text-xs tpl:opacity-60 tpl:text-[var(--tpl-text-muted)]" | ||
| }, $e = { class: "tpl-header-center tpl:flex tpl:items-center tpl:justify-center tpl:gap-10" }, et = { class: "tpl-header-right tpl:flex tpl:min-w-[200px] tpl:items-center tpl:justify-end tpl:gap-3" }, tt = ["data-tooltip"], nt = { | ||
| key: 1, | ||
| "aria-live": "polite", | ||
| class: "tpl-status tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:text-[var(--tpl-success)]" | ||
| }, rt = { | ||
| key: 2, | ||
| "aria-live": "polite", | ||
| class: "tpl-status tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:text-[var(--tpl-text-muted)]" | ||
| }, it = ["aria-label", "aria-expanded"], at = { | ||
| key: 0, | ||
| class: "tpl:inline-flex tpl:size-4.5 tpl:items-center tpl:justify-center tpl:rounded-full tpl:text-[10px] tpl:font-semibold tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]" | ||
| }, ot = ["aria-expanded"], st = { | ||
| key: 0, | ||
| class: "tpl:absolute tpl:right-0 tpl:top-full tpl:z-50 tpl:mt-1 tpl:origin-top-right" | ||
| }, ct = ["disabled"], lt = ["disabled"], ut = /* @__PURE__ */ E({ | ||
| __name: "CloudHeader", | ||
| props: { | ||
| editor: {}, | ||
| core: {}, | ||
| featureFlags: {}, | ||
| panelState: {}, | ||
| snapshotPreview: {}, | ||
| commentsInstance: {}, | ||
| testEmail: {}, | ||
| websocket: {}, | ||
| collaboration: {}, | ||
| isCollaborationEnabled: { type: Boolean }, | ||
| isSaveDisabled: { type: Boolean }, | ||
| isSaving: { type: Boolean } | ||
| }, | ||
| emits: ["save"], | ||
| setup(e) { | ||
| let t = u(() => import("./CollaboratorBar-C4CFs5EJ.js")), n = u(() => import("./features-D-2kVhHY.js").then((e) => e.r)), r = u(() => import("./AiFeatureMenu-Dayzk2H7.js")), { t: a, format: o } = Q(); | ||
| return (c, l) => (i(), p("header", Xe, [ | ||
| x("div", Ze, [e.featureFlags.templateLimit.value === null ? m("", !0) : (i(), p("span", Qe, d(h(o)(h(a).header.templatesUsed, { | ||
| used: e.featureFlags.templateCount.value, | ||
| max: e.featureFlags.templateLimit.value | ||
| })), 1))]), | ||
| x("div", $e, [ | ||
| D(Se, { | ||
| viewport: e.editor.state.viewport, | ||
| onChange: e.editor.setViewport | ||
| }, null, 8, ["viewport", "onChange"]), | ||
| D(Oe, { | ||
| "dark-mode": e.editor.state.darkMode, | ||
| onChange: e.editor.setDarkMode | ||
| }, null, 8, ["dark-mode", "onChange"]), | ||
| D(we, { | ||
| "preview-mode": e.editor.state.previewMode, | ||
| onChange: e.editor.setPreviewMode | ||
| }, null, 8, ["preview-mode", "onChange"]), | ||
| e.collaboration && e.isCollaborationEnabled ? (i(), v(h(t), { | ||
| key: 0, | ||
| collaborators: e.collaboration.collaborators.value, | ||
| "is-connected": e.websocket.isConnected.value | ||
| }, null, 8, ["collaborators", "is-connected"])) : m("", !0), | ||
| e.snapshotPreview.snapshotHistoryInstance.value ? (i(), v(h(n), { | ||
| key: 1, | ||
| snapshots: e.snapshotPreview.snapshotHistorySnapshots.value, | ||
| "is-loading": e.snapshotPreview.snapshotHistoryIsLoading.value, | ||
| "is-restoring": e.snapshotPreview.snapshotHistoryIsRestoring.value, | ||
| onLoad: e.snapshotPreview.loadSnapshotHistory, | ||
| onNavigate: e.snapshotPreview.handleSnapshotNavigate | ||
| }, null, 8, [ | ||
| "snapshots", | ||
| "is-loading", | ||
| "is-restoring", | ||
| "onLoad", | ||
| "onNavigate" | ||
| ])) : m("", !0) | ||
| ]), | ||
| x("div", et, [ | ||
| e.featureFlags.saveStatus.value === "error" ? (i(), p("div", { | ||
| key: 0, | ||
| "aria-live": "assertive", | ||
| class: "tpl-tooltip tpl-status tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:text-[var(--tpl-danger)]", | ||
| "data-tooltip": e.featureFlags.saveErrorMessage.value | ||
| }, [D(h(j), { | ||
| size: 12, | ||
| "stroke-width": 2.5 | ||
| }), T(" " + d(h(a).header.saveFailed), 1)], 8, tt)) : e.featureFlags.saveStatus.value === "saved" ? (i(), p("div", nt, [D(h(A), { | ||
| size: 12, | ||
| "stroke-width": 2.5 | ||
| }), T(" " + d(h(a).header.saved), 1)])) : e.editor.state.isDirty ? (i(), p("div", rt, [l[4] ||= x("span", { class: "tpl-pulse tpl:size-1.5 tpl:rounded-full tpl:bg-[var(--tpl-primary)]" }, null, -1), T(" " + d(h(a).header.unsaved), 1)])) : m("", !0), | ||
| e.commentsInstance.isEnabled.value && e.featureFlags.hasTemplateSaved.value ? (i(), p("button", { | ||
| key: 3, | ||
| "aria-label": e.commentsInstance.unresolvedCount.value > 0 ? `${h(a).comments.button} (${e.commentsInstance.unresolvedCount.value})` : h(a).comments.button, | ||
| "aria-expanded": e.panelState.commentsOpen.value, | ||
| class: b(h($)), | ||
| style: C({ | ||
| backgroundColor: e.panelState.commentsOpen.value ? "var(--tpl-primary)" : "transparent", | ||
| color: e.panelState.commentsOpen.value ? "var(--tpl-bg)" : "var(--tpl-primary)", | ||
| borderColor: "var(--tpl-primary)" | ||
| }), | ||
| onClick: l[0] ||= (t) => e.panelState.commentsOpen.value = !e.panelState.commentsOpen.value | ||
| }, [ | ||
| D(h(U), { | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| }), | ||
| T(" " + d(h(a).comments.button) + " ", 1), | ||
| e.commentsInstance.unresolvedCount.value > 0 && !e.panelState.commentsOpen.value ? (i(), p("span", at, d(e.commentsInstance.unresolvedCount.value), 1)) : m("", !0) | ||
| ], 14, it)) : m("", !0), | ||
| e.featureFlags.canUseAiGeneration.value && e.featureFlags.hasTemplateSaved.value ? (i(), p("div", { | ||
| key: 4, | ||
| ref: (t) => e.panelState.aiMenuRef.value = t, | ||
| class: "tpl:relative" | ||
| }, [x("button", { | ||
| "aria-expanded": e.panelState.aiMenuOpen.value, | ||
| class: b(["tpl-ai-btn tpl:inline-flex tpl:items-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:px-4 tpl:py-2 tpl:text-sm tpl:font-semibold tpl:whitespace-nowrap tpl:transition-all tpl:duration-200", e.panelState.aiButtonActive.value ? "tpl-ai-btn--active" : "tpl-ai-btn--idle"]), | ||
| onClick: l[1] ||= _((...t) => e.panelState.toggleAiMenu && e.panelState.toggleAiMenu(...t), ["stop"]) | ||
| }, [D(h(pe), { | ||
| size: 16, | ||
| "stroke-width": 2, | ||
| class: "tpl-ai-btn-icon" | ||
| }), T(" " + d(h(a).aiChat.button), 1)], 10, ot), D(y, { | ||
| "enter-active-class": "tpl:transition-all tpl:duration-150 tpl:ease-out", | ||
| "enter-from-class": "tpl:scale-95 tpl:opacity-0", | ||
| "enter-to-class": "tpl:scale-100 tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-all tpl:duration-100 tpl:ease-in", | ||
| "leave-from-class": "tpl:scale-100 tpl:opacity-100", | ||
| "leave-to-class": "tpl:scale-95 tpl:opacity-0" | ||
| }, { | ||
| default: s(() => [e.panelState.aiMenuOpen.value ? (i(), p("div", st, [D(h(r), { | ||
| "active-feature": e.panelState.activeAiFeature.value, | ||
| onSelect: e.panelState.handleAiFeatureSelect | ||
| }, null, 8, ["active-feature", "onSelect"])])) : m("", !0)]), | ||
| _: 1 | ||
| })], 512)) : m("", !0), | ||
| e.testEmail.isEnabled.value && e.featureFlags.canSendTestEmail.value ? (i(), p("button", { | ||
| key: 5, | ||
| class: b(h($)), | ||
| style: { | ||
| "background-color": "transparent", | ||
| color: "var(--tpl-primary)", | ||
| "border-color": "var(--tpl-primary)" | ||
| }, | ||
| disabled: e.testEmail.isSending.value || !e.featureFlags.hasTemplateSaved.value, | ||
| onClick: l[2] ||= (t) => e.panelState.testEmailModalOpen.value = !0 | ||
| }, [e.testEmail.isSending.value ? (i(), v(h(he), { | ||
| key: 1, | ||
| class: "tpl-spinner", | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })) : (i(), v(h(ce), { | ||
| key: 0, | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })), T(" " + d(h(a).testEmail.button), 1)], 10, ct)) : m("", !0), | ||
| x("button", { | ||
| class: b(h($)), | ||
| style: { | ||
| "background-color": "transparent", | ||
| color: "var(--tpl-primary)", | ||
| "border-color": "var(--tpl-primary)" | ||
| }, | ||
| disabled: e.isSaveDisabled, | ||
| onClick: l[3] ||= (e) => c.$emit("save") | ||
| }, [e.isSaving ? (i(), v(h(he), { | ||
| key: 1, | ||
| class: "tpl-spinner", | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })) : (i(), v(h(xe), { | ||
| key: 0, | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })), T(" " + d(e.isSaving ? h(a).header.saving : h(a).header.save), 1)], 10, lt) | ||
| ]) | ||
| ])); | ||
| } | ||
| }), dt = /* @__PURE__ */ E({ | ||
| __name: "CloudPanels", | ||
| props: { | ||
| config: {}, | ||
| editor: {}, | ||
| core: {}, | ||
| panelState: {}, | ||
| planConfigInstance: {}, | ||
| testEmail: {}, | ||
| mediaLib: {}, | ||
| savedModulesHeadless: {}, | ||
| showSaveModuleDialog: { type: Boolean }, | ||
| saveModulePreSelectedBlockId: {}, | ||
| showModuleBrowserModal: { type: Boolean } | ||
| }, | ||
| emits: [ | ||
| "update:showSaveModuleDialog", | ||
| "update:saveModulePreSelectedBlockId", | ||
| "update:showModuleBrowserModal", | ||
| "send-test-email", | ||
| "module-insert" | ||
| ], | ||
| setup(e, { expose: t, emit: n }) { | ||
| let r = u(() => import("./features-D-2kVhHY.js").then((e) => e.o)), a = u(() => import("./features-D-2kVhHY.js").then((e) => e.a)), o = u(() => import("./features-D-2kVhHY.js").then((e) => e.i)), s = u(() => import("./features-D-2kVhHY.js").then((e) => e.n)), l = u(() => import("./features-D-2kVhHY.js").then((e) => e.t)), d = u(() => import("./SaveModuleDialog-BrtDXzIz.js")), f = u(() => import("./ModuleBrowserModal-Cgjz4xAz.js")), g = u(async () => { | ||
| try { | ||
| return (await import("./src-ftxPuuQh.js")).MediaLibraryModal; | ||
| } catch { | ||
| throw Error("[Templatical] Cloud media library requires the optional peer dependency '@templatical/media-library'. Please install it."); | ||
| } | ||
| }), _ = n; | ||
| function y(e, t, n) { | ||
| t.history.record(), n.setContent(e), t.conditionPreview.reset(); | ||
| } | ||
| function b(e, t) { | ||
| _("module-insert", e, t); | ||
| } | ||
| let x = c(null); | ||
| function S(e) { | ||
| x.value?.filterByBlock(e); | ||
| } | ||
| return t({ filterCommentsByBlock: S }), (t, n) => (i(), p(w, null, [ | ||
| D(h(r), { | ||
| visible: e.panelState.aiChatOpen.value, | ||
| "on-apply": (t) => y(t, e.core, e.editor), | ||
| onClose: n[0] ||= (t) => e.panelState.aiChatOpen.value = !1 | ||
| }, null, 8, ["visible", "on-apply"]), | ||
| D(h(s), { | ||
| visible: e.panelState.scoringPanelOpen.value, | ||
| onClose: n[1] ||= (t) => e.panelState.scoringPanelOpen.value = !1 | ||
| }, null, 8, ["visible"]), | ||
| D(h(o), { | ||
| visible: e.panelState.designReferenceOpen.value, | ||
| "has-existing-blocks": e.editor.content.value.blocks.length > 0, | ||
| onClose: n[2] ||= (t) => e.panelState.designReferenceOpen.value = !1, | ||
| onApply: n[3] ||= (t) => y(t, e.core, e.editor) | ||
| }, null, 8, ["visible", "has-existing-blocks"]), | ||
| D(h(a), { | ||
| ref_key: "commentsSidebar", | ||
| ref: x, | ||
| visible: e.panelState.commentsOpen.value, | ||
| onClose: n[4] ||= (t) => e.panelState.commentsOpen.value = !1 | ||
| }, null, 8, ["visible"]), | ||
| D(h(l), { | ||
| visible: e.panelState.testEmailModalOpen.value, | ||
| "allowed-emails": e.testEmail.allowedEmails.value, | ||
| "is-sending": e.testEmail.isSending.value, | ||
| error: e.testEmail.error.value, | ||
| onSend: n[5] ||= (e) => _("send-test-email", e), | ||
| onClose: n[6] ||= (t) => e.panelState.testEmailModalOpen.value = !1 | ||
| }, null, 8, [ | ||
| "visible", | ||
| "allowed-emails", | ||
| "is-sending", | ||
| "error" | ||
| ]), | ||
| e.planConfigInstance.hasFeature("saved_modules") && e.config.modules !== !1 ? (i(), v(h(d), { | ||
| key: 0, | ||
| visible: e.showSaveModuleDialog, | ||
| "pre-selected-block-id": e.saveModulePreSelectedBlockId, | ||
| onClose: n[7] ||= (e) => { | ||
| _("update:showSaveModuleDialog", !1), _("update:saveModulePreSelectedBlockId", null); | ||
| }, | ||
| onSaved: n[8] ||= (t) => e.savedModulesHeadless.loadModules() | ||
| }, null, 8, ["visible", "pre-selected-block-id"])) : m("", !0), | ||
| e.planConfigInstance.hasFeature("saved_modules") && e.config.modules !== !1 ? (i(), v(h(f), { | ||
| key: 1, | ||
| visible: e.showModuleBrowserModal, | ||
| onClose: n[9] ||= (e) => _("update:showModuleBrowserModal", !1), | ||
| onInsert: b | ||
| }, null, 8, ["visible"])) : m("", !0), | ||
| D(h(g), { | ||
| visible: e.panelState.mediaLibraryOpen.value, | ||
| accept: e.panelState.mediaLibraryAccept.value, | ||
| "popover-target": e.core.popoverRoot.value, | ||
| onSelect: e.mediaLib.handleMediaSelect, | ||
| onClose: e.mediaLib.handleMediaLibraryClose | ||
| }, null, 8, [ | ||
| "visible", | ||
| "accept", | ||
| "popover-target", | ||
| "onSelect", | ||
| "onClose" | ||
| ]) | ||
| ], 64)); | ||
| } | ||
| }), ft = { | ||
| key: 0, | ||
| class: "tpl-loading tpl:absolute tpl:inset-0 tpl:z-overlay tpl:flex tpl:flex-col tpl:bg-[var(--tpl-bg)]" | ||
| }, pt = { class: "tpl:flex tpl:flex-1 tpl:overflow-hidden" }, mt = { class: "tpl:flex tpl:w-12 tpl:shrink-0 tpl:flex-col tpl:items-center tpl:gap-4 tpl:py-5 tpl:border-r tpl:border-[var(--tpl-border)]" }, ht = /* @__PURE__ */ E({ | ||
| __name: "CloudLoadingOverlay", | ||
| props: { visible: { type: Boolean } }, | ||
| setup(e) { | ||
| return (t, n) => e.visible ? (i(), p("div", ft, [n[1] ||= l("<div class=\"tpl:flex tpl:h-14 tpl:shrink-0 tpl:items-center tpl:justify-between tpl:px-4 tpl:border-b tpl:border-[var(--tpl-border)]\"><div class=\"tpl-shimmer tpl:h-5 tpl:w-28 tpl:rounded-[var(--tpl-radius-sm)]\"></div><div class=\"tpl:flex tpl:gap-3\"><div class=\"tpl-shimmer tpl:h-8 tpl:w-20 tpl:rounded-[var(--tpl-radius-sm)]\"></div><div class=\"tpl-shimmer tpl:h-8 tpl:w-20 tpl:rounded-[var(--tpl-radius-sm)]\"></div></div></div>", 1), x("div", pt, [x("div", mt, [(i(), p(w, null, o(5, (e) => x("div", { | ||
| key: e, | ||
| class: "tpl-shimmer tpl:size-7 tpl:rounded-[var(--tpl-radius-sm)]" | ||
| })), 64))]), n[0] ||= l("<div class=\"tpl:flex tpl:flex-1 tpl:items-start tpl:justify-center tpl:overflow-auto tpl:p-8 tpl:bg-[var(--tpl-canvas-bg)]\"><div class=\"tpl:w-full tpl:max-w-[600px] tpl:rounded-[var(--tpl-radius)] tpl:p-6 tpl:bg-[var(--tpl-bg)] tpl:shadow-[var(--tpl-shadow-sm)]\"><div class=\"tpl:space-y-2 tpl:py-4\"><div class=\"tpl-shimmer tpl:h-3 tpl:w-3/4 tpl:rounded\"></div><div class=\"tpl-shimmer tpl:h-3 tpl:w-full tpl:rounded\"></div><div class=\"tpl-shimmer tpl:h-3 tpl:w-5/6 tpl:rounded\"></div></div><div class=\"tpl:py-4\"><div class=\"tpl-shimmer tpl:h-44 tpl:w-full tpl:rounded-[var(--tpl-radius-sm)]\"></div></div><div class=\"tpl:space-y-2 tpl:py-4\"><div class=\"tpl-shimmer tpl:h-3 tpl:w-full tpl:rounded\"></div><div class=\"tpl-shimmer tpl:h-3 tpl:w-2/3 tpl:rounded\"></div></div><div class=\"tpl:flex tpl:justify-center tpl:py-4\"><div class=\"tpl-shimmer tpl:h-10 tpl:w-36 tpl:rounded-[var(--tpl-radius-sm)]\"></div></div><div class=\"tpl:space-y-2 tpl:py-4\"><div class=\"tpl-shimmer tpl:mx-auto tpl:h-2.5 tpl:w-1/2 tpl:rounded\"></div><div class=\"tpl-shimmer tpl:mx-auto tpl:h-2.5 tpl:w-1/3 tpl:rounded\"></div></div></div></div><div class=\"tpl:flex tpl:w-[320px] tpl:shrink-0 tpl:flex-col tpl:gap-4 tpl:p-4 tpl:border-l tpl:border-[var(--tpl-border)]\"><div class=\"tpl-shimmer tpl:h-8 tpl:rounded-[var(--tpl-radius-sm)]\"></div><div class=\"tpl-shimmer tpl:h-32 tpl:rounded-[var(--tpl-radius)]\"></div><div class=\"tpl-shimmer tpl:h-32 tpl:rounded-[var(--tpl-radius)]\"></div></div>", 2)])])) : m("", !0); | ||
| } | ||
| }), gt = { | ||
| key: 0, | ||
| role: "alert", | ||
| class: "tpl-error tpl:absolute tpl:inset-0 tpl:z-overlay tpl:flex tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-6 tpl:px-8 tpl:bg-[var(--tpl-bg)]" | ||
| }, _t = { class: "tpl:flex tpl:size-16 tpl:items-center tpl:justify-center tpl:rounded-full tpl:bg-[var(--tpl-danger-light)]" }, vt = { class: "tpl:flex tpl:flex-col tpl:items-center tpl:gap-2 tpl:text-center" }, yt = { class: "tpl:text-lg tpl:font-semibold tpl:text-[var(--tpl-text)]" }, bt = { class: "tpl:max-w-md tpl:text-sm tpl:text-[var(--tpl-text-muted)]" }, xt = /* @__PURE__ */ E({ | ||
| __name: "CloudErrorOverlay", | ||
| props: { | ||
| error: {}, | ||
| visible: { type: Boolean } | ||
| }, | ||
| emits: ["retry"], | ||
| setup(e, { emit: t }) { | ||
| let n = t, { t: r } = Q(); | ||
| function a(e) { | ||
| return "isUnauthorized" in e && e.isUnauthorized ? r.error.authFailed : "isNotFound" in e && e.isNotFound ? r.error.templateNotFound : r.error.defaultMessage; | ||
| } | ||
| function o(e) { | ||
| return "isNotFound" in e && !!e.isNotFound; | ||
| } | ||
| return (t, s) => e.visible && e.error ? (i(), p("div", gt, [ | ||
| x("div", _t, [D(h(j), { | ||
| size: 32, | ||
| "stroke-width": 1.5, | ||
| class: "tpl:text-[var(--tpl-danger)]" | ||
| })]), | ||
| x("div", vt, [x("h2", yt, d(h(r).error.title), 1), x("p", bt, d(a(e.error)), 1)]), | ||
| o(e.error) ? m("", !0) : (i(), p("button", { | ||
| key: 0, | ||
| class: "tpl-btn tpl-btn-primary tpl:inline-flex tpl:items-center tpl:gap-2 tpl:rounded-md tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:shadow-xs tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]", | ||
| onClick: s[0] ||= (e) => n("retry") | ||
| }, d(h(r).error.retry), 1)) | ||
| ])) : m("", !0); | ||
| } | ||
| }), St = { | ||
| key: 0, | ||
| class: "tpl-preview-banner tpl:absolute tpl:top-14 tpl:right-0 tpl:left-0 tpl:z-40 tpl:flex tpl:items-center tpl:justify-center tpl:gap-4 tpl:px-4 tpl:py-3 tpl:bg-[var(--tpl-primary-light)] tpl:border-b tpl:border-[var(--tpl-primary)]" | ||
| }, Ct = { class: "tpl:flex tpl:items-center tpl:gap-2 tpl:text-sm tpl:text-[var(--tpl-text)]" }, wt = { class: "tpl:flex tpl:items-center tpl:gap-2" }, Tt = /* @__PURE__ */ E({ | ||
| __name: "SnapshotPreviewBanner", | ||
| props: { visible: { type: Boolean } }, | ||
| emits: ["cancel", "confirm"], | ||
| setup(e, { emit: t }) { | ||
| let n = t, { t: r } = Q(); | ||
| return (t, a) => e.visible ? (i(), p("div", St, [x("div", Ct, [D(h(P), { | ||
| size: 18, | ||
| "stroke-width": 2, | ||
| class: "tpl:text-[var(--tpl-primary)]" | ||
| }), x("span", null, d(h(r).snapshotPreview.message), 1)]), x("div", wt, [x("button", { | ||
| class: "tpl:rounded-md tpl:px-3 tpl:py-1.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]", | ||
| style: { "background-color": "transparent" }, | ||
| onClick: a[0] ||= (e) => n("cancel") | ||
| }, d(h(r).snapshotPreview.cancel), 1), x("button", { | ||
| class: "tpl:rounded-md tpl:px-3 tpl:py-1.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]", | ||
| onClick: a[1] ||= (e) => n("confirm") | ||
| }, d(h(r).snapshotPreview.restore), 1)])])) : m("", !0); | ||
| } | ||
| }), Et = { | ||
| key: 0, | ||
| role: "status", | ||
| "aria-live": "polite", | ||
| class: "tpl:absolute tpl:top-16 tpl:left-1/2 tpl:z-toast tpl:-translate-x-1/2 tpl:rounded-[var(--tpl-radius)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:shadow-lg", | ||
| style: { | ||
| "background-color": "var(--tpl-warning-light)", | ||
| color: "var(--tpl-text)", | ||
| border: "1px solid var(--tpl-warning)" | ||
| } | ||
| }, Dt = /* @__PURE__ */ E({ | ||
| __name: "CollabUndoToast", | ||
| props: { visible: { type: Boolean } }, | ||
| setup(e) { | ||
| let { t } = F(); | ||
| return (n, r) => e.visible ? (i(), p("div", Et, d(h(t).history.collabWarning), 1)) : m("", !0); | ||
| } | ||
| }), Ot = ["data-tpl-theme"], kt = { class: "tpl:sticky tpl:top-0 tpl:z-40 tpl:h-0" }, At = { class: "tpl-main tpl:flex tpl:justify-center tpl:p-8" }, jt = ["aria-label"], Mt = /* @__PURE__ */ le(/* @__PURE__ */ E({ | ||
| __name: "CloudEditor", | ||
| props: { | ||
| config: {}, | ||
| translations: {}, | ||
| cloudTranslations: {}, | ||
| fontsManager: {}, | ||
| shadowRoot: {} | ||
| }, | ||
| emits: ["ready"], | ||
| setup(e, { expose: r, emit: o }) { | ||
| let l = e; | ||
| a(I, l.cloudTranslations); | ||
| let u = o, f = c(null), _ = c(null), w = Ie({ | ||
| config: l.config, | ||
| translations: l.translations, | ||
| fontsManager: l.fontsManager, | ||
| emit: u, | ||
| getCommentsSidebar: () => f.value ? { filterByBlock: f.value.filterCommentsByBlock } : null, | ||
| editorRoot: l.shadowRoot, | ||
| containerEl: _ | ||
| }), { isInitializing: E, isAuthReady: ee, initError: O, planConfigInstance: k, websocket: A, collaboration: j, isCollaborationEnabled: M, editor: N, core: P, featureFlags: F, mediaLib: te, exporter: ne, testEmail: L, commentsInstance: re, savedModulesHeadless: R, panelState: z, snapshotPreview: B, collabWarning: ie, showSaveModuleDialog: V, showModuleBrowserModal: H, saveModulePreSelectedBlockId: U, setThemeOverrides: W, setUiTheme: G } = w; | ||
| async function K(e) { | ||
| try { | ||
| await L.sendTestEmail(e), z.testEmailModalOpen.value = !1; | ||
| } catch {} | ||
| } | ||
| function q(e, t) { | ||
| for (let n = 0; n < e.content.length; n++) { | ||
| let r = _e(e.content[n]), i = t === void 0 ? void 0 : t + n; | ||
| N.addBlock(r, void 0, void 0, i); | ||
| } | ||
| H.value = !1; | ||
| } | ||
| let J = Re({ | ||
| config: l.config, | ||
| editor: N, | ||
| websocket: A, | ||
| planConfigInstance: k, | ||
| snapshotPreview: B, | ||
| core: P, | ||
| exporter: ne, | ||
| featureFlags: F, | ||
| isDestroyed: w.isDestroyed | ||
| }), Y = ze({ | ||
| issues: P.templateLint ? P.templateLint.issues : c([]), | ||
| planConfig: k.config | ||
| }); | ||
| async function X() { | ||
| await Y.tryRunSave(() => J.saveTemplate().catch((e) => l.config.onError?.(e))); | ||
| } | ||
| return w.onSaveHook.value = X, t(() => { | ||
| w.initialize(); | ||
| }), g(() => { | ||
| w.destroy(); | ||
| }), r({ | ||
| getContent: () => N.content.value, | ||
| setContent: (e) => N.setContent(e), | ||
| setTheme: G, | ||
| setThemeOverrides: W, | ||
| create: J.createTemplate, | ||
| load: J.loadTemplate, | ||
| save: J.saveTemplate, | ||
| sendTestEmail: L.sendTestEmail | ||
| }), (t, r) => (i(), p("div", { | ||
| ref_key: "rootEl", | ||
| ref: _, | ||
| class: b(["tpl tpl:relative tpl:h-full tpl:overflow-hidden", { "tpl:dark": h(N).state.darkMode }]), | ||
| "data-tpl-theme": h(P).resolvedTheme.value, | ||
| style: C(h(P).themeStyles.value) | ||
| }, [ | ||
| D(y, { | ||
| "enter-active-class": "tpl:transition-opacity tpl:duration-200", | ||
| "enter-from-class": "tpl:opacity-100", | ||
| "enter-to-class": "tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-opacity tpl:duration-300", | ||
| "leave-from-class": "tpl:opacity-100", | ||
| "leave-to-class": "tpl:opacity-0" | ||
| }, { | ||
| default: s(() => [D(ht, { visible: h(E) || h(N).state.isLoading }, null, 8, ["visible"])]), | ||
| _: 1 | ||
| }), | ||
| D(y, { | ||
| "enter-active-class": "tpl:transition-opacity tpl:duration-200", | ||
| "enter-from-class": "tpl:opacity-0", | ||
| "enter-to-class": "tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-opacity tpl:duration-300", | ||
| "leave-from-class": "tpl:opacity-100", | ||
| "leave-to-class": "tpl:opacity-0" | ||
| }, { | ||
| default: s(() => [D(xt, { | ||
| error: h(O), | ||
| visible: !!h(O) && !h(E), | ||
| onRetry: h(w).initialize | ||
| }, null, 8, [ | ||
| "error", | ||
| "visible", | ||
| "onRetry" | ||
| ])]), | ||
| _: 1 | ||
| }), | ||
| D(ut, { | ||
| editor: h(N), | ||
| core: h(P), | ||
| "feature-flags": h(F), | ||
| "panel-state": h(z), | ||
| "snapshot-preview": h(B), | ||
| "comments-instance": h(re), | ||
| "test-email": h(L), | ||
| websocket: h(A), | ||
| collaboration: h(j), | ||
| "is-collaboration-enabled": h(M), | ||
| "is-saving": h(N).state.isSaving || h(F).isSaveExporting.value, | ||
| "is-save-disabled": h(N).state.isSaving || h(F).isSaveExporting.value || !h(N).state.isDirty, | ||
| onSave: X | ||
| }, null, 8, [ | ||
| "editor", | ||
| "core", | ||
| "feature-flags", | ||
| "panel-state", | ||
| "snapshot-preview", | ||
| "comments-instance", | ||
| "test-email", | ||
| "websocket", | ||
| "collaboration", | ||
| "is-collaboration-enabled", | ||
| "is-saving", | ||
| "is-save-disabled" | ||
| ]), | ||
| D(Ye, { | ||
| open: h(Y).modalOpen.value, | ||
| issues: h(Y).blockingIssues.value, | ||
| onCancel: h(Y).cancel, | ||
| onConfirm: h(Y).confirmAndSave | ||
| }, null, 8, [ | ||
| "open", | ||
| "issues", | ||
| "onCancel", | ||
| "onConfirm" | ||
| ]), | ||
| D(Tt, { | ||
| visible: h(B).isPreviewingSnapshot.value, | ||
| onCancel: h(B).cancelPreview, | ||
| onConfirm: h(B).confirmRestoreSnapshot | ||
| }, null, 8, [ | ||
| "visible", | ||
| "onCancel", | ||
| "onConfirm" | ||
| ]), | ||
| D(y, { | ||
| "enter-active-class": "tpl:transition-all tpl:duration-200 tpl:ease-out", | ||
| "enter-from-class": "tpl:translate-y-[-8px] tpl:opacity-0", | ||
| "enter-to-class": "tpl:translate-y-0 tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-all tpl:duration-300 tpl:ease-in", | ||
| "leave-from-class": "tpl:translate-y-0 tpl:opacity-100", | ||
| "leave-to-class": "tpl:translate-y-[-8px] tpl:opacity-0" | ||
| }, { | ||
| default: s(() => [D(Dt, { visible: h(ie).collabUndoWarningVisible.value }, null, 8, ["visible"])]), | ||
| _: 1 | ||
| }), | ||
| n(D(ke, null, null, 512), [[S, !h(N).state.previewMode]]), | ||
| x("div", { | ||
| class: b(["tpl-body tpl:absolute tpl:bottom-0 tpl:overflow-auto", [h(N).state.previewMode ? "tpl:left-0 tpl:right-0" : h(z).rightPanelOpen.value ? "tpl:left-12 tpl:right-[680px]" : "tpl:left-12 tpl:right-[320px]", h(B).isPreviewingSnapshot.value ? "tpl:top-[104px]" : "tpl:top-14"]]), | ||
| style: { | ||
| transition: "all 300ms cubic-bezier(0.34, 1.56, 0.64, 1)", | ||
| "background-color": "var(--tpl-canvas-bg)" | ||
| } | ||
| }, [x("div", kt, [D(y, { name: "tpl-restore-btn" }, { | ||
| default: s(() => [h(P).conditionPreview.hasHiddenBlocks.value ? (i(), p("button", { | ||
| key: 0, | ||
| class: "tpl:absolute tpl:left-1/2 tpl:top-2 tpl:-translate-x-1/2 tpl:inline-flex tpl:items-center tpl:gap-1.5 tpl:rounded-full tpl:border tpl:px-3.5 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:whitespace-nowrap tpl:shadow-md tpl:hover:opacity-80", | ||
| style: { | ||
| "background-color": "var(--tpl-warning-light)", | ||
| color: "var(--tpl-warning)", | ||
| "border-color": "var(--tpl-warning)", | ||
| "backdrop-filter": "blur(8px)" | ||
| }, | ||
| onClick: r[0] ||= (e) => h(P).conditionPreview.reset() | ||
| }, [D(h(be), { | ||
| size: 13, | ||
| "stroke-width": 2 | ||
| }), T(" " + d(h(P).t.blockSettings.restoreHiddenBlocks), 1)])) : m("", !0)]), | ||
| _: 1 | ||
| })]), x("main", At, [D(Ce, { | ||
| viewport: h(N).state.viewport, | ||
| content: h(N).content.value, | ||
| "selected-block-id": h(N).state.selectedBlockId, | ||
| "dark-mode": h(N).state.darkMode, | ||
| "preview-mode": h(N).state.previewMode, | ||
| "locked-blocks": h(j)?.lockedBlocks.value ?? void 0, | ||
| onSelectBlock: h(N).selectBlock, | ||
| onOpenAiChat: r[1] ||= (e) => h(z).aiChatOpen.value = !0, | ||
| onOpenDesignReference: r[2] ||= (e) => h(z).designReferenceOpen.value = !0 | ||
| }, null, 8, [ | ||
| "viewport", | ||
| "content", | ||
| "selected-block-id", | ||
| "dark-mode", | ||
| "preview-mode", | ||
| "locked-blocks", | ||
| "onSelectBlock" | ||
| ])])], 2), | ||
| e.config.branding !== !1 && !h(F).isWhiteLabeled.value ? (i(), v(Ee, { | ||
| key: 0, | ||
| "position-class": [h(N).state.previewMode ? "tpl:left-0 tpl:right-0" : h(z).rightPanelOpen.value ? "tpl:left-12 tpl:right-[680px]" : "tpl:left-12 tpl:right-[320px]"] | ||
| }, null, 8, ["position-class"])) : m("", !0), | ||
| x("div", { | ||
| class: "tpl-sr-only", | ||
| role: "status", | ||
| "aria-live": "polite", | ||
| "aria-atomic": "true", | ||
| "aria-label": h(P).t.landmarks.reorderAnnouncements | ||
| }, d(h(P).keyboardReorder.announcement.value), 9, jt), | ||
| n(D(De, { | ||
| "selected-block": h(N).selectedBlock.value, | ||
| settings: h(N).content.value.settings, | ||
| "shifted-left": h(z).rightPanelOpen.value, | ||
| onUpdateBlock: r[3] ||= (e) => h(N).updateBlock(h(N).selectedBlock.value.id, e), | ||
| onDeleteBlock: r[4] ||= (e) => h(P).blockActions.deleteBlock(h(N).selectedBlock.value.id), | ||
| onDuplicateBlock: r[5] ||= (e) => h(P).blockActions.duplicateBlock(h(N).selectedBlock.value), | ||
| onUpdateSettings: h(N).updateSettings | ||
| }, null, 8, [ | ||
| "selected-block", | ||
| "settings", | ||
| "shifted-left", | ||
| "onUpdateSettings" | ||
| ]), [[S, !h(N).state.previewMode]]), | ||
| !h(E) && h(ee) ? (i(), v(dt, { | ||
| key: 1, | ||
| ref_key: "cloudPanelsRef", | ||
| ref: f, | ||
| config: l.config, | ||
| editor: h(N), | ||
| core: h(P), | ||
| "panel-state": h(z), | ||
| "plan-config-instance": h(k), | ||
| "test-email": h(L), | ||
| "media-lib": h(te), | ||
| "saved-modules-headless": h(R), | ||
| "show-save-module-dialog": h(V), | ||
| "save-module-pre-selected-block-id": h(U), | ||
| "show-module-browser-modal": h(H), | ||
| "onUpdate:showSaveModuleDialog": r[6] ||= (e) => V.value = e, | ||
| "onUpdate:saveModulePreSelectedBlockId": r[7] ||= (e) => U.value = e, | ||
| "onUpdate:showModuleBrowserModal": r[8] ||= (e) => H.value = e, | ||
| onSendTestEmail: K, | ||
| onModuleInsert: q | ||
| }, null, 8, [ | ||
| "config", | ||
| "editor", | ||
| "core", | ||
| "panel-state", | ||
| "plan-config-instance", | ||
| "test-email", | ||
| "media-lib", | ||
| "saved-modules-headless", | ||
| "show-save-module-dialog", | ||
| "save-module-pre-selected-block-id", | ||
| "show-module-browser-modal" | ||
| ])) : m("", !0), | ||
| x("div", { | ||
| ref: (e) => h(P).popoverRoot.value = e, | ||
| class: "tpl-popover-root" | ||
| }, null, 512), | ||
| D(Ae) | ||
| ], 14, Ot)); | ||
| } | ||
| }), [["__scopeId", "data-v-3f0f5cfa"]]); | ||
| //#endregion | ||
| export { Mt as default }; | ||
| //# sourceMappingURL=CloudEditor-CrZk-OwQ.js.map |
Sorry, the diff of this file is too big to display
| import { n as e } from "./rolldown-runtime-Dqa2HsxW.js"; | ||
| import { An as t, Dn as n, En as r, Fn as i, In as a, Ln as o, Mn as s, Nn as c, On as l, Pn as u, Rn as d, Tn as f, jn as p, kn as m } from "./features-D-2kVhHY.js"; | ||
| //#endregion | ||
| //#region ../renderer/src/render-context.ts | ||
| var h = `https://unpkg.com/@templatical/renderer@${{ | ||
| name: "@templatical/renderer", | ||
| description: "Render Templatical email templates to MJML", | ||
| version: "0.9.1", | ||
| bugs: "https://github.com/templatical/sdk/issues", | ||
| dependencies: { "@templatical/types": "workspace:*" }, | ||
| devDependencies: { | ||
| "@resvg/resvg-js": "^2.6.2", | ||
| mjml: "^5.2.2", | ||
| tsup: "^8.5.1", | ||
| typescript: "^6.0.3", | ||
| vitest: "^4.1.7" | ||
| }, | ||
| exports: { ".": { | ||
| types: "./dist/index.d.ts", | ||
| import: "./dist/index.js" | ||
| } }, | ||
| files: ["dist", "assets"], | ||
| homepage: "https://templatical.com", | ||
| keywords: [ | ||
| "email", | ||
| "email-template", | ||
| "html-email", | ||
| "mjml", | ||
| "renderer", | ||
| "templatical" | ||
| ], | ||
| license: "MIT", | ||
| module: "./dist/index.js", | ||
| publishConfig: { access: "public" }, | ||
| repository: { | ||
| type: "git", | ||
| url: "git+https://github.com/templatical/sdk.git", | ||
| directory: "packages/renderer" | ||
| }, | ||
| scripts: { | ||
| build: "tsup && node scripts/rasterize-social.mjs", | ||
| test: "vitest run --config vitest.config.ts", | ||
| typecheck: "tsc --noEmit" | ||
| }, | ||
| type: "module", | ||
| types: "./dist/index.d.ts" | ||
| }.version}/assets/social`, g = { | ||
| arial: "Arial, sans-serif", | ||
| helvetica: "Helvetica, sans-serif", | ||
| georgia: "Georgia, serif", | ||
| "times new roman": "'Times New Roman', serif", | ||
| verdana: "Verdana, sans-serif", | ||
| "trebuchet ms": "'Trebuchet MS', sans-serif", | ||
| "courier new": "'Courier New', monospace", | ||
| tahoma: "Tahoma, sans-serif" | ||
| }, _ = class e { | ||
| containerWidth; | ||
| customFonts; | ||
| defaultFallbackFont; | ||
| allowHtmlBlocks; | ||
| customBlockHtml; | ||
| socialIconsBaseUrl; | ||
| constructor(e, t, n, r, i = /* @__PURE__ */ new Map(), a = h) { | ||
| this.containerWidth = e, this.customFonts = t, this.defaultFallbackFont = n, this.allowHtmlBlocks = r, this.customBlockHtml = i, this.socialIconsBaseUrl = a; | ||
| } | ||
| withContainerWidth(t) { | ||
| return new e(t, this.customFonts, this.defaultFallbackFont, this.allowHtmlBlocks, this.customBlockHtml, this.socialIconsBaseUrl); | ||
| } | ||
| resolveFontFamily(e) { | ||
| for (let t of this.customFonts) if (t.name.toLowerCase() === e.toLowerCase()) { | ||
| let e = t.fallback ?? this.defaultFallbackFont; | ||
| return `'${t.name}', ${e}`; | ||
| } | ||
| return g[e.toLowerCase()] || e; | ||
| } | ||
| }, v = { | ||
| "&": "&", | ||
| "<": "<", | ||
| ">": ">", | ||
| "\"": """, | ||
| "'": "'" | ||
| }, y = /[&<>"']/g; | ||
| function b(e) { | ||
| return e === "" ? "" : e.replace(y, (e) => v[e] ?? e); | ||
| } | ||
| function x(e) { | ||
| return e === "" ? "" : e.replace(y, (e) => v[e] ?? e); | ||
| } | ||
| function S(e) { | ||
| return e === "" ? "" : x(e).replace(/[;{}\r\n]/g, ""); | ||
| } | ||
| function C(e) { | ||
| return e === "" ? "" : ee(e, (e) => w(e, "data-merge-tag") ?? w(e, "data-logic-merge-tag")); | ||
| } | ||
| function ee(e, t) { | ||
| let n = "", r = 0; | ||
| for (; r < e.length;) { | ||
| let i = e.indexOf("<span", r); | ||
| if (i === -1) { | ||
| n += e.substring(r); | ||
| break; | ||
| } | ||
| let a = e[i + 5]; | ||
| if (a !== ">" && a !== " " && a !== " " && a !== "\n" && a !== "\r" && a !== "/") { | ||
| n += e.substring(r, i + 5), r = i + 5; | ||
| continue; | ||
| } | ||
| let o = e.indexOf(">", i + 5); | ||
| if (o === -1) { | ||
| n += e.substring(r); | ||
| break; | ||
| } | ||
| let s = e.indexOf("</span>", o + 1); | ||
| if (s === -1) { | ||
| n += e.substring(r); | ||
| break; | ||
| } | ||
| let c = t(e.substring(i + 5, o)); | ||
| if (c === null) { | ||
| n += e.substring(r, i + 5), r = i + 5; | ||
| continue; | ||
| } | ||
| n += e.substring(r, i), n += c, r = s + 7; | ||
| } | ||
| return n; | ||
| } | ||
| function w(e, t) { | ||
| let n = RegExp(`(?:^|\\s)${t}="([^"<>]*)"`).exec(e); | ||
| return n ? n[1] : null; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/padding.ts | ||
| function T(e) { | ||
| return `${e.top}px ${e.right}px ${e.bottom}px ${e.left}px`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/utils.ts | ||
| function E(e, t) { | ||
| return e ? ` ${t === "native" ? "background-color" : "container-background-color"}="${e}"` : ""; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/visibility.ts | ||
| function D(e) { | ||
| let t = e.visibility; | ||
| return t ? !t.desktop && !t.tablet && !t.mobile : !1; | ||
| } | ||
| function O(e) { | ||
| let t = k(e); | ||
| return t === "" ? "" : ` css-class="${t}"`; | ||
| } | ||
| function k(e) { | ||
| let t = e.visibility; | ||
| if (!t) return ""; | ||
| let n = []; | ||
| return t.desktop || n.push("tpl-hide-desktop"), t.tablet || n.push("tpl-hide-tablet"), t.mobile || n.push("tpl-hide-mobile"), n.join(" "); | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/title.ts | ||
| function te(e, t) { | ||
| if (D(e)) return ""; | ||
| let n = T(e.styles.padding), r = E(e.styles.backgroundColor, "container"), i = ne(C(e.content)), a = d[e.level] ?? d[2], o = x(e.color), s = e.textAlign, c = re(e.fontFamily, t), l = O(e), u = `h${d[e.level] ? e.level : 2}`; | ||
| return `<mj-text | ||
| font-size="${a}px" | ||
| color="${o}" | ||
| align="${s}" | ||
| line-height="1.3" | ||
| padding="${n}"${r}${c}${l} | ||
| ><${u} style="margin:0;font-size:inherit;color:inherit;line-height:inherit">${i}</${u}></mj-text>`; | ||
| } | ||
| function ne(e) { | ||
| let t = e.match(/^\s*<p\b[^>]*>([\s\S]*)<\/p>\s*$/); | ||
| return !t || /<\/p>\s*<p\b/i.test(t[1]) ? e : t[1]; | ||
| } | ||
| function re(e, t) { | ||
| return e ? ` font-family="${t.resolveFontFamily(e)}"` : ""; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/paragraph.ts | ||
| function A(e, t) { | ||
| if (D(e) || e.content.replace(/<\/?p\b[^<>]*>/gi, "").trim() === "") return ""; | ||
| let n = T(e.styles.padding), r = E(e.styles.backgroundColor, "container"), i = C(e.content); | ||
| return `<mj-text | ||
| line-height="1.5" | ||
| padding="${n}"${r}${O(e)} | ||
| >${i}</mj-text>`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/image.ts | ||
| function j(e, t) { | ||
| if (D(e) || e.src === "") return ""; | ||
| let n = T(e.styles.padding), r = E(e.styles.backgroundColor, "container"), i = e.width === "full" ? t.containerWidth + "px" : e.width + "px", a = O(e), o = ""; | ||
| e.linkUrl && (o = ` href="${x(e.linkUrl)}"`, e.linkOpenInNewTab && (o += " target=\"_blank\" rel=\"noopener\"")); | ||
| let s = x(e.src), c = e.decorative === !0; | ||
| return `<mj-image | ||
| src="${s}" | ||
| alt="${c ? "" : x(e.alt)}" | ||
| width="${i}" | ||
| align="${e.align}" | ||
| padding="${n}"${r}${o}${a}${c ? " role=\"presentation\"" : ""} | ||
| />`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/button.ts | ||
| function M(e, t) { | ||
| if (D(e)) return ""; | ||
| let n = T(e.styles.padding), r = E(e.styles.backgroundColor, "container"), i = T(e.buttonPadding), a = e.url === "" ? "" : x(e.url), o = a === "" ? "" : ` href="${a}"`, s = x(e.backgroundColor), c = x(e.textColor), l = e.fontSize, u = e.borderRadius, d = b(e.text); | ||
| return `<mj-button${o}${e.openInNewTab ? " target=\"_blank\" rel=\"noopener\"" : ""} | ||
| background-color="${s}" | ||
| color="${c}" | ||
| font-size="${l}px" | ||
| font-weight="bold" | ||
| border-radius="${u}px" | ||
| inner-padding="${i}" | ||
| padding="${n}"${r}${N(e.fontFamily, t)}${O(e)} | ||
| >${d}</mj-button>`; | ||
| } | ||
| function N(e, t) { | ||
| return e ? ` font-family="${t.resolveFontFamily(e)}"` : ""; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/divider.ts | ||
| function P(e, t) { | ||
| if (D(e)) return ""; | ||
| let n = T(e.styles.padding), r = e.styles.backgroundColor ? ` container-background-color="${x(e.styles.backgroundColor)}"` : "", i = e.width === "full" ? "100%" : e.width + "px"; | ||
| return `<mj-divider | ||
| border-width="${e.thickness}px" | ||
| border-style="${e.lineStyle}" | ||
| border-color="${x(e.color)}" | ||
| width="${i}" | ||
| padding="${n}"${r}${O(e)} | ||
| />`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/spacer.ts | ||
| function F(e, t) { | ||
| return D(e) ? "" : `<mj-spacer height="${e.height}px" padding="0"${e.styles.backgroundColor ? ` container-background-color="${x(e.styles.backgroundColor)}"` : ""}${O(e)} />`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/html.ts | ||
| function I(e, t) { | ||
| if (D(e) || !t.allowHtmlBlocks) return ""; | ||
| let n = e.content; | ||
| return n === "" ? "" : `<mj-text${O(e)}> | ||
| ${n} | ||
| </mj-text>`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/social.ts | ||
| function L(e, t) { | ||
| if (D(e)) return ""; | ||
| let n = e.icons; | ||
| if (n.length === 0) return ""; | ||
| let r = T(e.styles.padding), i = e.styles.backgroundColor ? ` container-background-color="${x(e.styles.backgroundColor)}"` : "", a = O(e), o = e.align, s = e.iconSize, c = e.iconStyle, l = e.spacing, u; | ||
| switch (s) { | ||
| case "small": | ||
| u = 24; | ||
| break; | ||
| case "large": | ||
| u = 48; | ||
| break; | ||
| default: | ||
| u = 32; | ||
| break; | ||
| } | ||
| let d; | ||
| switch (c) { | ||
| case "circle": | ||
| d = "50%"; | ||
| break; | ||
| case "rounded": | ||
| d = "8px"; | ||
| break; | ||
| case "square": | ||
| d = "0"; | ||
| break; | ||
| default: | ||
| d = "4px"; | ||
| break; | ||
| } | ||
| let f = n.length; | ||
| return `<mj-social | ||
| mode="horizontal" | ||
| align="${o}" | ||
| icon-padding="0" | ||
| padding="${r}"${i}${a} | ||
| > | ||
| ${n.map((e, n) => { | ||
| let r = e.platform, i = x(e.url), a = `${t.socialIconsBaseUrl}/${c}/${r}.png`, o = n === f - 1 ? 0 : l; | ||
| return `<mj-social-element src="${a}" href="${i}" icon-size="${u}px" padding="0 ${o}px 0 0" border-radius="${d}" background-color="transparent"></mj-social-element>`; | ||
| }).join("\n")} | ||
| </mj-social>`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/menu.ts | ||
| function R(e, t) { | ||
| if (D(e) || e.items.length === 0) return ""; | ||
| let n = T(e.styles.padding), r = E(e.styles.backgroundColor, "container"), i = O(e), a = V(e.fontFamily, t), o = e.textAlign; | ||
| return `<mj-text | ||
| font-size="${e.fontSize}px" | ||
| color="${x(e.color)}" | ||
| align="${o}" | ||
| line-height="1.5" | ||
| padding="${n}"${r}${a}${i} | ||
| >${z(e)}</mj-text>`; | ||
| } | ||
| function z(e) { | ||
| let t = e.items, n = b(e.separator), r = S(e.separatorColor), i = e.spacing, a = e.linkColor ?? e.color, o = [], s = t.length; | ||
| for (let e = 0; e < s; e++) o.push(B(t[e], a)), e < s - 1 && o.push(`<span style="color: ${r}; padding: 0 ${i}px;">${n}</span>`); | ||
| return o.join(""); | ||
| } | ||
| function B(e, t) { | ||
| let n = b(e.text), r = x(e.url), i = S(e.color ?? t), a = e.openInNewTab ? " target=\"_blank\" rel=\"noopener\"" : "", o = [`color: ${i}`, "text-decoration: none"]; | ||
| return e.bold && o.push("font-weight: bold"), e.underline && o.push("text-decoration: underline"), `<a href="${r}" style="${o.join("; ")}"${a}>${n}</a>`; | ||
| } | ||
| function V(e, t) { | ||
| return e ? ` font-family="${t.resolveFontFamily(e)}"` : ""; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/table.ts | ||
| function H(e, t) { | ||
| if (D(e) || e.rows.length === 0) return ""; | ||
| let n = T(e.styles.padding), r = E(e.styles.backgroundColor, "container"), i = O(e), a = ie(e.fontFamily, t); | ||
| return `<mj-text | ||
| font-size="${e.fontSize}px" | ||
| color="${x(e.color)}" | ||
| align="${e.textAlign}" | ||
| line-height="1.5" | ||
| padding="${n}"${r}${a}${i} | ||
| >${U(e)}</mj-text>`; | ||
| } | ||
| function U(e) { | ||
| let t = S(e.borderColor), n = e.borderWidth, r = ""; | ||
| for (let i = 0; i < e.rows.length; i++) { | ||
| let a = e.rows[i]; | ||
| r += W(a, e, e.hasHeaderRow && i === 0, t, n); | ||
| } | ||
| return `<table style="width: 100%; border-collapse: collapse;">${r}</table>`; | ||
| } | ||
| function W(e, t, n, r, i) { | ||
| let a = ""; | ||
| for (let o of e.cells) a += G(o, t, n, r, i); | ||
| return `<tr>${a}</tr>`; | ||
| } | ||
| function G(e, t, n, r, i) { | ||
| let a = t.cellPadding, o = [`border: ${i}px solid ${r}`, `padding: ${a}px`]; | ||
| n && (o.push("font-weight: bold"), t.headerBackgroundColor && o.push(`background-color: ${S(t.headerBackgroundColor)}`)); | ||
| let s = o.join("; "), c = C(e.content), l = n ? "th" : "td"; | ||
| return `<${l} style="${s}">${c}</${l}>`; | ||
| } | ||
| function ie(e, t) { | ||
| return e ? ` font-family="${t.resolveFontFamily(e)}"` : ""; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/custom.ts | ||
| function K(e, t) { | ||
| if (D(e)) return ""; | ||
| let n = t.customBlockHtml.get(e.id) ?? e.renderedHtml; | ||
| if (!n || n === "") return ""; | ||
| let r = O(e); | ||
| return `<mj-text${E(e.styles?.backgroundColor, "container")}${r}> | ||
| ${n} | ||
| </mj-text>`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/columns.ts | ||
| function q(e) { | ||
| switch (e) { | ||
| case "2": return ["50%", "50%"]; | ||
| case "3": return [ | ||
| "33.33%", | ||
| "33.33%", | ||
| "33.34%" | ||
| ]; | ||
| case "1-2": return ["33.33%", "66.67%"]; | ||
| case "2-1": return ["66.67%", "33.33%"]; | ||
| default: return ["100%"]; | ||
| } | ||
| } | ||
| function J(e, t) { | ||
| switch (e) { | ||
| case "2": return [t * .5, t * .5]; | ||
| case "3": return [ | ||
| t / 3, | ||
| t / 3, | ||
| t / 3 | ||
| ]; | ||
| case "1-2": return [t / 3, t * 2 / 3]; | ||
| case "2-1": return [t * 2 / 3, t / 3]; | ||
| default: return [t]; | ||
| } | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/section.ts | ||
| function Y(e, t, n) { | ||
| if (D(e)) return ""; | ||
| let r = e.columns, i = q(r), a = J(r, t.containerWidth), o = T(e.styles.padding), c = E(e.styles.backgroundColor, "native"), l = O(e), u = e.children, d = []; | ||
| for (let e = 0; e < u.length; e++) { | ||
| let r = u[e], o = i[e] ?? "100%", c = Math.floor(a[e] ?? t.containerWidth), l = ae(r, t.allowHtmlBlocks).filter((e) => !s(e)), f = t.withContainerWidth(c), p = l.map((e) => n(e, f)).filter((e) => e !== "").join("\n"); | ||
| d.push(`<mj-column width="${o}"> | ||
| ${p === "" ? "<mj-text> </mj-text>" : p} | ||
| </mj-column>`); | ||
| } | ||
| return `<mj-section${c} padding="${o}"${l}> | ||
| ${d.join("\n")} | ||
| </mj-section>`; | ||
| } | ||
| function ae(e, t) { | ||
| return t ? e : e.filter((e) => e.type !== "html"); | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/video.ts | ||
| function oe(e, t) { | ||
| if (t) return t; | ||
| if (!e) return null; | ||
| for (let t of [/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/, /youtube\.com\/shorts\/([a-zA-Z0-9_-]{11})/]) { | ||
| let n = e.match(t); | ||
| if (n) return `https://img.youtube.com/vi/${n[1]}/maxresdefault.jpg`; | ||
| } | ||
| let n = e.match(/vimeo\.com\/(?:video\/)?(\d+)/); | ||
| return n ? `https://vumbnail.com/${n[1]}.jpg` : null; | ||
| } | ||
| function se(e, t) { | ||
| if (D(e)) return ""; | ||
| let n = oe(e.url, e.thumbnailUrl); | ||
| if (!n) return ""; | ||
| let r = T(e.styles.padding), i = E(e.styles.backgroundColor, "container"), a = e.width === "full" ? t.containerWidth + "px" : e.width + "px", o = O(e); | ||
| return `<mj-image | ||
| src="${x(n)}" | ||
| alt="${x(e.alt)}" | ||
| width="${a}" | ||
| align="${e.align}" | ||
| padding="${r}" | ||
| href="${x(e.url)}" | ||
| target="_blank" | ||
| rel="noopener"${i}${o} | ||
| />`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/index.ts | ||
| function X(e, d) { | ||
| return s(e) ? Y(e, d, X) : a(e) ? te(e, d) : p(e) ? A(e, d) : m(e) ? j(e, d) : f(e) ? M(e, d) : n(e) ? P(e, d) : u(e) ? F(e, d) : l(e) ? I(e, d) : c(e) ? L(e, d) : t(e) ? R(e, d) : i(e) ? H(e, d) : o(e) ? se(e, d) : r(e) ? K(e, d) : ""; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/index.ts | ||
| var ce = /* @__PURE__ */ e({ | ||
| DEFAULT_SOCIAL_ICONS_BASE_URL: () => h, | ||
| RenderContext: () => _, | ||
| convertMergeTagsToValues: () => C, | ||
| escapeAttr: () => x, | ||
| escapeHtml: () => b, | ||
| getCssClassAttr: () => O, | ||
| getCssClasses: () => k, | ||
| getWidthPercentages: () => q, | ||
| getWidthPixels: () => J, | ||
| isHiddenOnAll: () => D, | ||
| renderBlock: () => X, | ||
| renderToMjml: () => Z, | ||
| toPaddingString: () => T | ||
| }); | ||
| async function Z(e, t) { | ||
| let n = t?.customFonts ?? [], r = t?.defaultFallbackFont ?? "Arial, sans-serif", i = t?.allowHtmlBlocks ?? !0, a = de(t?.socialIconsBaseUrl ?? h), o = await he(e, t?.renderCustomBlock), s = new _(e.settings.width, n, r, i, o, a), c = me(e.blocks, i), l = s.resolveFontFamily(e.settings.fontFamily), u = e.settings.backgroundColor, d = c.map((e) => le(e, s)).filter((e) => e !== "").join("\n"), f = pe(n), p = fe(e.settings.preheaderText); | ||
| return `<mjml lang="${x(e.settings.locale)}"> | ||
| <mj-head>${p} | ||
| <mj-attributes> | ||
| <mj-all font-family="${l}" /> | ||
| <mj-text font-size="14px" /> | ||
| <mj-section padding="0" /> | ||
| <mj-column padding="0" /> | ||
| <mj-image fluid-on-mobile="true" /> | ||
| </mj-attributes>${f} | ||
| <mj-style> | ||
| a { color: inherit; text-decoration: none; } | ||
| @media only screen and (max-width: 480px) { | ||
| .tpl-hide-mobile { display: none !important; mso-hide: all !important; } | ||
| } | ||
| @media only screen and (min-width: 481px) and (max-width: 768px) { | ||
| .tpl-hide-tablet { display: none !important; mso-hide: all !important; } | ||
| } | ||
| @media only screen and (min-width: 769px) { | ||
| .tpl-hide-desktop { display: none !important; mso-hide: all !important; } | ||
| } | ||
| </mj-style> | ||
| </mj-head> | ||
| <mj-body width="${s.containerWidth}px" background-color="${u}"> | ||
| ${d} | ||
| </mj-body> | ||
| </mjml>`; | ||
| } | ||
| function le(e, t) { | ||
| return s(e) ? Q(e, X(e, t)) : Q(e, ue(X(e, t))); | ||
| } | ||
| function Q(e, t) { | ||
| if (t === "") return ""; | ||
| let n = e.displayCondition; | ||
| return n ? `<mj-raw>${n.before}</mj-raw> | ||
| ` + t + ` | ||
| <mj-raw>${n.after}</mj-raw>` : t; | ||
| } | ||
| function ue(e) { | ||
| return e === "" ? "" : `<mj-section> | ||
| <mj-column> | ||
| ${e} | ||
| </mj-column> | ||
| </mj-section>`; | ||
| } | ||
| function de(e) { | ||
| return e.endsWith("/") ? e.slice(0, -1) : e; | ||
| } | ||
| function fe(e) { | ||
| if (!e) return ""; | ||
| let t = e.trim(); | ||
| return t === "" ? "" : `\n <mj-preview>${b(t)}</mj-preview>`; | ||
| } | ||
| function pe(e) { | ||
| return e.length === 0 ? "" : e.map((e) => `\n <mj-font name="${x(e.name)}" href="${x(e.url)}" />`).join(""); | ||
| } | ||
| function me(e, t) { | ||
| return t ? e : e.filter((e) => e.type !== "html"); | ||
| } | ||
| async function he(e, t) { | ||
| let n = /* @__PURE__ */ new Map(); | ||
| if (!t) return n; | ||
| let r = []; | ||
| if ($(e.blocks, r), r.length === 0) return n; | ||
| let i = await Promise.all(r.map((e) => t(e))); | ||
| for (let e = 0; e < r.length; e++) n.set(r[e].id, i[e]); | ||
| return n; | ||
| } | ||
| function $(e, t) { | ||
| for (let n of e) { | ||
| if (r(n)) { | ||
| t.push(n); | ||
| continue; | ||
| } | ||
| if (s(n)) for (let e of n.children) $(e, t); | ||
| } | ||
| } | ||
| //#endregion | ||
| export { ce as t }; | ||
| //# sourceMappingURL=renderer-CfHPFI5v.js.map |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
| import { A as e, B as t, L as n, M as r, O as i, Q as a, X as o, _ as s, at as c, b as l, c as u, d, f, g as p, h as m, j as h, k as g, l as _, m as v, o as y, ot as b, p as x, q as S, rt as C, st as w, t as T, v as E, y as D, z as O } from "./vue.runtime.esm-bundler-BDSGA5hA.js"; | ||
| import { t as k } from "./timeouts-Bmi_yePw.js"; | ||
| import { E as A, i as j } from "./dist-CIV3Brg-.js"; | ||
| import { P as M, S as N, t as P } from "./useEditorCore-CEkf_VWX.js"; | ||
| import { c as F, t as I } from "./dist-CNLAS2v2.js"; | ||
| import { E as L, S as R, T as z, c as B, l as V, r as ee, s as te, t as H } from "./keys-BiQlvx51.js"; | ||
| import { t as U } from "./useI18n-Besvmtxy.js"; | ||
| import { t as W } from "./createLucideIcon-XgXOJ05E.js"; | ||
| import { t as G } from "./check-ChQyfxJ3.js"; | ||
| import { t as K } from "./circle-alert-CPH6l3Lc.js"; | ||
| import { a as q, c as ne, i as J, l as re, n as ie, o as ae, r as oe, s as se, t as ce, u as le } from "./styles-CxwIlb7Y.js"; | ||
| import { t as ue } from "./clock-DHl_BIkU.js"; | ||
| import { t as Y } from "./loader-circle-Rz_4vJLH.js"; | ||
| import { t as X } from "./message-circle-D-umK_MU.js"; | ||
| import { t as Z } from "./send-BhbhbIFT.js"; | ||
| import { t as de } from "./sparkles-CrUN0KWY.js"; | ||
| import { t as fe } from "./triangle-alert-MwJBKR2e.js"; | ||
| import { t as pe } from "./_plugin-vue_export-helper-B3ysoDQm.js"; | ||
| import { n as Q } from "./useCloudI18n-DKWJg6rJ.js"; | ||
| import { d as $ } from "./styleConstants-lGobwiLH.js"; | ||
| import { _ as me, a as he, c as ge, d as _e, f as ve, g as ye, h as be, l as xe, m as Se, n as Ce, o as we, p as Te, r as Ee, s as De, t as Oe, v as ke, y as Ae } from "./cloud-VxYMtfXC.js"; | ||
| var je = W("save", [ | ||
| ["path", { | ||
| d: "M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z", | ||
| key: "1c8476" | ||
| }], | ||
| ["path", { | ||
| d: "M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7", | ||
| key: "1ydtos" | ||
| }], | ||
| ["path", { | ||
| d: "M7 3v4a1 1 0 0 0 1 1h7", | ||
| key: "t51u73" | ||
| }] | ||
| ]); | ||
| //#endregion | ||
| //#region src/cloud/composables/useSnapshotPreview.ts | ||
| function Me(e) { | ||
| let { authManager: t, editor: n, history: r, conditionPreview: i, autoSave: s, onError: c } = e, l = a(null), u = o(null), f = o(null), p = !1; | ||
| S(() => { | ||
| p = !0; | ||
| }); | ||
| let m = d(() => u.value !== null), h = d(() => l.value?.snapshots.value ?? []), g = d(() => l.value?.isLoading.value ?? !1), _ = d(() => l.value?.isRestoring.value ?? !1); | ||
| function v() { | ||
| n.state.template?.id && !l.value && (l.value = ye({ | ||
| authManager: t, | ||
| templateId: n.state.template.id, | ||
| onRestore: y, | ||
| onError: c | ||
| }), l.value.loadSnapshots()); | ||
| } | ||
| function y(e) { | ||
| n.setContent(e.content, !1), r.clear(), i.reset(); | ||
| } | ||
| async function b(e) { | ||
| if (!p) { | ||
| if (u.value) { | ||
| u.value = e, n.setContent(e.content, !1); | ||
| return; | ||
| } | ||
| n.state.isDirty && n.hasTemplate() && (await n.createSnapshot(), p) || (f.value = structuredClone(n.content.value), s?.pause(), u.value = e, n.setContent(e.content, !1)); | ||
| } | ||
| } | ||
| async function x() { | ||
| if (!(!u.value || !l.value)) try { | ||
| if (await l.value.restoreSnapshot(u.value.id), p || (await l.value.loadSnapshots(), p)) return; | ||
| } finally { | ||
| p || (u.value = null, f.value = null, s?.resume()); | ||
| } | ||
| } | ||
| function C() { | ||
| !u.value || !f.value || (n.setContent(f.value, !1), u.value = null, f.value = null, s?.resume()); | ||
| } | ||
| async function w() { | ||
| p || l.value && await l.value.loadSnapshots(); | ||
| } | ||
| return { | ||
| snapshotHistoryInstance: l, | ||
| previewingSnapshot: u, | ||
| contentBeforePreview: f, | ||
| isPreviewingSnapshot: m, | ||
| snapshotHistorySnapshots: h, | ||
| snapshotHistoryIsLoading: g, | ||
| snapshotHistoryIsRestoring: _, | ||
| initSnapshotHistory: v, | ||
| handleRestore: y, | ||
| handleSnapshotNavigate: b, | ||
| confirmRestoreSnapshot: x, | ||
| cancelPreview: C, | ||
| loadSnapshotHistory: w | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudPanelState.ts | ||
| function Ne() { | ||
| let e = o(null), t = d({ | ||
| get: () => e.value === "ai-chat", | ||
| set: (t) => e.value = t ? "ai-chat" : null | ||
| }), n = d({ | ||
| get: () => e.value === "scoring", | ||
| set: (t) => e.value = t ? "scoring" : null | ||
| }), r = d({ | ||
| get: () => e.value === "design-reference", | ||
| set: (t) => e.value = t ? "design-reference" : null | ||
| }), i = d({ | ||
| get: () => e.value === "comments", | ||
| set: (t) => e.value = t ? "comments" : null | ||
| }), a = o(!1), s = o(!1), c = o(void 0), l = o(!1), u = o(null), f = d(() => e.value !== null), p = d(() => { | ||
| let t = e.value; | ||
| return t === "ai-chat" || t === "design-reference" || t === "scoring" ? t : null; | ||
| }), m = d(() => l.value || e.value === "ai-chat" || e.value === "design-reference" || e.value === "scoring"); | ||
| function h() { | ||
| l.value = !l.value; | ||
| } | ||
| function g(t) { | ||
| l.value = !1, e.value = e.value === t ? null : t; | ||
| } | ||
| return I(u, () => { | ||
| l.value = !1; | ||
| }), { | ||
| activePanel: e, | ||
| aiChatOpen: t, | ||
| scoringPanelOpen: n, | ||
| designReferenceOpen: r, | ||
| commentsOpen: i, | ||
| testEmailModalOpen: a, | ||
| mediaLibraryOpen: s, | ||
| mediaLibraryAccept: c, | ||
| aiMenuOpen: l, | ||
| aiMenuRef: u, | ||
| rightPanelOpen: f, | ||
| activeAiFeature: p, | ||
| aiButtonActive: m, | ||
| toggleAiMenu: h, | ||
| handleAiFeatureSelect: g | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCollabUndoWarning.ts | ||
| function Pe(e) { | ||
| let { isCollaborationEnabled: t, getCollaboratorCount: n, canUndo: r } = e, i = o(!1), a = o(!1), { start: s } = F(() => { | ||
| a.value = !1; | ||
| }, k, { immediate: !1 }); | ||
| function c() { | ||
| i.value || !t.value || n() === 0 || !r.value || (i.value = !0, a.value = !0, s()); | ||
| } | ||
| return { | ||
| collabUndoWarningVisible: a, | ||
| showCollabUndoWarning: c | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudFeatureFlags.ts | ||
| function Fe(e) { | ||
| let { planConfigInstance: t, aiConfig: n, editor: r } = e, i = d(() => t.hasFeature("ai_generation") && n.hasAnyMenuFeature.value), a = d(() => t.hasFeature("test_email")), s = d(() => !!r.state.template?.id), c = d(() => t.hasFeature("white_label")), l = d(() => t.config.value?.limits.max_templates ?? null), u = d(() => t.config.value?.template_count ?? 0), f = o(!1), p = o("idle"), m = o(""), { start: h } = F(() => { | ||
| p.value = "idle"; | ||
| }, 3e3, { immediate: !1 }); | ||
| return { | ||
| canUseAiGeneration: i, | ||
| canSendTestEmail: a, | ||
| hasTemplateSaved: s, | ||
| isWhiteLabeled: c, | ||
| templateLimit: l, | ||
| templateCount: u, | ||
| isSaveExporting: f, | ||
| saveStatus: p, | ||
| saveErrorMessage: m, | ||
| startSaveStatusClear: h | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudMediaLibrary.ts | ||
| function Ie(e) { | ||
| let { onRequestMedia: t, mediaLibraryOpen: n, mediaLibraryAccept: r } = e, i = null; | ||
| async function a() { | ||
| if (t) { | ||
| let e = await t({ accept: ["images"] }); | ||
| return e ? { | ||
| url: e.url, | ||
| alt: e.alt_text || void 0 | ||
| } : null; | ||
| } | ||
| return i &&= (i(null), null), r.value = ["images"], n.value = !0, new Promise((e) => { | ||
| i = (t) => { | ||
| e(t); | ||
| }; | ||
| }); | ||
| } | ||
| function o(e) { | ||
| n.value = !1, i?.({ | ||
| url: e.url, | ||
| alt: e.alt_text || void 0 | ||
| }), i = null; | ||
| } | ||
| function s() { | ||
| n.value = !1, i?.(null), i = null; | ||
| } | ||
| return S(() => { | ||
| i &&= (i(null), null); | ||
| }), { | ||
| handleRequestMedia: a, | ||
| handleMediaSelect: o, | ||
| handleMediaLibraryClose: s | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudInitialization.ts | ||
| function Le(e) { | ||
| let { config: t, translations: r, fontsManager: i, emit: a, getCommentsSidebar: s } = e, c = o(!0), l = o(!1), u = o(null), f = !1, p = { value: null }, m = null, g = null, _ = new Oe({ | ||
| ...t.auth, | ||
| onError: t.onError | ||
| }), v = Se({ | ||
| authManager: _, | ||
| onError: t.onError | ||
| }), y = o(/* @__PURE__ */ new Map()), b = _e({ | ||
| authManager: _, | ||
| defaultFontFamily: t.fonts?.defaultFont, | ||
| templateDefaults: t.templateDefaults, | ||
| onError: t.onError, | ||
| lockedBlocks: y | ||
| }), x = Ae({ | ||
| authManager: _, | ||
| onError: t.onError | ||
| }); | ||
| t.mcp?.enabled && Te({ | ||
| editor: b, | ||
| channel: x.channel, | ||
| onOperation: t.mcp.onOperation | ||
| }); | ||
| let S = null; | ||
| t.collaboration?.enabled && (S = we({ | ||
| authManager: _, | ||
| editor: b, | ||
| channel: x.channel, | ||
| onError: t.onError, | ||
| onCollaboratorJoined: t.collaboration.onCollaboratorJoined, | ||
| onCollaboratorLeft: t.collaboration.onCollaboratorLeft, | ||
| onBlockLocked: t.collaboration.onBlockLocked, | ||
| onBlockUnlocked: t.collaboration.onBlockUnlocked | ||
| }), n(() => S.lockedBlocks.value, (e) => { | ||
| y.value = e; | ||
| }, { immediate: !0 }), De(b, S)); | ||
| let C = d(() => !!t.collaboration?.enabled && v.hasFeature("collaboration")), w = P({ | ||
| editor: b, | ||
| config: { | ||
| uiTheme: t.uiTheme, | ||
| theme: void 0, | ||
| blockDefaults: t.blockDefaults, | ||
| customBlocks: [], | ||
| mergeTags: t.mergeTags, | ||
| displayConditions: t.displayConditions, | ||
| onRequestMedia: null, | ||
| lint: re(t), | ||
| onSave: () => { | ||
| p.value?.().catch((e) => { | ||
| t.onError?.(e); | ||
| }); | ||
| } | ||
| }, | ||
| translations: r, | ||
| fontsManager: i, | ||
| historyOptions: S ? { isRemoteOperation: () => S._isProcessingRemoteOperation() } : void 0, | ||
| autoSaveOptions: { | ||
| onChange: async () => { | ||
| b.hasTemplate() && (await b.createSnapshot(), m?.snapshotHistoryInstance.value?.loadSnapshots()); | ||
| }, | ||
| debounce: t.autoSaveDebounce ?? 5e3, | ||
| enabled: () => t.autoSave !== !1 && v.hasFeature("auto_save") | ||
| }, | ||
| themeExtraStyles: () => ({ "--tpl-drop-text": `"${r.canvas.dropHere}"` }), | ||
| keyboardOptions: { onBeforeUndo: () => g?.showCollabUndoWarning() }, | ||
| editorRoot: e.editorRoot, | ||
| containerEl: e.containerEl | ||
| }), T = Pe({ | ||
| isCollaborationEnabled: C, | ||
| getCollaboratorCount: () => S?.collaborators.value.length ?? 0, | ||
| canUndo: w.history.canUndo | ||
| }); | ||
| g = T; | ||
| let E = Me({ | ||
| authManager: _, | ||
| editor: b, | ||
| history: w.history, | ||
| conditionPreview: w.conditionPreview, | ||
| autoSave: w.autoSave, | ||
| onError: t.onError | ||
| }); | ||
| m = E; | ||
| let D = Ne(), O = he(t.ai), k = Fe({ | ||
| planConfigInstance: v, | ||
| aiConfig: O, | ||
| editor: b | ||
| }), A = Ie({ | ||
| onRequestMedia: t.onRequestMedia, | ||
| mediaLibraryOpen: D.mediaLibraryOpen, | ||
| mediaLibraryAccept: D.mediaLibraryAccept | ||
| }); | ||
| N({ | ||
| onBlockMove: b.moveBlock, | ||
| onBlockAdd: b.addBlock | ||
| }); | ||
| let j = ve({ | ||
| authManager: _, | ||
| getFontsConfig: () => t.fonts, | ||
| canUseCustomFonts: () => v.hasFeature("custom_fonts") | ||
| }), F = ke({ | ||
| authManager: _, | ||
| getTemplateId: () => b.state.template?.id ?? null, | ||
| save: () => b.save(), | ||
| exportHtml: (e) => j.exportHtml(e), | ||
| onError: t.onError, | ||
| isAuthReady: l, | ||
| onBeforeTestEmail: t.onBeforeTestEmail | ||
| }), I = xe({ | ||
| authManager: _, | ||
| getTemplateId: () => b.state.template?.id ?? null, | ||
| getSocketId: () => x.getSocketId(), | ||
| onComment: t.onComment, | ||
| onError: t.onError, | ||
| isAuthReady: l, | ||
| hasCommentingFeature: () => t.commenting !== !1 && v.hasFeature("commenting") | ||
| }); | ||
| ge({ | ||
| comments: I, | ||
| channel: x.channel | ||
| }); | ||
| let B = be({ | ||
| authManager: _, | ||
| onError: t.onError | ||
| }), U = o(!1), W = o(null), G = o(!1), K = me({ | ||
| authManager: _, | ||
| getTemplateId: () => b.state.template?.id ?? null | ||
| }); | ||
| function q(e) { | ||
| D.commentsOpen.value = !0, queueMicrotask(() => { | ||
| s()?.filterByBlock(e); | ||
| }); | ||
| } | ||
| h(R, A.handleRequestMedia), h(ee, _), h(H, O), h(V, I), h(z, B), h(L, K), h(te, { | ||
| plan: v, | ||
| ai: O, | ||
| comments: { | ||
| getBlockCount: (e) => I.commentCountByBlock.value.get(e) ?? 0, | ||
| openForBlock: q | ||
| }, | ||
| savedModules: { | ||
| openSaveDialog: (e) => { | ||
| W.value = e ?? null, U.value = !0; | ||
| }, | ||
| openBrowser: () => { | ||
| G.value = !0; | ||
| }, | ||
| moduleCount: d(() => B.modules.value.length) | ||
| } | ||
| }); | ||
| function ne(e) { | ||
| v.hasFeature("theme_customization") && (w.themeOverrides.value = e); | ||
| } | ||
| function J(e) { | ||
| b.setUiTheme(e); | ||
| } | ||
| async function ie() { | ||
| c.value = !0, u.value = null; | ||
| try { | ||
| if (await _.initialize(), f) return; | ||
| l.value = !0; | ||
| let e = await Ce({ authManager: _ }); | ||
| if (f) return; | ||
| if (!e.api.ok) throw Error("Health check failed: API is not reachable"); | ||
| if (!e.auth.ok) throw Error(`Health check failed: authentication error${e.auth.error ? ` - ${e.auth.error}` : ""}`); | ||
| if (e.websocket.ok || M.warn("WebSocket health check failed:", e.websocket.error ?? "unknown error", "-- real-time features will be disabled."), await v.fetchConfig(), f) return; | ||
| i.setCustomFontsEnabled(v.hasFeature("custom_fonts")), t.customBlocks?.length && v.hasFeature("custom_blocks") && w.registerCustomBlocks(t.customBlocks), t.theme && v.hasFeature("theme_customization") && (w.themeOverrides.value = t.theme), t.modules !== !1 && v.hasFeature("saved_modules") && B.loadModules(), a("ready"); | ||
| } catch (e) { | ||
| if (f) return; | ||
| let n = e instanceof Error ? e : Error("Initialization failed", { cause: e }); | ||
| u.value = n, t.onError?.(n); | ||
| } finally { | ||
| f || (c.value = !1); | ||
| } | ||
| } | ||
| function ae() { | ||
| f = !0, i.cleanupFontLinks(), x.disconnect(), w.destroy(), t.onUnmount?.(); | ||
| } | ||
| return { | ||
| isInitializing: c, | ||
| isAuthReady: l, | ||
| initError: u, | ||
| isDestroyed: () => f, | ||
| authManager: _, | ||
| planConfigInstance: v, | ||
| websocket: x, | ||
| collaboration: S, | ||
| isCollaborationEnabled: C, | ||
| editor: b, | ||
| core: w, | ||
| aiConfig: O, | ||
| featureFlags: k, | ||
| mediaLib: A, | ||
| exporter: j, | ||
| testEmail: F, | ||
| commentsInstance: I, | ||
| savedModulesHeadless: B, | ||
| scoringInstance: K, | ||
| panelState: D, | ||
| snapshotPreview: E, | ||
| collabWarning: T, | ||
| showSaveModuleDialog: U, | ||
| showModuleBrowserModal: G, | ||
| saveModulePreSelectedBlockId: W, | ||
| onSaveHook: p, | ||
| initialize: ie, | ||
| destroy: ae, | ||
| setThemeOverrides: ne, | ||
| setUiTheme: J, | ||
| openCommentsForBlock: q | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/utils/preRenderCustomBlocks.ts | ||
| async function Re(e, t) { | ||
| let n = async (e) => { | ||
| if (A(e)) { | ||
| let n = e; | ||
| try { | ||
| n.renderedHtml = await t.renderCustomBlock(n); | ||
| } catch { | ||
| n.renderedHtml = `<!-- Custom block render error: ${n.customType} -->`; | ||
| } | ||
| } | ||
| if (e.type === "section" && "children" in e) { | ||
| let t = e; | ||
| for (let e of t.children) for (let t of e) await n(t); | ||
| } | ||
| }; | ||
| for (let t of e.blocks) await n(t); | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudLifecycle.ts | ||
| function ze(e) { | ||
| let { config: t, editor: n, websocket: r, planConfigInstance: i, snapshotPreview: a, core: o, exporter: s, featureFlags: c, isDestroyed: l } = e; | ||
| function u() { | ||
| return Ee(i.config.value.websocket); | ||
| } | ||
| async function d(e) { | ||
| let i = await n.create(e); | ||
| return l() ? i : (t.onCreate?.(i), a.initSnapshotHistory(), r.connect(i.id, u()), i); | ||
| } | ||
| async function f(e) { | ||
| let i = await n.load(e); | ||
| return l() ? i : (t.onLoad?.(i), a.initSnapshotHistory(), r.connect(i.id, u()), i); | ||
| } | ||
| async function p() { | ||
| c.isSaveExporting.value = !0, c.saveStatus.value = "idle"; | ||
| try { | ||
| if (await Re(n.content.value, o.registry), l()) throw Error("Component unmounted during save"); | ||
| let e = await n.save(); | ||
| if (l()) throw Error("Component unmounted during save"); | ||
| a.initSnapshotHistory(), a.snapshotHistoryInstance.value?.loadSnapshots(); | ||
| let r = await s.exportHtml(e.id); | ||
| if (l()) throw Error("Component unmounted during save"); | ||
| let i = { | ||
| templateId: e.id, | ||
| html: r.html, | ||
| mjml: r.mjml, | ||
| content: e.content | ||
| }; | ||
| return t.onSave?.(i), c.saveStatus.value = "saved", c.startSaveStatusClear(), i; | ||
| } catch (e) { | ||
| throw l() || (c.saveStatus.value = "error", c.saveErrorMessage.value = e instanceof Error ? e.message : "Save failed"), e; | ||
| } finally { | ||
| l() || (c.isSaveExporting.value = !1); | ||
| } | ||
| } | ||
| return { | ||
| createTemplate: d, | ||
| loadTemplate: f, | ||
| saveTemplate: p | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudSaveGate.ts | ||
| function Be(e) { | ||
| let t = o(!1), n = null, r = d(() => e.planConfig.value?.accessibility?.blockOnError === !0), i = d(() => r.value ? e.issues.value.filter((e) => e.severity === "error") : []), a = d(() => i.value.length > 0); | ||
| async function s(e) { | ||
| return a.value ? (n = e, t.value = !0, !1) : (await e(), !0); | ||
| } | ||
| async function c() { | ||
| let e = n; | ||
| n = null, t.value = !1, e && await e(); | ||
| } | ||
| function l() { | ||
| n = null, t.value = !1; | ||
| } | ||
| return { | ||
| shouldBlock: a, | ||
| blockingIssues: i, | ||
| modalOpen: t, | ||
| tryRunSave: s, | ||
| confirmAndSave: c, | ||
| cancel: l | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/components/CloudSaveGateModal.vue?vue&type=script&setup=true&lang.ts | ||
| var Ve = ["aria-label"], He = { class: "tpl:flex tpl:max-h-[80vh] tpl:w-full tpl:max-w-md tpl:flex-col tpl:gap-4 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)] tpl:p-5 tpl:shadow-[var(--tpl-shadow-md)]" }, Ue = { class: "tpl:flex tpl:items-center tpl:gap-2" }, We = { class: "tpl:m-0 tpl:text-base tpl:font-semibold tpl:text-[var(--tpl-text)]" }, Ge = { class: "tpl:m-0 tpl:text-sm tpl:text-[var(--tpl-text-muted)]" }, Ke = { class: "tpl:m-0 tpl:flex tpl:max-h-64 tpl:list-none tpl:flex-col tpl:gap-1.5 tpl:overflow-y-auto tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-2" }, qe = { class: "tpl:text-xs tpl:text-[var(--tpl-text)]" }, Je = { class: "tpl:font-mono tpl:text-[10px] tpl:text-[var(--tpl-text-dim)]" }, Ye = { class: "tpl:flex tpl:justify-end tpl:gap-2" }, Xe = /* @__PURE__ */ l({ | ||
| __name: "CloudSaveGateModal", | ||
| props: { | ||
| open: { type: Boolean }, | ||
| issues: {} | ||
| }, | ||
| emits: ["cancel", "confirm"], | ||
| setup(t, { emit: n }) { | ||
| let i = n, { t: a } = Q(); | ||
| return (n, o) => (e(), x(T, { | ||
| "enter-active-class": "tpl:transition-opacity tpl:duration-150", | ||
| "leave-active-class": "tpl:transition-opacity tpl:duration-150", | ||
| "enter-from-class": "tpl:opacity-0", | ||
| "leave-to-class": "tpl:opacity-0" | ||
| }, { | ||
| default: O(() => [t.open ? (e(), m("div", { | ||
| key: 0, | ||
| role: "dialog", | ||
| "aria-modal": "true", | ||
| "aria-label": C(a).saveGate.title, | ||
| class: "tpl:fixed tpl:inset-0 tpl:z-50 tpl:flex tpl:items-center tpl:justify-center tpl:bg-black/40 tpl:p-6", | ||
| onClick: o[2] ||= u((e) => i("cancel"), ["self"]) | ||
| }, [f("div", He, [ | ||
| f("header", Ue, [E(C(fe), { | ||
| size: 18, | ||
| "stroke-width": 2, | ||
| class: "tpl:text-[var(--tpl-warning)]" | ||
| }), f("h2", We, w(C(a).saveGate.title), 1)]), | ||
| f("p", Ge, w(C(a).saveGate.body), 1), | ||
| f("ul", Ke, [(e(!0), m(_, null, r(t.issues, (t) => (e(), m("li", { | ||
| key: `${t.ruleId}-${t.blockId ?? "template"}`, | ||
| class: "tpl:flex tpl:flex-col tpl:gap-0.5 tpl:rounded tpl:px-2 tpl:py-1.5" | ||
| }, [f("span", qe, w(t.message), 1), f("span", Je, w(t.ruleId), 1)]))), 128))]), | ||
| f("footer", Ye, [f("button", { | ||
| type: "button", | ||
| class: "tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)]", | ||
| onClick: o[0] ||= (e) => i("cancel") | ||
| }, w(C(a).saveGate.cancel), 1), f("button", { | ||
| type: "button", | ||
| class: "tpl:rounded-md tpl:bg-[var(--tpl-danger)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:text-white", | ||
| onClick: o[1] ||= (e) => i("confirm") | ||
| }, w(C(a).saveGate.confirm), 1)]) | ||
| ])], 8, Ve)) : v("", !0)]), | ||
| _: 1 | ||
| })); | ||
| } | ||
| }), Ze = { | ||
| class: "tpl-header tpl:absolute tpl:top-0 tpl:right-0 tpl:left-0 tpl:z-50 tpl:grid tpl:h-14 tpl:grid-cols-[1fr_auto_1fr] tpl:items-center tpl:px-4", | ||
| style: { | ||
| "background-color": "color-mix(in srgb, var(--tpl-bg) 80%, transparent)", | ||
| "backdrop-filter": "blur(12px)", | ||
| "-webkit-backdrop-filter": "blur(12px)", | ||
| "box-shadow": "var(--tpl-shadow-md)", | ||
| "border-bottom": "1px solid var(--tpl-border)" | ||
| } | ||
| }, Qe = { class: "tpl-header-left tpl:flex tpl:min-w-[200px] tpl:items-center tpl:gap-3" }, $e = { | ||
| key: 0, | ||
| class: "tpl:text-xs tpl:opacity-60 tpl:text-[var(--tpl-text-muted)]" | ||
| }, et = { class: "tpl-header-center tpl:flex tpl:items-center tpl:justify-center tpl:gap-10" }, tt = { class: "tpl-header-right tpl:flex tpl:min-w-[200px] tpl:items-center tpl:justify-end tpl:gap-3" }, nt = ["data-tooltip"], rt = { | ||
| key: 1, | ||
| "aria-live": "polite", | ||
| class: "tpl-status tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:text-[var(--tpl-success)]" | ||
| }, it = { | ||
| key: 2, | ||
| "aria-live": "polite", | ||
| class: "tpl-status tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:text-[var(--tpl-text-muted)]" | ||
| }, at = ["aria-label", "aria-expanded"], ot = { | ||
| key: 0, | ||
| class: "tpl:inline-flex tpl:size-4.5 tpl:items-center tpl:justify-center tpl:rounded-full tpl:text-[10px] tpl:font-semibold tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]" | ||
| }, st = ["aria-expanded"], ct = { | ||
| key: 0, | ||
| class: "tpl:absolute tpl:right-0 tpl:top-full tpl:z-50 tpl:mt-1 tpl:origin-top-right" | ||
| }, lt = ["disabled"], ut = ["disabled"], dt = /* @__PURE__ */ l({ | ||
| __name: "CloudHeader", | ||
| props: { | ||
| editor: {}, | ||
| core: {}, | ||
| featureFlags: {}, | ||
| panelState: {}, | ||
| snapshotPreview: {}, | ||
| commentsInstance: {}, | ||
| testEmail: {}, | ||
| websocket: {}, | ||
| collaboration: {}, | ||
| isCollaborationEnabled: { type: Boolean }, | ||
| isSaveDisabled: { type: Boolean }, | ||
| isSaving: { type: Boolean } | ||
| }, | ||
| emits: ["save"], | ||
| setup(t) { | ||
| let n = D(() => import("./CollaboratorBar-Bc6q0gB9.js")), r = D(() => import("./SnapshotHistory-CIo2Jaw-.js")), i = D(() => import("./AiFeatureMenu-Co14YVJt.js")), { t: a, format: o } = Q(); | ||
| return (l, d) => (e(), m("header", Ze, [ | ||
| f("div", Qe, [t.featureFlags.templateLimit.value === null ? v("", !0) : (e(), m("span", $e, w(C(o)(C(a).header.templatesUsed, { | ||
| used: t.featureFlags.templateCount.value, | ||
| max: t.featureFlags.templateLimit.value | ||
| })), 1))]), | ||
| f("div", et, [ | ||
| E(q, { | ||
| viewport: t.editor.state.viewport, | ||
| onChange: t.editor.setViewport | ||
| }, null, 8, ["viewport", "onChange"]), | ||
| E(oe, { | ||
| "dark-mode": t.editor.state.darkMode, | ||
| onChange: t.editor.setDarkMode | ||
| }, null, 8, ["dark-mode", "onChange"]), | ||
| E(J, { | ||
| "preview-mode": t.editor.state.previewMode, | ||
| onChange: t.editor.setPreviewMode | ||
| }, null, 8, ["preview-mode", "onChange"]), | ||
| t.collaboration && t.isCollaborationEnabled ? (e(), x(C(n), { | ||
| key: 0, | ||
| collaborators: t.collaboration.collaborators.value, | ||
| "is-connected": t.websocket.isConnected.value | ||
| }, null, 8, ["collaborators", "is-connected"])) : v("", !0), | ||
| t.snapshotPreview.snapshotHistoryInstance.value ? (e(), x(C(r), { | ||
| key: 1, | ||
| snapshots: t.snapshotPreview.snapshotHistorySnapshots.value, | ||
| "is-loading": t.snapshotPreview.snapshotHistoryIsLoading.value, | ||
| "is-restoring": t.snapshotPreview.snapshotHistoryIsRestoring.value, | ||
| onLoad: t.snapshotPreview.loadSnapshotHistory, | ||
| onNavigate: t.snapshotPreview.handleSnapshotNavigate | ||
| }, null, 8, [ | ||
| "snapshots", | ||
| "is-loading", | ||
| "is-restoring", | ||
| "onLoad", | ||
| "onNavigate" | ||
| ])) : v("", !0) | ||
| ]), | ||
| f("div", tt, [ | ||
| t.featureFlags.saveStatus.value === "error" ? (e(), m("div", { | ||
| key: 0, | ||
| "aria-live": "assertive", | ||
| class: "tpl-tooltip tpl-status tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:text-[var(--tpl-danger)]", | ||
| "data-tooltip": t.featureFlags.saveErrorMessage.value | ||
| }, [E(C(K), { | ||
| size: 12, | ||
| "stroke-width": 2.5 | ||
| }), s(" " + w(C(a).header.saveFailed), 1)], 8, nt)) : t.featureFlags.saveStatus.value === "saved" ? (e(), m("div", rt, [E(C(G), { | ||
| size: 12, | ||
| "stroke-width": 2.5 | ||
| }), s(" " + w(C(a).header.saved), 1)])) : t.editor.state.isDirty ? (e(), m("div", it, [d[4] ||= f("span", { class: "tpl-pulse tpl:size-1.5 tpl:rounded-full tpl:bg-[var(--tpl-primary)]" }, null, -1), s(" " + w(C(a).header.unsaved), 1)])) : v("", !0), | ||
| t.commentsInstance.isEnabled.value && t.featureFlags.hasTemplateSaved.value ? (e(), m("button", { | ||
| key: 3, | ||
| "aria-label": t.commentsInstance.unresolvedCount.value > 0 ? `${C(a).comments.button} (${t.commentsInstance.unresolvedCount.value})` : C(a).comments.button, | ||
| "aria-expanded": t.panelState.commentsOpen.value, | ||
| class: c(C($)), | ||
| style: b({ | ||
| backgroundColor: t.panelState.commentsOpen.value ? "var(--tpl-primary)" : "transparent", | ||
| color: t.panelState.commentsOpen.value ? "var(--tpl-bg)" : "var(--tpl-primary)", | ||
| borderColor: "var(--tpl-primary)" | ||
| }), | ||
| onClick: d[0] ||= (e) => t.panelState.commentsOpen.value = !t.panelState.commentsOpen.value | ||
| }, [ | ||
| E(C(X), { | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| }), | ||
| s(" " + w(C(a).comments.button) + " ", 1), | ||
| t.commentsInstance.unresolvedCount.value > 0 && !t.panelState.commentsOpen.value ? (e(), m("span", ot, w(t.commentsInstance.unresolvedCount.value), 1)) : v("", !0) | ||
| ], 14, at)) : v("", !0), | ||
| t.featureFlags.canUseAiGeneration.value && t.featureFlags.hasTemplateSaved.value ? (e(), m("div", { | ||
| key: 4, | ||
| ref: (e) => t.panelState.aiMenuRef.value = e, | ||
| class: "tpl:relative" | ||
| }, [f("button", { | ||
| "aria-expanded": t.panelState.aiMenuOpen.value, | ||
| class: c(["tpl-ai-btn tpl:inline-flex tpl:items-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:px-4 tpl:py-2 tpl:text-sm tpl:font-semibold tpl:whitespace-nowrap tpl:transition-all tpl:duration-200", t.panelState.aiButtonActive.value ? "tpl-ai-btn--active" : "tpl-ai-btn--idle"]), | ||
| onClick: d[1] ||= u((...e) => t.panelState.toggleAiMenu && t.panelState.toggleAiMenu(...e), ["stop"]) | ||
| }, [E(C(de), { | ||
| size: 16, | ||
| "stroke-width": 2, | ||
| class: "tpl-ai-btn-icon" | ||
| }), s(" " + w(C(a).aiChat.button), 1)], 10, st), E(T, { | ||
| "enter-active-class": "tpl:transition-all tpl:duration-150 tpl:ease-out", | ||
| "enter-from-class": "tpl:scale-95 tpl:opacity-0", | ||
| "enter-to-class": "tpl:scale-100 tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-all tpl:duration-100 tpl:ease-in", | ||
| "leave-from-class": "tpl:scale-100 tpl:opacity-100", | ||
| "leave-to-class": "tpl:scale-95 tpl:opacity-0" | ||
| }, { | ||
| default: O(() => [t.panelState.aiMenuOpen.value ? (e(), m("div", ct, [E(C(i), { | ||
| "active-feature": t.panelState.activeAiFeature.value, | ||
| onSelect: t.panelState.handleAiFeatureSelect | ||
| }, null, 8, ["active-feature", "onSelect"])])) : v("", !0)]), | ||
| _: 1 | ||
| })], 512)) : v("", !0), | ||
| t.testEmail.isEnabled.value && t.featureFlags.canSendTestEmail.value ? (e(), m("button", { | ||
| key: 5, | ||
| class: c(C($)), | ||
| style: { | ||
| "background-color": "transparent", | ||
| color: "var(--tpl-primary)", | ||
| "border-color": "var(--tpl-primary)" | ||
| }, | ||
| disabled: t.testEmail.isSending.value || !t.featureFlags.hasTemplateSaved.value, | ||
| onClick: d[2] ||= (e) => t.panelState.testEmailModalOpen.value = !0 | ||
| }, [t.testEmail.isSending.value ? (e(), x(C(Y), { | ||
| key: 1, | ||
| class: "tpl-spinner", | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })) : (e(), x(C(Z), { | ||
| key: 0, | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })), s(" " + w(C(a).testEmail.button), 1)], 10, lt)) : v("", !0), | ||
| f("button", { | ||
| class: c(C($)), | ||
| style: { | ||
| "background-color": "transparent", | ||
| color: "var(--tpl-primary)", | ||
| "border-color": "var(--tpl-primary)" | ||
| }, | ||
| disabled: t.isSaveDisabled, | ||
| onClick: d[3] ||= (e) => l.$emit("save") | ||
| }, [t.isSaving ? (e(), x(C(Y), { | ||
| key: 1, | ||
| class: "tpl-spinner", | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })) : (e(), x(C(je), { | ||
| key: 0, | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })), s(" " + w(t.isSaving ? C(a).header.saving : C(a).header.save), 1)], 10, ut) | ||
| ]) | ||
| ])); | ||
| } | ||
| }), ft = /* @__PURE__ */ l({ | ||
| __name: "CloudPanels", | ||
| props: { | ||
| config: {}, | ||
| editor: {}, | ||
| core: {}, | ||
| panelState: {}, | ||
| planConfigInstance: {}, | ||
| testEmail: {}, | ||
| mediaLib: {}, | ||
| savedModulesHeadless: {}, | ||
| showSaveModuleDialog: { type: Boolean }, | ||
| saveModulePreSelectedBlockId: {}, | ||
| showModuleBrowserModal: { type: Boolean } | ||
| }, | ||
| emits: [ | ||
| "update:showSaveModuleDialog", | ||
| "update:saveModulePreSelectedBlockId", | ||
| "update:showModuleBrowserModal", | ||
| "send-test-email", | ||
| "module-insert" | ||
| ], | ||
| setup(t, { expose: n, emit: r }) { | ||
| let i = D(() => import("./AiChatSidebar-BUKj9n02.js")), a = D(() => import("./CommentsSidebar-DiH4R4F0.js")), s = D(() => import("./DesignReferenceSidebar-BP32MgpS.js")), c = D(() => import("./TemplateScoringPanel-seBvvn8O.js")), l = D(() => import("./TestEmailModal-BuCuWp3N.js")), u = D(() => import("./SaveModuleDialog-DWidA0c9.js")), d = D(() => import("./ModuleBrowserModal-CWegFoOA.js")), f = D(async () => { | ||
| try { | ||
| return (await import("@templatical/media-library")).MediaLibraryModal; | ||
| } catch { | ||
| throw Error("[Templatical] Cloud media library requires the optional peer dependency '@templatical/media-library'. Please install it."); | ||
| } | ||
| }), p = r; | ||
| function h(e, t, n) { | ||
| t.history.record(), n.setContent(e), t.conditionPreview.reset(); | ||
| } | ||
| function g(e, t) { | ||
| p("module-insert", e, t); | ||
| } | ||
| let y = o(null); | ||
| function b(e) { | ||
| y.value?.filterByBlock(e); | ||
| } | ||
| return n({ filterCommentsByBlock: b }), (n, r) => (e(), m(_, null, [ | ||
| E(C(i), { | ||
| visible: t.panelState.aiChatOpen.value, | ||
| "on-apply": (e) => h(e, t.core, t.editor), | ||
| onClose: r[0] ||= (e) => t.panelState.aiChatOpen.value = !1 | ||
| }, null, 8, ["visible", "on-apply"]), | ||
| E(C(c), { | ||
| visible: t.panelState.scoringPanelOpen.value, | ||
| onClose: r[1] ||= (e) => t.panelState.scoringPanelOpen.value = !1 | ||
| }, null, 8, ["visible"]), | ||
| E(C(s), { | ||
| visible: t.panelState.designReferenceOpen.value, | ||
| "has-existing-blocks": t.editor.content.value.blocks.length > 0, | ||
| onClose: r[2] ||= (e) => t.panelState.designReferenceOpen.value = !1, | ||
| onApply: r[3] ||= (e) => h(e, t.core, t.editor) | ||
| }, null, 8, ["visible", "has-existing-blocks"]), | ||
| E(C(a), { | ||
| ref_key: "commentsSidebar", | ||
| ref: y, | ||
| visible: t.panelState.commentsOpen.value, | ||
| onClose: r[4] ||= (e) => t.panelState.commentsOpen.value = !1 | ||
| }, null, 8, ["visible"]), | ||
| E(C(l), { | ||
| visible: t.panelState.testEmailModalOpen.value, | ||
| "allowed-emails": t.testEmail.allowedEmails.value, | ||
| "is-sending": t.testEmail.isSending.value, | ||
| error: t.testEmail.error.value, | ||
| onSend: r[5] ||= (e) => p("send-test-email", e), | ||
| onClose: r[6] ||= (e) => t.panelState.testEmailModalOpen.value = !1 | ||
| }, null, 8, [ | ||
| "visible", | ||
| "allowed-emails", | ||
| "is-sending", | ||
| "error" | ||
| ]), | ||
| t.planConfigInstance.hasFeature("saved_modules") && t.config.modules !== !1 ? (e(), x(C(u), { | ||
| key: 0, | ||
| visible: t.showSaveModuleDialog, | ||
| "pre-selected-block-id": t.saveModulePreSelectedBlockId, | ||
| onClose: r[7] ||= (e) => { | ||
| p("update:showSaveModuleDialog", !1), p("update:saveModulePreSelectedBlockId", null); | ||
| }, | ||
| onSaved: r[8] ||= (e) => t.savedModulesHeadless.loadModules() | ||
| }, null, 8, ["visible", "pre-selected-block-id"])) : v("", !0), | ||
| t.planConfigInstance.hasFeature("saved_modules") && t.config.modules !== !1 ? (e(), x(C(d), { | ||
| key: 1, | ||
| visible: t.showModuleBrowserModal, | ||
| onClose: r[9] ||= (e) => p("update:showModuleBrowserModal", !1), | ||
| onInsert: g | ||
| }, null, 8, ["visible"])) : v("", !0), | ||
| E(C(f), { | ||
| visible: t.panelState.mediaLibraryOpen.value, | ||
| accept: t.panelState.mediaLibraryAccept.value, | ||
| "popover-target": t.core.popoverRoot.value, | ||
| onSelect: t.mediaLib.handleMediaSelect, | ||
| onClose: t.mediaLib.handleMediaLibraryClose | ||
| }, null, 8, [ | ||
| "visible", | ||
| "accept", | ||
| "popover-target", | ||
| "onSelect", | ||
| "onClose" | ||
| ]) | ||
| ], 64)); | ||
| } | ||
| }), pt = { | ||
| key: 0, | ||
| class: "tpl-loading tpl:absolute tpl:inset-0 tpl:z-overlay tpl:flex tpl:flex-col tpl:bg-[var(--tpl-bg)]" | ||
| }, mt = { class: "tpl:flex tpl:flex-1 tpl:overflow-hidden" }, ht = { class: "tpl:flex tpl:w-12 tpl:shrink-0 tpl:flex-col tpl:items-center tpl:gap-4 tpl:py-5 tpl:border-r tpl:border-[var(--tpl-border)]" }, gt = /* @__PURE__ */ l({ | ||
| __name: "CloudLoadingOverlay", | ||
| props: { visible: { type: Boolean } }, | ||
| setup(t) { | ||
| return (n, i) => t.visible ? (e(), m("div", pt, [i[1] ||= p("<div class=\"tpl:flex tpl:h-14 tpl:shrink-0 tpl:items-center tpl:justify-between tpl:px-4 tpl:border-b tpl:border-[var(--tpl-border)]\"><div class=\"tpl-shimmer tpl:h-5 tpl:w-28 tpl:rounded-[var(--tpl-radius-sm)]\"></div><div class=\"tpl:flex tpl:gap-3\"><div class=\"tpl-shimmer tpl:h-8 tpl:w-20 tpl:rounded-[var(--tpl-radius-sm)]\"></div><div class=\"tpl-shimmer tpl:h-8 tpl:w-20 tpl:rounded-[var(--tpl-radius-sm)]\"></div></div></div>", 1), f("div", mt, [f("div", ht, [(e(), m(_, null, r(5, (e) => f("div", { | ||
| key: e, | ||
| class: "tpl-shimmer tpl:size-7 tpl:rounded-[var(--tpl-radius-sm)]" | ||
| })), 64))]), i[0] ||= p("<div class=\"tpl:flex tpl:flex-1 tpl:items-start tpl:justify-center tpl:overflow-auto tpl:p-8 tpl:bg-[var(--tpl-canvas-bg)]\"><div class=\"tpl:w-full tpl:max-w-[600px] tpl:rounded-[var(--tpl-radius)] tpl:p-6 tpl:bg-[var(--tpl-bg)] tpl:shadow-[var(--tpl-shadow-sm)]\"><div class=\"tpl:space-y-2 tpl:py-4\"><div class=\"tpl-shimmer tpl:h-3 tpl:w-3/4 tpl:rounded\"></div><div class=\"tpl-shimmer tpl:h-3 tpl:w-full tpl:rounded\"></div><div class=\"tpl-shimmer tpl:h-3 tpl:w-5/6 tpl:rounded\"></div></div><div class=\"tpl:py-4\"><div class=\"tpl-shimmer tpl:h-44 tpl:w-full tpl:rounded-[var(--tpl-radius-sm)]\"></div></div><div class=\"tpl:space-y-2 tpl:py-4\"><div class=\"tpl-shimmer tpl:h-3 tpl:w-full tpl:rounded\"></div><div class=\"tpl-shimmer tpl:h-3 tpl:w-2/3 tpl:rounded\"></div></div><div class=\"tpl:flex tpl:justify-center tpl:py-4\"><div class=\"tpl-shimmer tpl:h-10 tpl:w-36 tpl:rounded-[var(--tpl-radius-sm)]\"></div></div><div class=\"tpl:space-y-2 tpl:py-4\"><div class=\"tpl-shimmer tpl:mx-auto tpl:h-2.5 tpl:w-1/2 tpl:rounded\"></div><div class=\"tpl-shimmer tpl:mx-auto tpl:h-2.5 tpl:w-1/3 tpl:rounded\"></div></div></div></div><div class=\"tpl:flex tpl:w-[320px] tpl:shrink-0 tpl:flex-col tpl:gap-4 tpl:p-4 tpl:border-l tpl:border-[var(--tpl-border)]\"><div class=\"tpl-shimmer tpl:h-8 tpl:rounded-[var(--tpl-radius-sm)]\"></div><div class=\"tpl-shimmer tpl:h-32 tpl:rounded-[var(--tpl-radius)]\"></div><div class=\"tpl-shimmer tpl:h-32 tpl:rounded-[var(--tpl-radius)]\"></div></div>", 2)])])) : v("", !0); | ||
| } | ||
| }), _t = { | ||
| key: 0, | ||
| role: "alert", | ||
| class: "tpl-error tpl:absolute tpl:inset-0 tpl:z-overlay tpl:flex tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-6 tpl:px-8 tpl:bg-[var(--tpl-bg)]" | ||
| }, vt = { class: "tpl:flex tpl:size-16 tpl:items-center tpl:justify-center tpl:rounded-full tpl:bg-[var(--tpl-danger-light)]" }, yt = { class: "tpl:flex tpl:flex-col tpl:items-center tpl:gap-2 tpl:text-center" }, bt = { class: "tpl:text-lg tpl:font-semibold tpl:text-[var(--tpl-text)]" }, xt = { class: "tpl:max-w-md tpl:text-sm tpl:text-[var(--tpl-text-muted)]" }, St = /* @__PURE__ */ l({ | ||
| __name: "CloudErrorOverlay", | ||
| props: { | ||
| error: {}, | ||
| visible: { type: Boolean } | ||
| }, | ||
| emits: ["retry"], | ||
| setup(t, { emit: n }) { | ||
| let r = n, { t: i } = Q(); | ||
| function a(e) { | ||
| return "isUnauthorized" in e && e.isUnauthorized ? i.error.authFailed : "isNotFound" in e && e.isNotFound ? i.error.templateNotFound : i.error.defaultMessage; | ||
| } | ||
| function o(e) { | ||
| return "isNotFound" in e && !!e.isNotFound; | ||
| } | ||
| return (n, s) => t.visible && t.error ? (e(), m("div", _t, [ | ||
| f("div", vt, [E(C(K), { | ||
| size: 32, | ||
| "stroke-width": 1.5, | ||
| class: "tpl:text-[var(--tpl-danger)]" | ||
| })]), | ||
| f("div", yt, [f("h2", bt, w(C(i).error.title), 1), f("p", xt, w(a(t.error)), 1)]), | ||
| o(t.error) ? v("", !0) : (e(), m("button", { | ||
| key: 0, | ||
| class: "tpl-btn tpl-btn-primary tpl:inline-flex tpl:items-center tpl:gap-2 tpl:rounded-md tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:shadow-xs tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]", | ||
| onClick: s[0] ||= (e) => r("retry") | ||
| }, w(C(i).error.retry), 1)) | ||
| ])) : v("", !0); | ||
| } | ||
| }), Ct = { | ||
| key: 0, | ||
| class: "tpl-preview-banner tpl:absolute tpl:top-14 tpl:right-0 tpl:left-0 tpl:z-40 tpl:flex tpl:items-center tpl:justify-center tpl:gap-4 tpl:px-4 tpl:py-3 tpl:bg-[var(--tpl-primary-light)] tpl:border-b tpl:border-[var(--tpl-primary)]" | ||
| }, wt = { class: "tpl:flex tpl:items-center tpl:gap-2 tpl:text-sm tpl:text-[var(--tpl-text)]" }, Tt = { class: "tpl:flex tpl:items-center tpl:gap-2" }, Et = /* @__PURE__ */ l({ | ||
| __name: "SnapshotPreviewBanner", | ||
| props: { visible: { type: Boolean } }, | ||
| emits: ["cancel", "confirm"], | ||
| setup(t, { emit: n }) { | ||
| let r = n, { t: i } = Q(); | ||
| return (n, a) => t.visible ? (e(), m("div", Ct, [f("div", wt, [E(C(ue), { | ||
| size: 18, | ||
| "stroke-width": 2, | ||
| class: "tpl:text-[var(--tpl-primary)]" | ||
| }), f("span", null, w(C(i).snapshotPreview.message), 1)]), f("div", Tt, [f("button", { | ||
| class: "tpl:rounded-md tpl:px-3 tpl:py-1.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]", | ||
| style: { "background-color": "transparent" }, | ||
| onClick: a[0] ||= (e) => r("cancel") | ||
| }, w(C(i).snapshotPreview.cancel), 1), f("button", { | ||
| class: "tpl:rounded-md tpl:px-3 tpl:py-1.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]", | ||
| onClick: a[1] ||= (e) => r("confirm") | ||
| }, w(C(i).snapshotPreview.restore), 1)])])) : v("", !0); | ||
| } | ||
| }), Dt = { | ||
| key: 0, | ||
| role: "status", | ||
| "aria-live": "polite", | ||
| class: "tpl:absolute tpl:top-16 tpl:left-1/2 tpl:z-toast tpl:-translate-x-1/2 tpl:rounded-[var(--tpl-radius)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:shadow-lg", | ||
| style: { | ||
| "background-color": "var(--tpl-warning-light)", | ||
| color: "var(--tpl-text)", | ||
| border: "1px solid var(--tpl-warning)" | ||
| } | ||
| }, Ot = /* @__PURE__ */ l({ | ||
| __name: "CollabUndoToast", | ||
| props: { visible: { type: Boolean } }, | ||
| setup(t) { | ||
| let { t: n } = U(); | ||
| return (r, i) => t.visible ? (e(), m("div", Dt, w(C(n).history.collabWarning), 1)) : v("", !0); | ||
| } | ||
| }), kt = ["data-tpl-theme"], At = { class: "tpl:sticky tpl:top-0 tpl:z-40 tpl:h-0" }, jt = { class: "tpl-main tpl:flex tpl:justify-center tpl:p-8" }, Mt = ["aria-label"], Nt = /* @__PURE__ */ pe(/* @__PURE__ */ l({ | ||
| __name: "CloudEditor", | ||
| props: { | ||
| config: {}, | ||
| translations: {}, | ||
| cloudTranslations: {}, | ||
| fontsManager: {}, | ||
| shadowRoot: {} | ||
| }, | ||
| emits: ["ready"], | ||
| setup(n, { expose: r, emit: a }) { | ||
| let l = n; | ||
| h(B, l.cloudTranslations); | ||
| let u = a, d = o(null), p = o(null), _ = Le({ | ||
| config: l.config, | ||
| translations: l.translations, | ||
| fontsManager: l.fontsManager, | ||
| emit: u, | ||
| getCommentsSidebar: () => d.value ? { filterByBlock: d.value.filterCommentsByBlock } : null, | ||
| editorRoot: l.shadowRoot, | ||
| containerEl: p | ||
| }), { isInitializing: S, isAuthReady: D, initError: k, planConfigInstance: A, websocket: M, collaboration: N, isCollaborationEnabled: P, editor: F, core: I, featureFlags: L, mediaLib: R, exporter: z, testEmail: V, commentsInstance: ee, savedModulesHeadless: te, panelState: H, snapshotPreview: U, collabWarning: W, showSaveModuleDialog: G, showModuleBrowserModal: K, saveModulePreSelectedBlockId: q, setThemeOverrides: J, setUiTheme: re } = _; | ||
| async function oe(e) { | ||
| try { | ||
| await V.sendTestEmail(e), H.testEmailModalOpen.value = !1; | ||
| } catch {} | ||
| } | ||
| function ue(e, t) { | ||
| for (let n = 0; n < e.content.length; n++) { | ||
| let r = j(e.content[n]), i = t === void 0 ? void 0 : t + n; | ||
| F.addBlock(r, void 0, void 0, i); | ||
| } | ||
| K.value = !1; | ||
| } | ||
| let Y = ze({ | ||
| config: l.config, | ||
| editor: F, | ||
| websocket: M, | ||
| planConfigInstance: A, | ||
| snapshotPreview: U, | ||
| core: I, | ||
| exporter: z, | ||
| featureFlags: L, | ||
| isDestroyed: _.isDestroyed | ||
| }), X = Be({ | ||
| issues: I.templateLint ? I.templateLint.issues : o([]), | ||
| planConfig: A.config | ||
| }); | ||
| async function Z() { | ||
| await X.tryRunSave(() => Y.saveTemplate().catch((e) => l.config.onError?.(e))); | ||
| } | ||
| return _.onSaveHook.value = Z, i(() => { | ||
| _.initialize(); | ||
| }), g(() => { | ||
| _.destroy(); | ||
| }), r({ | ||
| getContent: () => F.content.value, | ||
| setContent: (e) => F.setContent(e), | ||
| setTheme: re, | ||
| setThemeOverrides: J, | ||
| create: Y.createTemplate, | ||
| load: Y.loadTemplate, | ||
| save: Y.saveTemplate, | ||
| sendTestEmail: V.sendTestEmail | ||
| }), (r, i) => (e(), m("div", { | ||
| ref_key: "rootEl", | ||
| ref: p, | ||
| class: c(["tpl tpl:relative tpl:h-full tpl:overflow-hidden", { "tpl:dark": C(F).state.darkMode }]), | ||
| "data-tpl-theme": C(I).resolvedTheme.value, | ||
| style: b(C(I).themeStyles.value) | ||
| }, [ | ||
| E(T, { | ||
| "enter-active-class": "tpl:transition-opacity tpl:duration-200", | ||
| "enter-from-class": "tpl:opacity-100", | ||
| "enter-to-class": "tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-opacity tpl:duration-300", | ||
| "leave-from-class": "tpl:opacity-100", | ||
| "leave-to-class": "tpl:opacity-0" | ||
| }, { | ||
| default: O(() => [E(gt, { visible: C(S) || C(F).state.isLoading }, null, 8, ["visible"])]), | ||
| _: 1 | ||
| }), | ||
| E(T, { | ||
| "enter-active-class": "tpl:transition-opacity tpl:duration-200", | ||
| "enter-from-class": "tpl:opacity-0", | ||
| "enter-to-class": "tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-opacity tpl:duration-300", | ||
| "leave-from-class": "tpl:opacity-100", | ||
| "leave-to-class": "tpl:opacity-0" | ||
| }, { | ||
| default: O(() => [E(St, { | ||
| error: C(k), | ||
| visible: !!C(k) && !C(S), | ||
| onRetry: C(_).initialize | ||
| }, null, 8, [ | ||
| "error", | ||
| "visible", | ||
| "onRetry" | ||
| ])]), | ||
| _: 1 | ||
| }), | ||
| E(dt, { | ||
| editor: C(F), | ||
| core: C(I), | ||
| "feature-flags": C(L), | ||
| "panel-state": C(H), | ||
| "snapshot-preview": C(U), | ||
| "comments-instance": C(ee), | ||
| "test-email": C(V), | ||
| websocket: C(M), | ||
| collaboration: C(N), | ||
| "is-collaboration-enabled": C(P), | ||
| "is-saving": C(F).state.isSaving || C(L).isSaveExporting.value, | ||
| "is-save-disabled": C(F).state.isSaving || C(L).isSaveExporting.value || !C(F).state.isDirty, | ||
| onSave: Z | ||
| }, null, 8, [ | ||
| "editor", | ||
| "core", | ||
| "feature-flags", | ||
| "panel-state", | ||
| "snapshot-preview", | ||
| "comments-instance", | ||
| "test-email", | ||
| "websocket", | ||
| "collaboration", | ||
| "is-collaboration-enabled", | ||
| "is-saving", | ||
| "is-save-disabled" | ||
| ]), | ||
| E(Xe, { | ||
| open: C(X).modalOpen.value, | ||
| issues: C(X).blockingIssues.value, | ||
| onCancel: C(X).cancel, | ||
| onConfirm: C(X).confirmAndSave | ||
| }, null, 8, [ | ||
| "open", | ||
| "issues", | ||
| "onCancel", | ||
| "onConfirm" | ||
| ]), | ||
| E(Et, { | ||
| visible: C(U).isPreviewingSnapshot.value, | ||
| onCancel: C(U).cancelPreview, | ||
| onConfirm: C(U).confirmRestoreSnapshot | ||
| }, null, 8, [ | ||
| "visible", | ||
| "onCancel", | ||
| "onConfirm" | ||
| ]), | ||
| E(T, { | ||
| "enter-active-class": "tpl:transition-all tpl:duration-200 tpl:ease-out", | ||
| "enter-from-class": "tpl:translate-y-[-8px] tpl:opacity-0", | ||
| "enter-to-class": "tpl:translate-y-0 tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-all tpl:duration-300 tpl:ease-in", | ||
| "leave-from-class": "tpl:translate-y-0 tpl:opacity-100", | ||
| "leave-to-class": "tpl:translate-y-[-8px] tpl:opacity-0" | ||
| }, { | ||
| default: O(() => [E(Ot, { visible: C(W).collabUndoWarningVisible.value }, null, 8, ["visible"])]), | ||
| _: 1 | ||
| }), | ||
| t(E(se, null, null, 512), [[y, !C(F).state.previewMode]]), | ||
| f("div", { | ||
| class: c(["tpl-body tpl:absolute tpl:bottom-0 tpl:overflow-auto", [C(F).state.previewMode ? "tpl:left-0 tpl:right-0" : C(H).rightPanelOpen.value ? "tpl:left-12 tpl:right-[680px]" : "tpl:left-12 tpl:right-[320px]", C(U).isPreviewingSnapshot.value ? "tpl:top-[104px]" : "tpl:top-14"]]), | ||
| style: { | ||
| transition: "all 300ms cubic-bezier(0.34, 1.56, 0.64, 1)", | ||
| "background-color": "var(--tpl-canvas-bg)" | ||
| } | ||
| }, [f("div", At, [E(T, { name: "tpl-restore-btn" }, { | ||
| default: O(() => [C(I).conditionPreview.hasHiddenBlocks.value ? (e(), m("button", { | ||
| key: 0, | ||
| class: "tpl:absolute tpl:left-1/2 tpl:top-2 tpl:-translate-x-1/2 tpl:inline-flex tpl:items-center tpl:gap-1.5 tpl:rounded-full tpl:border tpl:px-3.5 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:whitespace-nowrap tpl:shadow-md tpl:hover:opacity-80", | ||
| style: { | ||
| "background-color": "var(--tpl-warning-light)", | ||
| color: "var(--tpl-warning)", | ||
| "border-color": "var(--tpl-warning)", | ||
| "backdrop-filter": "blur(8px)" | ||
| }, | ||
| onClick: i[0] ||= (e) => C(I).conditionPreview.reset() | ||
| }, [E(C(le), { | ||
| size: 13, | ||
| "stroke-width": 2 | ||
| }), s(" " + w(C(I).t.blockSettings.restoreHiddenBlocks), 1)])) : v("", !0)]), | ||
| _: 1 | ||
| })]), f("main", jt, [E(ne, { | ||
| viewport: C(F).state.viewport, | ||
| content: C(F).content.value, | ||
| "selected-block-id": C(F).state.selectedBlockId, | ||
| "dark-mode": C(F).state.darkMode, | ||
| "preview-mode": C(F).state.previewMode, | ||
| "locked-blocks": C(N)?.lockedBlocks.value ?? void 0, | ||
| onSelectBlock: C(F).selectBlock, | ||
| onOpenAiChat: i[1] ||= (e) => C(H).aiChatOpen.value = !0, | ||
| onOpenDesignReference: i[2] ||= (e) => C(H).designReferenceOpen.value = !0 | ||
| }, null, 8, [ | ||
| "viewport", | ||
| "content", | ||
| "selected-block-id", | ||
| "dark-mode", | ||
| "preview-mode", | ||
| "locked-blocks", | ||
| "onSelectBlock" | ||
| ])])], 2), | ||
| n.config.branding !== !1 && !C(L).isWhiteLabeled.value ? (e(), x(ie, { | ||
| key: 0, | ||
| "position-class": [C(F).state.previewMode ? "tpl:left-0 tpl:right-0" : C(H).rightPanelOpen.value ? "tpl:left-12 tpl:right-[680px]" : "tpl:left-12 tpl:right-[320px]"] | ||
| }, null, 8, ["position-class"])) : v("", !0), | ||
| f("div", { | ||
| class: "tpl-sr-only", | ||
| role: "status", | ||
| "aria-live": "polite", | ||
| "aria-atomic": "true", | ||
| "aria-label": C(I).t.landmarks.reorderAnnouncements | ||
| }, w(C(I).keyboardReorder.announcement.value), 9, Mt), | ||
| t(E(ae, { | ||
| "selected-block": C(F).selectedBlock.value, | ||
| settings: C(F).content.value.settings, | ||
| "shifted-left": C(H).rightPanelOpen.value, | ||
| onUpdateBlock: i[3] ||= (e) => C(F).updateBlock(C(F).selectedBlock.value.id, e), | ||
| onDeleteBlock: i[4] ||= (e) => C(I).blockActions.deleteBlock(C(F).selectedBlock.value.id), | ||
| onDuplicateBlock: i[5] ||= (e) => C(I).blockActions.duplicateBlock(C(F).selectedBlock.value), | ||
| onUpdateSettings: C(F).updateSettings | ||
| }, null, 8, [ | ||
| "selected-block", | ||
| "settings", | ||
| "shifted-left", | ||
| "onUpdateSettings" | ||
| ]), [[y, !C(F).state.previewMode]]), | ||
| !C(S) && C(D) ? (e(), x(ft, { | ||
| key: 1, | ||
| ref_key: "cloudPanelsRef", | ||
| ref: d, | ||
| config: l.config, | ||
| editor: C(F), | ||
| core: C(I), | ||
| "panel-state": C(H), | ||
| "plan-config-instance": C(A), | ||
| "test-email": C(V), | ||
| "media-lib": C(R), | ||
| "saved-modules-headless": C(te), | ||
| "show-save-module-dialog": C(G), | ||
| "save-module-pre-selected-block-id": C(q), | ||
| "show-module-browser-modal": C(K), | ||
| "onUpdate:showSaveModuleDialog": i[6] ||= (e) => G.value = e, | ||
| "onUpdate:saveModulePreSelectedBlockId": i[7] ||= (e) => q.value = e, | ||
| "onUpdate:showModuleBrowserModal": i[8] ||= (e) => K.value = e, | ||
| onSendTestEmail: oe, | ||
| onModuleInsert: ue | ||
| }, null, 8, [ | ||
| "config", | ||
| "editor", | ||
| "core", | ||
| "panel-state", | ||
| "plan-config-instance", | ||
| "test-email", | ||
| "media-lib", | ||
| "saved-modules-headless", | ||
| "show-save-module-dialog", | ||
| "save-module-pre-selected-block-id", | ||
| "show-module-browser-modal" | ||
| ])) : v("", !0), | ||
| f("div", { | ||
| ref: (e) => C(I).popoverRoot.value = e, | ||
| class: "tpl-popover-root" | ||
| }, null, 512), | ||
| E(ce) | ||
| ], 14, kt)); | ||
| } | ||
| }), [["__scopeId", "data-v-3f0f5cfa"]]); | ||
| //#endregion | ||
| export { Nt as default }; |
Sorry, the diff of this file is too big to display
| { | ||
| "version": "0.9.0", | ||
| "initialGzipBytes": 157590, | ||
| "initialRawBytes": 551204, | ||
| "version": "0.9.1", | ||
| "initialGzipBytes": 157631, | ||
| "initialRawBytes": 551337, | ||
| "initialFileCount": 36, | ||
@@ -9,3 +9,3 @@ "lazyGzipBytes": 265837, | ||
| "lazyFileCount": 46, | ||
| "generatedAt": "2026-05-26T19:29:12.906Z" | ||
| "generatedAt": "2026-05-27T08:11:21.639Z" | ||
| } |
+7
-7
| { | ||
| "name": "@templatical/editor", | ||
| "description": "Vue 3 visual drag-and-drop email editor powered by Templatical", | ||
| "version": "0.9.0", | ||
| "version": "0.9.1", | ||
| "bugs": "https://github.com/templatical/sdk/issues", | ||
@@ -35,5 +35,5 @@ "devDependencies": { | ||
| "vue-tsc": "^3.3.1", | ||
| "@templatical/core": "0.9.0", | ||
| "@templatical/quality": "0.9.0", | ||
| "@templatical/types": "0.9.0" | ||
| "@templatical/quality": "0.9.1", | ||
| "@templatical/core": "0.9.1", | ||
| "@templatical/types": "0.9.1" | ||
| }, | ||
@@ -66,5 +66,5 @@ "exports": { | ||
| "peerDependencies": { | ||
| "@templatical/media-library": "0.9.0", | ||
| "@templatical/quality": "0.9.0", | ||
| "@templatical/renderer": "0.9.0" | ||
| "@templatical/quality": "0.9.1", | ||
| "@templatical/media-library": "0.9.1", | ||
| "@templatical/renderer": "0.9.1" | ||
| }, | ||
@@ -71,0 +71,0 @@ "peerDependenciesMeta": { |
| import { $ as e, A as t, H as n, J as r, M as i, N as a, P as o, V as s, Z as c, _ as l, b as u, ct as d, f, g as p, h as m, it as h, j as g, l as _, m as v, n as y, ot as b, p as x, s as S, st as C, u as w, v as T, x as E, y as D, z as ee } from "./draggable-BwWMFq33.js"; | ||
| import { $t as O, A as k, At as A, Dt as j, E as M, En as N, Et as P, Ft as F, Ht as I, It as te, Nt as ne, Qt as L, Rt as re, S as R, Ut as z, Vt as B, Z as ie, Zt as V, _ as H, _t as U, b as W, c as G, d as K, f as q, g as J, h as Y, in as X, l as ae, m as oe, p as se, pn as Z, pt as ce, rt as le, s as ue, st as de, tt as Q, u as fe, ut as pe, v as me, vt as he, x as ge, xn as _e, y as ve, zn as ye } from "./features-D-2kVhHY.js"; | ||
| import { C as be, S as xe } from "./icons-fZoyKV_s.js"; | ||
| import { a as Se, c as Ce, i as we, l as Te, n as Ee, o as De, r as Oe, s as ke, t as Ae } from "./styles-o0HIrw9F.js"; | ||
| import { d as $ } from "./styleConstants-lGobwiLH.js"; | ||
| //#region src/cloud/composables/useSnapshotPreview.ts | ||
| function je(t) { | ||
| let { authManager: n, editor: i, history: a, conditionPreview: o, autoSave: s, onError: l } = t, u = e(null), d = c(null), p = c(null), m = !1; | ||
| r(() => { | ||
| m = !0; | ||
| }); | ||
| let h = f(() => d.value !== null), g = f(() => u.value?.snapshots.value ?? []), _ = f(() => u.value?.isLoading.value ?? !1), v = f(() => u.value?.isRestoring.value ?? !1); | ||
| function y() { | ||
| i.state.template?.id && !u.value && (u.value = q({ | ||
| authManager: n, | ||
| templateId: i.state.template.id, | ||
| onRestore: b, | ||
| onError: l | ||
| }), u.value.loadSnapshots()); | ||
| } | ||
| function b(e) { | ||
| i.setContent(e.content, !1), a.clear(), o.reset(); | ||
| } | ||
| async function x(e) { | ||
| if (!m) { | ||
| if (d.value) { | ||
| d.value = e, i.setContent(e.content, !1); | ||
| return; | ||
| } | ||
| i.state.isDirty && i.hasTemplate() && (await i.createSnapshot(), m) || (p.value = structuredClone(i.content.value), s?.pause(), d.value = e, i.setContent(e.content, !1)); | ||
| } | ||
| } | ||
| async function S() { | ||
| if (!(!d.value || !u.value)) try { | ||
| if (await u.value.restoreSnapshot(d.value.id), m || (await u.value.loadSnapshots(), m)) return; | ||
| } finally { | ||
| m || (d.value = null, p.value = null, s?.resume()); | ||
| } | ||
| } | ||
| function C() { | ||
| !d.value || !p.value || (i.setContent(p.value, !1), d.value = null, p.value = null, s?.resume()); | ||
| } | ||
| async function w() { | ||
| m || u.value && await u.value.loadSnapshots(); | ||
| } | ||
| return { | ||
| snapshotHistoryInstance: u, | ||
| previewingSnapshot: d, | ||
| contentBeforePreview: p, | ||
| isPreviewingSnapshot: h, | ||
| snapshotHistorySnapshots: g, | ||
| snapshotHistoryIsLoading: _, | ||
| snapshotHistoryIsRestoring: v, | ||
| initSnapshotHistory: y, | ||
| handleRestore: b, | ||
| handleSnapshotNavigate: x, | ||
| confirmRestoreSnapshot: S, | ||
| cancelPreview: C, | ||
| loadSnapshotHistory: w | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudPanelState.ts | ||
| function Me() { | ||
| let e = c(null), t = f({ | ||
| get: () => e.value === "ai-chat", | ||
| set: (t) => e.value = t ? "ai-chat" : null | ||
| }), n = f({ | ||
| get: () => e.value === "scoring", | ||
| set: (t) => e.value = t ? "scoring" : null | ||
| }), r = f({ | ||
| get: () => e.value === "design-reference", | ||
| set: (t) => e.value = t ? "design-reference" : null | ||
| }), i = f({ | ||
| get: () => e.value === "comments", | ||
| set: (t) => e.value = t ? "comments" : null | ||
| }), a = c(!1), o = c(!1), s = c(void 0), l = c(!1), u = c(null), d = f(() => e.value !== null), p = f(() => { | ||
| let t = e.value; | ||
| return t === "ai-chat" || t === "design-reference" || t === "scoring" ? t : null; | ||
| }), m = f(() => l.value || e.value === "ai-chat" || e.value === "design-reference" || e.value === "scoring"); | ||
| function h() { | ||
| l.value = !l.value; | ||
| } | ||
| function g(t) { | ||
| l.value = !1, e.value = e.value === t ? null : t; | ||
| } | ||
| return X(u, () => { | ||
| l.value = !1; | ||
| }), { | ||
| activePanel: e, | ||
| aiChatOpen: t, | ||
| scoringPanelOpen: n, | ||
| designReferenceOpen: r, | ||
| commentsOpen: i, | ||
| testEmailModalOpen: a, | ||
| mediaLibraryOpen: o, | ||
| mediaLibraryAccept: s, | ||
| aiMenuOpen: l, | ||
| aiMenuRef: u, | ||
| rightPanelOpen: d, | ||
| activeAiFeature: p, | ||
| aiButtonActive: m, | ||
| toggleAiMenu: h, | ||
| handleAiFeatureSelect: g | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCollabUndoWarning.ts | ||
| function Ne(e) { | ||
| let { isCollaborationEnabled: t, getCollaboratorCount: n, canUndo: r } = e, i = c(!1), a = c(!1), { start: o } = Z(() => { | ||
| a.value = !1; | ||
| }, ye, { immediate: !1 }); | ||
| function s() { | ||
| i.value || !t.value || n() === 0 || !r.value || (i.value = !0, a.value = !0, o()); | ||
| } | ||
| return { | ||
| collabUndoWarningVisible: a, | ||
| showCollabUndoWarning: s | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudFeatureFlags.ts | ||
| function Pe(e) { | ||
| let { planConfigInstance: t, aiConfig: n, editor: r } = e, i = f(() => t.hasFeature("ai_generation") && n.hasAnyMenuFeature.value), a = f(() => t.hasFeature("test_email")), o = f(() => !!r.state.template?.id), s = f(() => t.hasFeature("white_label")), l = f(() => t.config.value?.limits.max_templates ?? null), u = f(() => t.config.value?.template_count ?? 0), d = c(!1), p = c("idle"), m = c(""), { start: h } = Z(() => { | ||
| p.value = "idle"; | ||
| }, 3e3, { immediate: !1 }); | ||
| return { | ||
| canUseAiGeneration: i, | ||
| canSendTestEmail: a, | ||
| hasTemplateSaved: o, | ||
| isWhiteLabeled: s, | ||
| templateLimit: l, | ||
| templateCount: u, | ||
| isSaveExporting: d, | ||
| saveStatus: p, | ||
| saveErrorMessage: m, | ||
| startSaveStatusClear: h | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudMediaLibrary.ts | ||
| function Fe(e) { | ||
| let { onRequestMedia: t, mediaLibraryOpen: n, mediaLibraryAccept: i } = e, a = null; | ||
| async function o() { | ||
| if (t) { | ||
| let e = await t({ accept: ["images"] }); | ||
| return e ? { | ||
| url: e.url, | ||
| alt: e.alt_text || void 0 | ||
| } : null; | ||
| } | ||
| return a &&= (a(null), null), i.value = ["images"], n.value = !0, new Promise((e) => { | ||
| a = (t) => { | ||
| e(t); | ||
| }; | ||
| }); | ||
| } | ||
| function s(e) { | ||
| n.value = !1, a?.({ | ||
| url: e.url, | ||
| alt: e.alt_text || void 0 | ||
| }), a = null; | ||
| } | ||
| function c() { | ||
| n.value = !1, a?.(null), a = null; | ||
| } | ||
| return r(() => { | ||
| a &&= (a(null), null); | ||
| }), { | ||
| handleRequestMedia: o, | ||
| handleMediaSelect: s, | ||
| handleMediaLibraryClose: c | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudInitialization.ts | ||
| function Ie(e) { | ||
| let { config: t, translations: n, fontsManager: r, emit: i, getCommentsSidebar: o } = e, s = c(!0), l = c(!1), u = c(null), d = !1, p = { value: null }, m = null, h = null, g = new M({ | ||
| ...t.auth, | ||
| onError: t.onError | ||
| }), _ = ae({ | ||
| authManager: g, | ||
| onError: t.onError | ||
| }), v = c(/* @__PURE__ */ new Map()), y = ge({ | ||
| authManager: g, | ||
| defaultFontFamily: t.fonts?.defaultFont, | ||
| templateDefaults: t.templateDefaults, | ||
| onError: t.onError, | ||
| lockedBlocks: v | ||
| }), b = oe({ | ||
| authManager: g, | ||
| onError: t.onError | ||
| }); | ||
| t.mcp?.enabled && ue({ | ||
| editor: y, | ||
| channel: b.channel, | ||
| onOperation: t.mcp.onOperation | ||
| }); | ||
| let x = null; | ||
| t.collaboration?.enabled && (x = J({ | ||
| authManager: g, | ||
| editor: y, | ||
| channel: b.channel, | ||
| onError: t.onError, | ||
| onCollaboratorJoined: t.collaboration.onCollaboratorJoined, | ||
| onCollaboratorLeft: t.collaboration.onCollaboratorLeft, | ||
| onBlockLocked: t.collaboration.onBlockLocked, | ||
| onBlockUnlocked: t.collaboration.onBlockUnlocked | ||
| }), ee(() => x.lockedBlocks.value, (e) => { | ||
| v.value = e; | ||
| }, { immediate: !0 }), Y(y, x)); | ||
| let S = f(() => !!t.collaboration?.enabled && _.hasFeature("collaboration")), C = k({ | ||
| editor: y, | ||
| config: { | ||
| uiTheme: t.uiTheme, | ||
| theme: void 0, | ||
| blockDefaults: t.blockDefaults, | ||
| customBlocks: [], | ||
| mergeTags: t.mergeTags, | ||
| displayConditions: t.displayConditions, | ||
| onRequestMedia: null, | ||
| lint: Te(t), | ||
| onSave: () => { | ||
| p.value?.().catch((e) => { | ||
| t.onError?.(e); | ||
| }); | ||
| } | ||
| }, | ||
| translations: n, | ||
| fontsManager: r, | ||
| historyOptions: x ? { isRemoteOperation: () => x._isProcessingRemoteOperation() } : void 0, | ||
| autoSaveOptions: { | ||
| onChange: async () => { | ||
| y.hasTemplate() && (await y.createSnapshot(), m?.snapshotHistoryInstance.value?.loadSnapshots()); | ||
| }, | ||
| debounce: t.autoSaveDebounce ?? 5e3, | ||
| enabled: () => t.autoSave !== !1 && _.hasFeature("auto_save") | ||
| }, | ||
| themeExtraStyles: () => ({ "--tpl-drop-text": `"${n.canvas.dropHere}"` }), | ||
| keyboardOptions: { onBeforeUndo: () => h?.showCollabUndoWarning() }, | ||
| editorRoot: e.editorRoot, | ||
| containerEl: e.containerEl | ||
| }), w = Ne({ | ||
| isCollaborationEnabled: S, | ||
| getCollaboratorCount: () => x?.collaborators.value.length ?? 0, | ||
| canUndo: C.history.canUndo | ||
| }); | ||
| h = w; | ||
| let T = je({ | ||
| authManager: g, | ||
| editor: y, | ||
| history: C.history, | ||
| conditionPreview: C.conditionPreview, | ||
| autoSave: C.autoSave, | ||
| onError: t.onError | ||
| }); | ||
| m = T; | ||
| let E = Me(), D = W(t.ai), A = Pe({ | ||
| planConfigInstance: _, | ||
| aiConfig: D, | ||
| editor: y | ||
| }), j = Fe({ | ||
| onRequestMedia: t.onRequestMedia, | ||
| mediaLibraryOpen: E.mediaLibraryOpen, | ||
| mediaLibraryAccept: E.mediaLibraryAccept | ||
| }); | ||
| ie({ | ||
| onBlockMove: y.moveBlock, | ||
| onBlockAdd: y.addBlock | ||
| }); | ||
| let N = fe({ | ||
| authManager: g, | ||
| getFontsConfig: () => t.fonts, | ||
| canUseCustomFonts: () => _.hasFeature("custom_fonts") | ||
| }), P = K({ | ||
| authManager: g, | ||
| getTemplateId: () => y.state.template?.id ?? null, | ||
| save: () => y.save(), | ||
| exportHtml: (e) => N.exportHtml(e), | ||
| onError: t.onError, | ||
| isAuthReady: l, | ||
| onBeforeTestEmail: t.onBeforeTestEmail | ||
| }), F = me({ | ||
| authManager: g, | ||
| getTemplateId: () => y.state.template?.id ?? null, | ||
| getSocketId: () => b.getSocketId(), | ||
| onComment: t.onComment, | ||
| onError: t.onError, | ||
| isAuthReady: l, | ||
| hasCommentingFeature: () => t.commenting !== !1 && _.hasFeature("commenting") | ||
| }); | ||
| H({ | ||
| comments: F, | ||
| channel: b.channel | ||
| }); | ||
| let I = se({ | ||
| authManager: g, | ||
| onError: t.onError | ||
| }), R = c(!1), U = c(null), q = c(!1), X = ve({ | ||
| authManager: g, | ||
| getTemplateId: () => y.state.template?.id ?? null | ||
| }); | ||
| function Z(e) { | ||
| E.commentsOpen.value = !0, queueMicrotask(() => { | ||
| o()?.filterByBlock(e); | ||
| }); | ||
| } | ||
| a(V, j.handleRequestMedia), a(re, g), a(te, D), a(z, F), a(L, I), a(O, X), a(B, { | ||
| plan: _, | ||
| ai: D, | ||
| comments: { | ||
| getBlockCount: (e) => F.commentCountByBlock.value.get(e) ?? 0, | ||
| openForBlock: Z | ||
| }, | ||
| savedModules: { | ||
| openSaveDialog: (e) => { | ||
| U.value = e ?? null, R.value = !0; | ||
| }, | ||
| openBrowser: () => { | ||
| q.value = !0; | ||
| }, | ||
| moduleCount: f(() => I.modules.value.length) | ||
| } | ||
| }); | ||
| function ce(e) { | ||
| _.hasFeature("theme_customization") && (C.themeOverrides.value = e); | ||
| } | ||
| function le(e) { | ||
| y.setUiTheme(e); | ||
| } | ||
| async function de() { | ||
| s.value = !0, u.value = null; | ||
| try { | ||
| if (await g.initialize(), d) return; | ||
| l.value = !0; | ||
| let e = await G({ authManager: g }); | ||
| if (d) return; | ||
| if (!e.api.ok) throw Error("Health check failed: API is not reachable"); | ||
| if (!e.auth.ok) throw Error(`Health check failed: authentication error${e.auth.error ? ` - ${e.auth.error}` : ""}`); | ||
| if (e.websocket.ok || ne.warn("WebSocket health check failed:", e.websocket.error ?? "unknown error", "-- real-time features will be disabled."), await _.fetchConfig(), d) return; | ||
| r.setCustomFontsEnabled(_.hasFeature("custom_fonts")), t.customBlocks?.length && _.hasFeature("custom_blocks") && C.registerCustomBlocks(t.customBlocks), t.theme && _.hasFeature("theme_customization") && (C.themeOverrides.value = t.theme), t.modules !== !1 && _.hasFeature("saved_modules") && I.loadModules(), i("ready"); | ||
| } catch (e) { | ||
| if (d) return; | ||
| let n = e instanceof Error ? e : Error("Initialization failed", { cause: e }); | ||
| u.value = n, t.onError?.(n); | ||
| } finally { | ||
| d || (s.value = !1); | ||
| } | ||
| } | ||
| function Q() { | ||
| d = !0, r.cleanupFontLinks(), b.disconnect(), C.destroy(), t.onUnmount?.(); | ||
| } | ||
| return { | ||
| isInitializing: s, | ||
| isAuthReady: l, | ||
| initError: u, | ||
| isDestroyed: () => d, | ||
| authManager: g, | ||
| planConfigInstance: _, | ||
| websocket: b, | ||
| collaboration: x, | ||
| isCollaborationEnabled: S, | ||
| editor: y, | ||
| core: C, | ||
| aiConfig: D, | ||
| featureFlags: A, | ||
| mediaLib: j, | ||
| exporter: N, | ||
| testEmail: P, | ||
| commentsInstance: F, | ||
| savedModulesHeadless: I, | ||
| scoringInstance: X, | ||
| panelState: E, | ||
| snapshotPreview: T, | ||
| collabWarning: w, | ||
| showSaveModuleDialog: R, | ||
| showModuleBrowserModal: q, | ||
| saveModulePreSelectedBlockId: U, | ||
| onSaveHook: p, | ||
| initialize: de, | ||
| destroy: Q, | ||
| setThemeOverrides: ce, | ||
| setUiTheme: le, | ||
| openCommentsForBlock: Z | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/utils/preRenderCustomBlocks.ts | ||
| async function Le(e, t) { | ||
| let n = async (e) => { | ||
| if (N(e)) { | ||
| let n = e; | ||
| try { | ||
| n.renderedHtml = await t.renderCustomBlock(n); | ||
| } catch { | ||
| n.renderedHtml = `<!-- Custom block render error: ${n.customType} -->`; | ||
| } | ||
| } | ||
| if (e.type === "section" && "children" in e) { | ||
| let t = e; | ||
| for (let e of t.children) for (let t of e) await n(t); | ||
| } | ||
| }; | ||
| for (let t of e.blocks) await n(t); | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudLifecycle.ts | ||
| function Re(e) { | ||
| let { config: t, editor: n, websocket: r, planConfigInstance: i, snapshotPreview: a, core: o, exporter: s, featureFlags: c, isDestroyed: l } = e; | ||
| function u() { | ||
| return R(i.config.value.websocket); | ||
| } | ||
| async function d(e) { | ||
| let i = await n.create(e); | ||
| return l() ? i : (t.onCreate?.(i), a.initSnapshotHistory(), r.connect(i.id, u()), i); | ||
| } | ||
| async function f(e) { | ||
| let i = await n.load(e); | ||
| return l() ? i : (t.onLoad?.(i), a.initSnapshotHistory(), r.connect(i.id, u()), i); | ||
| } | ||
| async function p() { | ||
| c.isSaveExporting.value = !0, c.saveStatus.value = "idle"; | ||
| try { | ||
| if (await Le(n.content.value, o.registry), l()) throw Error("Component unmounted during save"); | ||
| let e = await n.save(); | ||
| if (l()) throw Error("Component unmounted during save"); | ||
| a.initSnapshotHistory(), a.snapshotHistoryInstance.value?.loadSnapshots(); | ||
| let r = await s.exportHtml(e.id); | ||
| if (l()) throw Error("Component unmounted during save"); | ||
| let i = { | ||
| templateId: e.id, | ||
| html: r.html, | ||
| mjml: r.mjml, | ||
| content: e.content | ||
| }; | ||
| return t.onSave?.(i), c.saveStatus.value = "saved", c.startSaveStatusClear(), i; | ||
| } catch (e) { | ||
| throw l() || (c.saveStatus.value = "error", c.saveErrorMessage.value = e instanceof Error ? e.message : "Save failed"), e; | ||
| } finally { | ||
| l() || (c.isSaveExporting.value = !1); | ||
| } | ||
| } | ||
| return { | ||
| createTemplate: d, | ||
| loadTemplate: f, | ||
| saveTemplate: p | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudSaveGate.ts | ||
| function ze(e) { | ||
| let t = c(!1), n = null, r = f(() => e.planConfig.value?.accessibility?.blockOnError === !0), i = f(() => r.value ? e.issues.value.filter((e) => e.severity === "error") : []), a = f(() => i.value.length > 0); | ||
| async function o(e) { | ||
| return a.value ? (n = e, t.value = !0, !1) : (await e(), !0); | ||
| } | ||
| async function s() { | ||
| let e = n; | ||
| n = null, t.value = !1, e && await e(); | ||
| } | ||
| function l() { | ||
| n = null, t.value = !1; | ||
| } | ||
| return { | ||
| shouldBlock: a, | ||
| blockingIssues: i, | ||
| modalOpen: t, | ||
| tryRunSave: o, | ||
| confirmAndSave: s, | ||
| cancel: l | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/components/CloudSaveGateModal.vue?vue&type=script&setup=true&lang.ts | ||
| var Be = ["aria-label"], Ve = { class: "tpl:flex tpl:max-h-[80vh] tpl:w-full tpl:max-w-md tpl:flex-col tpl:gap-4 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)] tpl:p-5 tpl:shadow-[var(--tpl-shadow-md)]" }, He = { class: "tpl:flex tpl:items-center tpl:gap-2" }, Ue = { class: "tpl:m-0 tpl:text-base tpl:font-semibold tpl:text-[var(--tpl-text)]" }, We = { class: "tpl:m-0 tpl:text-sm tpl:text-[var(--tpl-text-muted)]" }, Ge = { class: "tpl:m-0 tpl:flex tpl:max-h-64 tpl:list-none tpl:flex-col tpl:gap-1.5 tpl:overflow-y-auto tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-2" }, Ke = { class: "tpl:text-xs tpl:text-[var(--tpl-text)]" }, qe = { class: "tpl:font-mono tpl:text-[10px] tpl:text-[var(--tpl-text-dim)]" }, Je = { class: "tpl:flex tpl:justify-end tpl:gap-2" }, Ye = /* @__PURE__ */ E({ | ||
| __name: "CloudSaveGateModal", | ||
| props: { | ||
| open: { type: Boolean }, | ||
| issues: {} | ||
| }, | ||
| emits: ["cancel", "confirm"], | ||
| setup(e, { emit: t }) { | ||
| let n = t, { t: r } = Q(); | ||
| return (t, a) => (i(), v(y, { | ||
| "enter-active-class": "tpl:transition-opacity tpl:duration-150", | ||
| "leave-active-class": "tpl:transition-opacity tpl:duration-150", | ||
| "enter-from-class": "tpl:opacity-0", | ||
| "leave-to-class": "tpl:opacity-0" | ||
| }, { | ||
| default: s(() => [e.open ? (i(), p("div", { | ||
| key: 0, | ||
| role: "dialog", | ||
| "aria-modal": "true", | ||
| "aria-label": h(r).saveGate.title, | ||
| class: "tpl:fixed tpl:inset-0 tpl:z-50 tpl:flex tpl:items-center tpl:justify-center tpl:bg-black/40 tpl:p-6", | ||
| onClick: a[2] ||= _((e) => n("cancel"), ["self"]) | ||
| }, [x("div", Ve, [ | ||
| x("header", He, [D(h(de), { | ||
| size: 18, | ||
| "stroke-width": 2, | ||
| class: "tpl:text-[var(--tpl-warning)]" | ||
| }), x("h2", Ue, d(h(r).saveGate.title), 1)]), | ||
| x("p", We, d(h(r).saveGate.body), 1), | ||
| x("ul", Ge, [(i(!0), p(w, null, o(e.issues, (e) => (i(), p("li", { | ||
| key: `${e.ruleId}-${e.blockId ?? "template"}`, | ||
| class: "tpl:flex tpl:flex-col tpl:gap-0.5 tpl:rounded tpl:px-2 tpl:py-1.5" | ||
| }, [x("span", Ke, d(e.message), 1), x("span", qe, d(e.ruleId), 1)]))), 128))]), | ||
| x("footer", Je, [x("button", { | ||
| type: "button", | ||
| class: "tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)]", | ||
| onClick: a[0] ||= (e) => n("cancel") | ||
| }, d(h(r).saveGate.cancel), 1), x("button", { | ||
| type: "button", | ||
| class: "tpl:rounded-md tpl:bg-[var(--tpl-danger)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:text-white", | ||
| onClick: a[1] ||= (e) => n("confirm") | ||
| }, d(h(r).saveGate.confirm), 1)]) | ||
| ])], 8, Be)) : m("", !0)]), | ||
| _: 1 | ||
| })); | ||
| } | ||
| }), Xe = { | ||
| class: "tpl-header tpl:absolute tpl:top-0 tpl:right-0 tpl:left-0 tpl:z-50 tpl:grid tpl:h-14 tpl:grid-cols-[1fr_auto_1fr] tpl:items-center tpl:px-4", | ||
| style: { | ||
| "background-color": "color-mix(in srgb, var(--tpl-bg) 80%, transparent)", | ||
| "backdrop-filter": "blur(12px)", | ||
| "-webkit-backdrop-filter": "blur(12px)", | ||
| "box-shadow": "var(--tpl-shadow-md)", | ||
| "border-bottom": "1px solid var(--tpl-border)" | ||
| } | ||
| }, Ze = { class: "tpl-header-left tpl:flex tpl:min-w-[200px] tpl:items-center tpl:gap-3" }, Qe = { | ||
| key: 0, | ||
| class: "tpl:text-xs tpl:opacity-60 tpl:text-[var(--tpl-text-muted)]" | ||
| }, $e = { class: "tpl-header-center tpl:flex tpl:items-center tpl:justify-center tpl:gap-10" }, et = { class: "tpl-header-right tpl:flex tpl:min-w-[200px] tpl:items-center tpl:justify-end tpl:gap-3" }, tt = ["data-tooltip"], nt = { | ||
| key: 1, | ||
| "aria-live": "polite", | ||
| class: "tpl-status tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:text-[var(--tpl-success)]" | ||
| }, rt = { | ||
| key: 2, | ||
| "aria-live": "polite", | ||
| class: "tpl-status tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:text-[var(--tpl-text-muted)]" | ||
| }, it = ["aria-label", "aria-expanded"], at = { | ||
| key: 0, | ||
| class: "tpl:inline-flex tpl:size-4.5 tpl:items-center tpl:justify-center tpl:rounded-full tpl:text-[10px] tpl:font-semibold tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]" | ||
| }, ot = ["aria-expanded"], st = { | ||
| key: 0, | ||
| class: "tpl:absolute tpl:right-0 tpl:top-full tpl:z-50 tpl:mt-1 tpl:origin-top-right" | ||
| }, ct = ["disabled"], lt = ["disabled"], ut = /* @__PURE__ */ E({ | ||
| __name: "CloudHeader", | ||
| props: { | ||
| editor: {}, | ||
| core: {}, | ||
| featureFlags: {}, | ||
| panelState: {}, | ||
| snapshotPreview: {}, | ||
| commentsInstance: {}, | ||
| testEmail: {}, | ||
| websocket: {}, | ||
| collaboration: {}, | ||
| isCollaborationEnabled: { type: Boolean }, | ||
| isSaveDisabled: { type: Boolean }, | ||
| isSaving: { type: Boolean } | ||
| }, | ||
| emits: ["save"], | ||
| setup(e) { | ||
| let t = u(() => import("./CollaboratorBar-C4CFs5EJ.js")), n = u(() => import("./features-D-2kVhHY.js").then((e) => e.r)), r = u(() => import("./AiFeatureMenu-Dayzk2H7.js")), { t: a, format: o } = Q(); | ||
| return (c, l) => (i(), p("header", Xe, [ | ||
| x("div", Ze, [e.featureFlags.templateLimit.value === null ? m("", !0) : (i(), p("span", Qe, d(h(o)(h(a).header.templatesUsed, { | ||
| used: e.featureFlags.templateCount.value, | ||
| max: e.featureFlags.templateLimit.value | ||
| })), 1))]), | ||
| x("div", $e, [ | ||
| D(Se, { | ||
| viewport: e.editor.state.viewport, | ||
| onChange: e.editor.setViewport | ||
| }, null, 8, ["viewport", "onChange"]), | ||
| D(Oe, { | ||
| "dark-mode": e.editor.state.darkMode, | ||
| onChange: e.editor.setDarkMode | ||
| }, null, 8, ["dark-mode", "onChange"]), | ||
| D(we, { | ||
| "preview-mode": e.editor.state.previewMode, | ||
| onChange: e.editor.setPreviewMode | ||
| }, null, 8, ["preview-mode", "onChange"]), | ||
| e.collaboration && e.isCollaborationEnabled ? (i(), v(h(t), { | ||
| key: 0, | ||
| collaborators: e.collaboration.collaborators.value, | ||
| "is-connected": e.websocket.isConnected.value | ||
| }, null, 8, ["collaborators", "is-connected"])) : m("", !0), | ||
| e.snapshotPreview.snapshotHistoryInstance.value ? (i(), v(h(n), { | ||
| key: 1, | ||
| snapshots: e.snapshotPreview.snapshotHistorySnapshots.value, | ||
| "is-loading": e.snapshotPreview.snapshotHistoryIsLoading.value, | ||
| "is-restoring": e.snapshotPreview.snapshotHistoryIsRestoring.value, | ||
| onLoad: e.snapshotPreview.loadSnapshotHistory, | ||
| onNavigate: e.snapshotPreview.handleSnapshotNavigate | ||
| }, null, 8, [ | ||
| "snapshots", | ||
| "is-loading", | ||
| "is-restoring", | ||
| "onLoad", | ||
| "onNavigate" | ||
| ])) : m("", !0) | ||
| ]), | ||
| x("div", et, [ | ||
| e.featureFlags.saveStatus.value === "error" ? (i(), p("div", { | ||
| key: 0, | ||
| "aria-live": "assertive", | ||
| class: "tpl-tooltip tpl-status tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:text-[var(--tpl-danger)]", | ||
| "data-tooltip": e.featureFlags.saveErrorMessage.value | ||
| }, [D(h(j), { | ||
| size: 12, | ||
| "stroke-width": 2.5 | ||
| }), T(" " + d(h(a).header.saveFailed), 1)], 8, tt)) : e.featureFlags.saveStatus.value === "saved" ? (i(), p("div", nt, [D(h(A), { | ||
| size: 12, | ||
| "stroke-width": 2.5 | ||
| }), T(" " + d(h(a).header.saved), 1)])) : e.editor.state.isDirty ? (i(), p("div", rt, [l[4] ||= x("span", { class: "tpl-pulse tpl:size-1.5 tpl:rounded-full tpl:bg-[var(--tpl-primary)]" }, null, -1), T(" " + d(h(a).header.unsaved), 1)])) : m("", !0), | ||
| e.commentsInstance.isEnabled.value && e.featureFlags.hasTemplateSaved.value ? (i(), p("button", { | ||
| key: 3, | ||
| "aria-label": e.commentsInstance.unresolvedCount.value > 0 ? `${h(a).comments.button} (${e.commentsInstance.unresolvedCount.value})` : h(a).comments.button, | ||
| "aria-expanded": e.panelState.commentsOpen.value, | ||
| class: b(h($)), | ||
| style: C({ | ||
| backgroundColor: e.panelState.commentsOpen.value ? "var(--tpl-primary)" : "transparent", | ||
| color: e.panelState.commentsOpen.value ? "var(--tpl-bg)" : "var(--tpl-primary)", | ||
| borderColor: "var(--tpl-primary)" | ||
| }), | ||
| onClick: l[0] ||= (t) => e.panelState.commentsOpen.value = !e.panelState.commentsOpen.value | ||
| }, [ | ||
| D(h(U), { | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| }), | ||
| T(" " + d(h(a).comments.button) + " ", 1), | ||
| e.commentsInstance.unresolvedCount.value > 0 && !e.panelState.commentsOpen.value ? (i(), p("span", at, d(e.commentsInstance.unresolvedCount.value), 1)) : m("", !0) | ||
| ], 14, it)) : m("", !0), | ||
| e.featureFlags.canUseAiGeneration.value && e.featureFlags.hasTemplateSaved.value ? (i(), p("div", { | ||
| key: 4, | ||
| ref: (t) => e.panelState.aiMenuRef.value = t, | ||
| class: "tpl:relative" | ||
| }, [x("button", { | ||
| "aria-expanded": e.panelState.aiMenuOpen.value, | ||
| class: b(["tpl-ai-btn tpl:inline-flex tpl:items-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:px-4 tpl:py-2 tpl:text-sm tpl:font-semibold tpl:whitespace-nowrap tpl:transition-all tpl:duration-200", e.panelState.aiButtonActive.value ? "tpl-ai-btn--active" : "tpl-ai-btn--idle"]), | ||
| onClick: l[1] ||= _((...t) => e.panelState.toggleAiMenu && e.panelState.toggleAiMenu(...t), ["stop"]) | ||
| }, [D(h(pe), { | ||
| size: 16, | ||
| "stroke-width": 2, | ||
| class: "tpl-ai-btn-icon" | ||
| }), T(" " + d(h(a).aiChat.button), 1)], 10, ot), D(y, { | ||
| "enter-active-class": "tpl:transition-all tpl:duration-150 tpl:ease-out", | ||
| "enter-from-class": "tpl:scale-95 tpl:opacity-0", | ||
| "enter-to-class": "tpl:scale-100 tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-all tpl:duration-100 tpl:ease-in", | ||
| "leave-from-class": "tpl:scale-100 tpl:opacity-100", | ||
| "leave-to-class": "tpl:scale-95 tpl:opacity-0" | ||
| }, { | ||
| default: s(() => [e.panelState.aiMenuOpen.value ? (i(), p("div", st, [D(h(r), { | ||
| "active-feature": e.panelState.activeAiFeature.value, | ||
| onSelect: e.panelState.handleAiFeatureSelect | ||
| }, null, 8, ["active-feature", "onSelect"])])) : m("", !0)]), | ||
| _: 1 | ||
| })], 512)) : m("", !0), | ||
| e.testEmail.isEnabled.value && e.featureFlags.canSendTestEmail.value ? (i(), p("button", { | ||
| key: 5, | ||
| class: b(h($)), | ||
| style: { | ||
| "background-color": "transparent", | ||
| color: "var(--tpl-primary)", | ||
| "border-color": "var(--tpl-primary)" | ||
| }, | ||
| disabled: e.testEmail.isSending.value || !e.featureFlags.hasTemplateSaved.value, | ||
| onClick: l[2] ||= (t) => e.panelState.testEmailModalOpen.value = !0 | ||
| }, [e.testEmail.isSending.value ? (i(), v(h(he), { | ||
| key: 1, | ||
| class: "tpl-spinner", | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })) : (i(), v(h(ce), { | ||
| key: 0, | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })), T(" " + d(h(a).testEmail.button), 1)], 10, ct)) : m("", !0), | ||
| x("button", { | ||
| class: b(h($)), | ||
| style: { | ||
| "background-color": "transparent", | ||
| color: "var(--tpl-primary)", | ||
| "border-color": "var(--tpl-primary)" | ||
| }, | ||
| disabled: e.isSaveDisabled, | ||
| onClick: l[3] ||= (e) => c.$emit("save") | ||
| }, [e.isSaving ? (i(), v(h(he), { | ||
| key: 1, | ||
| class: "tpl-spinner", | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })) : (i(), v(h(xe), { | ||
| key: 0, | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })), T(" " + d(e.isSaving ? h(a).header.saving : h(a).header.save), 1)], 10, lt) | ||
| ]) | ||
| ])); | ||
| } | ||
| }), dt = /* @__PURE__ */ E({ | ||
| __name: "CloudPanels", | ||
| props: { | ||
| config: {}, | ||
| editor: {}, | ||
| core: {}, | ||
| panelState: {}, | ||
| planConfigInstance: {}, | ||
| testEmail: {}, | ||
| mediaLib: {}, | ||
| savedModulesHeadless: {}, | ||
| showSaveModuleDialog: { type: Boolean }, | ||
| saveModulePreSelectedBlockId: {}, | ||
| showModuleBrowserModal: { type: Boolean } | ||
| }, | ||
| emits: [ | ||
| "update:showSaveModuleDialog", | ||
| "update:saveModulePreSelectedBlockId", | ||
| "update:showModuleBrowserModal", | ||
| "send-test-email", | ||
| "module-insert" | ||
| ], | ||
| setup(e, { expose: t, emit: n }) { | ||
| let r = u(() => import("./features-D-2kVhHY.js").then((e) => e.o)), a = u(() => import("./features-D-2kVhHY.js").then((e) => e.a)), o = u(() => import("./features-D-2kVhHY.js").then((e) => e.i)), s = u(() => import("./features-D-2kVhHY.js").then((e) => e.n)), l = u(() => import("./features-D-2kVhHY.js").then((e) => e.t)), d = u(() => import("./SaveModuleDialog-BrtDXzIz.js")), f = u(() => import("./ModuleBrowserModal-Cgjz4xAz.js")), g = u(async () => { | ||
| try { | ||
| return (await import("./src-ftxPuuQh.js")).MediaLibraryModal; | ||
| } catch { | ||
| throw Error("[Templatical] Cloud media library requires the optional peer dependency '@templatical/media-library'. Please install it."); | ||
| } | ||
| }), _ = n; | ||
| function y(e, t, n) { | ||
| t.history.record(), n.setContent(e), t.conditionPreview.reset(); | ||
| } | ||
| function b(e, t) { | ||
| _("module-insert", e, t); | ||
| } | ||
| let x = c(null); | ||
| function S(e) { | ||
| x.value?.filterByBlock(e); | ||
| } | ||
| return t({ filterCommentsByBlock: S }), (t, n) => (i(), p(w, null, [ | ||
| D(h(r), { | ||
| visible: e.panelState.aiChatOpen.value, | ||
| "on-apply": (t) => y(t, e.core, e.editor), | ||
| onClose: n[0] ||= (t) => e.panelState.aiChatOpen.value = !1 | ||
| }, null, 8, ["visible", "on-apply"]), | ||
| D(h(s), { | ||
| visible: e.panelState.scoringPanelOpen.value, | ||
| onClose: n[1] ||= (t) => e.panelState.scoringPanelOpen.value = !1 | ||
| }, null, 8, ["visible"]), | ||
| D(h(o), { | ||
| visible: e.panelState.designReferenceOpen.value, | ||
| "has-existing-blocks": e.editor.content.value.blocks.length > 0, | ||
| onClose: n[2] ||= (t) => e.panelState.designReferenceOpen.value = !1, | ||
| onApply: n[3] ||= (t) => y(t, e.core, e.editor) | ||
| }, null, 8, ["visible", "has-existing-blocks"]), | ||
| D(h(a), { | ||
| ref_key: "commentsSidebar", | ||
| ref: x, | ||
| visible: e.panelState.commentsOpen.value, | ||
| onClose: n[4] ||= (t) => e.panelState.commentsOpen.value = !1 | ||
| }, null, 8, ["visible"]), | ||
| D(h(l), { | ||
| visible: e.panelState.testEmailModalOpen.value, | ||
| "allowed-emails": e.testEmail.allowedEmails.value, | ||
| "is-sending": e.testEmail.isSending.value, | ||
| error: e.testEmail.error.value, | ||
| onSend: n[5] ||= (e) => _("send-test-email", e), | ||
| onClose: n[6] ||= (t) => e.panelState.testEmailModalOpen.value = !1 | ||
| }, null, 8, [ | ||
| "visible", | ||
| "allowed-emails", | ||
| "is-sending", | ||
| "error" | ||
| ]), | ||
| e.planConfigInstance.hasFeature("saved_modules") && e.config.modules !== !1 ? (i(), v(h(d), { | ||
| key: 0, | ||
| visible: e.showSaveModuleDialog, | ||
| "pre-selected-block-id": e.saveModulePreSelectedBlockId, | ||
| onClose: n[7] ||= (e) => { | ||
| _("update:showSaveModuleDialog", !1), _("update:saveModulePreSelectedBlockId", null); | ||
| }, | ||
| onSaved: n[8] ||= (t) => e.savedModulesHeadless.loadModules() | ||
| }, null, 8, ["visible", "pre-selected-block-id"])) : m("", !0), | ||
| e.planConfigInstance.hasFeature("saved_modules") && e.config.modules !== !1 ? (i(), v(h(f), { | ||
| key: 1, | ||
| visible: e.showModuleBrowserModal, | ||
| onClose: n[9] ||= (e) => _("update:showModuleBrowserModal", !1), | ||
| onInsert: b | ||
| }, null, 8, ["visible"])) : m("", !0), | ||
| D(h(g), { | ||
| visible: e.panelState.mediaLibraryOpen.value, | ||
| accept: e.panelState.mediaLibraryAccept.value, | ||
| "popover-target": e.core.popoverRoot.value, | ||
| onSelect: e.mediaLib.handleMediaSelect, | ||
| onClose: e.mediaLib.handleMediaLibraryClose | ||
| }, null, 8, [ | ||
| "visible", | ||
| "accept", | ||
| "popover-target", | ||
| "onSelect", | ||
| "onClose" | ||
| ]) | ||
| ], 64)); | ||
| } | ||
| }), ft = { | ||
| key: 0, | ||
| class: "tpl-loading tpl:absolute tpl:inset-0 tpl:z-overlay tpl:flex tpl:flex-col tpl:bg-[var(--tpl-bg)]" | ||
| }, pt = { class: "tpl:flex tpl:flex-1 tpl:overflow-hidden" }, mt = { class: "tpl:flex tpl:w-12 tpl:shrink-0 tpl:flex-col tpl:items-center tpl:gap-4 tpl:py-5 tpl:border-r tpl:border-[var(--tpl-border)]" }, ht = /* @__PURE__ */ E({ | ||
| __name: "CloudLoadingOverlay", | ||
| props: { visible: { type: Boolean } }, | ||
| setup(e) { | ||
| return (t, n) => e.visible ? (i(), p("div", ft, [n[1] ||= l("<div class=\"tpl:flex tpl:h-14 tpl:shrink-0 tpl:items-center tpl:justify-between tpl:px-4 tpl:border-b tpl:border-[var(--tpl-border)]\"><div class=\"tpl-shimmer tpl:h-5 tpl:w-28 tpl:rounded-[var(--tpl-radius-sm)]\"></div><div class=\"tpl:flex tpl:gap-3\"><div class=\"tpl-shimmer tpl:h-8 tpl:w-20 tpl:rounded-[var(--tpl-radius-sm)]\"></div><div class=\"tpl-shimmer tpl:h-8 tpl:w-20 tpl:rounded-[var(--tpl-radius-sm)]\"></div></div></div>", 1), x("div", pt, [x("div", mt, [(i(), p(w, null, o(5, (e) => x("div", { | ||
| key: e, | ||
| class: "tpl-shimmer tpl:size-7 tpl:rounded-[var(--tpl-radius-sm)]" | ||
| })), 64))]), n[0] ||= l("<div class=\"tpl:flex tpl:flex-1 tpl:items-start tpl:justify-center tpl:overflow-auto tpl:p-8 tpl:bg-[var(--tpl-canvas-bg)]\"><div class=\"tpl:w-full tpl:max-w-[600px] tpl:rounded-[var(--tpl-radius)] tpl:p-6 tpl:bg-[var(--tpl-bg)] tpl:shadow-[var(--tpl-shadow-sm)]\"><div class=\"tpl:space-y-2 tpl:py-4\"><div class=\"tpl-shimmer tpl:h-3 tpl:w-3/4 tpl:rounded\"></div><div class=\"tpl-shimmer tpl:h-3 tpl:w-full tpl:rounded\"></div><div class=\"tpl-shimmer tpl:h-3 tpl:w-5/6 tpl:rounded\"></div></div><div class=\"tpl:py-4\"><div class=\"tpl-shimmer tpl:h-44 tpl:w-full tpl:rounded-[var(--tpl-radius-sm)]\"></div></div><div class=\"tpl:space-y-2 tpl:py-4\"><div class=\"tpl-shimmer tpl:h-3 tpl:w-full tpl:rounded\"></div><div class=\"tpl-shimmer tpl:h-3 tpl:w-2/3 tpl:rounded\"></div></div><div class=\"tpl:flex tpl:justify-center tpl:py-4\"><div class=\"tpl-shimmer tpl:h-10 tpl:w-36 tpl:rounded-[var(--tpl-radius-sm)]\"></div></div><div class=\"tpl:space-y-2 tpl:py-4\"><div class=\"tpl-shimmer tpl:mx-auto tpl:h-2.5 tpl:w-1/2 tpl:rounded\"></div><div class=\"tpl-shimmer tpl:mx-auto tpl:h-2.5 tpl:w-1/3 tpl:rounded\"></div></div></div></div><div class=\"tpl:flex tpl:w-[320px] tpl:shrink-0 tpl:flex-col tpl:gap-4 tpl:p-4 tpl:border-l tpl:border-[var(--tpl-border)]\"><div class=\"tpl-shimmer tpl:h-8 tpl:rounded-[var(--tpl-radius-sm)]\"></div><div class=\"tpl-shimmer tpl:h-32 tpl:rounded-[var(--tpl-radius)]\"></div><div class=\"tpl-shimmer tpl:h-32 tpl:rounded-[var(--tpl-radius)]\"></div></div>", 2)])])) : m("", !0); | ||
| } | ||
| }), gt = { | ||
| key: 0, | ||
| role: "alert", | ||
| class: "tpl-error tpl:absolute tpl:inset-0 tpl:z-overlay tpl:flex tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-6 tpl:px-8 tpl:bg-[var(--tpl-bg)]" | ||
| }, _t = { class: "tpl:flex tpl:size-16 tpl:items-center tpl:justify-center tpl:rounded-full tpl:bg-[var(--tpl-danger-light)]" }, vt = { class: "tpl:flex tpl:flex-col tpl:items-center tpl:gap-2 tpl:text-center" }, yt = { class: "tpl:text-lg tpl:font-semibold tpl:text-[var(--tpl-text)]" }, bt = { class: "tpl:max-w-md tpl:text-sm tpl:text-[var(--tpl-text-muted)]" }, xt = /* @__PURE__ */ E({ | ||
| __name: "CloudErrorOverlay", | ||
| props: { | ||
| error: {}, | ||
| visible: { type: Boolean } | ||
| }, | ||
| emits: ["retry"], | ||
| setup(e, { emit: t }) { | ||
| let n = t, { t: r } = Q(); | ||
| function a(e) { | ||
| return "isUnauthorized" in e && e.isUnauthorized ? r.error.authFailed : "isNotFound" in e && e.isNotFound ? r.error.templateNotFound : r.error.defaultMessage; | ||
| } | ||
| function o(e) { | ||
| return "isNotFound" in e && !!e.isNotFound; | ||
| } | ||
| return (t, s) => e.visible && e.error ? (i(), p("div", gt, [ | ||
| x("div", _t, [D(h(j), { | ||
| size: 32, | ||
| "stroke-width": 1.5, | ||
| class: "tpl:text-[var(--tpl-danger)]" | ||
| })]), | ||
| x("div", vt, [x("h2", yt, d(h(r).error.title), 1), x("p", bt, d(a(e.error)), 1)]), | ||
| o(e.error) ? m("", !0) : (i(), p("button", { | ||
| key: 0, | ||
| class: "tpl-btn tpl-btn-primary tpl:inline-flex tpl:items-center tpl:gap-2 tpl:rounded-md tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:shadow-xs tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]", | ||
| onClick: s[0] ||= (e) => n("retry") | ||
| }, d(h(r).error.retry), 1)) | ||
| ])) : m("", !0); | ||
| } | ||
| }), St = { | ||
| key: 0, | ||
| class: "tpl-preview-banner tpl:absolute tpl:top-14 tpl:right-0 tpl:left-0 tpl:z-40 tpl:flex tpl:items-center tpl:justify-center tpl:gap-4 tpl:px-4 tpl:py-3 tpl:bg-[var(--tpl-primary-light)] tpl:border-b tpl:border-[var(--tpl-primary)]" | ||
| }, Ct = { class: "tpl:flex tpl:items-center tpl:gap-2 tpl:text-sm tpl:text-[var(--tpl-text)]" }, wt = { class: "tpl:flex tpl:items-center tpl:gap-2" }, Tt = /* @__PURE__ */ E({ | ||
| __name: "SnapshotPreviewBanner", | ||
| props: { visible: { type: Boolean } }, | ||
| emits: ["cancel", "confirm"], | ||
| setup(e, { emit: t }) { | ||
| let n = t, { t: r } = Q(); | ||
| return (t, a) => e.visible ? (i(), p("div", St, [x("div", Ct, [D(h(P), { | ||
| size: 18, | ||
| "stroke-width": 2, | ||
| class: "tpl:text-[var(--tpl-primary)]" | ||
| }), x("span", null, d(h(r).snapshotPreview.message), 1)]), x("div", wt, [x("button", { | ||
| class: "tpl:rounded-md tpl:px-3 tpl:py-1.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]", | ||
| style: { "background-color": "transparent" }, | ||
| onClick: a[0] ||= (e) => n("cancel") | ||
| }, d(h(r).snapshotPreview.cancel), 1), x("button", { | ||
| class: "tpl:rounded-md tpl:px-3 tpl:py-1.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]", | ||
| onClick: a[1] ||= (e) => n("confirm") | ||
| }, d(h(r).snapshotPreview.restore), 1)])])) : m("", !0); | ||
| } | ||
| }), Et = { | ||
| key: 0, | ||
| role: "status", | ||
| "aria-live": "polite", | ||
| class: "tpl:absolute tpl:top-16 tpl:left-1/2 tpl:z-toast tpl:-translate-x-1/2 tpl:rounded-[var(--tpl-radius)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:shadow-lg", | ||
| style: { | ||
| "background-color": "var(--tpl-warning-light)", | ||
| color: "var(--tpl-text)", | ||
| border: "1px solid var(--tpl-warning)" | ||
| } | ||
| }, Dt = /* @__PURE__ */ E({ | ||
| __name: "CollabUndoToast", | ||
| props: { visible: { type: Boolean } }, | ||
| setup(e) { | ||
| let { t } = F(); | ||
| return (n, r) => e.visible ? (i(), p("div", Et, d(h(t).history.collabWarning), 1)) : m("", !0); | ||
| } | ||
| }), Ot = ["data-tpl-theme"], kt = { class: "tpl:sticky tpl:top-0 tpl:z-40 tpl:h-0" }, At = { class: "tpl-main tpl:flex tpl:justify-center tpl:p-8" }, jt = ["aria-label"], Mt = /* @__PURE__ */ le(/* @__PURE__ */ E({ | ||
| __name: "CloudEditor", | ||
| props: { | ||
| config: {}, | ||
| translations: {}, | ||
| cloudTranslations: {}, | ||
| fontsManager: {}, | ||
| shadowRoot: {} | ||
| }, | ||
| emits: ["ready"], | ||
| setup(e, { expose: r, emit: o }) { | ||
| let l = e; | ||
| a(I, l.cloudTranslations); | ||
| let u = o, f = c(null), _ = c(null), w = Ie({ | ||
| config: l.config, | ||
| translations: l.translations, | ||
| fontsManager: l.fontsManager, | ||
| emit: u, | ||
| getCommentsSidebar: () => f.value ? { filterByBlock: f.value.filterCommentsByBlock } : null, | ||
| editorRoot: l.shadowRoot, | ||
| containerEl: _ | ||
| }), { isInitializing: E, isAuthReady: ee, initError: O, planConfigInstance: k, websocket: A, collaboration: j, isCollaborationEnabled: M, editor: N, core: P, featureFlags: F, mediaLib: te, exporter: ne, testEmail: L, commentsInstance: re, savedModulesHeadless: R, panelState: z, snapshotPreview: B, collabWarning: ie, showSaveModuleDialog: V, showModuleBrowserModal: H, saveModulePreSelectedBlockId: U, setThemeOverrides: W, setUiTheme: G } = w; | ||
| async function K(e) { | ||
| try { | ||
| await L.sendTestEmail(e), z.testEmailModalOpen.value = !1; | ||
| } catch {} | ||
| } | ||
| function q(e, t) { | ||
| for (let n = 0; n < e.content.length; n++) { | ||
| let r = _e(e.content[n]), i = t === void 0 ? void 0 : t + n; | ||
| N.addBlock(r, void 0, void 0, i); | ||
| } | ||
| H.value = !1; | ||
| } | ||
| let J = Re({ | ||
| config: l.config, | ||
| editor: N, | ||
| websocket: A, | ||
| planConfigInstance: k, | ||
| snapshotPreview: B, | ||
| core: P, | ||
| exporter: ne, | ||
| featureFlags: F, | ||
| isDestroyed: w.isDestroyed | ||
| }), Y = ze({ | ||
| issues: P.templateLint ? P.templateLint.issues : c([]), | ||
| planConfig: k.config | ||
| }); | ||
| async function X() { | ||
| await Y.tryRunSave(() => J.saveTemplate().catch((e) => l.config.onError?.(e))); | ||
| } | ||
| return w.onSaveHook.value = X, t(() => { | ||
| w.initialize(); | ||
| }), g(() => { | ||
| w.destroy(); | ||
| }), r({ | ||
| getContent: () => N.content.value, | ||
| setContent: (e) => N.setContent(e), | ||
| setTheme: G, | ||
| setThemeOverrides: W, | ||
| create: J.createTemplate, | ||
| load: J.loadTemplate, | ||
| save: J.saveTemplate, | ||
| sendTestEmail: L.sendTestEmail | ||
| }), (t, r) => (i(), p("div", { | ||
| ref_key: "rootEl", | ||
| ref: _, | ||
| class: b(["tpl tpl:relative tpl:h-full tpl:overflow-hidden", { "tpl:dark": h(N).state.darkMode }]), | ||
| "data-tpl-theme": h(P).resolvedTheme.value, | ||
| style: C(h(P).themeStyles.value) | ||
| }, [ | ||
| D(y, { | ||
| "enter-active-class": "tpl:transition-opacity tpl:duration-200", | ||
| "enter-from-class": "tpl:opacity-100", | ||
| "enter-to-class": "tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-opacity tpl:duration-300", | ||
| "leave-from-class": "tpl:opacity-100", | ||
| "leave-to-class": "tpl:opacity-0" | ||
| }, { | ||
| default: s(() => [D(ht, { visible: h(E) || h(N).state.isLoading }, null, 8, ["visible"])]), | ||
| _: 1 | ||
| }), | ||
| D(y, { | ||
| "enter-active-class": "tpl:transition-opacity tpl:duration-200", | ||
| "enter-from-class": "tpl:opacity-0", | ||
| "enter-to-class": "tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-opacity tpl:duration-300", | ||
| "leave-from-class": "tpl:opacity-100", | ||
| "leave-to-class": "tpl:opacity-0" | ||
| }, { | ||
| default: s(() => [D(xt, { | ||
| error: h(O), | ||
| visible: !!h(O) && !h(E), | ||
| onRetry: h(w).initialize | ||
| }, null, 8, [ | ||
| "error", | ||
| "visible", | ||
| "onRetry" | ||
| ])]), | ||
| _: 1 | ||
| }), | ||
| D(ut, { | ||
| editor: h(N), | ||
| core: h(P), | ||
| "feature-flags": h(F), | ||
| "panel-state": h(z), | ||
| "snapshot-preview": h(B), | ||
| "comments-instance": h(re), | ||
| "test-email": h(L), | ||
| websocket: h(A), | ||
| collaboration: h(j), | ||
| "is-collaboration-enabled": h(M), | ||
| "is-saving": h(N).state.isSaving || h(F).isSaveExporting.value, | ||
| "is-save-disabled": h(N).state.isSaving || h(F).isSaveExporting.value || !h(N).state.isDirty, | ||
| onSave: X | ||
| }, null, 8, [ | ||
| "editor", | ||
| "core", | ||
| "feature-flags", | ||
| "panel-state", | ||
| "snapshot-preview", | ||
| "comments-instance", | ||
| "test-email", | ||
| "websocket", | ||
| "collaboration", | ||
| "is-collaboration-enabled", | ||
| "is-saving", | ||
| "is-save-disabled" | ||
| ]), | ||
| D(Ye, { | ||
| open: h(Y).modalOpen.value, | ||
| issues: h(Y).blockingIssues.value, | ||
| onCancel: h(Y).cancel, | ||
| onConfirm: h(Y).confirmAndSave | ||
| }, null, 8, [ | ||
| "open", | ||
| "issues", | ||
| "onCancel", | ||
| "onConfirm" | ||
| ]), | ||
| D(Tt, { | ||
| visible: h(B).isPreviewingSnapshot.value, | ||
| onCancel: h(B).cancelPreview, | ||
| onConfirm: h(B).confirmRestoreSnapshot | ||
| }, null, 8, [ | ||
| "visible", | ||
| "onCancel", | ||
| "onConfirm" | ||
| ]), | ||
| D(y, { | ||
| "enter-active-class": "tpl:transition-all tpl:duration-200 tpl:ease-out", | ||
| "enter-from-class": "tpl:translate-y-[-8px] tpl:opacity-0", | ||
| "enter-to-class": "tpl:translate-y-0 tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-all tpl:duration-300 tpl:ease-in", | ||
| "leave-from-class": "tpl:translate-y-0 tpl:opacity-100", | ||
| "leave-to-class": "tpl:translate-y-[-8px] tpl:opacity-0" | ||
| }, { | ||
| default: s(() => [D(Dt, { visible: h(ie).collabUndoWarningVisible.value }, null, 8, ["visible"])]), | ||
| _: 1 | ||
| }), | ||
| n(D(ke, null, null, 512), [[S, !h(N).state.previewMode]]), | ||
| x("div", { | ||
| class: b(["tpl-body tpl:absolute tpl:bottom-0 tpl:overflow-auto", [h(N).state.previewMode ? "tpl:left-0 tpl:right-0" : h(z).rightPanelOpen.value ? "tpl:left-12 tpl:right-[680px]" : "tpl:left-12 tpl:right-[320px]", h(B).isPreviewingSnapshot.value ? "tpl:top-[104px]" : "tpl:top-14"]]), | ||
| style: { | ||
| transition: "all 300ms cubic-bezier(0.34, 1.56, 0.64, 1)", | ||
| "background-color": "var(--tpl-canvas-bg)" | ||
| } | ||
| }, [x("div", kt, [D(y, { name: "tpl-restore-btn" }, { | ||
| default: s(() => [h(P).conditionPreview.hasHiddenBlocks.value ? (i(), p("button", { | ||
| key: 0, | ||
| class: "tpl:absolute tpl:left-1/2 tpl:top-2 tpl:-translate-x-1/2 tpl:inline-flex tpl:items-center tpl:gap-1.5 tpl:rounded-full tpl:border tpl:px-3.5 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:whitespace-nowrap tpl:shadow-md tpl:hover:opacity-80", | ||
| style: { | ||
| "background-color": "var(--tpl-warning-light)", | ||
| color: "var(--tpl-warning)", | ||
| "border-color": "var(--tpl-warning)", | ||
| "backdrop-filter": "blur(8px)" | ||
| }, | ||
| onClick: r[0] ||= (e) => h(P).conditionPreview.reset() | ||
| }, [D(h(be), { | ||
| size: 13, | ||
| "stroke-width": 2 | ||
| }), T(" " + d(h(P).t.blockSettings.restoreHiddenBlocks), 1)])) : m("", !0)]), | ||
| _: 1 | ||
| })]), x("main", At, [D(Ce, { | ||
| viewport: h(N).state.viewport, | ||
| content: h(N).content.value, | ||
| "selected-block-id": h(N).state.selectedBlockId, | ||
| "dark-mode": h(N).state.darkMode, | ||
| "preview-mode": h(N).state.previewMode, | ||
| "locked-blocks": h(j)?.lockedBlocks.value ?? void 0, | ||
| onSelectBlock: h(N).selectBlock, | ||
| onOpenAiChat: r[1] ||= (e) => h(z).aiChatOpen.value = !0, | ||
| onOpenDesignReference: r[2] ||= (e) => h(z).designReferenceOpen.value = !0 | ||
| }, null, 8, [ | ||
| "viewport", | ||
| "content", | ||
| "selected-block-id", | ||
| "dark-mode", | ||
| "preview-mode", | ||
| "locked-blocks", | ||
| "onSelectBlock" | ||
| ])])], 2), | ||
| e.config.branding !== !1 && !h(F).isWhiteLabeled.value ? (i(), v(Ee, { | ||
| key: 0, | ||
| "position-class": [h(N).state.previewMode ? "tpl:left-0 tpl:right-0" : h(z).rightPanelOpen.value ? "tpl:left-12 tpl:right-[680px]" : "tpl:left-12 tpl:right-[320px]"] | ||
| }, null, 8, ["position-class"])) : m("", !0), | ||
| x("div", { | ||
| class: "tpl-sr-only", | ||
| role: "status", | ||
| "aria-live": "polite", | ||
| "aria-atomic": "true", | ||
| "aria-label": h(P).t.landmarks.reorderAnnouncements | ||
| }, d(h(P).keyboardReorder.announcement.value), 9, jt), | ||
| n(D(De, { | ||
| "selected-block": h(N).selectedBlock.value, | ||
| settings: h(N).content.value.settings, | ||
| "shifted-left": h(z).rightPanelOpen.value, | ||
| onUpdateBlock: r[3] ||= (e) => h(N).updateBlock(h(N).selectedBlock.value.id, e), | ||
| onDeleteBlock: r[4] ||= (e) => h(P).blockActions.deleteBlock(h(N).selectedBlock.value.id), | ||
| onDuplicateBlock: r[5] ||= (e) => h(P).blockActions.duplicateBlock(h(N).selectedBlock.value), | ||
| onUpdateSettings: h(N).updateSettings | ||
| }, null, 8, [ | ||
| "selected-block", | ||
| "settings", | ||
| "shifted-left", | ||
| "onUpdateSettings" | ||
| ]), [[S, !h(N).state.previewMode]]), | ||
| !h(E) && h(ee) ? (i(), v(dt, { | ||
| key: 1, | ||
| ref_key: "cloudPanelsRef", | ||
| ref: f, | ||
| config: l.config, | ||
| editor: h(N), | ||
| core: h(P), | ||
| "panel-state": h(z), | ||
| "plan-config-instance": h(k), | ||
| "test-email": h(L), | ||
| "media-lib": h(te), | ||
| "saved-modules-headless": h(R), | ||
| "show-save-module-dialog": h(V), | ||
| "save-module-pre-selected-block-id": h(U), | ||
| "show-module-browser-modal": h(H), | ||
| "onUpdate:showSaveModuleDialog": r[6] ||= (e) => V.value = e, | ||
| "onUpdate:saveModulePreSelectedBlockId": r[7] ||= (e) => U.value = e, | ||
| "onUpdate:showModuleBrowserModal": r[8] ||= (e) => H.value = e, | ||
| onSendTestEmail: K, | ||
| onModuleInsert: q | ||
| }, null, 8, [ | ||
| "config", | ||
| "editor", | ||
| "core", | ||
| "panel-state", | ||
| "plan-config-instance", | ||
| "test-email", | ||
| "media-lib", | ||
| "saved-modules-headless", | ||
| "show-save-module-dialog", | ||
| "save-module-pre-selected-block-id", | ||
| "show-module-browser-modal" | ||
| ])) : m("", !0), | ||
| x("div", { | ||
| ref: (e) => h(P).popoverRoot.value = e, | ||
| class: "tpl-popover-root" | ||
| }, null, 512), | ||
| D(Ae) | ||
| ], 14, Ot)); | ||
| } | ||
| }), [["__scopeId", "data-v-3f0f5cfa"]]); | ||
| //#endregion | ||
| export { Mt as default }; | ||
| //# sourceMappingURL=CloudEditor-CyJItWsK.js.map |
Sorry, the diff of this file is too big to display
| import { n as e } from "./rolldown-runtime-Dqa2HsxW.js"; | ||
| import { An as t, Dn as n, En as r, Fn as i, In as a, Ln as o, Mn as s, Nn as c, On as l, Pn as u, Rn as d, Tn as f, jn as p, kn as m } from "./features-D-2kVhHY.js"; | ||
| //#endregion | ||
| //#region ../renderer/src/render-context.ts | ||
| var h = `https://unpkg.com/@templatical/renderer@${{ | ||
| name: "@templatical/renderer", | ||
| description: "Render Templatical email templates to MJML", | ||
| version: "0.9.0", | ||
| bugs: "https://github.com/templatical/sdk/issues", | ||
| dependencies: { "@templatical/types": "workspace:*" }, | ||
| devDependencies: { | ||
| "@resvg/resvg-js": "^2.6.2", | ||
| mjml: "^5.2.2", | ||
| tsup: "^8.5.1", | ||
| typescript: "^6.0.3", | ||
| vitest: "^4.1.7" | ||
| }, | ||
| exports: { ".": { | ||
| types: "./dist/index.d.ts", | ||
| import: "./dist/index.js" | ||
| } }, | ||
| files: ["dist", "assets"], | ||
| homepage: "https://templatical.com", | ||
| keywords: [ | ||
| "email", | ||
| "email-template", | ||
| "html-email", | ||
| "mjml", | ||
| "renderer", | ||
| "templatical" | ||
| ], | ||
| license: "MIT", | ||
| module: "./dist/index.js", | ||
| publishConfig: { access: "public" }, | ||
| repository: { | ||
| type: "git", | ||
| url: "git+https://github.com/templatical/sdk.git", | ||
| directory: "packages/renderer" | ||
| }, | ||
| scripts: { | ||
| build: "tsup && node scripts/rasterize-social.mjs", | ||
| test: "vitest run --config vitest.config.ts", | ||
| typecheck: "tsc --noEmit" | ||
| }, | ||
| type: "module", | ||
| types: "./dist/index.d.ts" | ||
| }.version}/assets/social`, g = { | ||
| arial: "Arial, sans-serif", | ||
| helvetica: "Helvetica, sans-serif", | ||
| georgia: "Georgia, serif", | ||
| "times new roman": "'Times New Roman', serif", | ||
| verdana: "Verdana, sans-serif", | ||
| "trebuchet ms": "'Trebuchet MS', sans-serif", | ||
| "courier new": "'Courier New', monospace", | ||
| tahoma: "Tahoma, sans-serif" | ||
| }, _ = class e { | ||
| containerWidth; | ||
| customFonts; | ||
| defaultFallbackFont; | ||
| allowHtmlBlocks; | ||
| customBlockHtml; | ||
| socialIconsBaseUrl; | ||
| constructor(e, t, n, r, i = /* @__PURE__ */ new Map(), a = h) { | ||
| this.containerWidth = e, this.customFonts = t, this.defaultFallbackFont = n, this.allowHtmlBlocks = r, this.customBlockHtml = i, this.socialIconsBaseUrl = a; | ||
| } | ||
| withContainerWidth(t) { | ||
| return new e(t, this.customFonts, this.defaultFallbackFont, this.allowHtmlBlocks, this.customBlockHtml, this.socialIconsBaseUrl); | ||
| } | ||
| resolveFontFamily(e) { | ||
| for (let t of this.customFonts) if (t.name.toLowerCase() === e.toLowerCase()) { | ||
| let e = t.fallback ?? this.defaultFallbackFont; | ||
| return `'${t.name}', ${e}`; | ||
| } | ||
| return g[e.toLowerCase()] || e; | ||
| } | ||
| }, v = { | ||
| "&": "&", | ||
| "<": "<", | ||
| ">": ">", | ||
| "\"": """, | ||
| "'": "'" | ||
| }, y = /[&<>"']/g; | ||
| function b(e) { | ||
| return e === "" ? "" : e.replace(y, (e) => v[e] ?? e); | ||
| } | ||
| function x(e) { | ||
| return e === "" ? "" : e.replace(y, (e) => v[e] ?? e); | ||
| } | ||
| function S(e) { | ||
| return e === "" ? "" : x(e).replace(/[;{}\r\n]/g, ""); | ||
| } | ||
| function C(e) { | ||
| return e === "" ? "" : ee(e, (e) => w(e, "data-merge-tag") ?? w(e, "data-logic-merge-tag")); | ||
| } | ||
| function ee(e, t) { | ||
| let n = "", r = 0; | ||
| for (; r < e.length;) { | ||
| let i = e.indexOf("<span", r); | ||
| if (i === -1) { | ||
| n += e.substring(r); | ||
| break; | ||
| } | ||
| let a = e[i + 5]; | ||
| if (a !== ">" && a !== " " && a !== " " && a !== "\n" && a !== "\r" && a !== "/") { | ||
| n += e.substring(r, i + 5), r = i + 5; | ||
| continue; | ||
| } | ||
| let o = e.indexOf(">", i + 5); | ||
| if (o === -1) { | ||
| n += e.substring(r); | ||
| break; | ||
| } | ||
| let s = e.indexOf("</span>", o + 1); | ||
| if (s === -1) { | ||
| n += e.substring(r); | ||
| break; | ||
| } | ||
| let c = t(e.substring(i + 5, o)); | ||
| if (c === null) { | ||
| n += e.substring(r, i + 5), r = i + 5; | ||
| continue; | ||
| } | ||
| n += e.substring(r, i), n += c, r = s + 7; | ||
| } | ||
| return n; | ||
| } | ||
| function w(e, t) { | ||
| let n = RegExp(`(?:^|\\s)${t}="([^"<>]*)"`).exec(e); | ||
| return n ? n[1] : null; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/padding.ts | ||
| function T(e) { | ||
| return `${e.top}px ${e.right}px ${e.bottom}px ${e.left}px`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/utils.ts | ||
| function E(e, t) { | ||
| return e ? ` ${t === "native" ? "background-color" : "container-background-color"}="${e}"` : ""; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/visibility.ts | ||
| function D(e) { | ||
| let t = e.visibility; | ||
| return t ? !t.desktop && !t.tablet && !t.mobile : !1; | ||
| } | ||
| function O(e) { | ||
| let t = k(e); | ||
| return t === "" ? "" : ` css-class="${t}"`; | ||
| } | ||
| function k(e) { | ||
| let t = e.visibility; | ||
| if (!t) return ""; | ||
| let n = []; | ||
| return t.desktop || n.push("tpl-hide-desktop"), t.tablet || n.push("tpl-hide-tablet"), t.mobile || n.push("tpl-hide-mobile"), n.join(" "); | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/title.ts | ||
| function te(e, t) { | ||
| if (D(e)) return ""; | ||
| let n = T(e.styles.padding), r = E(e.styles.backgroundColor, "container"), i = ne(C(e.content)), a = d[e.level] ?? d[2], o = x(e.color), s = e.textAlign, c = re(e.fontFamily, t), l = O(e), u = `h${d[e.level] ? e.level : 2}`; | ||
| return `<mj-text | ||
| font-size="${a}px" | ||
| color="${o}" | ||
| align="${s}" | ||
| line-height="1.3" | ||
| padding="${n}"${r}${c}${l} | ||
| ><${u} style="margin:0;font-size:inherit;color:inherit;line-height:inherit">${i}</${u}></mj-text>`; | ||
| } | ||
| function ne(e) { | ||
| let t = e.match(/^\s*<p\b[^>]*>([\s\S]*)<\/p>\s*$/); | ||
| return !t || /<\/p>\s*<p\b/i.test(t[1]) ? e : t[1]; | ||
| } | ||
| function re(e, t) { | ||
| return e ? ` font-family="${t.resolveFontFamily(e)}"` : ""; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/paragraph.ts | ||
| function A(e, t) { | ||
| if (D(e) || e.content.replace(/<\/?p\b[^<>]*>/gi, "").trim() === "") return ""; | ||
| let n = T(e.styles.padding), r = E(e.styles.backgroundColor, "container"), i = C(e.content); | ||
| return `<mj-text | ||
| line-height="1.5" | ||
| padding="${n}"${r}${O(e)} | ||
| >${i}</mj-text>`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/image.ts | ||
| function j(e, t) { | ||
| if (D(e) || e.src === "") return ""; | ||
| let n = T(e.styles.padding), r = E(e.styles.backgroundColor, "container"), i = e.width === "full" ? t.containerWidth + "px" : e.width + "px", a = O(e), o = ""; | ||
| e.linkUrl && (o = ` href="${x(e.linkUrl)}"`, e.linkOpenInNewTab && (o += " target=\"_blank\" rel=\"noopener\"")); | ||
| let s = x(e.src), c = e.decorative === !0; | ||
| return `<mj-image | ||
| src="${s}" | ||
| alt="${c ? "" : x(e.alt)}" | ||
| width="${i}" | ||
| align="${e.align}" | ||
| padding="${n}"${r}${o}${a}${c ? " role=\"presentation\"" : ""} | ||
| />`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/button.ts | ||
| function M(e, t) { | ||
| if (D(e)) return ""; | ||
| let n = T(e.styles.padding), r = E(e.styles.backgroundColor, "container"), i = T(e.buttonPadding), a = e.url === "" ? "" : x(e.url), o = a === "" ? "" : ` href="${a}"`, s = x(e.backgroundColor), c = x(e.textColor), l = e.fontSize, u = e.borderRadius, d = b(e.text); | ||
| return `<mj-button${o}${e.openInNewTab ? " target=\"_blank\" rel=\"noopener\"" : ""} | ||
| background-color="${s}" | ||
| color="${c}" | ||
| font-size="${l}px" | ||
| font-weight="bold" | ||
| border-radius="${u}px" | ||
| inner-padding="${i}" | ||
| padding="${n}"${r}${N(e.fontFamily, t)}${O(e)} | ||
| >${d}</mj-button>`; | ||
| } | ||
| function N(e, t) { | ||
| return e ? ` font-family="${t.resolveFontFamily(e)}"` : ""; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/divider.ts | ||
| function P(e, t) { | ||
| if (D(e)) return ""; | ||
| let n = T(e.styles.padding), r = e.styles.backgroundColor ? ` container-background-color="${x(e.styles.backgroundColor)}"` : "", i = e.width === "full" ? "100%" : e.width + "px"; | ||
| return `<mj-divider | ||
| border-width="${e.thickness}px" | ||
| border-style="${e.lineStyle}" | ||
| border-color="${x(e.color)}" | ||
| width="${i}" | ||
| padding="${n}"${r}${O(e)} | ||
| />`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/spacer.ts | ||
| function F(e, t) { | ||
| return D(e) ? "" : `<mj-spacer height="${e.height}px" padding="0"${e.styles.backgroundColor ? ` container-background-color="${x(e.styles.backgroundColor)}"` : ""}${O(e)} />`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/html.ts | ||
| function I(e, t) { | ||
| if (D(e) || !t.allowHtmlBlocks) return ""; | ||
| let n = e.content; | ||
| return n === "" ? "" : `<mj-text${O(e)}> | ||
| ${n} | ||
| </mj-text>`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/social.ts | ||
| function L(e, t) { | ||
| if (D(e)) return ""; | ||
| let n = e.icons; | ||
| if (n.length === 0) return ""; | ||
| let r = T(e.styles.padding), i = e.styles.backgroundColor ? ` container-background-color="${x(e.styles.backgroundColor)}"` : "", a = O(e), o = e.align, s = e.iconSize, c = e.iconStyle, l = e.spacing, u; | ||
| switch (s) { | ||
| case "small": | ||
| u = 24; | ||
| break; | ||
| case "large": | ||
| u = 48; | ||
| break; | ||
| default: | ||
| u = 32; | ||
| break; | ||
| } | ||
| let d; | ||
| switch (c) { | ||
| case "circle": | ||
| d = "50%"; | ||
| break; | ||
| case "rounded": | ||
| d = "8px"; | ||
| break; | ||
| case "square": | ||
| d = "0"; | ||
| break; | ||
| default: | ||
| d = "4px"; | ||
| break; | ||
| } | ||
| let f = n.length; | ||
| return `<mj-social | ||
| mode="horizontal" | ||
| align="${o}" | ||
| icon-padding="0" | ||
| padding="${r}"${i}${a} | ||
| > | ||
| ${n.map((e, n) => { | ||
| let r = e.platform, i = x(e.url), a = `${t.socialIconsBaseUrl}/${c}/${r}.png`, o = n === f - 1 ? 0 : l; | ||
| return `<mj-social-element src="${a}" href="${i}" icon-size="${u}px" padding="0 ${o}px 0 0" border-radius="${d}" background-color="transparent"></mj-social-element>`; | ||
| }).join("\n")} | ||
| </mj-social>`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/menu.ts | ||
| function R(e, t) { | ||
| if (D(e) || e.items.length === 0) return ""; | ||
| let n = T(e.styles.padding), r = E(e.styles.backgroundColor, "container"), i = O(e), a = V(e.fontFamily, t), o = e.textAlign; | ||
| return `<mj-text | ||
| font-size="${e.fontSize}px" | ||
| color="${x(e.color)}" | ||
| align="${o}" | ||
| line-height="1.5" | ||
| padding="${n}"${r}${a}${i} | ||
| >${z(e)}</mj-text>`; | ||
| } | ||
| function z(e) { | ||
| let t = e.items, n = b(e.separator), r = S(e.separatorColor), i = e.spacing, a = e.linkColor ?? e.color, o = [], s = t.length; | ||
| for (let e = 0; e < s; e++) o.push(B(t[e], a)), e < s - 1 && o.push(`<span style="color: ${r}; padding: 0 ${i}px;">${n}</span>`); | ||
| return o.join(""); | ||
| } | ||
| function B(e, t) { | ||
| let n = b(e.text), r = x(e.url), i = S(e.color ?? t), a = e.openInNewTab ? " target=\"_blank\" rel=\"noopener\"" : "", o = [`color: ${i}`, "text-decoration: none"]; | ||
| return e.bold && o.push("font-weight: bold"), e.underline && o.push("text-decoration: underline"), `<a href="${r}" style="${o.join("; ")}"${a}>${n}</a>`; | ||
| } | ||
| function V(e, t) { | ||
| return e ? ` font-family="${t.resolveFontFamily(e)}"` : ""; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/table.ts | ||
| function H(e, t) { | ||
| if (D(e) || e.rows.length === 0) return ""; | ||
| let n = T(e.styles.padding), r = E(e.styles.backgroundColor, "container"), i = O(e), a = ie(e.fontFamily, t); | ||
| return `<mj-text | ||
| font-size="${e.fontSize}px" | ||
| color="${x(e.color)}" | ||
| align="${e.textAlign}" | ||
| line-height="1.5" | ||
| padding="${n}"${r}${a}${i} | ||
| >${U(e)}</mj-text>`; | ||
| } | ||
| function U(e) { | ||
| let t = S(e.borderColor), n = e.borderWidth, r = ""; | ||
| for (let i = 0; i < e.rows.length; i++) { | ||
| let a = e.rows[i]; | ||
| r += W(a, e, e.hasHeaderRow && i === 0, t, n); | ||
| } | ||
| return `<table style="width: 100%; border-collapse: collapse;">${r}</table>`; | ||
| } | ||
| function W(e, t, n, r, i) { | ||
| let a = ""; | ||
| for (let o of e.cells) a += G(o, t, n, r, i); | ||
| return `<tr>${a}</tr>`; | ||
| } | ||
| function G(e, t, n, r, i) { | ||
| let a = t.cellPadding, o = [`border: ${i}px solid ${r}`, `padding: ${a}px`]; | ||
| n && (o.push("font-weight: bold"), t.headerBackgroundColor && o.push(`background-color: ${S(t.headerBackgroundColor)}`)); | ||
| let s = o.join("; "), c = C(e.content), l = n ? "th" : "td"; | ||
| return `<${l} style="${s}">${c}</${l}>`; | ||
| } | ||
| function ie(e, t) { | ||
| return e ? ` font-family="${t.resolveFontFamily(e)}"` : ""; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/custom.ts | ||
| function K(e, t) { | ||
| if (D(e)) return ""; | ||
| let n = t.customBlockHtml.get(e.id) ?? e.renderedHtml; | ||
| if (!n || n === "") return ""; | ||
| let r = O(e); | ||
| return `<mj-text${E(e.styles?.backgroundColor, "container")}${r}> | ||
| ${n} | ||
| </mj-text>`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/columns.ts | ||
| function q(e) { | ||
| switch (e) { | ||
| case "2": return ["50%", "50%"]; | ||
| case "3": return [ | ||
| "33.33%", | ||
| "33.33%", | ||
| "33.34%" | ||
| ]; | ||
| case "1-2": return ["33.33%", "66.67%"]; | ||
| case "2-1": return ["66.67%", "33.33%"]; | ||
| default: return ["100%"]; | ||
| } | ||
| } | ||
| function J(e, t) { | ||
| switch (e) { | ||
| case "2": return [t * .5, t * .5]; | ||
| case "3": return [ | ||
| t / 3, | ||
| t / 3, | ||
| t / 3 | ||
| ]; | ||
| case "1-2": return [t / 3, t * 2 / 3]; | ||
| case "2-1": return [t * 2 / 3, t / 3]; | ||
| default: return [t]; | ||
| } | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/section.ts | ||
| function Y(e, t, n) { | ||
| if (D(e)) return ""; | ||
| let r = e.columns, i = q(r), a = J(r, t.containerWidth), o = T(e.styles.padding), c = E(e.styles.backgroundColor, "native"), l = O(e), u = e.children, d = []; | ||
| for (let e = 0; e < u.length; e++) { | ||
| let r = u[e], o = i[e] ?? "100%", c = Math.floor(a[e] ?? t.containerWidth), l = ae(r, t.allowHtmlBlocks).filter((e) => !s(e)), f = t.withContainerWidth(c), p = l.map((e) => n(e, f)).filter((e) => e !== "").join("\n"); | ||
| d.push(`<mj-column width="${o}"> | ||
| ${p === "" ? "<mj-text> </mj-text>" : p} | ||
| </mj-column>`); | ||
| } | ||
| return `<mj-section${c} padding="${o}"${l}> | ||
| ${d.join("\n")} | ||
| </mj-section>`; | ||
| } | ||
| function ae(e, t) { | ||
| return t ? e : e.filter((e) => e.type !== "html"); | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/video.ts | ||
| function oe(e, t) { | ||
| if (t) return t; | ||
| if (!e) return null; | ||
| for (let t of [/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/, /youtube\.com\/shorts\/([a-zA-Z0-9_-]{11})/]) { | ||
| let n = e.match(t); | ||
| if (n) return `https://img.youtube.com/vi/${n[1]}/maxresdefault.jpg`; | ||
| } | ||
| let n = e.match(/vimeo\.com\/(?:video\/)?(\d+)/); | ||
| return n ? `https://vumbnail.com/${n[1]}.jpg` : null; | ||
| } | ||
| function se(e, t) { | ||
| if (D(e)) return ""; | ||
| let n = oe(e.url, e.thumbnailUrl); | ||
| if (!n) return ""; | ||
| let r = T(e.styles.padding), i = E(e.styles.backgroundColor, "container"), a = e.width === "full" ? t.containerWidth + "px" : e.width + "px", o = O(e); | ||
| return `<mj-image | ||
| src="${x(n)}" | ||
| alt="${x(e.alt)}" | ||
| width="${a}" | ||
| align="${e.align}" | ||
| padding="${r}" | ||
| href="${x(e.url)}" | ||
| target="_blank" | ||
| rel="noopener"${i}${o} | ||
| />`; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/renderers/index.ts | ||
| function X(e, d) { | ||
| return s(e) ? Y(e, d, X) : a(e) ? te(e, d) : p(e) ? A(e, d) : m(e) ? j(e, d) : f(e) ? M(e, d) : n(e) ? P(e, d) : u(e) ? F(e, d) : l(e) ? I(e, d) : c(e) ? L(e, d) : t(e) ? R(e, d) : i(e) ? H(e, d) : o(e) ? se(e, d) : r(e) ? K(e, d) : ""; | ||
| } | ||
| //#endregion | ||
| //#region ../renderer/src/index.ts | ||
| var ce = /* @__PURE__ */ e({ | ||
| DEFAULT_SOCIAL_ICONS_BASE_URL: () => h, | ||
| RenderContext: () => _, | ||
| convertMergeTagsToValues: () => C, | ||
| escapeAttr: () => x, | ||
| escapeHtml: () => b, | ||
| getCssClassAttr: () => O, | ||
| getCssClasses: () => k, | ||
| getWidthPercentages: () => q, | ||
| getWidthPixels: () => J, | ||
| isHiddenOnAll: () => D, | ||
| renderBlock: () => X, | ||
| renderToMjml: () => Z, | ||
| toPaddingString: () => T | ||
| }); | ||
| async function Z(e, t) { | ||
| let n = t?.customFonts ?? [], r = t?.defaultFallbackFont ?? "Arial, sans-serif", i = t?.allowHtmlBlocks ?? !0, a = de(t?.socialIconsBaseUrl ?? h), o = await he(e, t?.renderCustomBlock), s = new _(e.settings.width, n, r, i, o, a), c = me(e.blocks, i), l = s.resolveFontFamily(e.settings.fontFamily), u = e.settings.backgroundColor, d = c.map((e) => le(e, s)).filter((e) => e !== "").join("\n"), f = pe(n), p = fe(e.settings.preheaderText); | ||
| return `<mjml lang="${x(e.settings.locale)}"> | ||
| <mj-head>${p} | ||
| <mj-attributes> | ||
| <mj-all font-family="${l}" /> | ||
| <mj-text font-size="14px" /> | ||
| <mj-section padding="0" /> | ||
| <mj-column padding="0" /> | ||
| <mj-image fluid-on-mobile="true" /> | ||
| </mj-attributes>${f} | ||
| <mj-style> | ||
| a { color: inherit; text-decoration: none; } | ||
| @media only screen and (max-width: 480px) { | ||
| .tpl-hide-mobile { display: none !important; mso-hide: all !important; } | ||
| } | ||
| @media only screen and (min-width: 481px) and (max-width: 768px) { | ||
| .tpl-hide-tablet { display: none !important; mso-hide: all !important; } | ||
| } | ||
| @media only screen and (min-width: 769px) { | ||
| .tpl-hide-desktop { display: none !important; mso-hide: all !important; } | ||
| } | ||
| </mj-style> | ||
| </mj-head> | ||
| <mj-body width="${s.containerWidth}px" background-color="${u}"> | ||
| ${d} | ||
| </mj-body> | ||
| </mjml>`; | ||
| } | ||
| function le(e, t) { | ||
| return s(e) ? Q(e, X(e, t)) : Q(e, ue(X(e, t))); | ||
| } | ||
| function Q(e, t) { | ||
| if (t === "") return ""; | ||
| let n = e.displayCondition; | ||
| return n ? `<mj-raw>${n.before}</mj-raw> | ||
| ` + t + ` | ||
| <mj-raw>${n.after}</mj-raw>` : t; | ||
| } | ||
| function ue(e) { | ||
| return e === "" ? "" : `<mj-section> | ||
| <mj-column> | ||
| ${e} | ||
| </mj-column> | ||
| </mj-section>`; | ||
| } | ||
| function de(e) { | ||
| return e.endsWith("/") ? e.slice(0, -1) : e; | ||
| } | ||
| function fe(e) { | ||
| if (!e) return ""; | ||
| let t = e.trim(); | ||
| return t === "" ? "" : `\n <mj-preview>${b(t)}</mj-preview>`; | ||
| } | ||
| function pe(e) { | ||
| return e.length === 0 ? "" : e.map((e) => `\n <mj-font name="${x(e.name)}" href="${x(e.url)}" />`).join(""); | ||
| } | ||
| function me(e, t) { | ||
| return t ? e : e.filter((e) => e.type !== "html"); | ||
| } | ||
| async function he(e, t) { | ||
| let n = /* @__PURE__ */ new Map(); | ||
| if (!t) return n; | ||
| let r = []; | ||
| if ($(e.blocks, r), r.length === 0) return n; | ||
| let i = await Promise.all(r.map((e) => t(e))); | ||
| for (let e = 0; e < r.length; e++) n.set(r[e].id, i[e]); | ||
| return n; | ||
| } | ||
| function $(e, t) { | ||
| for (let n of e) { | ||
| if (r(n)) { | ||
| t.push(n); | ||
| continue; | ||
| } | ||
| if (s(n)) for (let e of n.children) $(e, t); | ||
| } | ||
| } | ||
| //#endregion | ||
| export { ce as t }; | ||
| //# sourceMappingURL=renderer-7z2t_bYQ.js.map |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
| import { A as e, B as t, L as n, M as r, O as i, Q as a, X as o, _ as s, at as c, b as l, c as u, d, f, g as p, h as m, j as h, k as g, l as _, m as v, o as y, ot as b, p as x, q as S, rt as C, st as w, t as T, v as E, y as D, z as O } from "./vue.runtime.esm-bundler-BDSGA5hA.js"; | ||
| import { t as k } from "./timeouts-Bmi_yePw.js"; | ||
| import { E as A, i as j } from "./dist-CIV3Brg-.js"; | ||
| import { P as M, S as N, t as P } from "./useEditorCore-CEkf_VWX.js"; | ||
| import { c as F, t as I } from "./dist-CNLAS2v2.js"; | ||
| import { E as L, S as R, T as z, c as B, l as V, r as ee, s as te, t as H } from "./keys-BiQlvx51.js"; | ||
| import { t as U } from "./useI18n-Besvmtxy.js"; | ||
| import { t as W } from "./createLucideIcon-XgXOJ05E.js"; | ||
| import { t as G } from "./check-ChQyfxJ3.js"; | ||
| import { t as K } from "./circle-alert-CPH6l3Lc.js"; | ||
| import { a as q, c as ne, i as J, l as re, n as ie, o as ae, r as oe, s as se, t as ce, u as le } from "./styles-CJtcKmsx.js"; | ||
| import { t as ue } from "./clock-DHl_BIkU.js"; | ||
| import { t as Y } from "./loader-circle-Rz_4vJLH.js"; | ||
| import { t as X } from "./message-circle-D-umK_MU.js"; | ||
| import { t as Z } from "./send-BhbhbIFT.js"; | ||
| import { t as de } from "./sparkles-CrUN0KWY.js"; | ||
| import { t as fe } from "./triangle-alert-MwJBKR2e.js"; | ||
| import { t as pe } from "./_plugin-vue_export-helper-B3ysoDQm.js"; | ||
| import { n as Q } from "./useCloudI18n-DKWJg6rJ.js"; | ||
| import { d as $ } from "./styleConstants-lGobwiLH.js"; | ||
| import { _ as me, a as he, c as ge, d as _e, f as ve, g as ye, h as be, l as xe, m as Se, n as Ce, o as we, p as Te, r as Ee, s as De, t as Oe, v as ke, y as Ae } from "./cloud-VxYMtfXC.js"; | ||
| var je = W("save", [ | ||
| ["path", { | ||
| d: "M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z", | ||
| key: "1c8476" | ||
| }], | ||
| ["path", { | ||
| d: "M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7", | ||
| key: "1ydtos" | ||
| }], | ||
| ["path", { | ||
| d: "M7 3v4a1 1 0 0 0 1 1h7", | ||
| key: "t51u73" | ||
| }] | ||
| ]); | ||
| //#endregion | ||
| //#region src/cloud/composables/useSnapshotPreview.ts | ||
| function Me(e) { | ||
| let { authManager: t, editor: n, history: r, conditionPreview: i, autoSave: s, onError: c } = e, l = a(null), u = o(null), f = o(null), p = !1; | ||
| S(() => { | ||
| p = !0; | ||
| }); | ||
| let m = d(() => u.value !== null), h = d(() => l.value?.snapshots.value ?? []), g = d(() => l.value?.isLoading.value ?? !1), _ = d(() => l.value?.isRestoring.value ?? !1); | ||
| function v() { | ||
| n.state.template?.id && !l.value && (l.value = ye({ | ||
| authManager: t, | ||
| templateId: n.state.template.id, | ||
| onRestore: y, | ||
| onError: c | ||
| }), l.value.loadSnapshots()); | ||
| } | ||
| function y(e) { | ||
| n.setContent(e.content, !1), r.clear(), i.reset(); | ||
| } | ||
| async function b(e) { | ||
| if (!p) { | ||
| if (u.value) { | ||
| u.value = e, n.setContent(e.content, !1); | ||
| return; | ||
| } | ||
| n.state.isDirty && n.hasTemplate() && (await n.createSnapshot(), p) || (f.value = structuredClone(n.content.value), s?.pause(), u.value = e, n.setContent(e.content, !1)); | ||
| } | ||
| } | ||
| async function x() { | ||
| if (!(!u.value || !l.value)) try { | ||
| if (await l.value.restoreSnapshot(u.value.id), p || (await l.value.loadSnapshots(), p)) return; | ||
| } finally { | ||
| p || (u.value = null, f.value = null, s?.resume()); | ||
| } | ||
| } | ||
| function C() { | ||
| !u.value || !f.value || (n.setContent(f.value, !1), u.value = null, f.value = null, s?.resume()); | ||
| } | ||
| async function w() { | ||
| p || l.value && await l.value.loadSnapshots(); | ||
| } | ||
| return { | ||
| snapshotHistoryInstance: l, | ||
| previewingSnapshot: u, | ||
| contentBeforePreview: f, | ||
| isPreviewingSnapshot: m, | ||
| snapshotHistorySnapshots: h, | ||
| snapshotHistoryIsLoading: g, | ||
| snapshotHistoryIsRestoring: _, | ||
| initSnapshotHistory: v, | ||
| handleRestore: y, | ||
| handleSnapshotNavigate: b, | ||
| confirmRestoreSnapshot: x, | ||
| cancelPreview: C, | ||
| loadSnapshotHistory: w | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudPanelState.ts | ||
| function Ne() { | ||
| let e = o(null), t = d({ | ||
| get: () => e.value === "ai-chat", | ||
| set: (t) => e.value = t ? "ai-chat" : null | ||
| }), n = d({ | ||
| get: () => e.value === "scoring", | ||
| set: (t) => e.value = t ? "scoring" : null | ||
| }), r = d({ | ||
| get: () => e.value === "design-reference", | ||
| set: (t) => e.value = t ? "design-reference" : null | ||
| }), i = d({ | ||
| get: () => e.value === "comments", | ||
| set: (t) => e.value = t ? "comments" : null | ||
| }), a = o(!1), s = o(!1), c = o(void 0), l = o(!1), u = o(null), f = d(() => e.value !== null), p = d(() => { | ||
| let t = e.value; | ||
| return t === "ai-chat" || t === "design-reference" || t === "scoring" ? t : null; | ||
| }), m = d(() => l.value || e.value === "ai-chat" || e.value === "design-reference" || e.value === "scoring"); | ||
| function h() { | ||
| l.value = !l.value; | ||
| } | ||
| function g(t) { | ||
| l.value = !1, e.value = e.value === t ? null : t; | ||
| } | ||
| return I(u, () => { | ||
| l.value = !1; | ||
| }), { | ||
| activePanel: e, | ||
| aiChatOpen: t, | ||
| scoringPanelOpen: n, | ||
| designReferenceOpen: r, | ||
| commentsOpen: i, | ||
| testEmailModalOpen: a, | ||
| mediaLibraryOpen: s, | ||
| mediaLibraryAccept: c, | ||
| aiMenuOpen: l, | ||
| aiMenuRef: u, | ||
| rightPanelOpen: f, | ||
| activeAiFeature: p, | ||
| aiButtonActive: m, | ||
| toggleAiMenu: h, | ||
| handleAiFeatureSelect: g | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCollabUndoWarning.ts | ||
| function Pe(e) { | ||
| let { isCollaborationEnabled: t, getCollaboratorCount: n, canUndo: r } = e, i = o(!1), a = o(!1), { start: s } = F(() => { | ||
| a.value = !1; | ||
| }, k, { immediate: !1 }); | ||
| function c() { | ||
| i.value || !t.value || n() === 0 || !r.value || (i.value = !0, a.value = !0, s()); | ||
| } | ||
| return { | ||
| collabUndoWarningVisible: a, | ||
| showCollabUndoWarning: c | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudFeatureFlags.ts | ||
| function Fe(e) { | ||
| let { planConfigInstance: t, aiConfig: n, editor: r } = e, i = d(() => t.hasFeature("ai_generation") && n.hasAnyMenuFeature.value), a = d(() => t.hasFeature("test_email")), s = d(() => !!r.state.template?.id), c = d(() => t.hasFeature("white_label")), l = d(() => t.config.value?.limits.max_templates ?? null), u = d(() => t.config.value?.template_count ?? 0), f = o(!1), p = o("idle"), m = o(""), { start: h } = F(() => { | ||
| p.value = "idle"; | ||
| }, 3e3, { immediate: !1 }); | ||
| return { | ||
| canUseAiGeneration: i, | ||
| canSendTestEmail: a, | ||
| hasTemplateSaved: s, | ||
| isWhiteLabeled: c, | ||
| templateLimit: l, | ||
| templateCount: u, | ||
| isSaveExporting: f, | ||
| saveStatus: p, | ||
| saveErrorMessage: m, | ||
| startSaveStatusClear: h | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudMediaLibrary.ts | ||
| function Ie(e) { | ||
| let { onRequestMedia: t, mediaLibraryOpen: n, mediaLibraryAccept: r } = e, i = null; | ||
| async function a() { | ||
| if (t) { | ||
| let e = await t({ accept: ["images"] }); | ||
| return e ? { | ||
| url: e.url, | ||
| alt: e.alt_text || void 0 | ||
| } : null; | ||
| } | ||
| return i &&= (i(null), null), r.value = ["images"], n.value = !0, new Promise((e) => { | ||
| i = (t) => { | ||
| e(t); | ||
| }; | ||
| }); | ||
| } | ||
| function o(e) { | ||
| n.value = !1, i?.({ | ||
| url: e.url, | ||
| alt: e.alt_text || void 0 | ||
| }), i = null; | ||
| } | ||
| function s() { | ||
| n.value = !1, i?.(null), i = null; | ||
| } | ||
| return S(() => { | ||
| i &&= (i(null), null); | ||
| }), { | ||
| handleRequestMedia: a, | ||
| handleMediaSelect: o, | ||
| handleMediaLibraryClose: s | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudInitialization.ts | ||
| function Le(e) { | ||
| let { config: t, translations: r, fontsManager: i, emit: a, getCommentsSidebar: s } = e, c = o(!0), l = o(!1), u = o(null), f = !1, p = { value: null }, m = null, g = null, _ = new Oe({ | ||
| ...t.auth, | ||
| onError: t.onError | ||
| }), v = Se({ | ||
| authManager: _, | ||
| onError: t.onError | ||
| }), y = o(/* @__PURE__ */ new Map()), b = _e({ | ||
| authManager: _, | ||
| defaultFontFamily: t.fonts?.defaultFont, | ||
| templateDefaults: t.templateDefaults, | ||
| onError: t.onError, | ||
| lockedBlocks: y | ||
| }), x = Ae({ | ||
| authManager: _, | ||
| onError: t.onError | ||
| }); | ||
| t.mcp?.enabled && Te({ | ||
| editor: b, | ||
| channel: x.channel, | ||
| onOperation: t.mcp.onOperation | ||
| }); | ||
| let S = null; | ||
| t.collaboration?.enabled && (S = we({ | ||
| authManager: _, | ||
| editor: b, | ||
| channel: x.channel, | ||
| onError: t.onError, | ||
| onCollaboratorJoined: t.collaboration.onCollaboratorJoined, | ||
| onCollaboratorLeft: t.collaboration.onCollaboratorLeft, | ||
| onBlockLocked: t.collaboration.onBlockLocked, | ||
| onBlockUnlocked: t.collaboration.onBlockUnlocked | ||
| }), n(() => S.lockedBlocks.value, (e) => { | ||
| y.value = e; | ||
| }, { immediate: !0 }), De(b, S)); | ||
| let C = d(() => !!t.collaboration?.enabled && v.hasFeature("collaboration")), w = P({ | ||
| editor: b, | ||
| config: { | ||
| uiTheme: t.uiTheme, | ||
| theme: void 0, | ||
| blockDefaults: t.blockDefaults, | ||
| customBlocks: [], | ||
| mergeTags: t.mergeTags, | ||
| displayConditions: t.displayConditions, | ||
| onRequestMedia: null, | ||
| lint: re(t), | ||
| onSave: () => { | ||
| p.value?.().catch((e) => { | ||
| t.onError?.(e); | ||
| }); | ||
| } | ||
| }, | ||
| translations: r, | ||
| fontsManager: i, | ||
| historyOptions: S ? { isRemoteOperation: () => S._isProcessingRemoteOperation() } : void 0, | ||
| autoSaveOptions: { | ||
| onChange: async () => { | ||
| b.hasTemplate() && (await b.createSnapshot(), m?.snapshotHistoryInstance.value?.loadSnapshots()); | ||
| }, | ||
| debounce: t.autoSaveDebounce ?? 5e3, | ||
| enabled: () => t.autoSave !== !1 && v.hasFeature("auto_save") | ||
| }, | ||
| themeExtraStyles: () => ({ "--tpl-drop-text": `"${r.canvas.dropHere}"` }), | ||
| keyboardOptions: { onBeforeUndo: () => g?.showCollabUndoWarning() }, | ||
| editorRoot: e.editorRoot, | ||
| containerEl: e.containerEl | ||
| }), T = Pe({ | ||
| isCollaborationEnabled: C, | ||
| getCollaboratorCount: () => S?.collaborators.value.length ?? 0, | ||
| canUndo: w.history.canUndo | ||
| }); | ||
| g = T; | ||
| let E = Me({ | ||
| authManager: _, | ||
| editor: b, | ||
| history: w.history, | ||
| conditionPreview: w.conditionPreview, | ||
| autoSave: w.autoSave, | ||
| onError: t.onError | ||
| }); | ||
| m = E; | ||
| let D = Ne(), O = he(t.ai), k = Fe({ | ||
| planConfigInstance: v, | ||
| aiConfig: O, | ||
| editor: b | ||
| }), A = Ie({ | ||
| onRequestMedia: t.onRequestMedia, | ||
| mediaLibraryOpen: D.mediaLibraryOpen, | ||
| mediaLibraryAccept: D.mediaLibraryAccept | ||
| }); | ||
| N({ | ||
| onBlockMove: b.moveBlock, | ||
| onBlockAdd: b.addBlock | ||
| }); | ||
| let j = ve({ | ||
| authManager: _, | ||
| getFontsConfig: () => t.fonts, | ||
| canUseCustomFonts: () => v.hasFeature("custom_fonts") | ||
| }), F = ke({ | ||
| authManager: _, | ||
| getTemplateId: () => b.state.template?.id ?? null, | ||
| save: () => b.save(), | ||
| exportHtml: (e) => j.exportHtml(e), | ||
| onError: t.onError, | ||
| isAuthReady: l, | ||
| onBeforeTestEmail: t.onBeforeTestEmail | ||
| }), I = xe({ | ||
| authManager: _, | ||
| getTemplateId: () => b.state.template?.id ?? null, | ||
| getSocketId: () => x.getSocketId(), | ||
| onComment: t.onComment, | ||
| onError: t.onError, | ||
| isAuthReady: l, | ||
| hasCommentingFeature: () => t.commenting !== !1 && v.hasFeature("commenting") | ||
| }); | ||
| ge({ | ||
| comments: I, | ||
| channel: x.channel | ||
| }); | ||
| let B = be({ | ||
| authManager: _, | ||
| onError: t.onError | ||
| }), U = o(!1), W = o(null), G = o(!1), K = me({ | ||
| authManager: _, | ||
| getTemplateId: () => b.state.template?.id ?? null | ||
| }); | ||
| function q(e) { | ||
| D.commentsOpen.value = !0, queueMicrotask(() => { | ||
| s()?.filterByBlock(e); | ||
| }); | ||
| } | ||
| h(R, A.handleRequestMedia), h(ee, _), h(H, O), h(V, I), h(z, B), h(L, K), h(te, { | ||
| plan: v, | ||
| ai: O, | ||
| comments: { | ||
| getBlockCount: (e) => I.commentCountByBlock.value.get(e) ?? 0, | ||
| openForBlock: q | ||
| }, | ||
| savedModules: { | ||
| openSaveDialog: (e) => { | ||
| W.value = e ?? null, U.value = !0; | ||
| }, | ||
| openBrowser: () => { | ||
| G.value = !0; | ||
| }, | ||
| moduleCount: d(() => B.modules.value.length) | ||
| } | ||
| }); | ||
| function ne(e) { | ||
| v.hasFeature("theme_customization") && (w.themeOverrides.value = e); | ||
| } | ||
| function J(e) { | ||
| b.setUiTheme(e); | ||
| } | ||
| async function ie() { | ||
| c.value = !0, u.value = null; | ||
| try { | ||
| if (await _.initialize(), f) return; | ||
| l.value = !0; | ||
| let e = await Ce({ authManager: _ }); | ||
| if (f) return; | ||
| if (!e.api.ok) throw Error("Health check failed: API is not reachable"); | ||
| if (!e.auth.ok) throw Error(`Health check failed: authentication error${e.auth.error ? ` - ${e.auth.error}` : ""}`); | ||
| if (e.websocket.ok || M.warn("WebSocket health check failed:", e.websocket.error ?? "unknown error", "-- real-time features will be disabled."), await v.fetchConfig(), f) return; | ||
| i.setCustomFontsEnabled(v.hasFeature("custom_fonts")), t.customBlocks?.length && v.hasFeature("custom_blocks") && w.registerCustomBlocks(t.customBlocks), t.theme && v.hasFeature("theme_customization") && (w.themeOverrides.value = t.theme), t.modules !== !1 && v.hasFeature("saved_modules") && B.loadModules(), a("ready"); | ||
| } catch (e) { | ||
| if (f) return; | ||
| let n = e instanceof Error ? e : Error("Initialization failed", { cause: e }); | ||
| u.value = n, t.onError?.(n); | ||
| } finally { | ||
| f || (c.value = !1); | ||
| } | ||
| } | ||
| function ae() { | ||
| f = !0, i.cleanupFontLinks(), x.disconnect(), w.destroy(), t.onUnmount?.(); | ||
| } | ||
| return { | ||
| isInitializing: c, | ||
| isAuthReady: l, | ||
| initError: u, | ||
| isDestroyed: () => f, | ||
| authManager: _, | ||
| planConfigInstance: v, | ||
| websocket: x, | ||
| collaboration: S, | ||
| isCollaborationEnabled: C, | ||
| editor: b, | ||
| core: w, | ||
| aiConfig: O, | ||
| featureFlags: k, | ||
| mediaLib: A, | ||
| exporter: j, | ||
| testEmail: F, | ||
| commentsInstance: I, | ||
| savedModulesHeadless: B, | ||
| scoringInstance: K, | ||
| panelState: D, | ||
| snapshotPreview: E, | ||
| collabWarning: T, | ||
| showSaveModuleDialog: U, | ||
| showModuleBrowserModal: G, | ||
| saveModulePreSelectedBlockId: W, | ||
| onSaveHook: p, | ||
| initialize: ie, | ||
| destroy: ae, | ||
| setThemeOverrides: ne, | ||
| setUiTheme: J, | ||
| openCommentsForBlock: q | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/utils/preRenderCustomBlocks.ts | ||
| async function Re(e, t) { | ||
| let n = async (e) => { | ||
| if (A(e)) { | ||
| let n = e; | ||
| try { | ||
| n.renderedHtml = await t.renderCustomBlock(n); | ||
| } catch { | ||
| n.renderedHtml = `<!-- Custom block render error: ${n.customType} -->`; | ||
| } | ||
| } | ||
| if (e.type === "section" && "children" in e) { | ||
| let t = e; | ||
| for (let e of t.children) for (let t of e) await n(t); | ||
| } | ||
| }; | ||
| for (let t of e.blocks) await n(t); | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudLifecycle.ts | ||
| function ze(e) { | ||
| let { config: t, editor: n, websocket: r, planConfigInstance: i, snapshotPreview: a, core: o, exporter: s, featureFlags: c, isDestroyed: l } = e; | ||
| function u() { | ||
| return Ee(i.config.value.websocket); | ||
| } | ||
| async function d(e) { | ||
| let i = await n.create(e); | ||
| return l() ? i : (t.onCreate?.(i), a.initSnapshotHistory(), r.connect(i.id, u()), i); | ||
| } | ||
| async function f(e) { | ||
| let i = await n.load(e); | ||
| return l() ? i : (t.onLoad?.(i), a.initSnapshotHistory(), r.connect(i.id, u()), i); | ||
| } | ||
| async function p() { | ||
| c.isSaveExporting.value = !0, c.saveStatus.value = "idle"; | ||
| try { | ||
| if (await Re(n.content.value, o.registry), l()) throw Error("Component unmounted during save"); | ||
| let e = await n.save(); | ||
| if (l()) throw Error("Component unmounted during save"); | ||
| a.initSnapshotHistory(), a.snapshotHistoryInstance.value?.loadSnapshots(); | ||
| let r = await s.exportHtml(e.id); | ||
| if (l()) throw Error("Component unmounted during save"); | ||
| let i = { | ||
| templateId: e.id, | ||
| html: r.html, | ||
| mjml: r.mjml, | ||
| content: e.content | ||
| }; | ||
| return t.onSave?.(i), c.saveStatus.value = "saved", c.startSaveStatusClear(), i; | ||
| } catch (e) { | ||
| throw l() || (c.saveStatus.value = "error", c.saveErrorMessage.value = e instanceof Error ? e.message : "Save failed"), e; | ||
| } finally { | ||
| l() || (c.isSaveExporting.value = !1); | ||
| } | ||
| } | ||
| return { | ||
| createTemplate: d, | ||
| loadTemplate: f, | ||
| saveTemplate: p | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/composables/useCloudSaveGate.ts | ||
| function Be(e) { | ||
| let t = o(!1), n = null, r = d(() => e.planConfig.value?.accessibility?.blockOnError === !0), i = d(() => r.value ? e.issues.value.filter((e) => e.severity === "error") : []), a = d(() => i.value.length > 0); | ||
| async function s(e) { | ||
| return a.value ? (n = e, t.value = !0, !1) : (await e(), !0); | ||
| } | ||
| async function c() { | ||
| let e = n; | ||
| n = null, t.value = !1, e && await e(); | ||
| } | ||
| function l() { | ||
| n = null, t.value = !1; | ||
| } | ||
| return { | ||
| shouldBlock: a, | ||
| blockingIssues: i, | ||
| modalOpen: t, | ||
| tryRunSave: s, | ||
| confirmAndSave: c, | ||
| cancel: l | ||
| }; | ||
| } | ||
| //#endregion | ||
| //#region src/cloud/components/CloudSaveGateModal.vue?vue&type=script&setup=true&lang.ts | ||
| var Ve = ["aria-label"], He = { class: "tpl:flex tpl:max-h-[80vh] tpl:w-full tpl:max-w-md tpl:flex-col tpl:gap-4 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg-elevated)] tpl:p-5 tpl:shadow-[var(--tpl-shadow-md)]" }, Ue = { class: "tpl:flex tpl:items-center tpl:gap-2" }, We = { class: "tpl:m-0 tpl:text-base tpl:font-semibold tpl:text-[var(--tpl-text)]" }, Ge = { class: "tpl:m-0 tpl:text-sm tpl:text-[var(--tpl-text-muted)]" }, Ke = { class: "tpl:m-0 tpl:flex tpl:max-h-64 tpl:list-none tpl:flex-col tpl:gap-1.5 tpl:overflow-y-auto tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-2" }, qe = { class: "tpl:text-xs tpl:text-[var(--tpl-text)]" }, Je = { class: "tpl:font-mono tpl:text-[10px] tpl:text-[var(--tpl-text-dim)]" }, Ye = { class: "tpl:flex tpl:justify-end tpl:gap-2" }, Xe = /* @__PURE__ */ l({ | ||
| __name: "CloudSaveGateModal", | ||
| props: { | ||
| open: { type: Boolean }, | ||
| issues: {} | ||
| }, | ||
| emits: ["cancel", "confirm"], | ||
| setup(t, { emit: n }) { | ||
| let i = n, { t: a } = Q(); | ||
| return (n, o) => (e(), x(T, { | ||
| "enter-active-class": "tpl:transition-opacity tpl:duration-150", | ||
| "leave-active-class": "tpl:transition-opacity tpl:duration-150", | ||
| "enter-from-class": "tpl:opacity-0", | ||
| "leave-to-class": "tpl:opacity-0" | ||
| }, { | ||
| default: O(() => [t.open ? (e(), m("div", { | ||
| key: 0, | ||
| role: "dialog", | ||
| "aria-modal": "true", | ||
| "aria-label": C(a).saveGate.title, | ||
| class: "tpl:fixed tpl:inset-0 tpl:z-50 tpl:flex tpl:items-center tpl:justify-center tpl:bg-black/40 tpl:p-6", | ||
| onClick: o[2] ||= u((e) => i("cancel"), ["self"]) | ||
| }, [f("div", He, [ | ||
| f("header", Ue, [E(C(fe), { | ||
| size: 18, | ||
| "stroke-width": 2, | ||
| class: "tpl:text-[var(--tpl-warning)]" | ||
| }), f("h2", We, w(C(a).saveGate.title), 1)]), | ||
| f("p", Ge, w(C(a).saveGate.body), 1), | ||
| f("ul", Ke, [(e(!0), m(_, null, r(t.issues, (t) => (e(), m("li", { | ||
| key: `${t.ruleId}-${t.blockId ?? "template"}`, | ||
| class: "tpl:flex tpl:flex-col tpl:gap-0.5 tpl:rounded tpl:px-2 tpl:py-1.5" | ||
| }, [f("span", qe, w(t.message), 1), f("span", Je, w(t.ruleId), 1)]))), 128))]), | ||
| f("footer", Ye, [f("button", { | ||
| type: "button", | ||
| class: "tpl:rounded-md tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)]", | ||
| onClick: o[0] ||= (e) => i("cancel") | ||
| }, w(C(a).saveGate.cancel), 1), f("button", { | ||
| type: "button", | ||
| class: "tpl:rounded-md tpl:bg-[var(--tpl-danger)] tpl:px-3 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:text-white", | ||
| onClick: o[1] ||= (e) => i("confirm") | ||
| }, w(C(a).saveGate.confirm), 1)]) | ||
| ])], 8, Ve)) : v("", !0)]), | ||
| _: 1 | ||
| })); | ||
| } | ||
| }), Ze = { | ||
| class: "tpl-header tpl:absolute tpl:top-0 tpl:right-0 tpl:left-0 tpl:z-50 tpl:grid tpl:h-14 tpl:grid-cols-[1fr_auto_1fr] tpl:items-center tpl:px-4", | ||
| style: { | ||
| "background-color": "color-mix(in srgb, var(--tpl-bg) 80%, transparent)", | ||
| "backdrop-filter": "blur(12px)", | ||
| "-webkit-backdrop-filter": "blur(12px)", | ||
| "box-shadow": "var(--tpl-shadow-md)", | ||
| "border-bottom": "1px solid var(--tpl-border)" | ||
| } | ||
| }, Qe = { class: "tpl-header-left tpl:flex tpl:min-w-[200px] tpl:items-center tpl:gap-3" }, $e = { | ||
| key: 0, | ||
| class: "tpl:text-xs tpl:opacity-60 tpl:text-[var(--tpl-text-muted)]" | ||
| }, et = { class: "tpl-header-center tpl:flex tpl:items-center tpl:justify-center tpl:gap-10" }, tt = { class: "tpl-header-right tpl:flex tpl:min-w-[200px] tpl:items-center tpl:justify-end tpl:gap-3" }, nt = ["data-tooltip"], rt = { | ||
| key: 1, | ||
| "aria-live": "polite", | ||
| class: "tpl-status tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:text-[var(--tpl-success)]" | ||
| }, it = { | ||
| key: 2, | ||
| "aria-live": "polite", | ||
| class: "tpl-status tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:text-[var(--tpl-text-muted)]" | ||
| }, at = ["aria-label", "aria-expanded"], ot = { | ||
| key: 0, | ||
| class: "tpl:inline-flex tpl:size-4.5 tpl:items-center tpl:justify-center tpl:rounded-full tpl:text-[10px] tpl:font-semibold tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]" | ||
| }, st = ["aria-expanded"], ct = { | ||
| key: 0, | ||
| class: "tpl:absolute tpl:right-0 tpl:top-full tpl:z-50 tpl:mt-1 tpl:origin-top-right" | ||
| }, lt = ["disabled"], ut = ["disabled"], dt = /* @__PURE__ */ l({ | ||
| __name: "CloudHeader", | ||
| props: { | ||
| editor: {}, | ||
| core: {}, | ||
| featureFlags: {}, | ||
| panelState: {}, | ||
| snapshotPreview: {}, | ||
| commentsInstance: {}, | ||
| testEmail: {}, | ||
| websocket: {}, | ||
| collaboration: {}, | ||
| isCollaborationEnabled: { type: Boolean }, | ||
| isSaveDisabled: { type: Boolean }, | ||
| isSaving: { type: Boolean } | ||
| }, | ||
| emits: ["save"], | ||
| setup(t) { | ||
| let n = D(() => import("./CollaboratorBar-Bc6q0gB9.js")), r = D(() => import("./SnapshotHistory-CIo2Jaw-.js")), i = D(() => import("./AiFeatureMenu-Co14YVJt.js")), { t: a, format: o } = Q(); | ||
| return (l, d) => (e(), m("header", Ze, [ | ||
| f("div", Qe, [t.featureFlags.templateLimit.value === null ? v("", !0) : (e(), m("span", $e, w(C(o)(C(a).header.templatesUsed, { | ||
| used: t.featureFlags.templateCount.value, | ||
| max: t.featureFlags.templateLimit.value | ||
| })), 1))]), | ||
| f("div", et, [ | ||
| E(q, { | ||
| viewport: t.editor.state.viewport, | ||
| onChange: t.editor.setViewport | ||
| }, null, 8, ["viewport", "onChange"]), | ||
| E(oe, { | ||
| "dark-mode": t.editor.state.darkMode, | ||
| onChange: t.editor.setDarkMode | ||
| }, null, 8, ["dark-mode", "onChange"]), | ||
| E(J, { | ||
| "preview-mode": t.editor.state.previewMode, | ||
| onChange: t.editor.setPreviewMode | ||
| }, null, 8, ["preview-mode", "onChange"]), | ||
| t.collaboration && t.isCollaborationEnabled ? (e(), x(C(n), { | ||
| key: 0, | ||
| collaborators: t.collaboration.collaborators.value, | ||
| "is-connected": t.websocket.isConnected.value | ||
| }, null, 8, ["collaborators", "is-connected"])) : v("", !0), | ||
| t.snapshotPreview.snapshotHistoryInstance.value ? (e(), x(C(r), { | ||
| key: 1, | ||
| snapshots: t.snapshotPreview.snapshotHistorySnapshots.value, | ||
| "is-loading": t.snapshotPreview.snapshotHistoryIsLoading.value, | ||
| "is-restoring": t.snapshotPreview.snapshotHistoryIsRestoring.value, | ||
| onLoad: t.snapshotPreview.loadSnapshotHistory, | ||
| onNavigate: t.snapshotPreview.handleSnapshotNavigate | ||
| }, null, 8, [ | ||
| "snapshots", | ||
| "is-loading", | ||
| "is-restoring", | ||
| "onLoad", | ||
| "onNavigate" | ||
| ])) : v("", !0) | ||
| ]), | ||
| f("div", tt, [ | ||
| t.featureFlags.saveStatus.value === "error" ? (e(), m("div", { | ||
| key: 0, | ||
| "aria-live": "assertive", | ||
| class: "tpl-tooltip tpl-status tpl:flex tpl:items-center tpl:gap-1.5 tpl:text-xs tpl:text-[var(--tpl-danger)]", | ||
| "data-tooltip": t.featureFlags.saveErrorMessage.value | ||
| }, [E(C(K), { | ||
| size: 12, | ||
| "stroke-width": 2.5 | ||
| }), s(" " + w(C(a).header.saveFailed), 1)], 8, nt)) : t.featureFlags.saveStatus.value === "saved" ? (e(), m("div", rt, [E(C(G), { | ||
| size: 12, | ||
| "stroke-width": 2.5 | ||
| }), s(" " + w(C(a).header.saved), 1)])) : t.editor.state.isDirty ? (e(), m("div", it, [d[4] ||= f("span", { class: "tpl-pulse tpl:size-1.5 tpl:rounded-full tpl:bg-[var(--tpl-primary)]" }, null, -1), s(" " + w(C(a).header.unsaved), 1)])) : v("", !0), | ||
| t.commentsInstance.isEnabled.value && t.featureFlags.hasTemplateSaved.value ? (e(), m("button", { | ||
| key: 3, | ||
| "aria-label": t.commentsInstance.unresolvedCount.value > 0 ? `${C(a).comments.button} (${t.commentsInstance.unresolvedCount.value})` : C(a).comments.button, | ||
| "aria-expanded": t.panelState.commentsOpen.value, | ||
| class: c(C($)), | ||
| style: b({ | ||
| backgroundColor: t.panelState.commentsOpen.value ? "var(--tpl-primary)" : "transparent", | ||
| color: t.panelState.commentsOpen.value ? "var(--tpl-bg)" : "var(--tpl-primary)", | ||
| borderColor: "var(--tpl-primary)" | ||
| }), | ||
| onClick: d[0] ||= (e) => t.panelState.commentsOpen.value = !t.panelState.commentsOpen.value | ||
| }, [ | ||
| E(C(X), { | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| }), | ||
| s(" " + w(C(a).comments.button) + " ", 1), | ||
| t.commentsInstance.unresolvedCount.value > 0 && !t.panelState.commentsOpen.value ? (e(), m("span", ot, w(t.commentsInstance.unresolvedCount.value), 1)) : v("", !0) | ||
| ], 14, at)) : v("", !0), | ||
| t.featureFlags.canUseAiGeneration.value && t.featureFlags.hasTemplateSaved.value ? (e(), m("div", { | ||
| key: 4, | ||
| ref: (e) => t.panelState.aiMenuRef.value = e, | ||
| class: "tpl:relative" | ||
| }, [f("button", { | ||
| "aria-expanded": t.panelState.aiMenuOpen.value, | ||
| class: c(["tpl-ai-btn tpl:inline-flex tpl:items-center tpl:gap-1.5 tpl:rounded-[var(--tpl-radius-sm)] tpl:border-none tpl:px-4 tpl:py-2 tpl:text-sm tpl:font-semibold tpl:whitespace-nowrap tpl:transition-all tpl:duration-200", t.panelState.aiButtonActive.value ? "tpl-ai-btn--active" : "tpl-ai-btn--idle"]), | ||
| onClick: d[1] ||= u((...e) => t.panelState.toggleAiMenu && t.panelState.toggleAiMenu(...e), ["stop"]) | ||
| }, [E(C(de), { | ||
| size: 16, | ||
| "stroke-width": 2, | ||
| class: "tpl-ai-btn-icon" | ||
| }), s(" " + w(C(a).aiChat.button), 1)], 10, st), E(T, { | ||
| "enter-active-class": "tpl:transition-all tpl:duration-150 tpl:ease-out", | ||
| "enter-from-class": "tpl:scale-95 tpl:opacity-0", | ||
| "enter-to-class": "tpl:scale-100 tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-all tpl:duration-100 tpl:ease-in", | ||
| "leave-from-class": "tpl:scale-100 tpl:opacity-100", | ||
| "leave-to-class": "tpl:scale-95 tpl:opacity-0" | ||
| }, { | ||
| default: O(() => [t.panelState.aiMenuOpen.value ? (e(), m("div", ct, [E(C(i), { | ||
| "active-feature": t.panelState.activeAiFeature.value, | ||
| onSelect: t.panelState.handleAiFeatureSelect | ||
| }, null, 8, ["active-feature", "onSelect"])])) : v("", !0)]), | ||
| _: 1 | ||
| })], 512)) : v("", !0), | ||
| t.testEmail.isEnabled.value && t.featureFlags.canSendTestEmail.value ? (e(), m("button", { | ||
| key: 5, | ||
| class: c(C($)), | ||
| style: { | ||
| "background-color": "transparent", | ||
| color: "var(--tpl-primary)", | ||
| "border-color": "var(--tpl-primary)" | ||
| }, | ||
| disabled: t.testEmail.isSending.value || !t.featureFlags.hasTemplateSaved.value, | ||
| onClick: d[2] ||= (e) => t.panelState.testEmailModalOpen.value = !0 | ||
| }, [t.testEmail.isSending.value ? (e(), x(C(Y), { | ||
| key: 1, | ||
| class: "tpl-spinner", | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })) : (e(), x(C(Z), { | ||
| key: 0, | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })), s(" " + w(C(a).testEmail.button), 1)], 10, lt)) : v("", !0), | ||
| f("button", { | ||
| class: c(C($)), | ||
| style: { | ||
| "background-color": "transparent", | ||
| color: "var(--tpl-primary)", | ||
| "border-color": "var(--tpl-primary)" | ||
| }, | ||
| disabled: t.isSaveDisabled, | ||
| onClick: d[3] ||= (e) => l.$emit("save") | ||
| }, [t.isSaving ? (e(), x(C(Y), { | ||
| key: 1, | ||
| class: "tpl-spinner", | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })) : (e(), x(C(je), { | ||
| key: 0, | ||
| size: 16, | ||
| "stroke-width": 2 | ||
| })), s(" " + w(t.isSaving ? C(a).header.saving : C(a).header.save), 1)], 10, ut) | ||
| ]) | ||
| ])); | ||
| } | ||
| }), ft = /* @__PURE__ */ l({ | ||
| __name: "CloudPanels", | ||
| props: { | ||
| config: {}, | ||
| editor: {}, | ||
| core: {}, | ||
| panelState: {}, | ||
| planConfigInstance: {}, | ||
| testEmail: {}, | ||
| mediaLib: {}, | ||
| savedModulesHeadless: {}, | ||
| showSaveModuleDialog: { type: Boolean }, | ||
| saveModulePreSelectedBlockId: {}, | ||
| showModuleBrowserModal: { type: Boolean } | ||
| }, | ||
| emits: [ | ||
| "update:showSaveModuleDialog", | ||
| "update:saveModulePreSelectedBlockId", | ||
| "update:showModuleBrowserModal", | ||
| "send-test-email", | ||
| "module-insert" | ||
| ], | ||
| setup(t, { expose: n, emit: r }) { | ||
| let i = D(() => import("./AiChatSidebar-BUKj9n02.js")), a = D(() => import("./CommentsSidebar-DiH4R4F0.js")), s = D(() => import("./DesignReferenceSidebar-BP32MgpS.js")), c = D(() => import("./TemplateScoringPanel-seBvvn8O.js")), l = D(() => import("./TestEmailModal-BuCuWp3N.js")), u = D(() => import("./SaveModuleDialog-DWidA0c9.js")), d = D(() => import("./ModuleBrowserModal-CWegFoOA.js")), f = D(async () => { | ||
| try { | ||
| return (await import("@templatical/media-library")).MediaLibraryModal; | ||
| } catch { | ||
| throw Error("[Templatical] Cloud media library requires the optional peer dependency '@templatical/media-library'. Please install it."); | ||
| } | ||
| }), p = r; | ||
| function h(e, t, n) { | ||
| t.history.record(), n.setContent(e), t.conditionPreview.reset(); | ||
| } | ||
| function g(e, t) { | ||
| p("module-insert", e, t); | ||
| } | ||
| let y = o(null); | ||
| function b(e) { | ||
| y.value?.filterByBlock(e); | ||
| } | ||
| return n({ filterCommentsByBlock: b }), (n, r) => (e(), m(_, null, [ | ||
| E(C(i), { | ||
| visible: t.panelState.aiChatOpen.value, | ||
| "on-apply": (e) => h(e, t.core, t.editor), | ||
| onClose: r[0] ||= (e) => t.panelState.aiChatOpen.value = !1 | ||
| }, null, 8, ["visible", "on-apply"]), | ||
| E(C(c), { | ||
| visible: t.panelState.scoringPanelOpen.value, | ||
| onClose: r[1] ||= (e) => t.panelState.scoringPanelOpen.value = !1 | ||
| }, null, 8, ["visible"]), | ||
| E(C(s), { | ||
| visible: t.panelState.designReferenceOpen.value, | ||
| "has-existing-blocks": t.editor.content.value.blocks.length > 0, | ||
| onClose: r[2] ||= (e) => t.panelState.designReferenceOpen.value = !1, | ||
| onApply: r[3] ||= (e) => h(e, t.core, t.editor) | ||
| }, null, 8, ["visible", "has-existing-blocks"]), | ||
| E(C(a), { | ||
| ref_key: "commentsSidebar", | ||
| ref: y, | ||
| visible: t.panelState.commentsOpen.value, | ||
| onClose: r[4] ||= (e) => t.panelState.commentsOpen.value = !1 | ||
| }, null, 8, ["visible"]), | ||
| E(C(l), { | ||
| visible: t.panelState.testEmailModalOpen.value, | ||
| "allowed-emails": t.testEmail.allowedEmails.value, | ||
| "is-sending": t.testEmail.isSending.value, | ||
| error: t.testEmail.error.value, | ||
| onSend: r[5] ||= (e) => p("send-test-email", e), | ||
| onClose: r[6] ||= (e) => t.panelState.testEmailModalOpen.value = !1 | ||
| }, null, 8, [ | ||
| "visible", | ||
| "allowed-emails", | ||
| "is-sending", | ||
| "error" | ||
| ]), | ||
| t.planConfigInstance.hasFeature("saved_modules") && t.config.modules !== !1 ? (e(), x(C(u), { | ||
| key: 0, | ||
| visible: t.showSaveModuleDialog, | ||
| "pre-selected-block-id": t.saveModulePreSelectedBlockId, | ||
| onClose: r[7] ||= (e) => { | ||
| p("update:showSaveModuleDialog", !1), p("update:saveModulePreSelectedBlockId", null); | ||
| }, | ||
| onSaved: r[8] ||= (e) => t.savedModulesHeadless.loadModules() | ||
| }, null, 8, ["visible", "pre-selected-block-id"])) : v("", !0), | ||
| t.planConfigInstance.hasFeature("saved_modules") && t.config.modules !== !1 ? (e(), x(C(d), { | ||
| key: 1, | ||
| visible: t.showModuleBrowserModal, | ||
| onClose: r[9] ||= (e) => p("update:showModuleBrowserModal", !1), | ||
| onInsert: g | ||
| }, null, 8, ["visible"])) : v("", !0), | ||
| E(C(f), { | ||
| visible: t.panelState.mediaLibraryOpen.value, | ||
| accept: t.panelState.mediaLibraryAccept.value, | ||
| "popover-target": t.core.popoverRoot.value, | ||
| onSelect: t.mediaLib.handleMediaSelect, | ||
| onClose: t.mediaLib.handleMediaLibraryClose | ||
| }, null, 8, [ | ||
| "visible", | ||
| "accept", | ||
| "popover-target", | ||
| "onSelect", | ||
| "onClose" | ||
| ]) | ||
| ], 64)); | ||
| } | ||
| }), pt = { | ||
| key: 0, | ||
| class: "tpl-loading tpl:absolute tpl:inset-0 tpl:z-overlay tpl:flex tpl:flex-col tpl:bg-[var(--tpl-bg)]" | ||
| }, mt = { class: "tpl:flex tpl:flex-1 tpl:overflow-hidden" }, ht = { class: "tpl:flex tpl:w-12 tpl:shrink-0 tpl:flex-col tpl:items-center tpl:gap-4 tpl:py-5 tpl:border-r tpl:border-[var(--tpl-border)]" }, gt = /* @__PURE__ */ l({ | ||
| __name: "CloudLoadingOverlay", | ||
| props: { visible: { type: Boolean } }, | ||
| setup(t) { | ||
| return (n, i) => t.visible ? (e(), m("div", pt, [i[1] ||= p("<div class=\"tpl:flex tpl:h-14 tpl:shrink-0 tpl:items-center tpl:justify-between tpl:px-4 tpl:border-b tpl:border-[var(--tpl-border)]\"><div class=\"tpl-shimmer tpl:h-5 tpl:w-28 tpl:rounded-[var(--tpl-radius-sm)]\"></div><div class=\"tpl:flex tpl:gap-3\"><div class=\"tpl-shimmer tpl:h-8 tpl:w-20 tpl:rounded-[var(--tpl-radius-sm)]\"></div><div class=\"tpl-shimmer tpl:h-8 tpl:w-20 tpl:rounded-[var(--tpl-radius-sm)]\"></div></div></div>", 1), f("div", mt, [f("div", ht, [(e(), m(_, null, r(5, (e) => f("div", { | ||
| key: e, | ||
| class: "tpl-shimmer tpl:size-7 tpl:rounded-[var(--tpl-radius-sm)]" | ||
| })), 64))]), i[0] ||= p("<div class=\"tpl:flex tpl:flex-1 tpl:items-start tpl:justify-center tpl:overflow-auto tpl:p-8 tpl:bg-[var(--tpl-canvas-bg)]\"><div class=\"tpl:w-full tpl:max-w-[600px] tpl:rounded-[var(--tpl-radius)] tpl:p-6 tpl:bg-[var(--tpl-bg)] tpl:shadow-[var(--tpl-shadow-sm)]\"><div class=\"tpl:space-y-2 tpl:py-4\"><div class=\"tpl-shimmer tpl:h-3 tpl:w-3/4 tpl:rounded\"></div><div class=\"tpl-shimmer tpl:h-3 tpl:w-full tpl:rounded\"></div><div class=\"tpl-shimmer tpl:h-3 tpl:w-5/6 tpl:rounded\"></div></div><div class=\"tpl:py-4\"><div class=\"tpl-shimmer tpl:h-44 tpl:w-full tpl:rounded-[var(--tpl-radius-sm)]\"></div></div><div class=\"tpl:space-y-2 tpl:py-4\"><div class=\"tpl-shimmer tpl:h-3 tpl:w-full tpl:rounded\"></div><div class=\"tpl-shimmer tpl:h-3 tpl:w-2/3 tpl:rounded\"></div></div><div class=\"tpl:flex tpl:justify-center tpl:py-4\"><div class=\"tpl-shimmer tpl:h-10 tpl:w-36 tpl:rounded-[var(--tpl-radius-sm)]\"></div></div><div class=\"tpl:space-y-2 tpl:py-4\"><div class=\"tpl-shimmer tpl:mx-auto tpl:h-2.5 tpl:w-1/2 tpl:rounded\"></div><div class=\"tpl-shimmer tpl:mx-auto tpl:h-2.5 tpl:w-1/3 tpl:rounded\"></div></div></div></div><div class=\"tpl:flex tpl:w-[320px] tpl:shrink-0 tpl:flex-col tpl:gap-4 tpl:p-4 tpl:border-l tpl:border-[var(--tpl-border)]\"><div class=\"tpl-shimmer tpl:h-8 tpl:rounded-[var(--tpl-radius-sm)]\"></div><div class=\"tpl-shimmer tpl:h-32 tpl:rounded-[var(--tpl-radius)]\"></div><div class=\"tpl-shimmer tpl:h-32 tpl:rounded-[var(--tpl-radius)]\"></div></div>", 2)])])) : v("", !0); | ||
| } | ||
| }), _t = { | ||
| key: 0, | ||
| role: "alert", | ||
| class: "tpl-error tpl:absolute tpl:inset-0 tpl:z-overlay tpl:flex tpl:flex-col tpl:items-center tpl:justify-center tpl:gap-6 tpl:px-8 tpl:bg-[var(--tpl-bg)]" | ||
| }, vt = { class: "tpl:flex tpl:size-16 tpl:items-center tpl:justify-center tpl:rounded-full tpl:bg-[var(--tpl-danger-light)]" }, yt = { class: "tpl:flex tpl:flex-col tpl:items-center tpl:gap-2 tpl:text-center" }, bt = { class: "tpl:text-lg tpl:font-semibold tpl:text-[var(--tpl-text)]" }, xt = { class: "tpl:max-w-md tpl:text-sm tpl:text-[var(--tpl-text-muted)]" }, St = /* @__PURE__ */ l({ | ||
| __name: "CloudErrorOverlay", | ||
| props: { | ||
| error: {}, | ||
| visible: { type: Boolean } | ||
| }, | ||
| emits: ["retry"], | ||
| setup(t, { emit: n }) { | ||
| let r = n, { t: i } = Q(); | ||
| function a(e) { | ||
| return "isUnauthorized" in e && e.isUnauthorized ? i.error.authFailed : "isNotFound" in e && e.isNotFound ? i.error.templateNotFound : i.error.defaultMessage; | ||
| } | ||
| function o(e) { | ||
| return "isNotFound" in e && !!e.isNotFound; | ||
| } | ||
| return (n, s) => t.visible && t.error ? (e(), m("div", _t, [ | ||
| f("div", vt, [E(C(K), { | ||
| size: 32, | ||
| "stroke-width": 1.5, | ||
| class: "tpl:text-[var(--tpl-danger)]" | ||
| })]), | ||
| f("div", yt, [f("h2", bt, w(C(i).error.title), 1), f("p", xt, w(a(t.error)), 1)]), | ||
| o(t.error) ? v("", !0) : (e(), m("button", { | ||
| key: 0, | ||
| class: "tpl-btn tpl-btn-primary tpl:inline-flex tpl:items-center tpl:gap-2 tpl:rounded-md tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:font-medium tpl:shadow-xs tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]", | ||
| onClick: s[0] ||= (e) => r("retry") | ||
| }, w(C(i).error.retry), 1)) | ||
| ])) : v("", !0); | ||
| } | ||
| }), Ct = { | ||
| key: 0, | ||
| class: "tpl-preview-banner tpl:absolute tpl:top-14 tpl:right-0 tpl:left-0 tpl:z-40 tpl:flex tpl:items-center tpl:justify-center tpl:gap-4 tpl:px-4 tpl:py-3 tpl:bg-[var(--tpl-primary-light)] tpl:border-b tpl:border-[var(--tpl-primary)]" | ||
| }, wt = { class: "tpl:flex tpl:items-center tpl:gap-2 tpl:text-sm tpl:text-[var(--tpl-text)]" }, Tt = { class: "tpl:flex tpl:items-center tpl:gap-2" }, Et = /* @__PURE__ */ l({ | ||
| __name: "SnapshotPreviewBanner", | ||
| props: { visible: { type: Boolean } }, | ||
| emits: ["cancel", "confirm"], | ||
| setup(t, { emit: n }) { | ||
| let r = n, { t: i } = Q(); | ||
| return (n, a) => t.visible ? (e(), m("div", Ct, [f("div", wt, [E(C(ue), { | ||
| size: 18, | ||
| "stroke-width": 2, | ||
| class: "tpl:text-[var(--tpl-primary)]" | ||
| }), f("span", null, w(C(i).snapshotPreview.message), 1)]), f("div", Tt, [f("button", { | ||
| class: "tpl:rounded-md tpl:px-3 tpl:py-1.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:text-[var(--tpl-text-muted)] tpl:border tpl:border-[var(--tpl-border)]", | ||
| style: { "background-color": "transparent" }, | ||
| onClick: a[0] ||= (e) => r("cancel") | ||
| }, w(C(i).snapshotPreview.cancel), 1), f("button", { | ||
| class: "tpl:rounded-md tpl:px-3 tpl:py-1.5 tpl:text-sm tpl:font-medium tpl:transition-all tpl:duration-150 tpl:hover:opacity-90 tpl:bg-[var(--tpl-primary)] tpl:text-[var(--tpl-bg)]", | ||
| onClick: a[1] ||= (e) => r("confirm") | ||
| }, w(C(i).snapshotPreview.restore), 1)])])) : v("", !0); | ||
| } | ||
| }), Dt = { | ||
| key: 0, | ||
| role: "status", | ||
| "aria-live": "polite", | ||
| class: "tpl:absolute tpl:top-16 tpl:left-1/2 tpl:z-toast tpl:-translate-x-1/2 tpl:rounded-[var(--tpl-radius)] tpl:px-4 tpl:py-2.5 tpl:text-sm tpl:shadow-lg", | ||
| style: { | ||
| "background-color": "var(--tpl-warning-light)", | ||
| color: "var(--tpl-text)", | ||
| border: "1px solid var(--tpl-warning)" | ||
| } | ||
| }, Ot = /* @__PURE__ */ l({ | ||
| __name: "CollabUndoToast", | ||
| props: { visible: { type: Boolean } }, | ||
| setup(t) { | ||
| let { t: n } = U(); | ||
| return (r, i) => t.visible ? (e(), m("div", Dt, w(C(n).history.collabWarning), 1)) : v("", !0); | ||
| } | ||
| }), kt = ["data-tpl-theme"], At = { class: "tpl:sticky tpl:top-0 tpl:z-40 tpl:h-0" }, jt = { class: "tpl-main tpl:flex tpl:justify-center tpl:p-8" }, Mt = ["aria-label"], Nt = /* @__PURE__ */ pe(/* @__PURE__ */ l({ | ||
| __name: "CloudEditor", | ||
| props: { | ||
| config: {}, | ||
| translations: {}, | ||
| cloudTranslations: {}, | ||
| fontsManager: {}, | ||
| shadowRoot: {} | ||
| }, | ||
| emits: ["ready"], | ||
| setup(n, { expose: r, emit: a }) { | ||
| let l = n; | ||
| h(B, l.cloudTranslations); | ||
| let u = a, d = o(null), p = o(null), _ = Le({ | ||
| config: l.config, | ||
| translations: l.translations, | ||
| fontsManager: l.fontsManager, | ||
| emit: u, | ||
| getCommentsSidebar: () => d.value ? { filterByBlock: d.value.filterCommentsByBlock } : null, | ||
| editorRoot: l.shadowRoot, | ||
| containerEl: p | ||
| }), { isInitializing: S, isAuthReady: D, initError: k, planConfigInstance: A, websocket: M, collaboration: N, isCollaborationEnabled: P, editor: F, core: I, featureFlags: L, mediaLib: R, exporter: z, testEmail: V, commentsInstance: ee, savedModulesHeadless: te, panelState: H, snapshotPreview: U, collabWarning: W, showSaveModuleDialog: G, showModuleBrowserModal: K, saveModulePreSelectedBlockId: q, setThemeOverrides: J, setUiTheme: re } = _; | ||
| async function oe(e) { | ||
| try { | ||
| await V.sendTestEmail(e), H.testEmailModalOpen.value = !1; | ||
| } catch {} | ||
| } | ||
| function ue(e, t) { | ||
| for (let n = 0; n < e.content.length; n++) { | ||
| let r = j(e.content[n]), i = t === void 0 ? void 0 : t + n; | ||
| F.addBlock(r, void 0, void 0, i); | ||
| } | ||
| K.value = !1; | ||
| } | ||
| let Y = ze({ | ||
| config: l.config, | ||
| editor: F, | ||
| websocket: M, | ||
| planConfigInstance: A, | ||
| snapshotPreview: U, | ||
| core: I, | ||
| exporter: z, | ||
| featureFlags: L, | ||
| isDestroyed: _.isDestroyed | ||
| }), X = Be({ | ||
| issues: I.templateLint ? I.templateLint.issues : o([]), | ||
| planConfig: A.config | ||
| }); | ||
| async function Z() { | ||
| await X.tryRunSave(() => Y.saveTemplate().catch((e) => l.config.onError?.(e))); | ||
| } | ||
| return _.onSaveHook.value = Z, i(() => { | ||
| _.initialize(); | ||
| }), g(() => { | ||
| _.destroy(); | ||
| }), r({ | ||
| getContent: () => F.content.value, | ||
| setContent: (e) => F.setContent(e), | ||
| setTheme: re, | ||
| setThemeOverrides: J, | ||
| create: Y.createTemplate, | ||
| load: Y.loadTemplate, | ||
| save: Y.saveTemplate, | ||
| sendTestEmail: V.sendTestEmail | ||
| }), (r, i) => (e(), m("div", { | ||
| ref_key: "rootEl", | ||
| ref: p, | ||
| class: c(["tpl tpl:relative tpl:h-full tpl:overflow-hidden", { "tpl:dark": C(F).state.darkMode }]), | ||
| "data-tpl-theme": C(I).resolvedTheme.value, | ||
| style: b(C(I).themeStyles.value) | ||
| }, [ | ||
| E(T, { | ||
| "enter-active-class": "tpl:transition-opacity tpl:duration-200", | ||
| "enter-from-class": "tpl:opacity-100", | ||
| "enter-to-class": "tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-opacity tpl:duration-300", | ||
| "leave-from-class": "tpl:opacity-100", | ||
| "leave-to-class": "tpl:opacity-0" | ||
| }, { | ||
| default: O(() => [E(gt, { visible: C(S) || C(F).state.isLoading }, null, 8, ["visible"])]), | ||
| _: 1 | ||
| }), | ||
| E(T, { | ||
| "enter-active-class": "tpl:transition-opacity tpl:duration-200", | ||
| "enter-from-class": "tpl:opacity-0", | ||
| "enter-to-class": "tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-opacity tpl:duration-300", | ||
| "leave-from-class": "tpl:opacity-100", | ||
| "leave-to-class": "tpl:opacity-0" | ||
| }, { | ||
| default: O(() => [E(St, { | ||
| error: C(k), | ||
| visible: !!C(k) && !C(S), | ||
| onRetry: C(_).initialize | ||
| }, null, 8, [ | ||
| "error", | ||
| "visible", | ||
| "onRetry" | ||
| ])]), | ||
| _: 1 | ||
| }), | ||
| E(dt, { | ||
| editor: C(F), | ||
| core: C(I), | ||
| "feature-flags": C(L), | ||
| "panel-state": C(H), | ||
| "snapshot-preview": C(U), | ||
| "comments-instance": C(ee), | ||
| "test-email": C(V), | ||
| websocket: C(M), | ||
| collaboration: C(N), | ||
| "is-collaboration-enabled": C(P), | ||
| "is-saving": C(F).state.isSaving || C(L).isSaveExporting.value, | ||
| "is-save-disabled": C(F).state.isSaving || C(L).isSaveExporting.value || !C(F).state.isDirty, | ||
| onSave: Z | ||
| }, null, 8, [ | ||
| "editor", | ||
| "core", | ||
| "feature-flags", | ||
| "panel-state", | ||
| "snapshot-preview", | ||
| "comments-instance", | ||
| "test-email", | ||
| "websocket", | ||
| "collaboration", | ||
| "is-collaboration-enabled", | ||
| "is-saving", | ||
| "is-save-disabled" | ||
| ]), | ||
| E(Xe, { | ||
| open: C(X).modalOpen.value, | ||
| issues: C(X).blockingIssues.value, | ||
| onCancel: C(X).cancel, | ||
| onConfirm: C(X).confirmAndSave | ||
| }, null, 8, [ | ||
| "open", | ||
| "issues", | ||
| "onCancel", | ||
| "onConfirm" | ||
| ]), | ||
| E(Et, { | ||
| visible: C(U).isPreviewingSnapshot.value, | ||
| onCancel: C(U).cancelPreview, | ||
| onConfirm: C(U).confirmRestoreSnapshot | ||
| }, null, 8, [ | ||
| "visible", | ||
| "onCancel", | ||
| "onConfirm" | ||
| ]), | ||
| E(T, { | ||
| "enter-active-class": "tpl:transition-all tpl:duration-200 tpl:ease-out", | ||
| "enter-from-class": "tpl:translate-y-[-8px] tpl:opacity-0", | ||
| "enter-to-class": "tpl:translate-y-0 tpl:opacity-100", | ||
| "leave-active-class": "tpl:transition-all tpl:duration-300 tpl:ease-in", | ||
| "leave-from-class": "tpl:translate-y-0 tpl:opacity-100", | ||
| "leave-to-class": "tpl:translate-y-[-8px] tpl:opacity-0" | ||
| }, { | ||
| default: O(() => [E(Ot, { visible: C(W).collabUndoWarningVisible.value }, null, 8, ["visible"])]), | ||
| _: 1 | ||
| }), | ||
| t(E(se, null, null, 512), [[y, !C(F).state.previewMode]]), | ||
| f("div", { | ||
| class: c(["tpl-body tpl:absolute tpl:bottom-0 tpl:overflow-auto", [C(F).state.previewMode ? "tpl:left-0 tpl:right-0" : C(H).rightPanelOpen.value ? "tpl:left-12 tpl:right-[680px]" : "tpl:left-12 tpl:right-[320px]", C(U).isPreviewingSnapshot.value ? "tpl:top-[104px]" : "tpl:top-14"]]), | ||
| style: { | ||
| transition: "all 300ms cubic-bezier(0.34, 1.56, 0.64, 1)", | ||
| "background-color": "var(--tpl-canvas-bg)" | ||
| } | ||
| }, [f("div", At, [E(T, { name: "tpl-restore-btn" }, { | ||
| default: O(() => [C(I).conditionPreview.hasHiddenBlocks.value ? (e(), m("button", { | ||
| key: 0, | ||
| class: "tpl:absolute tpl:left-1/2 tpl:top-2 tpl:-translate-x-1/2 tpl:inline-flex tpl:items-center tpl:gap-1.5 tpl:rounded-full tpl:border tpl:px-3.5 tpl:py-1.5 tpl:text-xs tpl:font-medium tpl:whitespace-nowrap tpl:shadow-md tpl:hover:opacity-80", | ||
| style: { | ||
| "background-color": "var(--tpl-warning-light)", | ||
| color: "var(--tpl-warning)", | ||
| "border-color": "var(--tpl-warning)", | ||
| "backdrop-filter": "blur(8px)" | ||
| }, | ||
| onClick: i[0] ||= (e) => C(I).conditionPreview.reset() | ||
| }, [E(C(le), { | ||
| size: 13, | ||
| "stroke-width": 2 | ||
| }), s(" " + w(C(I).t.blockSettings.restoreHiddenBlocks), 1)])) : v("", !0)]), | ||
| _: 1 | ||
| })]), f("main", jt, [E(ne, { | ||
| viewport: C(F).state.viewport, | ||
| content: C(F).content.value, | ||
| "selected-block-id": C(F).state.selectedBlockId, | ||
| "dark-mode": C(F).state.darkMode, | ||
| "preview-mode": C(F).state.previewMode, | ||
| "locked-blocks": C(N)?.lockedBlocks.value ?? void 0, | ||
| onSelectBlock: C(F).selectBlock, | ||
| onOpenAiChat: i[1] ||= (e) => C(H).aiChatOpen.value = !0, | ||
| onOpenDesignReference: i[2] ||= (e) => C(H).designReferenceOpen.value = !0 | ||
| }, null, 8, [ | ||
| "viewport", | ||
| "content", | ||
| "selected-block-id", | ||
| "dark-mode", | ||
| "preview-mode", | ||
| "locked-blocks", | ||
| "onSelectBlock" | ||
| ])])], 2), | ||
| n.config.branding !== !1 && !C(L).isWhiteLabeled.value ? (e(), x(ie, { | ||
| key: 0, | ||
| "position-class": [C(F).state.previewMode ? "tpl:left-0 tpl:right-0" : C(H).rightPanelOpen.value ? "tpl:left-12 tpl:right-[680px]" : "tpl:left-12 tpl:right-[320px]"] | ||
| }, null, 8, ["position-class"])) : v("", !0), | ||
| f("div", { | ||
| class: "tpl-sr-only", | ||
| role: "status", | ||
| "aria-live": "polite", | ||
| "aria-atomic": "true", | ||
| "aria-label": C(I).t.landmarks.reorderAnnouncements | ||
| }, w(C(I).keyboardReorder.announcement.value), 9, Mt), | ||
| t(E(ae, { | ||
| "selected-block": C(F).selectedBlock.value, | ||
| settings: C(F).content.value.settings, | ||
| "shifted-left": C(H).rightPanelOpen.value, | ||
| onUpdateBlock: i[3] ||= (e) => C(F).updateBlock(C(F).selectedBlock.value.id, e), | ||
| onDeleteBlock: i[4] ||= (e) => C(I).blockActions.deleteBlock(C(F).selectedBlock.value.id), | ||
| onDuplicateBlock: i[5] ||= (e) => C(I).blockActions.duplicateBlock(C(F).selectedBlock.value), | ||
| onUpdateSettings: C(F).updateSettings | ||
| }, null, 8, [ | ||
| "selected-block", | ||
| "settings", | ||
| "shifted-left", | ||
| "onUpdateSettings" | ||
| ]), [[y, !C(F).state.previewMode]]), | ||
| !C(S) && C(D) ? (e(), x(ft, { | ||
| key: 1, | ||
| ref_key: "cloudPanelsRef", | ||
| ref: d, | ||
| config: l.config, | ||
| editor: C(F), | ||
| core: C(I), | ||
| "panel-state": C(H), | ||
| "plan-config-instance": C(A), | ||
| "test-email": C(V), | ||
| "media-lib": C(R), | ||
| "saved-modules-headless": C(te), | ||
| "show-save-module-dialog": C(G), | ||
| "save-module-pre-selected-block-id": C(q), | ||
| "show-module-browser-modal": C(K), | ||
| "onUpdate:showSaveModuleDialog": i[6] ||= (e) => G.value = e, | ||
| "onUpdate:saveModulePreSelectedBlockId": i[7] ||= (e) => q.value = e, | ||
| "onUpdate:showModuleBrowserModal": i[8] ||= (e) => K.value = e, | ||
| onSendTestEmail: oe, | ||
| onModuleInsert: ue | ||
| }, null, 8, [ | ||
| "config", | ||
| "editor", | ||
| "core", | ||
| "panel-state", | ||
| "plan-config-instance", | ||
| "test-email", | ||
| "media-lib", | ||
| "saved-modules-headless", | ||
| "show-save-module-dialog", | ||
| "save-module-pre-selected-block-id", | ||
| "show-module-browser-modal" | ||
| ])) : v("", !0), | ||
| f("div", { | ||
| ref: (e) => C(I).popoverRoot.value = e, | ||
| class: "tpl-popover-root" | ||
| }, null, 512), | ||
| E(ce) | ||
| ], 14, kt)); | ||
| } | ||
| }), [["__scopeId", "data-v-3f0f5cfa"]]); | ||
| //#endregion | ||
| export { Nt as default }; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
9344294
0.02%96237
0