@fonderie/vue-courier-admin-screens 0.8.0 → 0.9.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/dist/index.cjs +164 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -6
- package/dist/index.d.ts +36 -6
- package/dist/index.js +171 -40
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -414,6 +414,34 @@ var import_vue_courier_admin = require("@fonderie/vue-courier-admin");
|
|
|
414
414
|
var import_vue2 = require("vue");
|
|
415
415
|
var PREVIEW_DEBOUNCE_MS = 500;
|
|
416
416
|
var IMPLICIT = /* @__PURE__ */ new Set(["subject", "preheader", "brandName"]);
|
|
417
|
+
var tab = {
|
|
418
|
+
height: "32px",
|
|
419
|
+
padding: "0 10px",
|
|
420
|
+
background: "none",
|
|
421
|
+
border: "none",
|
|
422
|
+
borderBottom: "2px solid transparent",
|
|
423
|
+
color: "var(--fonderie-text-muted,#5c5c5c)",
|
|
424
|
+
fontSize: "13px",
|
|
425
|
+
fontFamily: 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace)',
|
|
426
|
+
cursor: "pointer"
|
|
427
|
+
};
|
|
428
|
+
var tabSelected = {
|
|
429
|
+
...tab,
|
|
430
|
+
color: "var(--fonderie-text,#171717)",
|
|
431
|
+
fontWeight: 600,
|
|
432
|
+
borderBottomColor: "var(--fonderie-text,#171717)",
|
|
433
|
+
cursor: "default"
|
|
434
|
+
};
|
|
435
|
+
var tabInactive = { ...tab, opacity: 0.55, textDecoration: "line-through" };
|
|
436
|
+
var tabBar = {
|
|
437
|
+
display: "flex",
|
|
438
|
+
alignItems: "flex-end",
|
|
439
|
+
gap: "12px",
|
|
440
|
+
borderBottom: "1px solid var(--fonderie-border,#e0e0e0)",
|
|
441
|
+
margin: "4px 0 12px",
|
|
442
|
+
paddingBottom: "6px"
|
|
443
|
+
};
|
|
444
|
+
var tabs = { display: "flex", flexWrap: "wrap", gap: "4px", marginBottom: "-7px" };
|
|
417
445
|
var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
418
446
|
name: "FonderieTemplateEditorScreen",
|
|
419
447
|
props: {
|
|
@@ -425,8 +453,13 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
425
453
|
* be edited and rolled back, never deleted — Delete is not offered.
|
|
426
454
|
*/
|
|
427
455
|
system: { type: Boolean, default: false },
|
|
428
|
-
/** Shows "+ Add locale"
|
|
456
|
+
/** Shows "+ Add locale" (emits add-locale). */
|
|
429
457
|
allowAddLocale: { type: Boolean, default: false },
|
|
458
|
+
/**
|
|
459
|
+
* Shows a tab per locale this email exists in (emits select-locale).
|
|
460
|
+
* Unsaved edits are confirmed before switching away.
|
|
461
|
+
*/
|
|
462
|
+
localeTabs: { type: Boolean, default: false },
|
|
430
463
|
/** The console language (`locale` is the template's); defaults to English. */
|
|
431
464
|
uiLocale: { type: String, default: void 0 }
|
|
432
465
|
},
|
|
@@ -434,8 +467,13 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
434
467
|
saved: () => true,
|
|
435
468
|
/** The template was deleted and no longer exists. */
|
|
436
469
|
deleted: () => true,
|
|
437
|
-
/**
|
|
438
|
-
|
|
470
|
+
/**
|
|
471
|
+
* Create a translation of this template. `locales` are the ones the app
|
|
472
|
+
* uses elsewhere that this email lacks — suggest them first.
|
|
473
|
+
*/
|
|
474
|
+
"add-locale": (_type, _context) => true,
|
|
475
|
+
/** Open another locale of this email. */
|
|
476
|
+
"select-locale": (_template) => true
|
|
439
477
|
},
|
|
440
478
|
setup(props, { emit }) {
|
|
441
479
|
const t = (key, params) => (0, import_client2.createAdminT)(props.uiLocale)(key, params);
|
|
@@ -444,7 +482,10 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
444
482
|
props.type,
|
|
445
483
|
props.locale
|
|
446
484
|
);
|
|
447
|
-
const { saveTemplate, removeTemplate } = (0, import_vue_courier_admin.useTemplates)(props.client);
|
|
485
|
+
const { templates, saveTemplate, removeTemplate } = (0, import_vue_courier_admin.useTemplates)(props.client);
|
|
486
|
+
const siblings = (0, import_vue2.computed)(
|
|
487
|
+
() => (0, import_client2.groupTemplatesByType)(templates.value).find((g) => g.type === props.type)?.entries ?? []
|
|
488
|
+
);
|
|
448
489
|
const isDeleting = (0, import_vue2.ref)(false);
|
|
449
490
|
const { revisions, rollback } = (0, import_vue_courier_admin.useTemplateRevisions)(props.client, props.type, props.locale);
|
|
450
491
|
const isSaving = (0, import_vue2.ref)(false);
|
|
@@ -529,6 +570,51 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
529
570
|
isSaving.value = false;
|
|
530
571
|
}
|
|
531
572
|
}
|
|
573
|
+
const leave = () => !dirty.value || window.confirm(t("templates.editor.discardChanges"));
|
|
574
|
+
function renderTabBar() {
|
|
575
|
+
if (!props.localeTabs && !props.allowAddLocale) return null;
|
|
576
|
+
return (0, import_vue2.h)("div", { style: tabBar }, [
|
|
577
|
+
props.localeTabs ? (
|
|
578
|
+
// Each tab opens another stored row, so this is navigation, not an
|
|
579
|
+
// ARIA tablist: plain buttons, the open one marked aria-current.
|
|
580
|
+
(0, import_vue2.h)(
|
|
581
|
+
"nav",
|
|
582
|
+
{ "aria-label": t("templates.editor.locales"), style: tabs },
|
|
583
|
+
siblings.value.map((entry) => {
|
|
584
|
+
const selected = entry.locale === (props.locale ?? null);
|
|
585
|
+
return (0, import_vue2.h)(
|
|
586
|
+
"button",
|
|
587
|
+
{
|
|
588
|
+
key: entry.locale ?? "",
|
|
589
|
+
type: "button",
|
|
590
|
+
"aria-current": selected ? "true" : void 0,
|
|
591
|
+
style: selected ? tabSelected : entry.active ? tab : tabInactive,
|
|
592
|
+
title: entry.active ? void 0 : t("common.status.inactive"),
|
|
593
|
+
onClick: () => {
|
|
594
|
+
if (!selected && leave()) emit("select-locale", entry);
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
entry.locale ?? t("templates.defaultChip")
|
|
598
|
+
);
|
|
599
|
+
})
|
|
600
|
+
)
|
|
601
|
+
) : null,
|
|
602
|
+
props.allowAddLocale ? (0, import_vue2.h)(
|
|
603
|
+
"button",
|
|
604
|
+
{
|
|
605
|
+
type: "button",
|
|
606
|
+
style: { ...styles.rollbackButton, marginLeft: "auto" },
|
|
607
|
+
onClick: () => {
|
|
608
|
+
if (leave())
|
|
609
|
+
emit("add-locale", props.type, {
|
|
610
|
+
locales: (0, import_client2.missingTemplateLocales)(templates.value, props.type)
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
},
|
|
614
|
+
t("templates.editor.addLocale")
|
|
615
|
+
) : null
|
|
616
|
+
]);
|
|
617
|
+
}
|
|
532
618
|
async function handleDelete() {
|
|
533
619
|
const message = props.locale ? t("templates.editor.confirmDeleteLocale", { locale: props.locale, type: props.type }) : t("templates.editor.confirmDelete", { type: props.type });
|
|
534
620
|
if (!window.confirm(message)) return;
|
|
@@ -561,22 +647,8 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
561
647
|
if (error.value)
|
|
562
648
|
return (0, import_vue2.h)("p", { style: styles.error, role: "alert" }, error.value.explanation);
|
|
563
649
|
return (0, import_vue2.h)("div", { style: styles.container }, [
|
|
564
|
-
(0, import_vue2.h)(
|
|
565
|
-
|
|
566
|
-
{ style: { display: "flex", alignItems: "center", gap: "12px", flexWrap: "wrap" } },
|
|
567
|
-
[
|
|
568
|
-
(0, import_vue2.h)("h1", { style: styles.title }, props.type),
|
|
569
|
-
props.allowAddLocale && !props.locale ? (0, import_vue2.h)(
|
|
570
|
-
"button",
|
|
571
|
-
{
|
|
572
|
-
type: "button",
|
|
573
|
-
style: { ...styles.rollbackButton, marginLeft: "auto" },
|
|
574
|
-
onClick: () => emit("add-locale", props.type)
|
|
575
|
-
},
|
|
576
|
-
t("templates.editor.addLocale")
|
|
577
|
-
) : null
|
|
578
|
-
]
|
|
579
|
-
),
|
|
650
|
+
(0, import_vue2.h)("h1", { style: styles.title }, props.type),
|
|
651
|
+
renderTabBar(),
|
|
580
652
|
(0, import_vue2.h)("p", { style: styles.meta }, [
|
|
581
653
|
(0, import_vue2.h)("strong", props.locale ?? t("templates.defaultLocale")),
|
|
582
654
|
` \xB7 v${template.value?.version ?? 1}`,
|
|
@@ -669,7 +741,11 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
669
741
|
) : null
|
|
670
742
|
])
|
|
671
743
|
]),
|
|
672
|
-
(0, import_vue2.h)(
|
|
744
|
+
(0, import_vue2.h)(
|
|
745
|
+
"label",
|
|
746
|
+
{ style: styles.label, for: "template-sample" },
|
|
747
|
+
t("templates.editor.sampleData")
|
|
748
|
+
),
|
|
673
749
|
(0, import_vue2.h)("textarea", {
|
|
674
750
|
id: "template-sample",
|
|
675
751
|
style: styles.textarea,
|
|
@@ -685,7 +761,11 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
685
761
|
(0, import_vue2.h)("div", { style: styles.previewColumn }, [
|
|
686
762
|
(0, import_vue2.h)("div", { style: styles.previewHeader }, [
|
|
687
763
|
(0, import_vue2.h)("span", { style: styles.label }, t("templates.editor.preview")),
|
|
688
|
-
(0, import_vue2.h)(
|
|
764
|
+
(0, import_vue2.h)(
|
|
765
|
+
"span",
|
|
766
|
+
{ style: styles.meta },
|
|
767
|
+
isPreviewing.value ? t("templates.editor.rendering") : t("templates.editor.live")
|
|
768
|
+
)
|
|
689
769
|
]),
|
|
690
770
|
previewError.value ? (0, import_vue2.h)("p", { style: styles.error, role: "alert" }, previewError.value.explanation) : null,
|
|
691
771
|
preview.value?.subject ? (0, import_vue2.h)("p", { style: styles.previewSubject }, preview.value.subject) : null,
|
|
@@ -723,6 +803,33 @@ var builtIn = {
|
|
|
723
803
|
border: "1px solid var(--fonderie-border,#e0e0e0)",
|
|
724
804
|
color: "var(--fonderie-text-muted,#5c5c5c)"
|
|
725
805
|
};
|
|
806
|
+
var chip = {
|
|
807
|
+
height: "24px",
|
|
808
|
+
boxSizing: "border-box",
|
|
809
|
+
padding: "0 8px",
|
|
810
|
+
borderRadius: "6px",
|
|
811
|
+
border: "1px solid var(--fonderie-border,#e0e0e0)",
|
|
812
|
+
background: "var(--fonderie-surface,#fff)",
|
|
813
|
+
color: "var(--fonderie-text,#171717)",
|
|
814
|
+
fontSize: "12px",
|
|
815
|
+
fontFamily: 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace)',
|
|
816
|
+
cursor: "pointer"
|
|
817
|
+
};
|
|
818
|
+
var chipInactive = { ...chip, opacity: 0.5, textDecoration: "line-through" };
|
|
819
|
+
var row = {
|
|
820
|
+
...styles.row,
|
|
821
|
+
display: "flex",
|
|
822
|
+
alignItems: "center",
|
|
823
|
+
gap: "8px",
|
|
824
|
+
paddingRight: "16px"
|
|
825
|
+
};
|
|
826
|
+
var rowButton = { ...styles.rowButton, width: "auto", flex: "1", minWidth: "0" };
|
|
827
|
+
var chips = {
|
|
828
|
+
display: "flex",
|
|
829
|
+
flexWrap: "wrap",
|
|
830
|
+
justifyContent: "flex-end",
|
|
831
|
+
gap: "6px"
|
|
832
|
+
};
|
|
726
833
|
var newButton = {
|
|
727
834
|
display: "inline-flex",
|
|
728
835
|
alignItems: "center",
|
|
@@ -748,7 +855,10 @@ var TemplateListScreen = (0, import_vue3.defineComponent)({
|
|
|
748
855
|
locale: { type: String, default: void 0 }
|
|
749
856
|
},
|
|
750
857
|
emits: {
|
|
751
|
-
/**
|
|
858
|
+
/**
|
|
859
|
+
* The whole row — type AND locale, and whether it is built-in. One row
|
|
860
|
+
* per email: the row opens the default locale, a locale chip that locale.
|
|
861
|
+
*/
|
|
752
862
|
"select-template": (_template) => true,
|
|
753
863
|
/** Receives the locales in use, to suggest. */
|
|
754
864
|
"create-template": (_context) => true
|
|
@@ -756,24 +866,44 @@ var TemplateListScreen = (0, import_vue3.defineComponent)({
|
|
|
756
866
|
setup(props, { emit }) {
|
|
757
867
|
const { templates, isLoading, error } = (0, import_vue_courier_admin2.useTemplates)(props.client);
|
|
758
868
|
const t = (key, params) => (0, import_client3.createAdminT)(props.locale)(key, params);
|
|
759
|
-
function renderRow(
|
|
760
|
-
|
|
869
|
+
function renderRow(group) {
|
|
870
|
+
const primary = group.primary;
|
|
871
|
+
return (0, import_vue3.h)("li", { key: group.type, style: row }, [
|
|
761
872
|
(0, import_vue3.h)(
|
|
762
873
|
"button",
|
|
763
874
|
{
|
|
764
875
|
type: "button",
|
|
765
|
-
style:
|
|
766
|
-
onClick: () => emit("select-template",
|
|
876
|
+
style: rowButton,
|
|
877
|
+
onClick: () => emit("select-template", primary)
|
|
767
878
|
},
|
|
768
879
|
[
|
|
769
|
-
(0, import_vue3.h)("span", { style: styles.type },
|
|
770
|
-
(0, import_vue3.h)("span", { style:
|
|
771
|
-
|
|
772
|
-
(0, import_vue3.h)("span", { style: template.active ? styles.active : styles.inactive }, [
|
|
880
|
+
(0, import_vue3.h)("span", { style: styles.type }, group.type),
|
|
881
|
+
group.system ? (0, import_vue3.h)("span", { style: builtIn }, t("templates.builtInBadge")) : null,
|
|
882
|
+
(0, import_vue3.h)("span", { style: primary.active ? styles.active : styles.inactive }, [
|
|
773
883
|
(0, import_vue3.h)("span", { style: styles.dot }),
|
|
774
|
-
|
|
884
|
+
primary.active ? t("common.status.active") : t("common.status.inactive")
|
|
775
885
|
])
|
|
776
886
|
]
|
|
887
|
+
),
|
|
888
|
+
// Siblings of the row button, not inside it: a button cannot hold buttons.
|
|
889
|
+
(0, import_vue3.h)(
|
|
890
|
+
"span",
|
|
891
|
+
{ style: chips },
|
|
892
|
+
group.entries.map((entry) => {
|
|
893
|
+
const name = entry.locale ?? t("templates.defaultChip");
|
|
894
|
+
return (0, import_vue3.h)(
|
|
895
|
+
"button",
|
|
896
|
+
{
|
|
897
|
+
key: entry.locale ?? "",
|
|
898
|
+
type: "button",
|
|
899
|
+
style: entry.active ? chip : chipInactive,
|
|
900
|
+
"aria-label": t("templates.list.openLocale", { type: group.type, locale: name }),
|
|
901
|
+
title: entry.active ? void 0 : t("common.status.inactive"),
|
|
902
|
+
onClick: () => emit("select-template", entry)
|
|
903
|
+
},
|
|
904
|
+
name
|
|
905
|
+
);
|
|
906
|
+
})
|
|
777
907
|
)
|
|
778
908
|
]);
|
|
779
909
|
}
|
|
@@ -807,12 +937,8 @@ var TemplateListScreen = (0, import_vue3.defineComponent)({
|
|
|
807
937
|
) : null
|
|
808
938
|
]
|
|
809
939
|
),
|
|
810
|
-
(0, import_vue3.h)(
|
|
811
|
-
|
|
812
|
-
{ style: styles.hint },
|
|
813
|
-
t("templates.list.hint")
|
|
814
|
-
),
|
|
815
|
-
isLoading.value ? (0, import_vue3.h)("p", { style: styles.status }, t("templates.list.loading")) : error.value ? (0, import_vue3.h)("p", { style: styles.error, role: "alert" }, error.value.explanation) : (0, import_vue3.h)("ul", { style: styles.list }, templates.value.map(renderRow))
|
|
940
|
+
(0, import_vue3.h)("p", { style: styles.hint }, t("templates.list.hint")),
|
|
941
|
+
isLoading.value ? (0, import_vue3.h)("p", { style: styles.status }, t("templates.list.loading")) : error.value ? (0, import_vue3.h)("p", { style: styles.error, role: "alert" }, error.value.explanation) : (0, import_vue3.h)("ul", { style: styles.list }, (0, import_client3.groupTemplatesByType)(templates.value).map(renderRow))
|
|
816
942
|
]);
|
|
817
943
|
}
|
|
818
944
|
});
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/screens/TemplateCreateScreen.ts","../src/styles.ts","../src/screens/TemplateEditorScreen.ts","../src/screens/TemplateListScreen.ts"],"sourcesContent":["export { TemplateCreateScreen, TemplateEditorScreen, TemplateListScreen } from './screens';\n","import type {\n\tAdminLocale,\n\tAdminMessageKey,\n\tAdminMessageParams,\n\tCourierAdminClient,\n\tISetTemplateInput,\n} from '@fonderie/client';\nimport { createAdminT, FonderieApiError } from '@fonderie/client';\nimport type { PropType } from 'vue';\nimport { defineComponent, h, onMounted, ref } from 'vue';\nimport { styles } from '../styles';\n\nconst TYPE_RE = /^[a-z0-9][a-z0-9_-]{0,80}$/;\nconst LOCALE_RE = /^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/;\n\n// Creating is its own screen: the editor loads an existing row, and a new\n// template or locale has none yet. Once saved, the editor takes over.\nexport const TemplateCreateScreen = defineComponent({\n\tname: 'FonderieTemplateCreateScreen',\n\tprops: {\n\t\tclient: { type: Object as PropType<CourierAdminClient>, required: true },\n\t\t/**\n\t\t * Given ⇒ add a LOCALE of this existing template: the type is fixed and the\n\t\t * form starts from its default-locale copy. Omitted ⇒ a brand-new template\n\t\t * type (one the app sends that has no stored copy yet).\n\t\t */\n\t\ttype: { type: String, default: undefined },\n\t\t/** Locales already in use, offered as suggestions. */\n\t\tlocales: { type: Array as PropType<string[]>, default: () => [] },\n\t\t/** The console language; defaults to English. */\n\t\tlocale: { type: String as PropType<AdminLocale>, default: undefined },\n\t},\n\temits: {\n\t\t/** What was created, so the caller can open it in the editor. */\n\t\tcreated: (_created: { type: string; locale: string | null }) => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst addingLocale = props.type !== undefined;\n\t\tconst newType = ref('');\n\t\tconst targetLocale = ref('');\n\t\tconst subject = ref('');\n\t\tconst html = ref('');\n\t\tconst text = ref('');\n\t\tconst error = ref<string | null>(null);\n\t\tconst busy = ref(false);\n\t\t// `tr`, not `t`: submit() uses `t` for the template type.\n\t\tconst tr = (key: AdminMessageKey, params?: AdminMessageParams) =>\n\t\t\tcreateAdminT(props.locale)(key, params);\n\n\t\t// A new locale starts from the default copy, so translating is editing.\n\t\tonMounted(() => {\n\t\t\tif (!props.type) return;\n\t\t\tprops.client\n\t\t\t\t.getTemplate(props.type, null)\n\t\t\t\t.then(({ result }) => {\n\t\t\t\t\tsubject.value = result.subject ?? '';\n\t\t\t\t\thtml.value = result.html ?? '';\n\t\t\t\t\ttext.value = result.text;\n\t\t\t\t})\n\t\t\t\t.catch(() => undefined);\n\t\t});\n\n\t\tasync function submit(e: Event) {\n\t\t\te.preventDefault();\n\t\t\terror.value = null;\n\t\t\tconst t = addingLocale ? (props.type as string) : newType.value.trim();\n\t\t\tconst l = targetLocale.value.trim() || null;\n\t\t\tif (!TYPE_RE.test(t)) {\n\t\t\t\terror.value = tr('templates.create.errorType');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (addingLocale && !l) {\n\t\t\t\terror.value = tr('templates.create.errorLocaleRequired');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (l && !LOCALE_RE.test(l)) {\n\t\t\t\terror.value = tr('templates.create.errorLocale');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!text.value.trim()) {\n\t\t\t\terror.value = tr('templates.create.errorText');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbusy.value = true;\n\t\t\ttry {\n\t\t\t\t// Refuse to overwrite: creating an existing row would replace it.\n\t\t\t\tconst exists = await props.client.getTemplate(t, l).then(\n\t\t\t\t\t() => true,\n\t\t\t\t\t(err: unknown) => !(err instanceof FonderieApiError && err.status === 404),\n\t\t\t\t);\n\t\t\t\tif (exists) {\n\t\t\t\t\terror.value = l\n\t\t\t\t\t\t? tr('templates.create.existsLocale', { type: t, locale: l })\n\t\t\t\t\t\t: tr('templates.create.exists', { type: t });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst input: ISetTemplateInput = { text: text.value, active: true };\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\tawait props.client.setTemplate(t, input, l);\n\t\t\t\temit('created', { type: t, locale: l });\n\t\t\t} catch (err) {\n\t\t\t\terror.value = err instanceof FonderieApiError ? err.explanation : String(err);\n\t\t\t} finally {\n\t\t\t\tbusy.value = false;\n\t\t\t}\n\t\t}\n\n\t\tconst field = (\n\t\t\tid: string,\n\t\t\tlabel: string,\n\t\t\tmodel: typeof subject,\n\t\t\topts: Record<string, unknown> = {},\n\t\t) => [\n\t\t\th('label', { style: styles.label, for: id }, label),\n\t\t\th(opts.textarea ? 'textarea' : 'input', {\n\t\t\t\tid,\n\t\t\t\tstyle: opts.textarea ? { ...styles.textarea, minHeight: opts.minHeight } : styles.input,\n\t\t\t\tvalue: model.value,\n\t\t\t\tautocomplete: 'off',\n\t\t\t\tspellcheck: false,\n\t\t\t\t...(opts.placeholder ? { placeholder: opts.placeholder } : {}),\n\t\t\t\t...(opts.list ? { list: opts.list } : {}),\n\t\t\t\tonInput: (ev: Event) => {\n\t\t\t\t\tmodel.value = (ev.target as HTMLInputElement).value;\n\t\t\t\t},\n\t\t\t}),\n\t\t];\n\n\t\treturn () =>\n\t\t\th('div', { style: { ...styles.container, maxWidth: '760px' } }, [\n\t\t\t\th(\n\t\t\t\t\t'h1',\n\t\t\t\t\t{ style: styles.title },\n\t\t\t\t\taddingLocale\n\t\t\t\t\t\t? tr('templates.create.titleLocale', { type: props.type as string })\n\t\t\t\t\t\t: tr('templates.create.titleNew'),\n\t\t\t\t),\n\t\t\t\th(\n\t\t\t\t\t'p',\n\t\t\t\t\t{ style: { ...styles.meta, lineHeight: 1.5 } },\n\t\t\t\t\taddingLocale\n\t\t\t\t\t\t? tr('templates.create.hintLocale')\n\t\t\t\t\t\t: tr('templates.create.hintNew'),\n\t\t\t\t),\n\t\t\t\th('form', { style: styles.form, onSubmit: (ev: Event) => void submit(ev) }, [\n\t\t\t\t\t...(addingLocale\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: field('new-template-type', tr('templates.create.type'), newType, { placeholder: 'weekly-digest' })),\n\t\t\t\t\t...field(\n\t\t\t\t\t\t'new-template-locale',\n\t\t\t\t\t\taddingLocale ? tr('templates.create.locale') : tr('templates.create.localeOptional'),\n\t\t\t\t\t\ttargetLocale,\n\t\t\t\t\t\t{ placeholder: 'fr', list: 'new-template-locales' },\n\t\t\t\t\t),\n\t\t\t\t\th(\n\t\t\t\t\t\t'datalist',\n\t\t\t\t\t\t{ id: 'new-template-locales' },\n\t\t\t\t\t\t[...new Set(props.locales)].map((l) => h('option', { key: l, value: l })),\n\t\t\t\t\t),\n\t\t\t\t\t...field('new-template-subject', tr('templates.subject'), subject),\n\t\t\t\t\t...field('new-template-html', tr('templates.htmlBody'), html, { textarea: true, minHeight: '160px' }),\n\t\t\t\t\t...field('new-template-text', tr('templates.textBody'), text, {\n\t\t\t\t\t\ttextarea: true,\n\t\t\t\t\t\tminHeight: '100px',\n\t\t\t\t\t}),\n\t\t\t\t\terror.value ? h('p', { style: styles.error, role: 'alert' }, error.value) : null,\n\t\t\t\t\th(\n\t\t\t\t\t\t'button',\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'submit',\n\t\t\t\t\t\t\tdisabled: busy.value,\n\t\t\t\t\t\t\tstyle: { ...styles.button, marginTop: '16px' },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbusy.value\n\t\t\t\t\t\t\t? tr('templates.create.creating')\n\t\t\t\t\t\t\t: addingLocale\n\t\t\t\t\t\t\t\t? tr('templates.create.submitLocale')\n\t\t\t\t\t\t\t\t: tr('templates.create.submitNew'),\n\t\t\t\t\t),\n\t\t\t\t]),\n\t\t\t]);\n\t},\n});\n","import type { CSSProperties } from 'vue';\n\nexport const styles: Record<string, CSSProperties> = {\n\tcontainer: { padding: '8px 40px 64px', maxWidth: '1400px', boxSizing: 'border-box' },\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: {\n\t\tdisplay: 'grid',\n\t\tgridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)',\n\t\tgap: '24px',\n\t\talignItems: 'start',\n\t},\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: {\n\t\tminWidth: '0',\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tposition: 'sticky',\n\t\ttop: '16px',\n\t},\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\tboxShadow: 'var(--fonderie-shadow-card,0 2px 3px 0 rgba(0,0,0,.05))',\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:\n\t\t\t'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\t},\n\ttitle: {\n\t\tfontSize: '22px',\n\t\tfontWeight: 600,\n\t\tmargin: '8px 0 4px',\n\t\tletterSpacing: 'var(--fonderie-tracking-display,-0.05em)',\n\t\tlineHeight: 1.25,\n\t},\n\tsubtitle: {\n\t\tfontSize: '15px',\n\t\tfontWeight: 600,\n\t\tmargin: '0 0 10px',\n\t\tletterSpacing: 'var(--fonderie-tracking-display,-0.05em)',\n\t},\n\tmeta: { fontSize: '13px', color: 'var(--fonderie-text-muted,#5c5c5c)', marginBottom: '20px' },\n\tstatus: { padding: '24px 0', color: 'var(--fonderie-text-muted,#5c5c5c)', fontSize: '13.5px' },\n\terror: {\n\t\tcolor: 'var(--fonderie-danger,#e00)',\n\t\tbackground: 'color-mix(in srgb, var(--fonderie-danger,#e00) 8%, transparent)',\n\t\tborderRadius: '6px',\n\t\tpadding: '8px 12px',\n\t\tmargin: '8px 0',\n\t\tfontSize: '13.5px',\n\t},\n\tlist: {\n\t\tlistStyle: 'none',\n\t\tpadding: '0',\n\t\tmargin: '0',\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 'var(--fonderie-radius-lg,8px)',\n\t\toverflow: 'hidden',\n\t\tboxShadow: 'var(--fonderie-shadow-card,0 2px 3px 0 rgba(0,0,0,.05))',\n\t},\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\tgap: '16px',\n\t\tpadding: '13px 16px',\n\t\tbackground: 'none',\n\t\tborder: 'none',\n\t\tcursor: 'pointer',\n\t\ttextAlign: 'left',\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t\tfontFamily: 'inherit',\n\t},\n\ttype: {\n\t\tfontSize: '13px',\n\t\tfontWeight: 600,\n\t\tflex: '1',\n\t\tfontFamily:\n\t\t\t'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\t},\n\tlocale: { fontSize: '12.5px', color: 'var(--fonderie-text-muted,#5c5c5c)' },\n\tactive: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\tgap: '6px',\n\t\tborderRadius: '999px',\n\t\tpadding: '2px 9px 2px 8px',\n\t\tfontSize: '12px',\n\t\tfontWeight: 600,\n\t\tlineHeight: 1.5,\n\t\tminWidth: '64px',\n\t\tcolor: 'var(--fonderie-accent-strong,#009767)',\n\t\tbackground: 'color-mix(in srgb, var(--fonderie-accent-strong,#009767) 13%, transparent)',\n\t},\n\tinactive: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\tgap: '6px',\n\t\tborderRadius: '999px',\n\t\tpadding: '2px 9px 2px 8px',\n\t\tfontSize: '12px',\n\t\tfontWeight: 600,\n\t\tlineHeight: 1.5,\n\t\tminWidth: '64px',\n\t\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n\t\tbackground: 'color-mix(in srgb, var(--fonderie-text-muted,#5c5c5c) 10%, transparent)',\n\t},\n\tform: {\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tgap: '4px',\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 'var(--fonderie-radius-lg,8px)',\n\t\tpadding: '6px 20px 20px',\n\t\tboxShadow: 'var(--fonderie-shadow-card,0 2px 3px 0 rgba(0,0,0,.05))',\n\t},\n\tlabel: { fontSize: '13px', fontWeight: 500, marginTop: '14px', marginBottom: '2px' },\n\tinput: {\n\t\theight: '36px',\n\t\tboxSizing: 'border-box',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '6px',\n\t\tpadding: '0 10px',\n\t\tfontSize: '13.5px',\n\t\tfontFamily: 'inherit',\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t},\n\ttextarea: {\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '6px',\n\t\tpadding: '10px',\n\t\tfontSize: '13px',\n\t\tlineHeight: 1.55,\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t\tfontFamily:\n\t\t\t'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\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: '36px',\n\t\tboxSizing: 'border-box',\n\t\tbackgroundColor: 'var(--fonderie-text,#171717)',\n\t\tcolor: 'var(--fonderie-surface,#fff)',\n\t\tpadding: '0 16px',\n\t\tborderRadius: '6px',\n\t\tborder: '1px solid var(--fonderie-text,#171717)',\n\t\tfontSize: '13.5px',\n\t\tfontWeight: 600,\n\t\tfontFamily: 'inherit',\n\t\talignSelf: 'flex-start',\n\t\tcursor: 'pointer',\n\t},\n\tbuttonDisabled: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: '36px',\n\t\tboxSizing: 'border-box',\n\t\tbackgroundColor: 'var(--fonderie-text,#171717)',\n\t\tcolor: 'var(--fonderie-surface,#fff)',\n\t\tpadding: '0 16px',\n\t\tborderRadius: '6px',\n\t\tborder: '1px solid var(--fonderie-text,#171717)',\n\t\tfontSize: '13.5px',\n\t\tfontWeight: 600,\n\t\tfontFamily: 'inherit',\n\t\talignSelf: 'flex-start',\n\t\topacity: 0.45,\n\t\tcursor: 'not-allowed',\n\t},\n\trevisions: { marginTop: '32px' },\n\trevisionRow: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tgap: '12px',\n\t\tpadding: '9px 16px',\n\t\tborderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)',\n\t\tfontSize: '13px',\n\t},\n\trollbackButton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: '28px',\n\t\tboxSizing: 'border-box',\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '6px',\n\t\tpadding: '0 10px',\n\t\tfontSize: '12.5px',\n\t\tfontWeight: 500,\n\t\tfontFamily: 'inherit',\n\t\tcursor: 'pointer',\n\t},\n\t// Template list: matches @fonderie/vue-admin-screens' shell look with local\n\t// values — this package sits below the admin screens and cannot import them.\n\tlistContainer: { padding: '32px 40px 64px', maxWidth: '1160px', boxSizing: 'border-box' },\n\tlistTitle: {\n\t\tfontSize: '22px',\n\t\tfontWeight: 600,\n\t\tmargin: '0',\n\t\tletterSpacing: 'var(--fonderie-tracking-display,-0.05em)',\n\t\tlineHeight: 1.25,\n\t},\n\thint: { fontSize: '13.5px', color: 'var(--fonderie-text-muted,#5c5c5c)', margin: '4px 0 24px' },\n\tdot: { width: '6px', height: '6px', borderRadius: '999px', background: 'currentColor' },\n};\n","import type {\n\tAdminLocale,\n\tAdminMessageKey,\n\tAdminMessageParams,\n\tCourierAdminClient,\n\tFonderieApiError,\n\tISetTemplateInput,\n\tITemplateRevision,\n} from '@fonderie/client';\nimport { createAdminT, formatAdminDate } 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\t/**\n\t\t * A built-in email's default-locale row (the list's `system` flag): it can\n\t\t * be edited and rolled back, never deleted — Delete is not offered.\n\t\t */\n\t\tsystem: { type: Boolean, default: false },\n\t\t/** Shows \"+ Add locale\" on the default locale (emits add-locale). */\n\t\tallowAddLocale: { type: Boolean, default: false },\n\t\t/** The console language (`locale` is the template's); defaults to English. */\n\t\tuiLocale: { type: String as PropType<AdminLocale>, default: undefined },\n\t},\n\temits: {\n\t\tsaved: () => true,\n\t\t/** The template was deleted and no longer exists. */\n\t\tdeleted: () => true,\n\t\t/** Create a translation of this template. */\n\t\t'add-locale': (_type: string) => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst t = (key: AdminMessageKey, params?: AdminMessageParams) =>\n\t\t\tcreateAdminT(props.uiLocale)(key, params);\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, removeTemplate } = useTemplates(props.client);\n\t\tconst isDeleting = ref(false);\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<AdminMessageKey | 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 = 'templates.editor.sampleNotObject';\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 = 'templates.editor.sampleInvalid';\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\tasync function handleDelete() {\n\t\t\tconst message = props.locale\n\t\t\t\t? t('templates.editor.confirmDeleteLocale', { locale: props.locale, type: props.type })\n\t\t\t\t: t('templates.editor.confirmDelete', { type: props.type });\n\t\t\tif (!window.confirm(message)) return;\n\t\t\tisDeleting.value = true;\n\t\t\tsaveError.value = null;\n\t\t\ttry {\n\t\t\t\tawait removeTemplate(props.type, props.locale);\n\t\t\t\temit('deleted');\n\t\t\t} catch (err) {\n\t\t\t\tsaveError.value = err as FonderieApiError;\n\t\t\t} finally {\n\t\t\t\tisDeleting.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 ?? t('templates.editor.unknownActor')} — ${formatAdminDate(rev.createdAt, props.uiLocale)}`,\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\tt('templates.editor.rollBack'),\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 }, t('templates.editor.loading'));\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(\n\t\t\t\t\t'div',\n\t\t\t\t\t{ style: { display: 'flex', alignItems: 'center', gap: '12px', flexWrap: 'wrap' } },\n\t\t\t\t\t[\n\t\t\t\t\t\th('h1', { style: styles.title }, props.type),\n\t\t\t\t\t\tprops.allowAddLocale && !props.locale\n\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t\t\t\tstyle: { ...styles.rollbackButton, marginLeft: 'auto' },\n\t\t\t\t\t\t\t\t\t\tonClick: () => emit('add-locale', props.type),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tt('templates.editor.addLocale'),\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\t],\n\t\t\t\t),\n\t\t\t\th('p', { style: styles.meta }, [\n\t\t\t\t\th('strong', props.locale ?? t('templates.defaultLocale')),\n\t\t\t\t\t` · v${template.value?.version ?? 1}`,\n\t\t\t\t\tprops.system ? ` · ${t('templates.editor.builtInNote')}` : '',\n\t\t\t\t]),\n\t\t\t\th('div', { style: styles.split }, [\n\t\t\t\t\th('div', { style: styles.column }, [\n\t\t\t\t\t\th('form', { style: styles.form, onSubmit: handleSubmit }, [\n\t\t\t\t\t\t\th('label', { style: styles.label, for: 'template-subject' }, t('templates.subject')),\n\t\t\t\t\t\t\th('input', {\n\t\t\t\t\t\t\t\tid: 'template-subject',\n\t\t\t\t\t\t\t\tstyle: styles.input,\n\t\t\t\t\t\t\t\tvalue: subject.value,\n\t\t\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\t\t\tsubject.value = (e.target as HTMLInputElement).value;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\th('label', { style: styles.label, for: 'template-html' }, t('templates.htmlBody')),\n\t\t\t\t\t\t\th('textarea', {\n\t\t\t\t\t\t\t\tid: 'template-html',\n\t\t\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\t\t\trows: 8,\n\t\t\t\t\t\t\t\tvalue: html.value,\n\t\t\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\t\t\thtml.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\th('label', { style: styles.label, for: 'template-text' }, t('templates.textBody')),\n\t\t\t\t\t\t\th('textarea', {\n\t\t\t\t\t\t\t\tid: 'template-text',\n\t\t\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\t\t\trows: 4,\n\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\tvalue: text.value,\n\t\t\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\t\t\ttext.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\th('label', { style: styles.checkboxLabel }, [\n\t\t\t\t\t\t\t\th('input', {\n\t\t\t\t\t\t\t\t\ttype: 'checkbox',\n\t\t\t\t\t\t\t\t\tchecked: active.value,\n\t\t\t\t\t\t\t\t\tonChange: (e: Event) => {\n\t\t\t\t\t\t\t\t\t\tactive.value = (e.target as HTMLInputElement).checked;\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\tt('templates.editor.active'),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\tsaveError.value?.reason === 'VERSION_CONFLICT'\n\t\t\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, [\n\t\t\t\t\t\t\t\t\t\t`${t('templates.editor.conflict')} `,\n\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t\t\t\t\t\tstyle: styles.rollbackButton,\n\t\t\t\t\t\t\t\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tsaveError.value = null;\n\t\t\t\t\t\t\t\t\t\t\t\t\tvoid refresh();\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tt('common.reload'),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t\t: saveError.value\n\t\t\t\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, saveError.value.explanation)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\th('div', { style: styles.saveRow }, [\n\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: 'submit',\n\t\t\t\t\t\t\t\t\t\tdisabled: isSaving.value || !dirty.value,\n\t\t\t\t\t\t\t\t\t\tstyle: dirty.value ? styles.button : styles.buttonDisabled,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tisSaving.value ? t('common.saving') : t('common.save'),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t!dirty.value && !isSaving.value\n\t\t\t\t\t\t\t\t\t? h('span', { style: styles.meta }, t('templates.editor.noChanges'))\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\t!props.system\n\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t\t\t\t\t\tdisabled: isDeleting.value,\n\t\t\t\t\t\t\t\t\t\t\t\tonClick: () => void handleDelete(),\n\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t...styles.rollbackButton,\n\t\t\t\t\t\t\t\t\t\t\t\t\theight: '36px',\n\t\t\t\t\t\t\t\t\t\t\t\t\tmarginLeft: 'auto',\n\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: 'var(--fonderie-danger,#e00)',\n\t\t\t\t\t\t\t\t\t\t\t\t\tborderColor:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'color-mix(in srgb, var(--fonderie-danger,#e00) 40%, transparent)',\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tisDeleting.value ? t('common.deleting') : t('common.delete'),\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t]),\n\t\t\t\t\t\th('label', { style: styles.label, for: 'template-sample' }, t('templates.editor.sampleData')),\n\t\t\t\t\t\th('textarea', {\n\t\t\t\t\t\t\tid: 'template-sample',\n\t\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\t\trows: 6,\n\t\t\t\t\t\t\tspellcheck: false,\n\t\t\t\t\t\t\tvalue: sampleJson.value,\n\t\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\t\tsampleJson.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tsampleError.value\n\t\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, t(sampleError.value))\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\t]),\n\t\t\t\t\th('div', { style: styles.previewColumn }, [\n\t\t\t\t\t\th('div', { style: styles.previewHeader }, [\n\t\t\t\t\t\t\th('span', { style: styles.label }, t('templates.editor.preview')),\n\t\t\t\t\t\t\th('span', { style: styles.meta }, isPreviewing.value ? t('templates.editor.rendering') : t('templates.editor.live')),\n\t\t\t\t\t\t]),\n\t\t\t\t\t\tpreviewError.value\n\t\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, previewError.value.explanation)\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\tpreview.value?.subject\n\t\t\t\t\t\t\t? h('p', { style: styles.previewSubject }, preview.value.subject)\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\tpreview.value?.html\n\t\t\t\t\t\t\t? // sandbox= — no scripts, no same-origin. Operator-authored HTML\n\t\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\t// token lives.\n\t\t\t\t\t\t\t\th('iframe', {\n\t\t\t\t\t\t\t\t\ttitle: t('templates.editor.previewTitle'),\n\t\t\t\t\t\t\t\t\tstyle: styles.previewFrame,\n\t\t\t\t\t\t\t\t\tsandbox: '',\n\t\t\t\t\t\t\t\t\tsrcdoc: preview.value.html,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t: preview.value\n\t\t\t\t\t\t\t\t? h('pre', { style: styles.previewText }, preview.value.text)\n\t\t\t\t\t\t\t\t: h('p', { style: styles.meta }, t('templates.editor.nothingRendered')),\n\t\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 }, t('templates.editor.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 {\n\tAdminLocale,\n\tAdminMessageKey,\n\tAdminMessageParams,\n\tCourierAdminClient,\n\tITemplateEntry,\n} from '@fonderie/client';\nimport { createAdminT } from '@fonderie/client';\nimport { useTemplates } from '@fonderie/vue-courier-admin';\nimport type { CSSProperties, PropType } from 'vue';\nimport { defineComponent, h } from 'vue';\nimport { styles } from '../styles';\n\nconst builtIn: CSSProperties = {\n\tfontSize: '11px',\n\tfontWeight: 500,\n\tpadding: '1px 7px',\n\tborderRadius: '999px',\n\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n};\nconst newButton: CSSProperties = {\n\tdisplay: 'inline-flex',\n\talignItems: 'center',\n\theight: '32px',\n\tboxSizing: 'border-box',\n\tborderRadius: '6px',\n\tpadding: '0 12px',\n\tfontSize: '13px',\n\tfontWeight: 500,\n\tfontFamily: 'inherit',\n\tcursor: 'pointer',\n\tbackgroundColor: 'var(--fonderie-text,#171717)',\n\tcolor: 'var(--fonderie-surface,#fff)',\n\tborder: '1px solid var(--fonderie-text,#171717)',\n};\n\nexport const TemplateListScreen = defineComponent({\n\tname: 'FonderieTemplateListScreen',\n\tprops: {\n\t\tclient: { type: Object as PropType<CourierAdminClient>, required: true },\n\t\t/** Shows a \"New template\" button (emits create-template). */\n\t\tallowCreate: { type: Boolean, default: false },\n\t\t/** The console language; defaults to English. */\n\t\tlocale: { type: String as PropType<AdminLocale>, default: undefined },\n\t},\n\temits: {\n\t\t/** The whole row — type AND locale, and whether it is built-in. */\n\t\t'select-template': (_template: ITemplateEntry) => true,\n\t\t/** Receives the locales in use, to suggest. */\n\t\t'create-template': (_context: { locales: string[] }) => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst { templates, isLoading, error } = useTemplates(props.client);\n\t\tconst t = (key: AdminMessageKey, params?: AdminMessageParams) =>\n\t\t\tcreateAdminT(props.locale)(key, params);\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 ?? t('templates.defaultLocale')),\n\t\t\t\t\t\ttemplate.system ? h('span', { style: builtIn }, t('templates.builtInBadge')) : null,\n\t\t\t\t\t\th('span', { style: template.active ? styles.active : styles.inactive }, [\n\t\t\t\t\t\t\th('span', { style: styles.dot }),\n\t\t\t\t\t\t\ttemplate.active ? t('common.status.active') : t('common.status.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\th('div', { style: styles.listContainer }, [\n\t\t\t\th(\n\t\t\t\t\t'div',\n\t\t\t\t\t{\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\tgap: '16px',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t[\n\t\t\t\t\t\th('h1', { style: styles.listTitle }, t('templates.list.title')),\n\t\t\t\t\t\tprops.allowCreate\n\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t\t\t\tstyle: newButton,\n\t\t\t\t\t\t\t\t\t\tonClick: () =>\n\t\t\t\t\t\t\t\t\t\t\temit('create-template', {\n\t\t\t\t\t\t\t\t\t\t\t\tlocales: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t...new Set(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttemplates.value.map((tpl) => tpl.locale).filter((l): l is string => !!l),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tt('templates.list.newTemplate'),\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\t],\n\t\t\t\t),\n\t\t\t\th(\n\t\t\t\t\t'p',\n\t\t\t\t\t{ style: styles.hint },\n\t\t\t\t\tt('templates.list.hint'),\n\t\t\t\t),\n\t\t\t\tisLoading.value\n\t\t\t\t\t? h('p', { style: styles.status }, t('templates.list.loading'))\n\t\t\t\t\t: error.value\n\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, error.value.explanation)\n\t\t\t\t\t\t: h('ul', { style: styles.list }, templates.value.map(renderRow)),\n\t\t\t]);\n\t},\n});\n"],"mappings":"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","names":["import_client","import_vue","import_client","import_vue_courier_admin","import_vue"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/screens/TemplateCreateScreen.ts","../src/styles.ts","../src/screens/TemplateEditorScreen.ts","../src/screens/TemplateListScreen.ts"],"sourcesContent":["export { TemplateCreateScreen, TemplateEditorScreen, TemplateListScreen } from './screens';\n","import type {\n\tAdminLocale,\n\tAdminMessageKey,\n\tAdminMessageParams,\n\tCourierAdminClient,\n\tISetTemplateInput,\n} from '@fonderie/client';\nimport { createAdminT, FonderieApiError } from '@fonderie/client';\nimport type { PropType } from 'vue';\nimport { defineComponent, h, onMounted, ref } from 'vue';\nimport { styles } from '../styles';\n\nconst TYPE_RE = /^[a-z0-9][a-z0-9_-]{0,80}$/;\nconst LOCALE_RE = /^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/;\n\n// Creating is its own screen: the editor loads an existing row, and a new\n// template or locale has none yet. Once saved, the editor takes over.\nexport const TemplateCreateScreen = defineComponent({\n\tname: 'FonderieTemplateCreateScreen',\n\tprops: {\n\t\tclient: { type: Object as PropType<CourierAdminClient>, required: true },\n\t\t/**\n\t\t * Given ⇒ add a LOCALE of this existing template: the type is fixed and the\n\t\t * form starts from its default-locale copy. Omitted ⇒ a brand-new template\n\t\t * type (one the app sends that has no stored copy yet).\n\t\t */\n\t\ttype: { type: String, default: undefined },\n\t\t/** Locales already in use, offered as suggestions. */\n\t\tlocales: { type: Array as PropType<string[]>, default: () => [] },\n\t\t/** The console language; defaults to English. */\n\t\tlocale: { type: String as PropType<AdminLocale>, default: undefined },\n\t},\n\temits: {\n\t\t/** What was created, so the caller can open it in the editor. */\n\t\tcreated: (_created: { type: string; locale: string | null }) => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst addingLocale = props.type !== undefined;\n\t\tconst newType = ref('');\n\t\tconst targetLocale = ref('');\n\t\tconst subject = ref('');\n\t\tconst html = ref('');\n\t\tconst text = ref('');\n\t\tconst error = ref<string | null>(null);\n\t\tconst busy = ref(false);\n\t\t// `tr`, not `t`: submit() uses `t` for the template type.\n\t\tconst tr = (key: AdminMessageKey, params?: AdminMessageParams) =>\n\t\t\tcreateAdminT(props.locale)(key, params);\n\n\t\t// A new locale starts from the default copy, so translating is editing.\n\t\tonMounted(() => {\n\t\t\tif (!props.type) return;\n\t\t\tprops.client\n\t\t\t\t.getTemplate(props.type, null)\n\t\t\t\t.then(({ result }) => {\n\t\t\t\t\tsubject.value = result.subject ?? '';\n\t\t\t\t\thtml.value = result.html ?? '';\n\t\t\t\t\ttext.value = result.text;\n\t\t\t\t})\n\t\t\t\t.catch(() => undefined);\n\t\t});\n\n\t\tasync function submit(e: Event) {\n\t\t\te.preventDefault();\n\t\t\terror.value = null;\n\t\t\tconst t = addingLocale ? (props.type as string) : newType.value.trim();\n\t\t\tconst l = targetLocale.value.trim() || null;\n\t\t\tif (!TYPE_RE.test(t)) {\n\t\t\t\terror.value = tr('templates.create.errorType');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (addingLocale && !l) {\n\t\t\t\terror.value = tr('templates.create.errorLocaleRequired');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (l && !LOCALE_RE.test(l)) {\n\t\t\t\terror.value = tr('templates.create.errorLocale');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!text.value.trim()) {\n\t\t\t\terror.value = tr('templates.create.errorText');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbusy.value = true;\n\t\t\ttry {\n\t\t\t\t// Refuse to overwrite: creating an existing row would replace it.\n\t\t\t\tconst exists = await props.client.getTemplate(t, l).then(\n\t\t\t\t\t() => true,\n\t\t\t\t\t(err: unknown) => !(err instanceof FonderieApiError && err.status === 404),\n\t\t\t\t);\n\t\t\t\tif (exists) {\n\t\t\t\t\terror.value = l\n\t\t\t\t\t\t? tr('templates.create.existsLocale', { type: t, locale: l })\n\t\t\t\t\t\t: tr('templates.create.exists', { type: t });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst input: ISetTemplateInput = { text: text.value, active: true };\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\tawait props.client.setTemplate(t, input, l);\n\t\t\t\temit('created', { type: t, locale: l });\n\t\t\t} catch (err) {\n\t\t\t\terror.value = err instanceof FonderieApiError ? err.explanation : String(err);\n\t\t\t} finally {\n\t\t\t\tbusy.value = false;\n\t\t\t}\n\t\t}\n\n\t\tconst field = (\n\t\t\tid: string,\n\t\t\tlabel: string,\n\t\t\tmodel: typeof subject,\n\t\t\topts: Record<string, unknown> = {},\n\t\t) => [\n\t\t\th('label', { style: styles.label, for: id }, label),\n\t\t\th(opts.textarea ? 'textarea' : 'input', {\n\t\t\t\tid,\n\t\t\t\tstyle: opts.textarea ? { ...styles.textarea, minHeight: opts.minHeight } : styles.input,\n\t\t\t\tvalue: model.value,\n\t\t\t\tautocomplete: 'off',\n\t\t\t\tspellcheck: false,\n\t\t\t\t...(opts.placeholder ? { placeholder: opts.placeholder } : {}),\n\t\t\t\t...(opts.list ? { list: opts.list } : {}),\n\t\t\t\tonInput: (ev: Event) => {\n\t\t\t\t\tmodel.value = (ev.target as HTMLInputElement).value;\n\t\t\t\t},\n\t\t\t}),\n\t\t];\n\n\t\treturn () =>\n\t\t\th('div', { style: { ...styles.container, maxWidth: '760px' } }, [\n\t\t\t\th(\n\t\t\t\t\t'h1',\n\t\t\t\t\t{ style: styles.title },\n\t\t\t\t\taddingLocale\n\t\t\t\t\t\t? tr('templates.create.titleLocale', { type: props.type as string })\n\t\t\t\t\t\t: tr('templates.create.titleNew'),\n\t\t\t\t),\n\t\t\t\th(\n\t\t\t\t\t'p',\n\t\t\t\t\t{ style: { ...styles.meta, lineHeight: 1.5 } },\n\t\t\t\t\taddingLocale\n\t\t\t\t\t\t? tr('templates.create.hintLocale')\n\t\t\t\t\t\t: tr('templates.create.hintNew'),\n\t\t\t\t),\n\t\t\t\th('form', { style: styles.form, onSubmit: (ev: Event) => void submit(ev) }, [\n\t\t\t\t\t...(addingLocale\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: field('new-template-type', tr('templates.create.type'), newType, { placeholder: 'weekly-digest' })),\n\t\t\t\t\t...field(\n\t\t\t\t\t\t'new-template-locale',\n\t\t\t\t\t\taddingLocale ? tr('templates.create.locale') : tr('templates.create.localeOptional'),\n\t\t\t\t\t\ttargetLocale,\n\t\t\t\t\t\t{ placeholder: 'fr', list: 'new-template-locales' },\n\t\t\t\t\t),\n\t\t\t\t\th(\n\t\t\t\t\t\t'datalist',\n\t\t\t\t\t\t{ id: 'new-template-locales' },\n\t\t\t\t\t\t[...new Set(props.locales)].map((l) => h('option', { key: l, value: l })),\n\t\t\t\t\t),\n\t\t\t\t\t...field('new-template-subject', tr('templates.subject'), subject),\n\t\t\t\t\t...field('new-template-html', tr('templates.htmlBody'), html, { textarea: true, minHeight: '160px' }),\n\t\t\t\t\t...field('new-template-text', tr('templates.textBody'), text, {\n\t\t\t\t\t\ttextarea: true,\n\t\t\t\t\t\tminHeight: '100px',\n\t\t\t\t\t}),\n\t\t\t\t\terror.value ? h('p', { style: styles.error, role: 'alert' }, error.value) : null,\n\t\t\t\t\th(\n\t\t\t\t\t\t'button',\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'submit',\n\t\t\t\t\t\t\tdisabled: busy.value,\n\t\t\t\t\t\t\tstyle: { ...styles.button, marginTop: '16px' },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbusy.value\n\t\t\t\t\t\t\t? tr('templates.create.creating')\n\t\t\t\t\t\t\t: addingLocale\n\t\t\t\t\t\t\t\t? tr('templates.create.submitLocale')\n\t\t\t\t\t\t\t\t: tr('templates.create.submitNew'),\n\t\t\t\t\t),\n\t\t\t\t]),\n\t\t\t]);\n\t},\n});\n","import type { CSSProperties } from 'vue';\n\nexport const styles: Record<string, CSSProperties> = {\n\tcontainer: { padding: '8px 40px 64px', maxWidth: '1400px', boxSizing: 'border-box' },\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: {\n\t\tdisplay: 'grid',\n\t\tgridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)',\n\t\tgap: '24px',\n\t\talignItems: 'start',\n\t},\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: {\n\t\tminWidth: '0',\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tposition: 'sticky',\n\t\ttop: '16px',\n\t},\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\tboxShadow: 'var(--fonderie-shadow-card,0 2px 3px 0 rgba(0,0,0,.05))',\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:\n\t\t\t'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\t},\n\ttitle: {\n\t\tfontSize: '22px',\n\t\tfontWeight: 600,\n\t\tmargin: '8px 0 4px',\n\t\tletterSpacing: 'var(--fonderie-tracking-display,-0.05em)',\n\t\tlineHeight: 1.25,\n\t},\n\tsubtitle: {\n\t\tfontSize: '15px',\n\t\tfontWeight: 600,\n\t\tmargin: '0 0 10px',\n\t\tletterSpacing: 'var(--fonderie-tracking-display,-0.05em)',\n\t},\n\tmeta: { fontSize: '13px', color: 'var(--fonderie-text-muted,#5c5c5c)', marginBottom: '20px' },\n\tstatus: { padding: '24px 0', color: 'var(--fonderie-text-muted,#5c5c5c)', fontSize: '13.5px' },\n\terror: {\n\t\tcolor: 'var(--fonderie-danger,#e00)',\n\t\tbackground: 'color-mix(in srgb, var(--fonderie-danger,#e00) 8%, transparent)',\n\t\tborderRadius: '6px',\n\t\tpadding: '8px 12px',\n\t\tmargin: '8px 0',\n\t\tfontSize: '13.5px',\n\t},\n\tlist: {\n\t\tlistStyle: 'none',\n\t\tpadding: '0',\n\t\tmargin: '0',\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 'var(--fonderie-radius-lg,8px)',\n\t\toverflow: 'hidden',\n\t\tboxShadow: 'var(--fonderie-shadow-card,0 2px 3px 0 rgba(0,0,0,.05))',\n\t},\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\tgap: '16px',\n\t\tpadding: '13px 16px',\n\t\tbackground: 'none',\n\t\tborder: 'none',\n\t\tcursor: 'pointer',\n\t\ttextAlign: 'left',\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t\tfontFamily: 'inherit',\n\t},\n\ttype: {\n\t\tfontSize: '13px',\n\t\tfontWeight: 600,\n\t\tflex: '1',\n\t\tfontFamily:\n\t\t\t'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\t},\n\tlocale: { fontSize: '12.5px', color: 'var(--fonderie-text-muted,#5c5c5c)' },\n\tactive: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\tgap: '6px',\n\t\tborderRadius: '999px',\n\t\tpadding: '2px 9px 2px 8px',\n\t\tfontSize: '12px',\n\t\tfontWeight: 600,\n\t\tlineHeight: 1.5,\n\t\tminWidth: '64px',\n\t\tcolor: 'var(--fonderie-accent-strong,#009767)',\n\t\tbackground: 'color-mix(in srgb, var(--fonderie-accent-strong,#009767) 13%, transparent)',\n\t},\n\tinactive: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\tgap: '6px',\n\t\tborderRadius: '999px',\n\t\tpadding: '2px 9px 2px 8px',\n\t\tfontSize: '12px',\n\t\tfontWeight: 600,\n\t\tlineHeight: 1.5,\n\t\tminWidth: '64px',\n\t\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n\t\tbackground: 'color-mix(in srgb, var(--fonderie-text-muted,#5c5c5c) 10%, transparent)',\n\t},\n\tform: {\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tgap: '4px',\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 'var(--fonderie-radius-lg,8px)',\n\t\tpadding: '6px 20px 20px',\n\t\tboxShadow: 'var(--fonderie-shadow-card,0 2px 3px 0 rgba(0,0,0,.05))',\n\t},\n\tlabel: { fontSize: '13px', fontWeight: 500, marginTop: '14px', marginBottom: '2px' },\n\tinput: {\n\t\theight: '36px',\n\t\tboxSizing: 'border-box',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '6px',\n\t\tpadding: '0 10px',\n\t\tfontSize: '13.5px',\n\t\tfontFamily: 'inherit',\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t},\n\ttextarea: {\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '6px',\n\t\tpadding: '10px',\n\t\tfontSize: '13px',\n\t\tlineHeight: 1.55,\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t\tfontFamily:\n\t\t\t'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\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: '36px',\n\t\tboxSizing: 'border-box',\n\t\tbackgroundColor: 'var(--fonderie-text,#171717)',\n\t\tcolor: 'var(--fonderie-surface,#fff)',\n\t\tpadding: '0 16px',\n\t\tborderRadius: '6px',\n\t\tborder: '1px solid var(--fonderie-text,#171717)',\n\t\tfontSize: '13.5px',\n\t\tfontWeight: 600,\n\t\tfontFamily: 'inherit',\n\t\talignSelf: 'flex-start',\n\t\tcursor: 'pointer',\n\t},\n\tbuttonDisabled: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: '36px',\n\t\tboxSizing: 'border-box',\n\t\tbackgroundColor: 'var(--fonderie-text,#171717)',\n\t\tcolor: 'var(--fonderie-surface,#fff)',\n\t\tpadding: '0 16px',\n\t\tborderRadius: '6px',\n\t\tborder: '1px solid var(--fonderie-text,#171717)',\n\t\tfontSize: '13.5px',\n\t\tfontWeight: 600,\n\t\tfontFamily: 'inherit',\n\t\talignSelf: 'flex-start',\n\t\topacity: 0.45,\n\t\tcursor: 'not-allowed',\n\t},\n\trevisions: { marginTop: '32px' },\n\trevisionRow: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tgap: '12px',\n\t\tpadding: '9px 16px',\n\t\tborderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)',\n\t\tfontSize: '13px',\n\t},\n\trollbackButton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: '28px',\n\t\tboxSizing: 'border-box',\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: '6px',\n\t\tpadding: '0 10px',\n\t\tfontSize: '12.5px',\n\t\tfontWeight: 500,\n\t\tfontFamily: 'inherit',\n\t\tcursor: 'pointer',\n\t},\n\t// Template list: matches @fonderie/vue-admin-screens' shell look with local\n\t// values — this package sits below the admin screens and cannot import them.\n\tlistContainer: { padding: '32px 40px 64px', maxWidth: '1160px', boxSizing: 'border-box' },\n\tlistTitle: {\n\t\tfontSize: '22px',\n\t\tfontWeight: 600,\n\t\tmargin: '0',\n\t\tletterSpacing: 'var(--fonderie-tracking-display,-0.05em)',\n\t\tlineHeight: 1.25,\n\t},\n\thint: { fontSize: '13.5px', color: 'var(--fonderie-text-muted,#5c5c5c)', margin: '4px 0 24px' },\n\tdot: { width: '6px', height: '6px', borderRadius: '999px', background: 'currentColor' },\n};\n","import type {\n\tAdminLocale,\n\tAdminMessageKey,\n\tAdminMessageParams,\n\tCourierAdminClient,\n\tFonderieApiError,\n\tISetTemplateInput,\n\tITemplateEntry,\n\tITemplateRevision,\n} from '@fonderie/client';\nimport {\n\tcreateAdminT,\n\tformatAdminDate,\n\tgroupTemplatesByType,\n\tmissingTemplateLocales,\n} from '@fonderie/client';\nimport {\n\tuseTemplate,\n\tuseTemplatePreview,\n\tuseTemplateRevisions,\n\tuseTemplates,\n} from '@fonderie/vue-courier-admin';\nimport type { CSSProperties, 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\n// One tab per locale of this email, underlined like a document's tabs.\nconst tab: CSSProperties = {\n\theight: '32px',\n\tpadding: '0 10px',\n\tbackground: 'none',\n\tborder: 'none',\n\tborderBottom: '2px solid transparent',\n\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n\tfontSize: '13px',\n\tfontFamily:\n\t\t'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\tcursor: 'pointer',\n};\nconst tabSelected: CSSProperties = {\n\t...tab,\n\tcolor: 'var(--fonderie-text,#171717)',\n\tfontWeight: 600,\n\tborderBottomColor: 'var(--fonderie-text,#171717)',\n\tcursor: 'default',\n};\nconst tabInactive: CSSProperties = { ...tab, opacity: 0.55, textDecoration: 'line-through' };\nconst tabBar: CSSProperties = {\n\tdisplay: 'flex',\n\talignItems: 'flex-end',\n\tgap: '12px',\n\tborderBottom: '1px solid var(--fonderie-border,#e0e0e0)',\n\tmargin: '4px 0 12px',\n\tpaddingBottom: '6px',\n};\nconst tabs: CSSProperties = { display: 'flex', flexWrap: 'wrap', gap: '4px', marginBottom: '-7px' };\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\t/**\n\t\t * A built-in email's default-locale row (the list's `system` flag): it can\n\t\t * be edited and rolled back, never deleted — Delete is not offered.\n\t\t */\n\t\tsystem: { type: Boolean, default: false },\n\t\t/** Shows \"+ Add locale\" (emits add-locale). */\n\t\tallowAddLocale: { type: Boolean, default: false },\n\t\t/**\n\t\t * Shows a tab per locale this email exists in (emits select-locale).\n\t\t * Unsaved edits are confirmed before switching away.\n\t\t */\n\t\tlocaleTabs: { type: Boolean, default: false },\n\t\t/** The console language (`locale` is the template's); defaults to English. */\n\t\tuiLocale: { type: String as PropType<AdminLocale>, default: undefined },\n\t},\n\temits: {\n\t\tsaved: () => true,\n\t\t/** The template was deleted and no longer exists. */\n\t\tdeleted: () => true,\n\t\t/**\n\t\t * Create a translation of this template. `locales` are the ones the app\n\t\t * uses elsewhere that this email lacks — suggest them first.\n\t\t */\n\t\t'add-locale': (_type: string, _context: { locales: string[] }) => true,\n\t\t/** Open another locale of this email. */\n\t\t'select-locale': (_template: ITemplateEntry) => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst t = (key: AdminMessageKey, params?: AdminMessageParams) =>\n\t\t\tcreateAdminT(props.uiLocale)(key, params);\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 { templates, saveTemplate, removeTemplate } = useTemplates(props.client);\n\t\t// This email's locales, for the tabs. The list is already fetched for saves.\n\t\tconst siblings = computed(\n\t\t\t() => groupTemplatesByType(templates.value).find((g) => g.type === props.type)?.entries ?? [],\n\t\t);\n\t\tconst isDeleting = ref(false);\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<AdminMessageKey | 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 = 'templates.editor.sampleNotObject';\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 = 'templates.editor.sampleInvalid';\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\t// Leaving a locale with unsaved edits asks first: they would be lost.\n\t\tconst leave = () => !dirty.value || window.confirm(t('templates.editor.discardChanges'));\n\n\t\tfunction renderTabBar() {\n\t\t\tif (!props.localeTabs && !props.allowAddLocale) return null;\n\t\t\treturn h('div', { style: tabBar }, [\n\t\t\t\tprops.localeTabs\n\t\t\t\t\t? // Each tab opens another stored row, so this is navigation, not an\n\t\t\t\t\t\t// ARIA tablist: plain buttons, the open one marked aria-current.\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t'nav',\n\t\t\t\t\t\t\t{ 'aria-label': t('templates.editor.locales'), style: tabs },\n\t\t\t\t\t\t\tsiblings.value.map((entry) => {\n\t\t\t\t\t\t\t\tconst selected = entry.locale === (props.locale ?? null);\n\t\t\t\t\t\t\t\treturn h(\n\t\t\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkey: entry.locale ?? '',\n\t\t\t\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t\t\t\t'aria-current': selected ? 'true' : undefined,\n\t\t\t\t\t\t\t\t\t\tstyle: selected ? tabSelected : entry.active ? tab : tabInactive,\n\t\t\t\t\t\t\t\t\t\ttitle: entry.active ? undefined : t('common.status.inactive'),\n\t\t\t\t\t\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t\t\t\t\t\tif (!selected && leave()) emit('select-locale', entry);\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tentry.locale ?? t('templates.defaultChip'),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\t: null,\n\t\t\t\tprops.allowAddLocale\n\t\t\t\t\t? h(\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, marginLeft: 'auto' },\n\t\t\t\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t\t\t\tif (leave())\n\t\t\t\t\t\t\t\t\t\temit('add-locale', props.type, {\n\t\t\t\t\t\t\t\t\t\t\tlocales: missingTemplateLocales(templates.value, props.type),\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tt('templates.editor.addLocale'),\n\t\t\t\t\t\t)\n\t\t\t\t\t: null,\n\t\t\t]);\n\t\t}\n\n\t\tasync function handleDelete() {\n\t\t\tconst message = props.locale\n\t\t\t\t? t('templates.editor.confirmDeleteLocale', { locale: props.locale, type: props.type })\n\t\t\t\t: t('templates.editor.confirmDelete', { type: props.type });\n\t\t\tif (!window.confirm(message)) return;\n\t\t\tisDeleting.value = true;\n\t\t\tsaveError.value = null;\n\t\t\ttry {\n\t\t\t\tawait removeTemplate(props.type, props.locale);\n\t\t\t\temit('deleted');\n\t\t\t} catch (err) {\n\t\t\t\tsaveError.value = err as FonderieApiError;\n\t\t\t} finally {\n\t\t\t\tisDeleting.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 ?? t('templates.editor.unknownActor')} — ${formatAdminDate(rev.createdAt, props.uiLocale)}`,\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\tt('templates.editor.rollBack'),\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 }, t('templates.editor.loading'));\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\trenderTabBar(),\n\t\t\t\th('p', { style: styles.meta }, [\n\t\t\t\t\th('strong', props.locale ?? t('templates.defaultLocale')),\n\t\t\t\t\t` · v${template.value?.version ?? 1}`,\n\t\t\t\t\tprops.system ? ` · ${t('templates.editor.builtInNote')}` : '',\n\t\t\t\t]),\n\t\t\t\th('div', { style: styles.split }, [\n\t\t\t\t\th('div', { style: styles.column }, [\n\t\t\t\t\t\th('form', { style: styles.form, onSubmit: handleSubmit }, [\n\t\t\t\t\t\t\th('label', { style: styles.label, for: 'template-subject' }, t('templates.subject')),\n\t\t\t\t\t\t\th('input', {\n\t\t\t\t\t\t\t\tid: 'template-subject',\n\t\t\t\t\t\t\t\tstyle: styles.input,\n\t\t\t\t\t\t\t\tvalue: subject.value,\n\t\t\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\t\t\tsubject.value = (e.target as HTMLInputElement).value;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\th('label', { style: styles.label, for: 'template-html' }, t('templates.htmlBody')),\n\t\t\t\t\t\t\th('textarea', {\n\t\t\t\t\t\t\t\tid: 'template-html',\n\t\t\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\t\t\trows: 8,\n\t\t\t\t\t\t\t\tvalue: html.value,\n\t\t\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\t\t\thtml.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\th('label', { style: styles.label, for: 'template-text' }, t('templates.textBody')),\n\t\t\t\t\t\t\th('textarea', {\n\t\t\t\t\t\t\t\tid: 'template-text',\n\t\t\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\t\t\trows: 4,\n\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\tvalue: text.value,\n\t\t\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\t\t\ttext.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\th('label', { style: styles.checkboxLabel }, [\n\t\t\t\t\t\t\t\th('input', {\n\t\t\t\t\t\t\t\t\ttype: 'checkbox',\n\t\t\t\t\t\t\t\t\tchecked: active.value,\n\t\t\t\t\t\t\t\t\tonChange: (e: Event) => {\n\t\t\t\t\t\t\t\t\t\tactive.value = (e.target as HTMLInputElement).checked;\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\tt('templates.editor.active'),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\tsaveError.value?.reason === 'VERSION_CONFLICT'\n\t\t\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, [\n\t\t\t\t\t\t\t\t\t\t`${t('templates.editor.conflict')} `,\n\t\t\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t\t\t\t\t\tstyle: styles.rollbackButton,\n\t\t\t\t\t\t\t\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tsaveError.value = null;\n\t\t\t\t\t\t\t\t\t\t\t\t\tvoid refresh();\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tt('common.reload'),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t\t: saveError.value\n\t\t\t\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, saveError.value.explanation)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\th('div', { style: styles.saveRow }, [\n\t\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: 'submit',\n\t\t\t\t\t\t\t\t\t\tdisabled: isSaving.value || !dirty.value,\n\t\t\t\t\t\t\t\t\t\tstyle: dirty.value ? styles.button : styles.buttonDisabled,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tisSaving.value ? t('common.saving') : t('common.save'),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t!dirty.value && !isSaving.value\n\t\t\t\t\t\t\t\t\t? h('span', { style: styles.meta }, t('templates.editor.noChanges'))\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t\t!props.system\n\t\t\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t\t\t\t\t\tdisabled: isDeleting.value,\n\t\t\t\t\t\t\t\t\t\t\t\tonClick: () => void handleDelete(),\n\t\t\t\t\t\t\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t...styles.rollbackButton,\n\t\t\t\t\t\t\t\t\t\t\t\t\theight: '36px',\n\t\t\t\t\t\t\t\t\t\t\t\t\tmarginLeft: 'auto',\n\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: 'var(--fonderie-danger,#e00)',\n\t\t\t\t\t\t\t\t\t\t\t\t\tborderColor:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'color-mix(in srgb, var(--fonderie-danger,#e00) 40%, transparent)',\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tisDeleting.value ? t('common.deleting') : t('common.delete'),\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t]),\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\t'label',\n\t\t\t\t\t\t\t{ style: styles.label, for: 'template-sample' },\n\t\t\t\t\t\t\tt('templates.editor.sampleData'),\n\t\t\t\t\t\t),\n\t\t\t\t\t\th('textarea', {\n\t\t\t\t\t\t\tid: 'template-sample',\n\t\t\t\t\t\t\tstyle: styles.textarea,\n\t\t\t\t\t\t\trows: 6,\n\t\t\t\t\t\t\tspellcheck: false,\n\t\t\t\t\t\t\tvalue: sampleJson.value,\n\t\t\t\t\t\t\tonInput: (e: Event) => {\n\t\t\t\t\t\t\t\tsampleJson.value = (e.target as HTMLTextAreaElement).value;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tsampleError.value\n\t\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, t(sampleError.value))\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\t]),\n\t\t\t\t\th('div', { style: styles.previewColumn }, [\n\t\t\t\t\t\th('div', { style: styles.previewHeader }, [\n\t\t\t\t\t\t\th('span', { style: styles.label }, t('templates.editor.preview')),\n\t\t\t\t\t\t\th(\n\t\t\t\t\t\t\t\t'span',\n\t\t\t\t\t\t\t\t{ style: styles.meta },\n\t\t\t\t\t\t\t\tisPreviewing.value ? t('templates.editor.rendering') : t('templates.editor.live'),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t]),\n\t\t\t\t\t\tpreviewError.value\n\t\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, previewError.value.explanation)\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\tpreview.value?.subject\n\t\t\t\t\t\t\t? h('p', { style: styles.previewSubject }, preview.value.subject)\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\tpreview.value?.html\n\t\t\t\t\t\t\t? // sandbox= — no scripts, no same-origin. Operator-authored HTML\n\t\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\t// token lives.\n\t\t\t\t\t\t\t\th('iframe', {\n\t\t\t\t\t\t\t\t\ttitle: t('templates.editor.previewTitle'),\n\t\t\t\t\t\t\t\t\tstyle: styles.previewFrame,\n\t\t\t\t\t\t\t\t\tsandbox: '',\n\t\t\t\t\t\t\t\t\tsrcdoc: preview.value.html,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t: preview.value\n\t\t\t\t\t\t\t\t? h('pre', { style: styles.previewText }, preview.value.text)\n\t\t\t\t\t\t\t\t: h('p', { style: styles.meta }, t('templates.editor.nothingRendered')),\n\t\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 }, t('templates.editor.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 {\n\tAdminLocale,\n\tAdminMessageKey,\n\tAdminMessageParams,\n\tCourierAdminClient,\n\tITemplateEntry,\n} from '@fonderie/client';\nimport { createAdminT, groupTemplatesByType } from '@fonderie/client';\nimport type { ITemplateGroup } from '@fonderie/client';\nimport { useTemplates } from '@fonderie/vue-courier-admin';\nimport type { CSSProperties, PropType } from 'vue';\nimport { defineComponent, h } from 'vue';\nimport { styles } from '../styles';\n\nconst builtIn: CSSProperties = {\n\tfontSize: '11px',\n\tfontWeight: 500,\n\tpadding: '1px 7px',\n\tborderRadius: '999px',\n\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n};\n// One per locale the email exists in. Monospace: they are language tags.\nconst chip: CSSProperties = {\n\theight: '24px',\n\tboxSizing: 'border-box',\n\tpadding: '0 8px',\n\tborderRadius: '6px',\n\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\tbackground: 'var(--fonderie-surface,#fff)',\n\tcolor: 'var(--fonderie-text,#171717)',\n\tfontSize: '12px',\n\tfontFamily:\n\t\t'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\tcursor: 'pointer',\n};\nconst chipInactive: CSSProperties = { ...chip, opacity: 0.5, textDecoration: 'line-through' };\nconst row: CSSProperties = {\n\t...styles.row,\n\tdisplay: 'flex',\n\talignItems: 'center',\n\tgap: '8px',\n\tpaddingRight: '16px',\n};\nconst rowButton: CSSProperties = { ...styles.rowButton, width: 'auto', flex: '1', minWidth: '0' };\nconst chips: CSSProperties = {\n\tdisplay: 'flex',\n\tflexWrap: 'wrap',\n\tjustifyContent: 'flex-end',\n\tgap: '6px',\n};\nconst newButton: CSSProperties = {\n\tdisplay: 'inline-flex',\n\talignItems: 'center',\n\theight: '32px',\n\tboxSizing: 'border-box',\n\tborderRadius: '6px',\n\tpadding: '0 12px',\n\tfontSize: '13px',\n\tfontWeight: 500,\n\tfontFamily: 'inherit',\n\tcursor: 'pointer',\n\tbackgroundColor: 'var(--fonderie-text,#171717)',\n\tcolor: 'var(--fonderie-surface,#fff)',\n\tborder: '1px solid var(--fonderie-text,#171717)',\n};\n\nexport const TemplateListScreen = defineComponent({\n\tname: 'FonderieTemplateListScreen',\n\tprops: {\n\t\tclient: { type: Object as PropType<CourierAdminClient>, required: true },\n\t\t/** Shows a \"New template\" button (emits create-template). */\n\t\tallowCreate: { type: Boolean, default: false },\n\t\t/** The console language; defaults to English. */\n\t\tlocale: { type: String as PropType<AdminLocale>, default: undefined },\n\t},\n\temits: {\n\t\t/**\n\t\t * The whole row — type AND locale, and whether it is built-in. One row\n\t\t * per email: the row opens the default locale, a locale chip that locale.\n\t\t */\n\t\t'select-template': (_template: ITemplateEntry) => true,\n\t\t/** Receives the locales in use, to suggest. */\n\t\t'create-template': (_context: { locales: string[] }) => true,\n\t},\n\tsetup(props, { emit }) {\n\t\tconst { templates, isLoading, error } = useTemplates(props.client);\n\t\tconst t = (key: AdminMessageKey, params?: AdminMessageParams) =>\n\t\t\tcreateAdminT(props.locale)(key, params);\n\n\t\tfunction renderRow(group: ITemplateGroup) {\n\t\t\tconst primary: ITemplateEntry = group.primary;\n\t\t\treturn h('li', { key: group.type, style: 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: rowButton,\n\t\t\t\t\t\tonClick: () => emit('select-template', primary),\n\t\t\t\t\t},\n\t\t\t\t\t[\n\t\t\t\t\t\th('span', { style: styles.type }, group.type),\n\t\t\t\t\t\tgroup.system ? h('span', { style: builtIn }, t('templates.builtInBadge')) : null,\n\t\t\t\t\t\th('span', { style: primary.active ? styles.active : styles.inactive }, [\n\t\t\t\t\t\t\th('span', { style: styles.dot }),\n\t\t\t\t\t\t\tprimary.active ? t('common.status.active') : t('common.status.inactive'),\n\t\t\t\t\t\t]),\n\t\t\t\t\t],\n\t\t\t\t),\n\t\t\t\t// Siblings of the row button, not inside it: a button cannot hold buttons.\n\t\t\t\th(\n\t\t\t\t\t'span',\n\t\t\t\t\t{ style: chips },\n\t\t\t\t\tgroup.entries.map((entry) => {\n\t\t\t\t\t\tconst name = entry.locale ?? t('templates.defaultChip');\n\t\t\t\t\t\treturn h(\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\tkey: entry.locale ?? '',\n\t\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t\tstyle: entry.active ? chip : chipInactive,\n\t\t\t\t\t\t\t\t'aria-label': t('templates.list.openLocale', { type: group.type, locale: name }),\n\t\t\t\t\t\t\t\ttitle: entry.active ? undefined : t('common.status.inactive'),\n\t\t\t\t\t\t\t\tonClick: () => emit('select-template', entry),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tname,\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\th('div', { style: styles.listContainer }, [\n\t\t\t\th(\n\t\t\t\t\t'div',\n\t\t\t\t\t{\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\t\t\talignItems: 'center',\n\t\t\t\t\t\t\tjustifyContent: 'space-between',\n\t\t\t\t\t\t\tgap: '16px',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t[\n\t\t\t\t\t\th('h1', { style: styles.listTitle }, t('templates.list.title')),\n\t\t\t\t\t\tprops.allowCreate\n\t\t\t\t\t\t\t? h(\n\t\t\t\t\t\t\t\t\t'button',\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: 'button',\n\t\t\t\t\t\t\t\t\t\tstyle: newButton,\n\t\t\t\t\t\t\t\t\t\tonClick: () =>\n\t\t\t\t\t\t\t\t\t\t\temit('create-template', {\n\t\t\t\t\t\t\t\t\t\t\t\tlocales: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t...new Set(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttemplates.value\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.map((tpl) => tpl.locale)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.filter((l): l is string => !!l),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tt('templates.list.newTemplate'),\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\t],\n\t\t\t\t),\n\t\t\t\th('p', { style: styles.hint }, t('templates.list.hint')),\n\t\t\t\tisLoading.value\n\t\t\t\t\t? h('p', { style: styles.status }, t('templates.list.loading'))\n\t\t\t\t\t: error.value\n\t\t\t\t\t\t? h('p', { style: styles.error, role: 'alert' }, error.value.explanation)\n\t\t\t\t\t\t: h('ul', { style: styles.list }, groupTemplatesByType(templates.value).map(renderRow)),\n\t\t\t]);\n\t},\n});\n"],"mappings":"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","names":["import_client","import_vue","import_client","import_vue_courier_admin","import_vue"]}
|