@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 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" on the default locale (emits 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
- /** Create a translation of this template. */
438
- "add-locale": (_type) => true
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
- "div",
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)("label", { style: styles.label, for: "template-sample" }, t("templates.editor.sampleData")),
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)("span", { style: styles.meta }, isPreviewing.value ? t("templates.editor.rendering") : t("templates.editor.live"))
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
- /** The whole row — type AND locale, and whether it is built-in. */
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(template) {
760
- return (0, import_vue3.h)("li", { key: `${template.type}:${template.locale ?? "base"}`, style: styles.row }, [
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: styles.rowButton,
766
- onClick: () => emit("select-template", template)
876
+ style: rowButton,
877
+ onClick: () => emit("select-template", primary)
767
878
  },
768
879
  [
769
- (0, import_vue3.h)("span", { style: styles.type }, template.type),
770
- (0, import_vue3.h)("span", { style: styles.locale }, template.locale ?? t("templates.defaultLocale")),
771
- template.system ? (0, import_vue3.h)("span", { style: builtIn }, t("templates.builtInBadge")) : null,
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
- template.active ? t("common.status.active") : t("common.status.inactive")
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
- "p",
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
  });
@@ -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"]}