@fonderie/vue-courier-admin-screens 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/index.cjs +43 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +44 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Pre-built Vue 3 screens for the Fonderie courier admin API —
|
|
4
4
|
`TemplateListScreen` and `TemplateEditorScreen` — built on
|
|
5
|
-
[`@fonderie/vue-courier-admin`](https://github.com/fonderiejs/
|
|
5
|
+
[`@fonderie/vue-courier-admin`](https://github.com/fonderiejs/fonderie/tree/main/packages/vue-courier-admin)
|
|
6
6
|
composables. Plain HTML elements via Vue's `h()` render function, inline
|
|
7
7
|
styles you can override, zero UI library dependency.
|
|
8
8
|
|
|
@@ -43,7 +43,7 @@ directly.
|
|
|
43
43
|
You've shipped this plumbing before — auth, teams, billing, messaging —
|
|
44
44
|
and the next project will ask for it again. Fonderie packages it once:
|
|
45
45
|
plain TypeScript modules for
|
|
46
|
-
[`@fonderie/core`](https://github.com/fonderiejs/
|
|
46
|
+
[`@fonderie/core`](https://github.com/fonderiejs/fonderie/tree/main/packages/core),
|
|
47
47
|
PostgreSQL-backed, self-hosted, MIT. No external control plane, no
|
|
48
48
|
per-seat anything. Register the modules you need; skip the ones you don't.
|
|
49
49
|
|
|
@@ -53,7 +53,7 @@ design system whenever you outgrow it — `@fonderie/vue-courier-admin`'s
|
|
|
53
53
|
composables work standalone.
|
|
54
54
|
|
|
55
55
|
Browse the whole set at
|
|
56
|
-
[fonderiejs/
|
|
56
|
+
[fonderiejs/fonderie](https://github.com/fonderiejs/fonderie) · follow
|
|
57
57
|
[@fonderiejs](https://x.com/fonderiejs)
|
|
58
58
|
|
|
59
59
|
## License
|
package/dist/index.cjs
CHANGED
|
@@ -31,9 +31,14 @@ var import_vue = require("vue");
|
|
|
31
31
|
|
|
32
32
|
// src/styles.ts
|
|
33
33
|
var styles = {
|
|
34
|
-
container: { padding: "24px"
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
container: { padding: "24px" },
|
|
35
|
+
// Two columns, always: editor left, rendered result right. Stacking the
|
|
36
|
+
// preview under a long form hid it below the fold.
|
|
37
|
+
split: { display: "grid", gridTemplateColumns: "minmax(0, 1fr) minmax(0, 1fr)", gap: "24px", alignItems: "start" },
|
|
38
|
+
column: { minWidth: "0", display: "flex", flexDirection: "column" },
|
|
39
|
+
// Pinned while the form scrolls, so the preview stays in view as you edit.
|
|
40
|
+
previewColumn: { minWidth: "0", display: "flex", flexDirection: "column", position: "sticky", top: "16px" },
|
|
41
|
+
saveRow: { display: "flex", alignItems: "center", gap: "12px", marginTop: "16px" },
|
|
37
42
|
previewHeader: {
|
|
38
43
|
display: "flex",
|
|
39
44
|
justifyContent: "space-between",
|
|
@@ -96,7 +101,6 @@ var styles = {
|
|
|
96
101
|
fontSize: "14px"
|
|
97
102
|
},
|
|
98
103
|
button: {
|
|
99
|
-
marginTop: "16px",
|
|
100
104
|
backgroundColor: "var(--fonderie-text,#171717)",
|
|
101
105
|
color: "var(--fonderie-surface,#fff)",
|
|
102
106
|
padding: "10px 20px",
|
|
@@ -107,6 +111,17 @@ var styles = {
|
|
|
107
111
|
cursor: "pointer",
|
|
108
112
|
alignSelf: "flex-start"
|
|
109
113
|
},
|
|
114
|
+
buttonDisabled: {
|
|
115
|
+
backgroundColor: "var(--fonderie-border,#e0e0e0)",
|
|
116
|
+
color: "var(--fonderie-text-muted,#5c5c5c)",
|
|
117
|
+
padding: "10px 20px",
|
|
118
|
+
borderRadius: "8px",
|
|
119
|
+
border: "none",
|
|
120
|
+
fontSize: "14px",
|
|
121
|
+
fontWeight: 600,
|
|
122
|
+
cursor: "not-allowed",
|
|
123
|
+
alignSelf: "flex-start"
|
|
124
|
+
},
|
|
110
125
|
revisions: { marginTop: "32px" },
|
|
111
126
|
revisionRow: {
|
|
112
127
|
display: "flex",
|
|
@@ -127,6 +142,7 @@ var styles = {
|
|
|
127
142
|
};
|
|
128
143
|
|
|
129
144
|
// src/screens/TemplateEditorScreen.ts
|
|
145
|
+
var PREVIEW_DEBOUNCE_MS = 500;
|
|
130
146
|
var IMPLICIT = /* @__PURE__ */ new Set(["subject", "preheader", "brandName"]);
|
|
131
147
|
var TemplateEditorScreen = (0, import_vue.defineComponent)({
|
|
132
148
|
name: "FonderieTemplateEditorScreen",
|
|
@@ -200,8 +216,15 @@ var TemplateEditorScreen = (0, import_vue.defineComponent)({
|
|
|
200
216
|
);
|
|
201
217
|
}
|
|
202
218
|
}
|
|
203
|
-
|
|
204
|
-
|
|
219
|
+
let previewTimer;
|
|
220
|
+
(0, import_vue.watch)([template, subject, html, text, sampleJson], () => {
|
|
221
|
+
if (!template.value) return;
|
|
222
|
+
clearTimeout(previewTimer);
|
|
223
|
+
previewTimer = setTimeout(() => void run(), PREVIEW_DEBOUNCE_MS);
|
|
224
|
+
});
|
|
225
|
+
const dirty = (0, import_vue.computed)(() => {
|
|
226
|
+
const tpl = template.value;
|
|
227
|
+
return !!tpl && (subject.value !== (tpl.subject ?? "") || html.value !== (tpl.html ?? "") || text.value !== tpl.text || active.value !== tpl.active);
|
|
205
228
|
});
|
|
206
229
|
async function handleSubmit(event) {
|
|
207
230
|
event.preventDefault();
|
|
@@ -289,11 +312,18 @@ var TemplateEditorScreen = (0, import_vue.defineComponent)({
|
|
|
289
312
|
"Active"
|
|
290
313
|
]),
|
|
291
314
|
saveError.value ? (0, import_vue.h)("p", { style: styles.error, role: "alert" }, saveError.value.explanation) : null,
|
|
292
|
-
(0, import_vue.h)(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
315
|
+
(0, import_vue.h)("div", { style: styles.saveRow }, [
|
|
316
|
+
(0, import_vue.h)(
|
|
317
|
+
"button",
|
|
318
|
+
{
|
|
319
|
+
type: "submit",
|
|
320
|
+
disabled: isSaving.value || !dirty.value,
|
|
321
|
+
style: dirty.value ? styles.button : styles.buttonDisabled
|
|
322
|
+
},
|
|
323
|
+
isSaving.value ? "Saving\u2026" : "Save"
|
|
324
|
+
),
|
|
325
|
+
!dirty.value && !isSaving.value ? (0, import_vue.h)("span", { style: styles.meta }, "No changes to save") : null
|
|
326
|
+
])
|
|
297
327
|
]),
|
|
298
328
|
(0, import_vue.h)("label", { style: styles.label, for: "template-sample" }, "Sample data"),
|
|
299
329
|
(0, import_vue.h)("textarea", {
|
|
@@ -308,19 +338,10 @@ var TemplateEditorScreen = (0, import_vue.defineComponent)({
|
|
|
308
338
|
}),
|
|
309
339
|
sampleError.value ? (0, import_vue.h)("p", { style: styles.error, role: "alert" }, sampleError.value) : null
|
|
310
340
|
]),
|
|
311
|
-
(0, import_vue.h)("div", { style: styles.
|
|
341
|
+
(0, import_vue.h)("div", { style: styles.previewColumn }, [
|
|
312
342
|
(0, import_vue.h)("div", { style: styles.previewHeader }, [
|
|
313
343
|
(0, import_vue.h)("span", { style: styles.label }, "Preview"),
|
|
314
|
-
(0, import_vue.h)(
|
|
315
|
-
"button",
|
|
316
|
-
{
|
|
317
|
-
type: "button",
|
|
318
|
-
style: styles.rollbackButton,
|
|
319
|
-
disabled: isPreviewing.value,
|
|
320
|
-
onClick: () => void run()
|
|
321
|
-
},
|
|
322
|
-
isPreviewing.value ? "Rendering\u2026" : "Render"
|
|
323
|
-
)
|
|
344
|
+
(0, import_vue.h)("span", { style: styles.meta }, isPreviewing.value ? "Rendering\u2026" : "Live")
|
|
324
345
|
]),
|
|
325
346
|
previewError.value ? (0, import_vue.h)("p", { style: styles.error, role: "alert" }, previewError.value.explanation) : null,
|
|
326
347
|
preview.value?.subject ? (0, import_vue.h)("p", { style: styles.previewSubject }, preview.value.subject) : null,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/screens/TemplateEditorScreen.ts","../src/styles.ts","../src/screens/TemplateListScreen.ts"],"sourcesContent":["export { TemplateEditorScreen, TemplateListScreen } from './screens';\n","import type {\n\tCourierAdminClient,\n\tFonderieApiError,\n\tISetTemplateInput,\n\tITemplateRevision,\n} from '@fonderie/client';\nimport {\n\tuseTemplate,\n\tuseTemplatePreview,\n\tuseTemplateRevisions,\n\tuseTemplates,\n} from '@fonderie/vue-courier-admin';\nimport type { PropType } from 'vue';\nimport { defineComponent, h, ref, watch } from 'vue';\nimport { styles } from '../styles';\n\n// Implicit variables the layout injects — an operator never supplies these, so\n// offering them as fields would just be noise.\nconst IMPLICIT = new Set(['subject', 'preheader', 'brandName']);\n\nexport const TemplateEditorScreen = defineComponent({\n\tname: 'FonderieTemplateEditorScreen',\n\tprops: {\n\t\tclient: { type: Object as PropType<CourierAdminClient>, required: true },\n\t\ttype: { type: String, required: true },\n\t\tlocale: { type: String as PropType<string | null>, default: null },\n\t},\n\temits: {\n\t\tsaved: () => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst { template, isLoading, error, refresh } = useTemplate(\n\t\t\tprops.client,\n\t\t\tprops.type,\n\t\t\tprops.locale,\n\t\t);\n\t\t// Saves go through the list composable (which re-fetches the template list\n\t\t// after each write); mounting it adds a template-list fetch to this\n\t\t// single-template editor — acceptable for an admin dashboard. Its\n\t\t// isLoading/error track that list fetch, so the save action keeps local state.\n\t\tconst { saveTemplate } = useTemplates(props.client);\n\t\tconst { revisions, rollback } = useTemplateRevisions(props.client, props.type, props.locale);\n\t\tconst isSaving = ref(false);\n\t\tconst saveError = ref<FonderieApiError | null>(null);\n\n\t\tconst subject = ref('');\n\t\tconst html = ref('');\n\t\tconst text = ref('');\n\t\tconst active = ref(true);\n\n\t\twatch(template, (tpl) => {\n\t\t\tif (!tpl) return;\n\t\t\tsubject.value = tpl.subject ?? '';\n\t\t\thtml.value = tpl.html ?? '';\n\t\t\ttext.value = tpl.text;\n\t\t\tactive.value = tpl.active;\n\t\t});\n\n\t\tconst {\n\t\t\tpreview,\n\t\t\tisPreviewing,\n\t\t\terror: previewError,\n\t\t\trenderPreview,\n\t\t} = useTemplatePreview(props.client);\n\t\t// Sample values as JSON text rather than an object, so a half-typed value\n\t\t// does not have to parse on every keystroke.\n\t\tconst sampleJson = ref('{}');\n\t\tconst sampleError = ref<string | null>(null);\n\n\t\tasync function run() {\n\t\t\tlet data: Record<string, unknown> = {};\n\t\t\ttry {\n\t\t\t\tconst parsed: unknown = JSON.parse(sampleJson.value || '{}');\n\t\t\t\tif (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n\t\t\t\t\tsampleError.value = 'Sample data must be a JSON object.';\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tdata = parsed as Record<string, unknown>;\n\t\t\t\tsampleError.value = null;\n\t\t\t} catch {\n\t\t\t\tsampleError.value = 'Sample data is not valid JSON.';\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst result = await renderPreview(\n\t\t\t\tprops.type,\n\t\t\t\t{\n\t\t\t\t\ttext: text.value,\n\t\t\t\t\tdata,\n\t\t\t\t\t...(subject.value ? { subject: subject.value } : {}),\n\t\t\t\t\t...(html.value ? { html: html.value } : {}),\n\t\t\t\t},\n\t\t\t\tprops.locale,\n\t\t\t);\n\t\t\t// The server reports which variables this content uses; seed the ones\n\t\t\t// with no value yet with their own name so the render shows where each\n\t\t\t// lands. Never overwrite something already typed.\n\t\t\tconst missing = result.variables.filter((v) => !IMPLICIT.has(v) && !(v in data));\n\t\t\tif (missing.length > 0) {\n\t\t\t\tsampleJson.value = JSON.stringify(\n\t\t\t\t\t{ ...data, ...Object.fromEntries(missing.map((v) => [v, v])) },\n\t\t\t\t\tnull,\n\t\t\t\t\t2,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// One render once the template has loaded, so the pane is never empty on\n\t\t// arrival. After that it is explicit — a request per keystroke is not a\n\t\t// preview, it is a load test.\n\t\twatch(template, (tpl) => {\n\t\t\tif (tpl) void run();\n\t\t});\n\n\t\tasync function handleSubmit(event: Event) {\n\t\t\tevent.preventDefault();\n\t\t\tisSaving.value = true;\n\t\t\tsaveError.value = null;\n\t\t\ttry {\n\t\t\t\tconst input: ISetTemplateInput = { text: text.value, active: active.value };\n\t\t\t\tif (subject.value) input.subject = subject.value;\n\t\t\t\tif (html.value) input.html = html.value;\n\t\t\t\tif (template.value?.version !== undefined) input.ifVersion = template.value.version;\n\t\t\t\tawait saveTemplate(props.type, input, props.locale);\n\t\t\t\t// The list composable refreshes its own list; this screen renders the\n\t\t\t\t// single template, so re-read it too.\n\t\t\t\tawait refresh();\n\t\t\t\temit('saved');\n\t\t\t} catch (err) {\n\t\t\t\t// useTemplates normalizes every failure to FonderieApiError before throwing.\n\t\t\t\tsaveError.value = err as FonderieApiError;\n\t\t\t} finally {\n\t\t\t\tisSaving.value = false;\n\t\t\t}\n\t\t}\n\n\t\tfunction renderRevision(rev: ITemplateRevision) {\n\t\t\treturn h('li', { key: rev.version, style: styles.revisionRow }, [\n\t\t\t\th(\n\t\t\t\t\t'span',\n\t\t\t\t\t`v${rev.version} — ${rev.actor ?? 'unknown'} — ${new Date(rev.createdAt).toLocaleString()}`,\n\t\t\t\t),\n\t\t\t\th(\n\t\t\t\t\t'button',\n\t\t\t\t\t{ type: 'button', style: styles.rollbackButton, onClick: () => rollback(rev.version) },\n\t\t\t\t\t'Roll back',\n\t\t\t\t),\n\t\t\t]);\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (isLoading.value) return h('p', { style: styles.status }, 'Loading template…');\n\t\t\tif (error.value)\n\t\t\t\treturn h('p', { style: styles.error, role: 'alert' }, error.value.explanation);\n\n\t\t\treturn h('div', { style: styles.container }, [\n\t\t\t\th('h1', { style: styles.title }, props.type),\n\t\t\t\th(\n\t\t\t\t\t'p',\n\t\t\t\t\t{ style: styles.meta },\n\t\t\t\t\t`${props.locale ?? 'base'} · v${template.value?.version ?? 1}`,\n\t\t\t\t),\n\t\t\t\th('div', { style: styles.split }, [\n\t\t\t\th('div', { style: styles.column }, [\n\t\t\t\th('form', { style: styles.form, onSubmit: handleSubmit }, [\n\t\t\t\t\th('label', { style: styles.label, for: 'template-subject' }, 'Subject'),\n\t\t\t\t\th('input', {\n\t\t\t\t\t\tid: 'template-subject',\n\t\t\t\t\t\tstyle: styles.input,\n\t\t\t\t\t\tvalue: subject.value,\n\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\tsubject.value = (e.target as HTMLInputElement).value;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\th('label', { style: styles.label, for: 'template-html' }, 'HTML body'),\n\t\t\t\t\th('textarea', {\n\t\t\t\t\t\tid: 'template-html',\n\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\trows: 8,\n\t\t\t\t\t\tvalue: html.value,\n\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\thtml.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\th('label', { style: styles.label, for: 'template-text' }, 'Plain-text body'),\n\t\t\t\t\th('textarea', {\n\t\t\t\t\t\tid: 'template-text',\n\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\trows: 4,\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tvalue: text.value,\n\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\ttext.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\th('label', { style: styles.checkboxLabel }, [\n\t\t\t\t\t\th('input', {\n\t\t\t\t\t\t\ttype: 'checkbox',\n\t\t\t\t\t\t\tchecked: active.value,\n\t\t\t\t\t\t\tonChange: (e: Event) => {\n\t\t\t\t\t\t\t\tactive.value = (e.target as HTMLInputElement).checked;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t'Active',\n\t\t\t\t\t]),\n\t\t\t\t\tsaveError.value\n\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, saveError.value.explanation)\n\t\t\t\t\t\t: null,\n\t\t\t\t\th(\n\t\t\t\t\t\t'button',\n\t\t\t\t\t\t{ type: 'submit', disabled: isSaving.value, style: styles.button },\n\t\t\t\t\t\tisSaving.value ? 'Saving…' : 'Save',\n\t\t\t\t\t),\n\t\t\t\t]),\n\t\t\t\th('label', { style: styles.label, for: 'template-sample' }, 'Sample data'),\n\t\t\t\th('textarea', {\n\t\t\t\t\tid: 'template-sample',\n\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\trows: 6,\n\t\t\t\t\tspellcheck: false,\n\t\t\t\t\tvalue: sampleJson.value,\n\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\tsampleJson.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\tsampleError.value\n\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, sampleError.value)\n\t\t\t\t\t: null,\n\t\t\t\t]),\n\t\t\t\th('div', { style: styles.column }, [\n\t\t\t\t\th('div', { style: styles.previewHeader }, [\n\t\t\t\t\t\th('span', { style: styles.label }, 'Preview'),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t\tstyle: styles.rollbackButton,\n\t\t\t\t\t\t\t\tdisabled: isPreviewing.value,\n\t\t\t\t\t\t\t\tonClick: () => void run(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tisPreviewing.value ? 'Rendering…' : 'Render',\n\t\t\t\t\t\t),\n\t\t\t\t\t]),\n\t\t\t\t\tpreviewError.value\n\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, previewError.value.explanation)\n\t\t\t\t\t\t: null,\n\t\t\t\t\tpreview.value?.subject\n\t\t\t\t\t\t? h('p', { style: styles.previewSubject }, preview.value.subject)\n\t\t\t\t\t\t: null,\n\t\t\t\t\tpreview.value?.html\n\t\t\t\t\t\t? // sandbox= — no scripts, no same-origin. Operator-authored HTML\n\t\t\t\t\t\t\t// must never execute in the dashboard's origin, where the admin\n\t\t\t\t\t\t\t// token lives.\n\t\t\t\t\t\t\th('iframe', {\n\t\t\t\t\t\t\t\ttitle: 'Template preview',\n\t\t\t\t\t\t\t\tstyle: styles.previewFrame,\n\t\t\t\t\t\t\t\tsandbox: '',\n\t\t\t\t\t\t\t\tsrcdoc: preview.value.html,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: preview.value\n\t\t\t\t\t\t\t? h('pre', { style: styles.previewText }, preview.value.text)\n\t\t\t\t\t\t\t: h('p', { style: styles.meta }, 'Nothing rendered yet.'),\n\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t\trevisions.value.length > 0\n\t\t\t\t\t? h('div', { style: styles.revisions }, [\n\t\t\t\t\t\t\th('h2', { style: styles.subtitle }, 'History'),\n\t\t\t\t\t\t\th('ul', { style: styles.list }, revisions.value.map(renderRevision)),\n\t\t\t\t\t\t])\n\t\t\t\t\t: null,\n\t\t\t]);\n\t\t};\n\t},\n});\n","import type { CSSProperties } from 'vue';\n\nexport const styles: Record<string, CSSProperties> = {\n\tcontainer: { padding: '24px', maxWidth: '1180px' },\n\tsplit: { display: 'flex', gap: '24px', alignItems: 'flex-start', flexWrap: 'wrap' },\n\tcolumn: { flex: '1 1 460px', minWidth: '320px', display: 'flex', flexDirection: 'column' },\n\tpreviewHeader: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tmarginTop: '12px',\n\t},\n\tpreviewSubject: { fontSize: '14px', fontWeight: '600', margin: '8px 0' },\n\tpreviewFrame: {\n\t\twidth: '100%',\n\t\theight: '520px',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t},\n\tpreviewText: {\n\t\twhiteSpace: 'pre-wrap',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tpadding: '12px',\n\t\tfontSize: '13px',\n\t\tfontFamily: 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\t},\n\ttitle: { fontSize: '24px', fontWeight: 700 },\n\tsubtitle: { fontSize: '16px', fontWeight: 600, marginBottom: '8px' },\n\tmeta: { fontSize: '13px', color: 'var(--fonderie-text-muted,#5c5c5c)', marginBottom: '16px' },\n\tstatus: { padding: '24px', textAlign: 'center', color: 'var(--fonderie-text-muted,#5c5c5c)' },\n\terror: { color: 'var(--fonderie-danger,#e00)', marginBottom: '12px', fontSize: '14px' },\n\tlist: { listStyle: 'none', padding: '0', margin: '0' },\n\trow: { borderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)' },\n\trowButton: {\n\t\twidth: '100%',\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tpadding: '12px 0',\n\t\tbackground: 'none',\n\t\tborder: 'none',\n\t\tcursor: 'pointer',\n\t\ttextAlign: 'left',\n\t},\n\ttype: { fontSize: '14px', fontWeight: 600, flex: '1' },\n\tlocale: { fontSize: '13px', color: 'var(--fonderie-text-muted,#5c5c5c)', marginRight: '16px' },\n\tactive: { fontSize: '12px', color: 'var(--fonderie-accent-strong,#009767)' },\n\tinactive: { fontSize: '12px', color: 'var(--fonderie-text-muted,#5c5c5c)' },\n\tform: { display: 'flex', flexDirection: 'column', gap: '4px' },\n\tlabel: { fontSize: '13px', fontWeight: 600, marginTop: '12px' },\n\tinput: { border: '1px solid var(--fonderie-border,#e0e0e0)', borderRadius: '8px', padding: '10px', fontSize: '14px' },\n\ttextarea: {\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tpadding: '10px',\n\t\tfontSize: '14px',\n\t\tfontFamily: 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\t},\n\tcheckboxLabel: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tgap: '8px',\n\t\tmarginTop: '12px',\n\t\tfontSize: '14px',\n\t},\n\tbutton: {\n\t\tmarginTop: '16px',\n\t\tbackgroundColor: 'var(--fonderie-text,#171717)',\n\t\tcolor: 'var(--fonderie-surface,#fff)',\n\t\tpadding: '10px 20px',\n\t\tborderRadius: '8px',\n\t\tborder: 'none',\n\t\tfontSize: '14px',\n\t\tfontWeight: 600,\n\t\tcursor: 'pointer',\n\t\talignSelf: 'flex-start',\n\t},\n\trevisions: { marginTop: '32px' },\n\trevisionRow: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tpadding: '8px 0',\n\t\tborderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)',\n\t\tfontSize: '13px',\n\t},\n\trollbackButton: {\n\t\tbackground: 'none',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tpadding: '4px 10px',\n\t\tfontSize: '12px',\n\t\tcursor: 'pointer',\n\t},\n};\n","import type { CourierAdminClient, ITemplateEntry } from '@fonderie/client';\nimport { useTemplates } from '@fonderie/vue-courier-admin';\nimport type { PropType } from 'vue';\nimport { defineComponent, h } from 'vue';\nimport { styles } from '../styles';\n\nexport const TemplateListScreen = defineComponent({\n\tname: 'FonderieTemplateListScreen',\n\tprops: {\n\t\tclient: { type: Object as PropType<CourierAdminClient>, required: true },\n\t},\n\temits: {\n\t\t'select-template': (_template: ITemplateEntry) => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst { templates, isLoading, error } = useTemplates(props.client);\n\n\t\tfunction renderRow(template: ITemplateEntry) {\n\t\t\treturn h('li', { key: `${template.type}:${template.locale ?? 'base'}`, style: styles.row }, [\n\t\t\t\th(\n\t\t\t\t\t'button',\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\tstyle: styles.rowButton,\n\t\t\t\t\t\tonClick: () => emit('select-template', template),\n\t\t\t\t\t},\n\t\t\t\t\t[\n\t\t\t\t\t\th('span', { style: styles.type }, template.type),\n\t\t\t\t\t\th('span', { style: styles.locale }, template.locale ?? 'base'),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t'span',\n\t\t\t\t\t\t\t{ style: template.active ? styles.active : styles.inactive },\n\t\t\t\t\t\t\ttemplate.active ? 'Active' : 'Inactive',\n\t\t\t\t\t\t),\n\t\t\t\t\t],\n\t\t\t\t),\n\t\t\t]);\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (isLoading.value) return h('p', { style: styles.status }, 'Loading templates…');\n\t\t\tif (error.value)\n\t\t\t\treturn h('p', { style: styles.error, role: 'alert' }, error.value.explanation);\n\n\t\t\treturn h('div', { style: styles.container }, [\n\t\t\t\th('h1', { style: styles.title }, 'Templates'),\n\t\t\t\th('ul', { style: styles.list }, templates.value.map(renderRow)),\n\t\t\t]);\n\t\t};\n\t},\n});\n"],"mappings":"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","names":["import_vue_courier_admin","import_vue"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/screens/TemplateEditorScreen.ts","../src/styles.ts","../src/screens/TemplateListScreen.ts"],"sourcesContent":["export { TemplateEditorScreen, TemplateListScreen } from './screens';\n","import type {\n\tCourierAdminClient,\n\tFonderieApiError,\n\tISetTemplateInput,\n\tITemplateRevision,\n} from '@fonderie/client';\nimport {\n\tuseTemplate,\n\tuseTemplatePreview,\n\tuseTemplateRevisions,\n\tuseTemplates,\n} from '@fonderie/vue-courier-admin';\nimport type { PropType } from 'vue';\nimport { computed, defineComponent, h, ref, watch } from 'vue';\n\nconst PREVIEW_DEBOUNCE_MS = 500;\nimport { styles } from '../styles';\n\n// Implicit variables the layout injects — an operator never supplies these, so\n// offering them as fields would just be noise.\nconst IMPLICIT = new Set(['subject', 'preheader', 'brandName']);\n\nexport const TemplateEditorScreen = defineComponent({\n\tname: 'FonderieTemplateEditorScreen',\n\tprops: {\n\t\tclient: { type: Object as PropType<CourierAdminClient>, required: true },\n\t\ttype: { type: String, required: true },\n\t\tlocale: { type: String as PropType<string | null>, default: null },\n\t},\n\temits: {\n\t\tsaved: () => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst { template, isLoading, error, refresh } = useTemplate(\n\t\t\tprops.client,\n\t\t\tprops.type,\n\t\t\tprops.locale,\n\t\t);\n\t\t// Saves go through the list composable (which re-fetches the template list\n\t\t// after each write); mounting it adds a template-list fetch to this\n\t\t// single-template editor — acceptable for an admin dashboard. Its\n\t\t// isLoading/error track that list fetch, so the save action keeps local state.\n\t\tconst { saveTemplate } = useTemplates(props.client);\n\t\tconst { revisions, rollback } = useTemplateRevisions(props.client, props.type, props.locale);\n\t\tconst isSaving = ref(false);\n\t\tconst saveError = ref<FonderieApiError | null>(null);\n\n\t\tconst subject = ref('');\n\t\tconst html = ref('');\n\t\tconst text = ref('');\n\t\tconst active = ref(true);\n\n\t\twatch(template, (tpl) => {\n\t\t\tif (!tpl) return;\n\t\t\tsubject.value = tpl.subject ?? '';\n\t\t\thtml.value = tpl.html ?? '';\n\t\t\ttext.value = tpl.text;\n\t\t\tactive.value = tpl.active;\n\t\t});\n\n\t\tconst {\n\t\t\tpreview,\n\t\t\tisPreviewing,\n\t\t\terror: previewError,\n\t\t\trenderPreview,\n\t\t} = useTemplatePreview(props.client);\n\t\t// Sample values as JSON text rather than an object, so a half-typed value\n\t\t// does not have to parse on every keystroke.\n\t\tconst sampleJson = ref('{}');\n\t\tconst sampleError = ref<string | null>(null);\n\n\t\tasync function run() {\n\t\t\tlet data: Record<string, unknown> = {};\n\t\t\ttry {\n\t\t\t\tconst parsed: unknown = JSON.parse(sampleJson.value || '{}');\n\t\t\t\tif (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n\t\t\t\t\tsampleError.value = 'Sample data must be a JSON object.';\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tdata = parsed as Record<string, unknown>;\n\t\t\t\tsampleError.value = null;\n\t\t\t} catch {\n\t\t\t\tsampleError.value = 'Sample data is not valid JSON.';\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst result = await renderPreview(\n\t\t\t\tprops.type,\n\t\t\t\t{\n\t\t\t\t\ttext: text.value,\n\t\t\t\t\tdata,\n\t\t\t\t\t...(subject.value ? { subject: subject.value } : {}),\n\t\t\t\t\t...(html.value ? { html: html.value } : {}),\n\t\t\t\t},\n\t\t\t\tprops.locale,\n\t\t\t);\n\t\t\t// The server reports which variables this content uses; seed the ones\n\t\t\t// with no value yet with their own name so the render shows where each\n\t\t\t// lands. Never overwrite something already typed.\n\t\t\tconst missing = result.variables.filter((v) => !IMPLICIT.has(v) && !(v in data));\n\t\t\tif (missing.length > 0) {\n\t\t\t\tsampleJson.value = JSON.stringify(\n\t\t\t\t\t{ ...data, ...Object.fromEntries(missing.map((v) => [v, v])) },\n\t\t\t\t\tnull,\n\t\t\t\t\t2,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// The preview is always live: it renders once the template loads, then\n\t\t// again PREVIEW_DEBOUNCE_MS after the last edit to the content or the sample\n\t\t// data — debounced, so typing a paragraph costs one request, not one per key.\n\t\tlet previewTimer: ReturnType<typeof setTimeout> | undefined;\n\t\twatch([template, subject, html, text, sampleJson], () => {\n\t\t\tif (!template.value) return;\n\t\t\tclearTimeout(previewTimer);\n\t\t\tpreviewTimer = setTimeout(() => void run(), PREVIEW_DEBOUNCE_MS);\n\t\t});\n\n\t\t// Saving what is already stored would only mint an identical version (the\n\t\t// server treats it as a no-op anyway), so Save waits for a real change.\n\t\tconst dirty = computed(() => {\n\t\t\tconst tpl = template.value;\n\t\t\treturn (\n\t\t\t\t!!tpl &&\n\t\t\t\t(subject.value !== (tpl.subject ?? '') ||\n\t\t\t\t\thtml.value !== (tpl.html ?? '') ||\n\t\t\t\t\ttext.value !== tpl.text ||\n\t\t\t\t\tactive.value !== tpl.active)\n\t\t\t);\n\t\t});\n\n\t\tasync function handleSubmit(event: Event) {\n\t\t\tevent.preventDefault();\n\t\t\tisSaving.value = true;\n\t\t\tsaveError.value = null;\n\t\t\ttry {\n\t\t\t\tconst input: ISetTemplateInput = { text: text.value, active: active.value };\n\t\t\t\tif (subject.value) input.subject = subject.value;\n\t\t\t\tif (html.value) input.html = html.value;\n\t\t\t\tif (template.value?.version !== undefined) input.ifVersion = template.value.version;\n\t\t\t\tawait saveTemplate(props.type, input, props.locale);\n\t\t\t\t// The list composable refreshes its own list; this screen renders the\n\t\t\t\t// single template, so re-read it too.\n\t\t\t\tawait refresh();\n\t\t\t\temit('saved');\n\t\t\t} catch (err) {\n\t\t\t\t// useTemplates normalizes every failure to FonderieApiError before throwing.\n\t\t\t\tsaveError.value = err as FonderieApiError;\n\t\t\t} finally {\n\t\t\t\tisSaving.value = false;\n\t\t\t}\n\t\t}\n\n\t\tfunction renderRevision(rev: ITemplateRevision) {\n\t\t\treturn h('li', { key: rev.version, style: styles.revisionRow }, [\n\t\t\t\th(\n\t\t\t\t\t'span',\n\t\t\t\t\t`v${rev.version} — ${rev.actor ?? 'unknown'} — ${new Date(rev.createdAt).toLocaleString()}`,\n\t\t\t\t),\n\t\t\t\th(\n\t\t\t\t\t'button',\n\t\t\t\t\t{ type: 'button', style: styles.rollbackButton, onClick: () => rollback(rev.version) },\n\t\t\t\t\t'Roll back',\n\t\t\t\t),\n\t\t\t]);\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (isLoading.value) return h('p', { style: styles.status }, 'Loading template…');\n\t\t\tif (error.value)\n\t\t\t\treturn h('p', { style: styles.error, role: 'alert' }, error.value.explanation);\n\n\t\t\treturn h('div', { style: styles.container }, [\n\t\t\t\th('h1', { style: styles.title }, props.type),\n\t\t\t\th(\n\t\t\t\t\t'p',\n\t\t\t\t\t{ style: styles.meta },\n\t\t\t\t\t`${props.locale ?? 'base'} · v${template.value?.version ?? 1}`,\n\t\t\t\t),\n\t\t\t\th('div', { style: styles.split }, [\n\t\t\t\th('div', { style: styles.column }, [\n\t\t\t\th('form', { style: styles.form, onSubmit: handleSubmit }, [\n\t\t\t\t\th('label', { style: styles.label, for: 'template-subject' }, 'Subject'),\n\t\t\t\t\th('input', {\n\t\t\t\t\t\tid: 'template-subject',\n\t\t\t\t\t\tstyle: styles.input,\n\t\t\t\t\t\tvalue: subject.value,\n\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\tsubject.value = (e.target as HTMLInputElement).value;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\th('label', { style: styles.label, for: 'template-html' }, 'HTML body'),\n\t\t\t\t\th('textarea', {\n\t\t\t\t\t\tid: 'template-html',\n\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\trows: 8,\n\t\t\t\t\t\tvalue: html.value,\n\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\thtml.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\th('label', { style: styles.label, for: 'template-text' }, 'Plain-text body'),\n\t\t\t\t\th('textarea', {\n\t\t\t\t\t\tid: 'template-text',\n\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\trows: 4,\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tvalue: text.value,\n\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\ttext.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\th('label', { style: styles.checkboxLabel }, [\n\t\t\t\t\t\th('input', {\n\t\t\t\t\t\t\ttype: 'checkbox',\n\t\t\t\t\t\t\tchecked: active.value,\n\t\t\t\t\t\t\tonChange: (e: Event) => {\n\t\t\t\t\t\t\t\tactive.value = (e.target as HTMLInputElement).checked;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t'Active',\n\t\t\t\t\t]),\n\t\t\t\t\tsaveError.value\n\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, saveError.value.explanation)\n\t\t\t\t\t\t: null,\n\t\t\t\t\th('div', { style: styles.saveRow }, [\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'submit',\n\t\t\t\t\t\t\t\tdisabled: isSaving.value || !dirty.value,\n\t\t\t\t\t\t\t\tstyle: dirty.value ? styles.button : styles.buttonDisabled,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tisSaving.value ? 'Saving…' : 'Save',\n\t\t\t\t\t\t),\n\t\t\t\t\t\t!dirty.value && !isSaving.value ? h('span', { style: styles.meta }, 'No changes to save') : null,\n\t\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t\th('label', { style: styles.label, for: 'template-sample' }, 'Sample data'),\n\t\t\t\th('textarea', {\n\t\t\t\t\tid: 'template-sample',\n\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\trows: 6,\n\t\t\t\t\tspellcheck: false,\n\t\t\t\t\tvalue: sampleJson.value,\n\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\tsampleJson.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\tsampleError.value\n\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, sampleError.value)\n\t\t\t\t\t: null,\n\t\t\t\t]),\n\t\t\t\th('div', { style: styles.previewColumn }, [\n\t\t\t\t\th('div', { style: styles.previewHeader }, [\n\t\t\t\t\t\th('span', { style: styles.label }, 'Preview'),\n\t\t\t\t\t\th('span', { style: styles.meta }, isPreviewing.value ? 'Rendering…' : 'Live'),\n\t\t\t\t\t]),\n\t\t\t\t\tpreviewError.value\n\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, previewError.value.explanation)\n\t\t\t\t\t\t: null,\n\t\t\t\t\tpreview.value?.subject\n\t\t\t\t\t\t? h('p', { style: styles.previewSubject }, preview.value.subject)\n\t\t\t\t\t\t: null,\n\t\t\t\t\tpreview.value?.html\n\t\t\t\t\t\t? // sandbox= — no scripts, no same-origin. Operator-authored HTML\n\t\t\t\t\t\t\t// must never execute in the dashboard's origin, where the admin\n\t\t\t\t\t\t\t// token lives.\n\t\t\t\t\t\t\th('iframe', {\n\t\t\t\t\t\t\t\ttitle: 'Template preview',\n\t\t\t\t\t\t\t\tstyle: styles.previewFrame,\n\t\t\t\t\t\t\t\tsandbox: '',\n\t\t\t\t\t\t\t\tsrcdoc: preview.value.html,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: preview.value\n\t\t\t\t\t\t\t? h('pre', { style: styles.previewText }, preview.value.text)\n\t\t\t\t\t\t\t: h('p', { style: styles.meta }, 'Nothing rendered yet.'),\n\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t\trevisions.value.length > 0\n\t\t\t\t\t? h('div', { style: styles.revisions }, [\n\t\t\t\t\t\t\th('h2', { style: styles.subtitle }, 'History'),\n\t\t\t\t\t\t\th('ul', { style: styles.list }, revisions.value.map(renderRevision)),\n\t\t\t\t\t\t])\n\t\t\t\t\t: null,\n\t\t\t]);\n\t\t};\n\t},\n});\n","import type { CSSProperties } from 'vue';\n\nexport const styles: Record<string, CSSProperties> = {\n\tcontainer: { padding: '24px' },\n\t// Two columns, always: editor left, rendered result right. Stacking the\n\t// preview under a long form hid it below the fold.\n\tsplit: { display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)', gap: '24px', alignItems: 'start' },\n\tcolumn: { minWidth: '0', display: 'flex', flexDirection: 'column' },\n\t// Pinned while the form scrolls, so the preview stays in view as you edit.\n\tpreviewColumn: { minWidth: '0', display: 'flex', flexDirection: 'column', position: 'sticky', top: '16px' },\n\tsaveRow: { display: 'flex', alignItems: 'center', gap: '12px', marginTop: '16px' },\n\tpreviewHeader: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tmarginTop: '12px',\n\t},\n\tpreviewSubject: { fontSize: '14px', fontWeight: '600', margin: '8px 0' },\n\tpreviewFrame: {\n\t\twidth: '100%',\n\t\theight: '520px',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t},\n\tpreviewText: {\n\t\twhiteSpace: 'pre-wrap',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tpadding: '12px',\n\t\tfontSize: '13px',\n\t\tfontFamily: 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\t},\n\ttitle: { fontSize: '24px', fontWeight: 700 },\n\tsubtitle: { fontSize: '16px', fontWeight: 600, marginBottom: '8px' },\n\tmeta: { fontSize: '13px', color: 'var(--fonderie-text-muted,#5c5c5c)', marginBottom: '16px' },\n\tstatus: { padding: '24px', textAlign: 'center', color: 'var(--fonderie-text-muted,#5c5c5c)' },\n\terror: { color: 'var(--fonderie-danger,#e00)', marginBottom: '12px', fontSize: '14px' },\n\tlist: { listStyle: 'none', padding: '0', margin: '0' },\n\trow: { borderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)' },\n\trowButton: {\n\t\twidth: '100%',\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tpadding: '12px 0',\n\t\tbackground: 'none',\n\t\tborder: 'none',\n\t\tcursor: 'pointer',\n\t\ttextAlign: 'left',\n\t},\n\ttype: { fontSize: '14px', fontWeight: 600, flex: '1' },\n\tlocale: { fontSize: '13px', color: 'var(--fonderie-text-muted,#5c5c5c)', marginRight: '16px' },\n\tactive: { fontSize: '12px', color: 'var(--fonderie-accent-strong,#009767)' },\n\tinactive: { fontSize: '12px', color: 'var(--fonderie-text-muted,#5c5c5c)' },\n\tform: { display: 'flex', flexDirection: 'column', gap: '4px' },\n\tlabel: { fontSize: '13px', fontWeight: 600, marginTop: '12px' },\n\tinput: { border: '1px solid var(--fonderie-border,#e0e0e0)', borderRadius: '8px', padding: '10px', fontSize: '14px' },\n\ttextarea: {\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tpadding: '10px',\n\t\tfontSize: '14px',\n\t\tfontFamily: 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\t},\n\tcheckboxLabel: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tgap: '8px',\n\t\tmarginTop: '12px',\n\t\tfontSize: '14px',\n\t},\n\tbutton: {\n\t\tbackgroundColor: 'var(--fonderie-text,#171717)',\n\t\tcolor: 'var(--fonderie-surface,#fff)',\n\t\tpadding: '10px 20px',\n\t\tborderRadius: '8px',\n\t\tborder: 'none',\n\t\tfontSize: '14px',\n\t\tfontWeight: 600,\n\t\tcursor: 'pointer',\n\t\talignSelf: 'flex-start',\n\t},\n\tbuttonDisabled: {\n\t\tbackgroundColor: 'var(--fonderie-border,#e0e0e0)',\n\t\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n\t\tpadding: '10px 20px',\n\t\tborderRadius: '8px',\n\t\tborder: 'none',\n\t\tfontSize: '14px',\n\t\tfontWeight: 600,\n\t\tcursor: 'not-allowed',\n\t\talignSelf: 'flex-start',\n\t},\n\trevisions: { marginTop: '32px' },\n\trevisionRow: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tpadding: '8px 0',\n\t\tborderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)',\n\t\tfontSize: '13px',\n\t},\n\trollbackButton: {\n\t\tbackground: 'none',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tpadding: '4px 10px',\n\t\tfontSize: '12px',\n\t\tcursor: 'pointer',\n\t},\n};\n","import type { CourierAdminClient, ITemplateEntry } from '@fonderie/client';\nimport { useTemplates } from '@fonderie/vue-courier-admin';\nimport type { PropType } from 'vue';\nimport { defineComponent, h } from 'vue';\nimport { styles } from '../styles';\n\nexport const TemplateListScreen = defineComponent({\n\tname: 'FonderieTemplateListScreen',\n\tprops: {\n\t\tclient: { type: Object as PropType<CourierAdminClient>, required: true },\n\t},\n\temits: {\n\t\t'select-template': (_template: ITemplateEntry) => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst { templates, isLoading, error } = useTemplates(props.client);\n\n\t\tfunction renderRow(template: ITemplateEntry) {\n\t\t\treturn h('li', { key: `${template.type}:${template.locale ?? 'base'}`, style: styles.row }, [\n\t\t\t\th(\n\t\t\t\t\t'button',\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\tstyle: styles.rowButton,\n\t\t\t\t\t\tonClick: () => emit('select-template', template),\n\t\t\t\t\t},\n\t\t\t\t\t[\n\t\t\t\t\t\th('span', { style: styles.type }, template.type),\n\t\t\t\t\t\th('span', { style: styles.locale }, template.locale ?? 'base'),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t'span',\n\t\t\t\t\t\t\t{ style: template.active ? styles.active : styles.inactive },\n\t\t\t\t\t\t\ttemplate.active ? 'Active' : 'Inactive',\n\t\t\t\t\t\t),\n\t\t\t\t\t],\n\t\t\t\t),\n\t\t\t]);\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (isLoading.value) return h('p', { style: styles.status }, 'Loading templates…');\n\t\t\tif (error.value)\n\t\t\t\treturn h('p', { style: styles.error, role: 'alert' }, error.value.explanation);\n\n\t\t\treturn h('div', { style: styles.container }, [\n\t\t\t\th('h1', { style: styles.title }, 'Templates'),\n\t\t\t\th('ul', { style: styles.list }, templates.value.map(renderRow)),\n\t\t\t]);\n\t\t};\n\t},\n});\n"],"mappings":"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","names":["import_vue_courier_admin","import_vue"]}
|
package/dist/index.js
CHANGED
|
@@ -5,13 +5,18 @@ import {
|
|
|
5
5
|
useTemplateRevisions,
|
|
6
6
|
useTemplates
|
|
7
7
|
} from "@fonderie/vue-courier-admin";
|
|
8
|
-
import { defineComponent, h, ref, watch } from "vue";
|
|
8
|
+
import { computed, defineComponent, h, ref, watch } from "vue";
|
|
9
9
|
|
|
10
10
|
// src/styles.ts
|
|
11
11
|
var styles = {
|
|
12
|
-
container: { padding: "24px"
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
container: { padding: "24px" },
|
|
13
|
+
// Two columns, always: editor left, rendered result right. Stacking the
|
|
14
|
+
// preview under a long form hid it below the fold.
|
|
15
|
+
split: { display: "grid", gridTemplateColumns: "minmax(0, 1fr) minmax(0, 1fr)", gap: "24px", alignItems: "start" },
|
|
16
|
+
column: { minWidth: "0", display: "flex", flexDirection: "column" },
|
|
17
|
+
// Pinned while the form scrolls, so the preview stays in view as you edit.
|
|
18
|
+
previewColumn: { minWidth: "0", display: "flex", flexDirection: "column", position: "sticky", top: "16px" },
|
|
19
|
+
saveRow: { display: "flex", alignItems: "center", gap: "12px", marginTop: "16px" },
|
|
15
20
|
previewHeader: {
|
|
16
21
|
display: "flex",
|
|
17
22
|
justifyContent: "space-between",
|
|
@@ -74,7 +79,6 @@ var styles = {
|
|
|
74
79
|
fontSize: "14px"
|
|
75
80
|
},
|
|
76
81
|
button: {
|
|
77
|
-
marginTop: "16px",
|
|
78
82
|
backgroundColor: "var(--fonderie-text,#171717)",
|
|
79
83
|
color: "var(--fonderie-surface,#fff)",
|
|
80
84
|
padding: "10px 20px",
|
|
@@ -85,6 +89,17 @@ var styles = {
|
|
|
85
89
|
cursor: "pointer",
|
|
86
90
|
alignSelf: "flex-start"
|
|
87
91
|
},
|
|
92
|
+
buttonDisabled: {
|
|
93
|
+
backgroundColor: "var(--fonderie-border,#e0e0e0)",
|
|
94
|
+
color: "var(--fonderie-text-muted,#5c5c5c)",
|
|
95
|
+
padding: "10px 20px",
|
|
96
|
+
borderRadius: "8px",
|
|
97
|
+
border: "none",
|
|
98
|
+
fontSize: "14px",
|
|
99
|
+
fontWeight: 600,
|
|
100
|
+
cursor: "not-allowed",
|
|
101
|
+
alignSelf: "flex-start"
|
|
102
|
+
},
|
|
88
103
|
revisions: { marginTop: "32px" },
|
|
89
104
|
revisionRow: {
|
|
90
105
|
display: "flex",
|
|
@@ -105,6 +120,7 @@ var styles = {
|
|
|
105
120
|
};
|
|
106
121
|
|
|
107
122
|
// src/screens/TemplateEditorScreen.ts
|
|
123
|
+
var PREVIEW_DEBOUNCE_MS = 500;
|
|
108
124
|
var IMPLICIT = /* @__PURE__ */ new Set(["subject", "preheader", "brandName"]);
|
|
109
125
|
var TemplateEditorScreen = defineComponent({
|
|
110
126
|
name: "FonderieTemplateEditorScreen",
|
|
@@ -178,8 +194,15 @@ var TemplateEditorScreen = defineComponent({
|
|
|
178
194
|
);
|
|
179
195
|
}
|
|
180
196
|
}
|
|
181
|
-
|
|
182
|
-
|
|
197
|
+
let previewTimer;
|
|
198
|
+
watch([template, subject, html, text, sampleJson], () => {
|
|
199
|
+
if (!template.value) return;
|
|
200
|
+
clearTimeout(previewTimer);
|
|
201
|
+
previewTimer = setTimeout(() => void run(), PREVIEW_DEBOUNCE_MS);
|
|
202
|
+
});
|
|
203
|
+
const dirty = computed(() => {
|
|
204
|
+
const tpl = template.value;
|
|
205
|
+
return !!tpl && (subject.value !== (tpl.subject ?? "") || html.value !== (tpl.html ?? "") || text.value !== tpl.text || active.value !== tpl.active);
|
|
183
206
|
});
|
|
184
207
|
async function handleSubmit(event) {
|
|
185
208
|
event.preventDefault();
|
|
@@ -267,11 +290,18 @@ var TemplateEditorScreen = defineComponent({
|
|
|
267
290
|
"Active"
|
|
268
291
|
]),
|
|
269
292
|
saveError.value ? h("p", { style: styles.error, role: "alert" }, saveError.value.explanation) : null,
|
|
270
|
-
h(
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
293
|
+
h("div", { style: styles.saveRow }, [
|
|
294
|
+
h(
|
|
295
|
+
"button",
|
|
296
|
+
{
|
|
297
|
+
type: "submit",
|
|
298
|
+
disabled: isSaving.value || !dirty.value,
|
|
299
|
+
style: dirty.value ? styles.button : styles.buttonDisabled
|
|
300
|
+
},
|
|
301
|
+
isSaving.value ? "Saving\u2026" : "Save"
|
|
302
|
+
),
|
|
303
|
+
!dirty.value && !isSaving.value ? h("span", { style: styles.meta }, "No changes to save") : null
|
|
304
|
+
])
|
|
275
305
|
]),
|
|
276
306
|
h("label", { style: styles.label, for: "template-sample" }, "Sample data"),
|
|
277
307
|
h("textarea", {
|
|
@@ -286,19 +316,10 @@ var TemplateEditorScreen = defineComponent({
|
|
|
286
316
|
}),
|
|
287
317
|
sampleError.value ? h("p", { style: styles.error, role: "alert" }, sampleError.value) : null
|
|
288
318
|
]),
|
|
289
|
-
h("div", { style: styles.
|
|
319
|
+
h("div", { style: styles.previewColumn }, [
|
|
290
320
|
h("div", { style: styles.previewHeader }, [
|
|
291
321
|
h("span", { style: styles.label }, "Preview"),
|
|
292
|
-
h(
|
|
293
|
-
"button",
|
|
294
|
-
{
|
|
295
|
-
type: "button",
|
|
296
|
-
style: styles.rollbackButton,
|
|
297
|
-
disabled: isPreviewing.value,
|
|
298
|
-
onClick: () => void run()
|
|
299
|
-
},
|
|
300
|
-
isPreviewing.value ? "Rendering\u2026" : "Render"
|
|
301
|
-
)
|
|
322
|
+
h("span", { style: styles.meta }, isPreviewing.value ? "Rendering\u2026" : "Live")
|
|
302
323
|
]),
|
|
303
324
|
previewError.value ? h("p", { style: styles.error, role: "alert" }, previewError.value.explanation) : null,
|
|
304
325
|
preview.value?.subject ? h("p", { style: styles.previewSubject }, preview.value.subject) : null,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/screens/TemplateEditorScreen.ts","../src/styles.ts","../src/screens/TemplateListScreen.ts"],"sourcesContent":["import type {\n\tCourierAdminClient,\n\tFonderieApiError,\n\tISetTemplateInput,\n\tITemplateRevision,\n} from '@fonderie/client';\nimport {\n\tuseTemplate,\n\tuseTemplatePreview,\n\tuseTemplateRevisions,\n\tuseTemplates,\n} from '@fonderie/vue-courier-admin';\nimport type { PropType } from 'vue';\nimport { defineComponent, h, ref, watch } from 'vue';\nimport { styles } from '../styles';\n\n// Implicit variables the layout injects — an operator never supplies these, so\n// offering them as fields would just be noise.\nconst IMPLICIT = new Set(['subject', 'preheader', 'brandName']);\n\nexport const TemplateEditorScreen = defineComponent({\n\tname: 'FonderieTemplateEditorScreen',\n\tprops: {\n\t\tclient: { type: Object as PropType<CourierAdminClient>, required: true },\n\t\ttype: { type: String, required: true },\n\t\tlocale: { type: String as PropType<string | null>, default: null },\n\t},\n\temits: {\n\t\tsaved: () => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst { template, isLoading, error, refresh } = useTemplate(\n\t\t\tprops.client,\n\t\t\tprops.type,\n\t\t\tprops.locale,\n\t\t);\n\t\t// Saves go through the list composable (which re-fetches the template list\n\t\t// after each write); mounting it adds a template-list fetch to this\n\t\t// single-template editor — acceptable for an admin dashboard. Its\n\t\t// isLoading/error track that list fetch, so the save action keeps local state.\n\t\tconst { saveTemplate } = useTemplates(props.client);\n\t\tconst { revisions, rollback } = useTemplateRevisions(props.client, props.type, props.locale);\n\t\tconst isSaving = ref(false);\n\t\tconst saveError = ref<FonderieApiError | null>(null);\n\n\t\tconst subject = ref('');\n\t\tconst html = ref('');\n\t\tconst text = ref('');\n\t\tconst active = ref(true);\n\n\t\twatch(template, (tpl) => {\n\t\t\tif (!tpl) return;\n\t\t\tsubject.value = tpl.subject ?? '';\n\t\t\thtml.value = tpl.html ?? '';\n\t\t\ttext.value = tpl.text;\n\t\t\tactive.value = tpl.active;\n\t\t});\n\n\t\tconst {\n\t\t\tpreview,\n\t\t\tisPreviewing,\n\t\t\terror: previewError,\n\t\t\trenderPreview,\n\t\t} = useTemplatePreview(props.client);\n\t\t// Sample values as JSON text rather than an object, so a half-typed value\n\t\t// does not have to parse on every keystroke.\n\t\tconst sampleJson = ref('{}');\n\t\tconst sampleError = ref<string | null>(null);\n\n\t\tasync function run() {\n\t\t\tlet data: Record<string, unknown> = {};\n\t\t\ttry {\n\t\t\t\tconst parsed: unknown = JSON.parse(sampleJson.value || '{}');\n\t\t\t\tif (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n\t\t\t\t\tsampleError.value = 'Sample data must be a JSON object.';\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tdata = parsed as Record<string, unknown>;\n\t\t\t\tsampleError.value = null;\n\t\t\t} catch {\n\t\t\t\tsampleError.value = 'Sample data is not valid JSON.';\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst result = await renderPreview(\n\t\t\t\tprops.type,\n\t\t\t\t{\n\t\t\t\t\ttext: text.value,\n\t\t\t\t\tdata,\n\t\t\t\t\t...(subject.value ? { subject: subject.value } : {}),\n\t\t\t\t\t...(html.value ? { html: html.value } : {}),\n\t\t\t\t},\n\t\t\t\tprops.locale,\n\t\t\t);\n\t\t\t// The server reports which variables this content uses; seed the ones\n\t\t\t// with no value yet with their own name so the render shows where each\n\t\t\t// lands. Never overwrite something already typed.\n\t\t\tconst missing = result.variables.filter((v) => !IMPLICIT.has(v) && !(v in data));\n\t\t\tif (missing.length > 0) {\n\t\t\t\tsampleJson.value = JSON.stringify(\n\t\t\t\t\t{ ...data, ...Object.fromEntries(missing.map((v) => [v, v])) },\n\t\t\t\t\tnull,\n\t\t\t\t\t2,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// One render once the template has loaded, so the pane is never empty on\n\t\t// arrival. After that it is explicit — a request per keystroke is not a\n\t\t// preview, it is a load test.\n\t\twatch(template, (tpl) => {\n\t\t\tif (tpl) void run();\n\t\t});\n\n\t\tasync function handleSubmit(event: Event) {\n\t\t\tevent.preventDefault();\n\t\t\tisSaving.value = true;\n\t\t\tsaveError.value = null;\n\t\t\ttry {\n\t\t\t\tconst input: ISetTemplateInput = { text: text.value, active: active.value };\n\t\t\t\tif (subject.value) input.subject = subject.value;\n\t\t\t\tif (html.value) input.html = html.value;\n\t\t\t\tif (template.value?.version !== undefined) input.ifVersion = template.value.version;\n\t\t\t\tawait saveTemplate(props.type, input, props.locale);\n\t\t\t\t// The list composable refreshes its own list; this screen renders the\n\t\t\t\t// single template, so re-read it too.\n\t\t\t\tawait refresh();\n\t\t\t\temit('saved');\n\t\t\t} catch (err) {\n\t\t\t\t// useTemplates normalizes every failure to FonderieApiError before throwing.\n\t\t\t\tsaveError.value = err as FonderieApiError;\n\t\t\t} finally {\n\t\t\t\tisSaving.value = false;\n\t\t\t}\n\t\t}\n\n\t\tfunction renderRevision(rev: ITemplateRevision) {\n\t\t\treturn h('li', { key: rev.version, style: styles.revisionRow }, [\n\t\t\t\th(\n\t\t\t\t\t'span',\n\t\t\t\t\t`v${rev.version} — ${rev.actor ?? 'unknown'} — ${new Date(rev.createdAt).toLocaleString()}`,\n\t\t\t\t),\n\t\t\t\th(\n\t\t\t\t\t'button',\n\t\t\t\t\t{ type: 'button', style: styles.rollbackButton, onClick: () => rollback(rev.version) },\n\t\t\t\t\t'Roll back',\n\t\t\t\t),\n\t\t\t]);\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (isLoading.value) return h('p', { style: styles.status }, 'Loading template…');\n\t\t\tif (error.value)\n\t\t\t\treturn h('p', { style: styles.error, role: 'alert' }, error.value.explanation);\n\n\t\t\treturn h('div', { style: styles.container }, [\n\t\t\t\th('h1', { style: styles.title }, props.type),\n\t\t\t\th(\n\t\t\t\t\t'p',\n\t\t\t\t\t{ style: styles.meta },\n\t\t\t\t\t`${props.locale ?? 'base'} · v${template.value?.version ?? 1}`,\n\t\t\t\t),\n\t\t\t\th('div', { style: styles.split }, [\n\t\t\t\th('div', { style: styles.column }, [\n\t\t\t\th('form', { style: styles.form, onSubmit: handleSubmit }, [\n\t\t\t\t\th('label', { style: styles.label, for: 'template-subject' }, 'Subject'),\n\t\t\t\t\th('input', {\n\t\t\t\t\t\tid: 'template-subject',\n\t\t\t\t\t\tstyle: styles.input,\n\t\t\t\t\t\tvalue: subject.value,\n\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\tsubject.value = (e.target as HTMLInputElement).value;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\th('label', { style: styles.label, for: 'template-html' }, 'HTML body'),\n\t\t\t\t\th('textarea', {\n\t\t\t\t\t\tid: 'template-html',\n\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\trows: 8,\n\t\t\t\t\t\tvalue: html.value,\n\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\thtml.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\th('label', { style: styles.label, for: 'template-text' }, 'Plain-text body'),\n\t\t\t\t\th('textarea', {\n\t\t\t\t\t\tid: 'template-text',\n\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\trows: 4,\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tvalue: text.value,\n\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\ttext.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\th('label', { style: styles.checkboxLabel }, [\n\t\t\t\t\t\th('input', {\n\t\t\t\t\t\t\ttype: 'checkbox',\n\t\t\t\t\t\t\tchecked: active.value,\n\t\t\t\t\t\t\tonChange: (e: Event) => {\n\t\t\t\t\t\t\t\tactive.value = (e.target as HTMLInputElement).checked;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t'Active',\n\t\t\t\t\t]),\n\t\t\t\t\tsaveError.value\n\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, saveError.value.explanation)\n\t\t\t\t\t\t: null,\n\t\t\t\t\th(\n\t\t\t\t\t\t'button',\n\t\t\t\t\t\t{ type: 'submit', disabled: isSaving.value, style: styles.button },\n\t\t\t\t\t\tisSaving.value ? 'Saving…' : 'Save',\n\t\t\t\t\t),\n\t\t\t\t]),\n\t\t\t\th('label', { style: styles.label, for: 'template-sample' }, 'Sample data'),\n\t\t\t\th('textarea', {\n\t\t\t\t\tid: 'template-sample',\n\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\trows: 6,\n\t\t\t\t\tspellcheck: false,\n\t\t\t\t\tvalue: sampleJson.value,\n\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\tsampleJson.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\tsampleError.value\n\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, sampleError.value)\n\t\t\t\t\t: null,\n\t\t\t\t]),\n\t\t\t\th('div', { style: styles.column }, [\n\t\t\t\t\th('div', { style: styles.previewHeader }, [\n\t\t\t\t\t\th('span', { style: styles.label }, 'Preview'),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t\tstyle: styles.rollbackButton,\n\t\t\t\t\t\t\t\tdisabled: isPreviewing.value,\n\t\t\t\t\t\t\t\tonClick: () => void run(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tisPreviewing.value ? 'Rendering…' : 'Render',\n\t\t\t\t\t\t),\n\t\t\t\t\t]),\n\t\t\t\t\tpreviewError.value\n\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, previewError.value.explanation)\n\t\t\t\t\t\t: null,\n\t\t\t\t\tpreview.value?.subject\n\t\t\t\t\t\t? h('p', { style: styles.previewSubject }, preview.value.subject)\n\t\t\t\t\t\t: null,\n\t\t\t\t\tpreview.value?.html\n\t\t\t\t\t\t? // sandbox= — no scripts, no same-origin. Operator-authored HTML\n\t\t\t\t\t\t\t// must never execute in the dashboard's origin, where the admin\n\t\t\t\t\t\t\t// token lives.\n\t\t\t\t\t\t\th('iframe', {\n\t\t\t\t\t\t\t\ttitle: 'Template preview',\n\t\t\t\t\t\t\t\tstyle: styles.previewFrame,\n\t\t\t\t\t\t\t\tsandbox: '',\n\t\t\t\t\t\t\t\tsrcdoc: preview.value.html,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: preview.value\n\t\t\t\t\t\t\t? h('pre', { style: styles.previewText }, preview.value.text)\n\t\t\t\t\t\t\t: h('p', { style: styles.meta }, 'Nothing rendered yet.'),\n\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t\trevisions.value.length > 0\n\t\t\t\t\t? h('div', { style: styles.revisions }, [\n\t\t\t\t\t\t\th('h2', { style: styles.subtitle }, 'History'),\n\t\t\t\t\t\t\th('ul', { style: styles.list }, revisions.value.map(renderRevision)),\n\t\t\t\t\t\t])\n\t\t\t\t\t: null,\n\t\t\t]);\n\t\t};\n\t},\n});\n","import type { CSSProperties } from 'vue';\n\nexport const styles: Record<string, CSSProperties> = {\n\tcontainer: { padding: '24px', maxWidth: '1180px' },\n\tsplit: { display: 'flex', gap: '24px', alignItems: 'flex-start', flexWrap: 'wrap' },\n\tcolumn: { flex: '1 1 460px', minWidth: '320px', display: 'flex', flexDirection: 'column' },\n\tpreviewHeader: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tmarginTop: '12px',\n\t},\n\tpreviewSubject: { fontSize: '14px', fontWeight: '600', margin: '8px 0' },\n\tpreviewFrame: {\n\t\twidth: '100%',\n\t\theight: '520px',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t},\n\tpreviewText: {\n\t\twhiteSpace: 'pre-wrap',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tpadding: '12px',\n\t\tfontSize: '13px',\n\t\tfontFamily: 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\t},\n\ttitle: { fontSize: '24px', fontWeight: 700 },\n\tsubtitle: { fontSize: '16px', fontWeight: 600, marginBottom: '8px' },\n\tmeta: { fontSize: '13px', color: 'var(--fonderie-text-muted,#5c5c5c)', marginBottom: '16px' },\n\tstatus: { padding: '24px', textAlign: 'center', color: 'var(--fonderie-text-muted,#5c5c5c)' },\n\terror: { color: 'var(--fonderie-danger,#e00)', marginBottom: '12px', fontSize: '14px' },\n\tlist: { listStyle: 'none', padding: '0', margin: '0' },\n\trow: { borderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)' },\n\trowButton: {\n\t\twidth: '100%',\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tpadding: '12px 0',\n\t\tbackground: 'none',\n\t\tborder: 'none',\n\t\tcursor: 'pointer',\n\t\ttextAlign: 'left',\n\t},\n\ttype: { fontSize: '14px', fontWeight: 600, flex: '1' },\n\tlocale: { fontSize: '13px', color: 'var(--fonderie-text-muted,#5c5c5c)', marginRight: '16px' },\n\tactive: { fontSize: '12px', color: 'var(--fonderie-accent-strong,#009767)' },\n\tinactive: { fontSize: '12px', color: 'var(--fonderie-text-muted,#5c5c5c)' },\n\tform: { display: 'flex', flexDirection: 'column', gap: '4px' },\n\tlabel: { fontSize: '13px', fontWeight: 600, marginTop: '12px' },\n\tinput: { border: '1px solid var(--fonderie-border,#e0e0e0)', borderRadius: '8px', padding: '10px', fontSize: '14px' },\n\ttextarea: {\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tpadding: '10px',\n\t\tfontSize: '14px',\n\t\tfontFamily: 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\t},\n\tcheckboxLabel: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tgap: '8px',\n\t\tmarginTop: '12px',\n\t\tfontSize: '14px',\n\t},\n\tbutton: {\n\t\tmarginTop: '16px',\n\t\tbackgroundColor: 'var(--fonderie-text,#171717)',\n\t\tcolor: 'var(--fonderie-surface,#fff)',\n\t\tpadding: '10px 20px',\n\t\tborderRadius: '8px',\n\t\tborder: 'none',\n\t\tfontSize: '14px',\n\t\tfontWeight: 600,\n\t\tcursor: 'pointer',\n\t\talignSelf: 'flex-start',\n\t},\n\trevisions: { marginTop: '32px' },\n\trevisionRow: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tpadding: '8px 0',\n\t\tborderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)',\n\t\tfontSize: '13px',\n\t},\n\trollbackButton: {\n\t\tbackground: 'none',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tpadding: '4px 10px',\n\t\tfontSize: '12px',\n\t\tcursor: 'pointer',\n\t},\n};\n","import type { CourierAdminClient, ITemplateEntry } from '@fonderie/client';\nimport { useTemplates } from '@fonderie/vue-courier-admin';\nimport type { PropType } from 'vue';\nimport { defineComponent, h } from 'vue';\nimport { styles } from '../styles';\n\nexport const TemplateListScreen = defineComponent({\n\tname: 'FonderieTemplateListScreen',\n\tprops: {\n\t\tclient: { type: Object as PropType<CourierAdminClient>, required: true },\n\t},\n\temits: {\n\t\t'select-template': (_template: ITemplateEntry) => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst { templates, isLoading, error } = useTemplates(props.client);\n\n\t\tfunction renderRow(template: ITemplateEntry) {\n\t\t\treturn h('li', { key: `${template.type}:${template.locale ?? 'base'}`, style: styles.row }, [\n\t\t\t\th(\n\t\t\t\t\t'button',\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\tstyle: styles.rowButton,\n\t\t\t\t\t\tonClick: () => emit('select-template', template),\n\t\t\t\t\t},\n\t\t\t\t\t[\n\t\t\t\t\t\th('span', { style: styles.type }, template.type),\n\t\t\t\t\t\th('span', { style: styles.locale }, template.locale ?? 'base'),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t'span',\n\t\t\t\t\t\t\t{ style: template.active ? styles.active : styles.inactive },\n\t\t\t\t\t\t\ttemplate.active ? 'Active' : 'Inactive',\n\t\t\t\t\t\t),\n\t\t\t\t\t],\n\t\t\t\t),\n\t\t\t]);\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (isLoading.value) return h('p', { style: styles.status }, 'Loading templates…');\n\t\t\tif (error.value)\n\t\t\t\treturn h('p', { style: styles.error, role: 'alert' }, error.value.explanation);\n\n\t\t\treturn h('div', { style: styles.container }, [\n\t\t\t\th('h1', { style: styles.title }, 'Templates'),\n\t\t\t\th('ul', { style: styles.list }, templates.value.map(renderRow)),\n\t\t\t]);\n\t\t};\n\t},\n});\n"],"mappings":"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","names":["useTemplates","defineComponent","h","defineComponent","useTemplates","h"]}
|
|
1
|
+
{"version":3,"sources":["../src/screens/TemplateEditorScreen.ts","../src/styles.ts","../src/screens/TemplateListScreen.ts"],"sourcesContent":["import type {\n\tCourierAdminClient,\n\tFonderieApiError,\n\tISetTemplateInput,\n\tITemplateRevision,\n} from '@fonderie/client';\nimport {\n\tuseTemplate,\n\tuseTemplatePreview,\n\tuseTemplateRevisions,\n\tuseTemplates,\n} from '@fonderie/vue-courier-admin';\nimport type { PropType } from 'vue';\nimport { computed, defineComponent, h, ref, watch } from 'vue';\n\nconst PREVIEW_DEBOUNCE_MS = 500;\nimport { styles } from '../styles';\n\n// Implicit variables the layout injects — an operator never supplies these, so\n// offering them as fields would just be noise.\nconst IMPLICIT = new Set(['subject', 'preheader', 'brandName']);\n\nexport const TemplateEditorScreen = defineComponent({\n\tname: 'FonderieTemplateEditorScreen',\n\tprops: {\n\t\tclient: { type: Object as PropType<CourierAdminClient>, required: true },\n\t\ttype: { type: String, required: true },\n\t\tlocale: { type: String as PropType<string | null>, default: null },\n\t},\n\temits: {\n\t\tsaved: () => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst { template, isLoading, error, refresh } = useTemplate(\n\t\t\tprops.client,\n\t\t\tprops.type,\n\t\t\tprops.locale,\n\t\t);\n\t\t// Saves go through the list composable (which re-fetches the template list\n\t\t// after each write); mounting it adds a template-list fetch to this\n\t\t// single-template editor — acceptable for an admin dashboard. Its\n\t\t// isLoading/error track that list fetch, so the save action keeps local state.\n\t\tconst { saveTemplate } = useTemplates(props.client);\n\t\tconst { revisions, rollback } = useTemplateRevisions(props.client, props.type, props.locale);\n\t\tconst isSaving = ref(false);\n\t\tconst saveError = ref<FonderieApiError | null>(null);\n\n\t\tconst subject = ref('');\n\t\tconst html = ref('');\n\t\tconst text = ref('');\n\t\tconst active = ref(true);\n\n\t\twatch(template, (tpl) => {\n\t\t\tif (!tpl) return;\n\t\t\tsubject.value = tpl.subject ?? '';\n\t\t\thtml.value = tpl.html ?? '';\n\t\t\ttext.value = tpl.text;\n\t\t\tactive.value = tpl.active;\n\t\t});\n\n\t\tconst {\n\t\t\tpreview,\n\t\t\tisPreviewing,\n\t\t\terror: previewError,\n\t\t\trenderPreview,\n\t\t} = useTemplatePreview(props.client);\n\t\t// Sample values as JSON text rather than an object, so a half-typed value\n\t\t// does not have to parse on every keystroke.\n\t\tconst sampleJson = ref('{}');\n\t\tconst sampleError = ref<string | null>(null);\n\n\t\tasync function run() {\n\t\t\tlet data: Record<string, unknown> = {};\n\t\t\ttry {\n\t\t\t\tconst parsed: unknown = JSON.parse(sampleJson.value || '{}');\n\t\t\t\tif (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n\t\t\t\t\tsampleError.value = 'Sample data must be a JSON object.';\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tdata = parsed as Record<string, unknown>;\n\t\t\t\tsampleError.value = null;\n\t\t\t} catch {\n\t\t\t\tsampleError.value = 'Sample data is not valid JSON.';\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst result = await renderPreview(\n\t\t\t\tprops.type,\n\t\t\t\t{\n\t\t\t\t\ttext: text.value,\n\t\t\t\t\tdata,\n\t\t\t\t\t...(subject.value ? { subject: subject.value } : {}),\n\t\t\t\t\t...(html.value ? { html: html.value } : {}),\n\t\t\t\t},\n\t\t\t\tprops.locale,\n\t\t\t);\n\t\t\t// The server reports which variables this content uses; seed the ones\n\t\t\t// with no value yet with their own name so the render shows where each\n\t\t\t// lands. Never overwrite something already typed.\n\t\t\tconst missing = result.variables.filter((v) => !IMPLICIT.has(v) && !(v in data));\n\t\t\tif (missing.length > 0) {\n\t\t\t\tsampleJson.value = JSON.stringify(\n\t\t\t\t\t{ ...data, ...Object.fromEntries(missing.map((v) => [v, v])) },\n\t\t\t\t\tnull,\n\t\t\t\t\t2,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// The preview is always live: it renders once the template loads, then\n\t\t// again PREVIEW_DEBOUNCE_MS after the last edit to the content or the sample\n\t\t// data — debounced, so typing a paragraph costs one request, not one per key.\n\t\tlet previewTimer: ReturnType<typeof setTimeout> | undefined;\n\t\twatch([template, subject, html, text, sampleJson], () => {\n\t\t\tif (!template.value) return;\n\t\t\tclearTimeout(previewTimer);\n\t\t\tpreviewTimer = setTimeout(() => void run(), PREVIEW_DEBOUNCE_MS);\n\t\t});\n\n\t\t// Saving what is already stored would only mint an identical version (the\n\t\t// server treats it as a no-op anyway), so Save waits for a real change.\n\t\tconst dirty = computed(() => {\n\t\t\tconst tpl = template.value;\n\t\t\treturn (\n\t\t\t\t!!tpl &&\n\t\t\t\t(subject.value !== (tpl.subject ?? '') ||\n\t\t\t\t\thtml.value !== (tpl.html ?? '') ||\n\t\t\t\t\ttext.value !== tpl.text ||\n\t\t\t\t\tactive.value !== tpl.active)\n\t\t\t);\n\t\t});\n\n\t\tasync function handleSubmit(event: Event) {\n\t\t\tevent.preventDefault();\n\t\t\tisSaving.value = true;\n\t\t\tsaveError.value = null;\n\t\t\ttry {\n\t\t\t\tconst input: ISetTemplateInput = { text: text.value, active: active.value };\n\t\t\t\tif (subject.value) input.subject = subject.value;\n\t\t\t\tif (html.value) input.html = html.value;\n\t\t\t\tif (template.value?.version !== undefined) input.ifVersion = template.value.version;\n\t\t\t\tawait saveTemplate(props.type, input, props.locale);\n\t\t\t\t// The list composable refreshes its own list; this screen renders the\n\t\t\t\t// single template, so re-read it too.\n\t\t\t\tawait refresh();\n\t\t\t\temit('saved');\n\t\t\t} catch (err) {\n\t\t\t\t// useTemplates normalizes every failure to FonderieApiError before throwing.\n\t\t\t\tsaveError.value = err as FonderieApiError;\n\t\t\t} finally {\n\t\t\t\tisSaving.value = false;\n\t\t\t}\n\t\t}\n\n\t\tfunction renderRevision(rev: ITemplateRevision) {\n\t\t\treturn h('li', { key: rev.version, style: styles.revisionRow }, [\n\t\t\t\th(\n\t\t\t\t\t'span',\n\t\t\t\t\t`v${rev.version} — ${rev.actor ?? 'unknown'} — ${new Date(rev.createdAt).toLocaleString()}`,\n\t\t\t\t),\n\t\t\t\th(\n\t\t\t\t\t'button',\n\t\t\t\t\t{ type: 'button', style: styles.rollbackButton, onClick: () => rollback(rev.version) },\n\t\t\t\t\t'Roll back',\n\t\t\t\t),\n\t\t\t]);\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (isLoading.value) return h('p', { style: styles.status }, 'Loading template…');\n\t\t\tif (error.value)\n\t\t\t\treturn h('p', { style: styles.error, role: 'alert' }, error.value.explanation);\n\n\t\t\treturn h('div', { style: styles.container }, [\n\t\t\t\th('h1', { style: styles.title }, props.type),\n\t\t\t\th(\n\t\t\t\t\t'p',\n\t\t\t\t\t{ style: styles.meta },\n\t\t\t\t\t`${props.locale ?? 'base'} · v${template.value?.version ?? 1}`,\n\t\t\t\t),\n\t\t\t\th('div', { style: styles.split }, [\n\t\t\t\th('div', { style: styles.column }, [\n\t\t\t\th('form', { style: styles.form, onSubmit: handleSubmit }, [\n\t\t\t\t\th('label', { style: styles.label, for: 'template-subject' }, 'Subject'),\n\t\t\t\t\th('input', {\n\t\t\t\t\t\tid: 'template-subject',\n\t\t\t\t\t\tstyle: styles.input,\n\t\t\t\t\t\tvalue: subject.value,\n\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\tsubject.value = (e.target as HTMLInputElement).value;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\th('label', { style: styles.label, for: 'template-html' }, 'HTML body'),\n\t\t\t\t\th('textarea', {\n\t\t\t\t\t\tid: 'template-html',\n\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\trows: 8,\n\t\t\t\t\t\tvalue: html.value,\n\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\thtml.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\th('label', { style: styles.label, for: 'template-text' }, 'Plain-text body'),\n\t\t\t\t\th('textarea', {\n\t\t\t\t\t\tid: 'template-text',\n\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\trows: 4,\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tvalue: text.value,\n\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\ttext.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\th('label', { style: styles.checkboxLabel }, [\n\t\t\t\t\t\th('input', {\n\t\t\t\t\t\t\ttype: 'checkbox',\n\t\t\t\t\t\t\tchecked: active.value,\n\t\t\t\t\t\t\tonChange: (e: Event) => {\n\t\t\t\t\t\t\t\tactive.value = (e.target as HTMLInputElement).checked;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t'Active',\n\t\t\t\t\t]),\n\t\t\t\t\tsaveError.value\n\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, saveError.value.explanation)\n\t\t\t\t\t\t: null,\n\t\t\t\t\th('div', { style: styles.saveRow }, [\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'submit',\n\t\t\t\t\t\t\t\tdisabled: isSaving.value || !dirty.value,\n\t\t\t\t\t\t\t\tstyle: dirty.value ? styles.button : styles.buttonDisabled,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tisSaving.value ? 'Saving…' : 'Save',\n\t\t\t\t\t\t),\n\t\t\t\t\t\t!dirty.value && !isSaving.value ? h('span', { style: styles.meta }, 'No changes to save') : null,\n\t\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t\th('label', { style: styles.label, for: 'template-sample' }, 'Sample data'),\n\t\t\t\th('textarea', {\n\t\t\t\t\tid: 'template-sample',\n\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\trows: 6,\n\t\t\t\t\tspellcheck: false,\n\t\t\t\t\tvalue: sampleJson.value,\n\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\tsampleJson.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\tsampleError.value\n\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, sampleError.value)\n\t\t\t\t\t: null,\n\t\t\t\t]),\n\t\t\t\th('div', { style: styles.previewColumn }, [\n\t\t\t\t\th('div', { style: styles.previewHeader }, [\n\t\t\t\t\t\th('span', { style: styles.label }, 'Preview'),\n\t\t\t\t\t\th('span', { style: styles.meta }, isPreviewing.value ? 'Rendering…' : 'Live'),\n\t\t\t\t\t]),\n\t\t\t\t\tpreviewError.value\n\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, previewError.value.explanation)\n\t\t\t\t\t\t: null,\n\t\t\t\t\tpreview.value?.subject\n\t\t\t\t\t\t? h('p', { style: styles.previewSubject }, preview.value.subject)\n\t\t\t\t\t\t: null,\n\t\t\t\t\tpreview.value?.html\n\t\t\t\t\t\t? // sandbox= — no scripts, no same-origin. Operator-authored HTML\n\t\t\t\t\t\t\t// must never execute in the dashboard's origin, where the admin\n\t\t\t\t\t\t\t// token lives.\n\t\t\t\t\t\t\th('iframe', {\n\t\t\t\t\t\t\t\ttitle: 'Template preview',\n\t\t\t\t\t\t\t\tstyle: styles.previewFrame,\n\t\t\t\t\t\t\t\tsandbox: '',\n\t\t\t\t\t\t\t\tsrcdoc: preview.value.html,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: preview.value\n\t\t\t\t\t\t\t? h('pre', { style: styles.previewText }, preview.value.text)\n\t\t\t\t\t\t\t: h('p', { style: styles.meta }, 'Nothing rendered yet.'),\n\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t\trevisions.value.length > 0\n\t\t\t\t\t? h('div', { style: styles.revisions }, [\n\t\t\t\t\t\t\th('h2', { style: styles.subtitle }, 'History'),\n\t\t\t\t\t\t\th('ul', { style: styles.list }, revisions.value.map(renderRevision)),\n\t\t\t\t\t\t])\n\t\t\t\t\t: null,\n\t\t\t]);\n\t\t};\n\t},\n});\n","import type { CSSProperties } from 'vue';\n\nexport const styles: Record<string, CSSProperties> = {\n\tcontainer: { padding: '24px' },\n\t// Two columns, always: editor left, rendered result right. Stacking the\n\t// preview under a long form hid it below the fold.\n\tsplit: { display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)', gap: '24px', alignItems: 'start' },\n\tcolumn: { minWidth: '0', display: 'flex', flexDirection: 'column' },\n\t// Pinned while the form scrolls, so the preview stays in view as you edit.\n\tpreviewColumn: { minWidth: '0', display: 'flex', flexDirection: 'column', position: 'sticky', top: '16px' },\n\tsaveRow: { display: 'flex', alignItems: 'center', gap: '12px', marginTop: '16px' },\n\tpreviewHeader: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tmarginTop: '12px',\n\t},\n\tpreviewSubject: { fontSize: '14px', fontWeight: '600', margin: '8px 0' },\n\tpreviewFrame: {\n\t\twidth: '100%',\n\t\theight: '520px',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t},\n\tpreviewText: {\n\t\twhiteSpace: 'pre-wrap',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tpadding: '12px',\n\t\tfontSize: '13px',\n\t\tfontFamily: 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\t},\n\ttitle: { fontSize: '24px', fontWeight: 700 },\n\tsubtitle: { fontSize: '16px', fontWeight: 600, marginBottom: '8px' },\n\tmeta: { fontSize: '13px', color: 'var(--fonderie-text-muted,#5c5c5c)', marginBottom: '16px' },\n\tstatus: { padding: '24px', textAlign: 'center', color: 'var(--fonderie-text-muted,#5c5c5c)' },\n\terror: { color: 'var(--fonderie-danger,#e00)', marginBottom: '12px', fontSize: '14px' },\n\tlist: { listStyle: 'none', padding: '0', margin: '0' },\n\trow: { borderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)' },\n\trowButton: {\n\t\twidth: '100%',\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tpadding: '12px 0',\n\t\tbackground: 'none',\n\t\tborder: 'none',\n\t\tcursor: 'pointer',\n\t\ttextAlign: 'left',\n\t},\n\ttype: { fontSize: '14px', fontWeight: 600, flex: '1' },\n\tlocale: { fontSize: '13px', color: 'var(--fonderie-text-muted,#5c5c5c)', marginRight: '16px' },\n\tactive: { fontSize: '12px', color: 'var(--fonderie-accent-strong,#009767)' },\n\tinactive: { fontSize: '12px', color: 'var(--fonderie-text-muted,#5c5c5c)' },\n\tform: { display: 'flex', flexDirection: 'column', gap: '4px' },\n\tlabel: { fontSize: '13px', fontWeight: 600, marginTop: '12px' },\n\tinput: { border: '1px solid var(--fonderie-border,#e0e0e0)', borderRadius: '8px', padding: '10px', fontSize: '14px' },\n\ttextarea: {\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tpadding: '10px',\n\t\tfontSize: '14px',\n\t\tfontFamily: 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\t},\n\tcheckboxLabel: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tgap: '8px',\n\t\tmarginTop: '12px',\n\t\tfontSize: '14px',\n\t},\n\tbutton: {\n\t\tbackgroundColor: 'var(--fonderie-text,#171717)',\n\t\tcolor: 'var(--fonderie-surface,#fff)',\n\t\tpadding: '10px 20px',\n\t\tborderRadius: '8px',\n\t\tborder: 'none',\n\t\tfontSize: '14px',\n\t\tfontWeight: 600,\n\t\tcursor: 'pointer',\n\t\talignSelf: 'flex-start',\n\t},\n\tbuttonDisabled: {\n\t\tbackgroundColor: 'var(--fonderie-border,#e0e0e0)',\n\t\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n\t\tpadding: '10px 20px',\n\t\tborderRadius: '8px',\n\t\tborder: 'none',\n\t\tfontSize: '14px',\n\t\tfontWeight: 600,\n\t\tcursor: 'not-allowed',\n\t\talignSelf: 'flex-start',\n\t},\n\trevisions: { marginTop: '32px' },\n\trevisionRow: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tpadding: '8px 0',\n\t\tborderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)',\n\t\tfontSize: '13px',\n\t},\n\trollbackButton: {\n\t\tbackground: 'none',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '8px',\n\t\tpadding: '4px 10px',\n\t\tfontSize: '12px',\n\t\tcursor: 'pointer',\n\t},\n};\n","import type { CourierAdminClient, ITemplateEntry } from '@fonderie/client';\nimport { useTemplates } from '@fonderie/vue-courier-admin';\nimport type { PropType } from 'vue';\nimport { defineComponent, h } from 'vue';\nimport { styles } from '../styles';\n\nexport const TemplateListScreen = defineComponent({\n\tname: 'FonderieTemplateListScreen',\n\tprops: {\n\t\tclient: { type: Object as PropType<CourierAdminClient>, required: true },\n\t},\n\temits: {\n\t\t'select-template': (_template: ITemplateEntry) => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst { templates, isLoading, error } = useTemplates(props.client);\n\n\t\tfunction renderRow(template: ITemplateEntry) {\n\t\t\treturn h('li', { key: `${template.type}:${template.locale ?? 'base'}`, style: styles.row }, [\n\t\t\t\th(\n\t\t\t\t\t'button',\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\tstyle: styles.rowButton,\n\t\t\t\t\t\tonClick: () => emit('select-template', template),\n\t\t\t\t\t},\n\t\t\t\t\t[\n\t\t\t\t\t\th('span', { style: styles.type }, template.type),\n\t\t\t\t\t\th('span', { style: styles.locale }, template.locale ?? 'base'),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t'span',\n\t\t\t\t\t\t\t{ style: template.active ? styles.active : styles.inactive },\n\t\t\t\t\t\t\ttemplate.active ? 'Active' : 'Inactive',\n\t\t\t\t\t\t),\n\t\t\t\t\t],\n\t\t\t\t),\n\t\t\t]);\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (isLoading.value) return h('p', { style: styles.status }, 'Loading templates…');\n\t\t\tif (error.value)\n\t\t\t\treturn h('p', { style: styles.error, role: 'alert' }, error.value.explanation);\n\n\t\t\treturn h('div', { style: styles.container }, [\n\t\t\t\th('h1', { style: styles.title }, 'Templates'),\n\t\t\t\th('ul', { style: styles.list }, templates.value.map(renderRow)),\n\t\t\t]);\n\t\t};\n\t},\n});\n"],"mappings":"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","names":["useTemplates","defineComponent","h","defineComponent","useTemplates","h"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fonderie/vue-courier-admin-screens",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Pre-built Vue screens for the Fonderie courier admin API — template list, template editor with revision history and rollback.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fonderiejs",
|