@fonderie/react-courier-admin-screens 0.10.0 → 0.11.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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/screens/TemplateEditorScreen.tsx","../src/screens/TemplateListScreen.tsx","../src/screens/TemplateCreateScreen.tsx"],"sourcesContent":["import {\n\ttype AdminLocale,\n\ttype CourierAdminClient,\n\ttype FonderieApiError,\n\ttype ISetTemplateInput,\n\ttype ITemplateEntry,\n\tcreateAdminT,\n\tformatAdminDate,\n\tgroupTemplatesByType,\n\tmissingTemplateLocales,\n} from '@fonderie/client';\nimport {\n\tuseTemplate,\n\tuseTemplatePreview,\n\tuseTemplateRevisions,\n\tuseTemplates,\n} from '@fonderie/react-courier-admin';\nimport type { CSSProperties, FormEvent } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\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\nconst PREVIEW_DEBOUNCE_MS = 500;\n\nexport interface ITemplateEditorScreenProps {\n\tclient: CourierAdminClient;\n\ttype: string;\n\tlocale?: string | null;\n\tonSaved?: () => void;\n\t/**\n\t * A built-in email's default-locale row (the list's `system` flag): it can\n\t * be edited and rolled back, never deleted — Delete is not offered.\n\t */\n\tsystem?: boolean;\n\t/** Called after a delete; the template no longer exists. */\n\tonDeleted?: () => void;\n\t/**\n\t * Shows \"Add locale\": create a translation of this template. `locales` are\n\t * the ones the app uses elsewhere that this email lacks — suggest them first.\n\t */\n\tonAddLocale?: (type: string, context: { locales: string[] }) => void;\n\t/**\n\t * Shows a tab per locale this email exists in; receives the row to open.\n\t * Unsaved edits are confirmed before switching away.\n\t */\n\tonSelectLocale?: (template: ITemplateEntry) => void;\n\t/**\n\t * The CONSOLE's language (default English). Named `uiLocale` because\n\t * `locale` here is the template's own locale.\n\t */\n\tuiLocale?: AdminLocale | undefined;\n}\n\nexport function TemplateEditorScreen({\n\tclient,\n\ttype,\n\tlocale,\n\tonSaved,\n\tsystem = false,\n\tonDeleted,\n\tonAddLocale,\n\tonSelectLocale,\n\tuiLocale,\n}: ITemplateEditorScreenProps) {\n\t// Memoized: `run` below depends on it, and a new translator per render would\n\t// restart the preview debounce on every render.\n\tconst t = useMemo(() => createAdminT(uiLocale), [uiLocale]);\n\tconst { template, isLoading, error, refresh } = useTemplate(client, type, locale);\n\t// Saves go through the list hook (which re-fetches the template list after\n\t// each write); mounting it adds a template-list fetch to this single-template\n\t// editor — acceptable for an admin dashboard. Its isLoading/error track that\n\t// list fetch, so the save action keeps local state.\n\tconst { templates, saveTemplate, removeTemplate } = useTemplates(client);\n\t// This email's locales, for the tabs. The list is already fetched for saves.\n\tconst siblings = groupTemplatesByType(templates).find((g) => g.type === type)?.entries ?? [];\n\tconst [isDeleting, setIsDeleting] = useState(false);\n\tconst { revisions, rollback } = useTemplateRevisions(client, type, locale);\n\tconst [isSaving, setIsSaving] = useState(false);\n\tconst [saveError, setSaveError] = useState<FonderieApiError | null>(null);\n\n\tconst [subject, setSubject] = useState('');\n\tconst [html, setHtml] = useState('');\n\tconst [text, setText] = useState('');\n\tconst [active, setActive] = useState(true);\n\n\tconst { preview, isPreviewing, error: previewError, renderPreview } = useTemplatePreview(client);\n\t// The sample values, as JSON the operator can edit. Text rather than an\n\t// object so a half-typed value does not have to parse on every keystroke.\n\tconst [sampleJson, setSampleJson] = useState('{}');\n\tconst [sampleError, setSampleError] = useState<string | null>(null);\n\n\tuseEffect(() => {\n\t\tif (!template) return;\n\t\tsetSubject(template.subject ?? '');\n\t\tsetHtml(template.html ?? '');\n\t\tsetText(template.text);\n\t\tsetActive(template.active);\n\t}, [template]);\n\n\tconst run = useCallback(async () => {\n\t\tlet data: Record<string, unknown> = {};\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(sampleJson || '{}');\n\t\t\tif (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n\t\t\t\tsetSampleError(t('templates.editor.sampleNotObject'));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdata = parsed as Record<string, unknown>;\n\t\t\tsetSampleError(null);\n\t\t} catch {\n\t\t\tsetSampleError(t('templates.editor.sampleInvalid'));\n\t\t\treturn;\n\t\t}\n\t\tconst result = await renderPreview(\n\t\t\ttype,\n\t\t\t{ text, data, ...(subject ? { subject } : {}), ...(html ? { html } : {}) },\n\t\t\tlocale,\n\t\t);\n\t\t// The server reports which variables this content uses; seed the ones\n\t\t// that have no value yet with their own name, so the render shows where\n\t\t// each lands. Never overwrite something already typed.\n\t\tconst missing = result.variables.filter((v) => !IMPLICIT.has(v) && !(v in data));\n\t\tif (missing.length > 0) {\n\t\t\tconst seeded = { ...data, ...Object.fromEntries(missing.map((v) => [v, v])) };\n\t\t\tsetSampleJson(JSON.stringify(seeded, null, 2));\n\t\t}\n\t}, [renderPreview, type, text, subject, html, locale, sampleJson, t]);\n\n\t// The preview is always live: it renders once the template loads, then again\n\t// PREVIEW_DEBOUNCE_MS after the last edit to the content or the sample data.\n\t// Debounced, not per keystroke, so typing a paragraph costs one request.\n\t// `run` is a new function on every keystroke (it closes over the fields), so\n\t// the effect keys on the fields themselves and calls the latest `run`.\n\tconst runRef = useRef(run);\n\trunRef.current = run;\n\tconst loadedType = template ? `${type}:${locale ?? ''}` : null;\n\t// The fields ARE the trigger: each edit restarts the debounce. The effect\n\t// body reads the latest `run` through the ref, so it does not use them.\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: see above\n\tuseEffect(() => {\n\t\tif (!loadedType) return;\n\t\tconst timer = setTimeout(() => void runRef.current(), PREVIEW_DEBOUNCE_MS);\n\t\treturn () => clearTimeout(timer);\n\t}, [loadedType, subject, html, text, sampleJson]);\n\n\t// Saving what is already stored would only mint an identical version (the\n\t// server treats it as a no-op anyway), so Save waits for a real change.\n\tconst dirty =\n\t\t!!template &&\n\t\t(subject !== (template.subject ?? '') ||\n\t\t\thtml !== (template.html ?? '') ||\n\t\t\ttext !== template.text ||\n\t\t\tactive !== template.active);\n\n\tconst handleSubmit = async (event: FormEvent) => {\n\t\tevent.preventDefault();\n\t\tsetIsSaving(true);\n\t\tsetSaveError(null);\n\t\ttry {\n\t\t\tconst input: ISetTemplateInput = { text, active };\n\t\t\tif (subject) input.subject = subject;\n\t\t\tif (html) input.html = html;\n\t\t\tif (template?.version !== undefined) input.ifVersion = template.version;\n\t\t\tawait saveTemplate(type, input, locale);\n\t\t\t// The list hook refreshes its own list; this screen renders the single\n\t\t\t// template, so re-read it too.\n\t\t\tawait refresh();\n\t\t\tonSaved?.();\n\t\t} catch (err) {\n\t\t\t// useTemplates normalizes every failure to FonderieApiError before throwing.\n\t\t\tsetSaveError(err as FonderieApiError);\n\t\t} finally {\n\t\t\tsetIsSaving(false);\n\t\t}\n\t};\n\n\tconst switchTo = (entry: ITemplateEntry) => {\n\t\tif (dirty && !window.confirm(t('templates.editor.discardChanges'))) return;\n\t\tonSelectLocale?.(entry);\n\t};\n\n\tconst handleDelete = async () => {\n\t\tconst message = locale\n\t\t\t? t('templates.editor.confirmDeleteLocale', { type, locale })\n\t\t\t: t('templates.editor.confirmDelete', { type });\n\t\tif (!window.confirm(message)) return;\n\t\tsetIsDeleting(true);\n\t\tsetSaveError(null);\n\t\ttry {\n\t\t\tawait removeTemplate(type, locale);\n\t\t\tonDeleted?.();\n\t\t} catch (err) {\n\t\t\tsetSaveError(err as FonderieApiError);\n\t\t} finally {\n\t\t\tsetIsDeleting(false);\n\t\t}\n\t};\n\n\tif (isLoading) return <p style={styles.status}>{t('templates.editor.loading')}</p>;\n\tif (error)\n\t\treturn (\n\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t{error.explanation}\n\t\t\t</p>\n\t\t);\n\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>{type}</h1>\n\t\t\t{onSelectLocale || onAddLocale ? (\n\t\t\t\t<div style={styles.tabBar}>\n\t\t\t\t\t{onSelectLocale ? (\n\t\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\t<nav aria-label={t('templates.editor.locales')} style={styles.tabs}>\n\t\t\t\t\t\t\t{siblings.map((entry) => {\n\t\t\t\t\t\t\t\tconst selected = entry.locale === (locale ?? null);\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<button\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\taria-current={selected ? 'true' : undefined}\n\t\t\t\t\t\t\t\t\t\tonClick={() => (selected ? undefined : switchTo(entry))}\n\t\t\t\t\t\t\t\t\t\tstyle={selected ? styles.tabSelected : entry.active ? styles.tab : styles.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>\n\t\t\t\t\t\t\t\t\t\t{entry.locale ?? t('templates.defaultChip')}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</nav>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{onAddLocale ? (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tstyle={{ ...styles.rollbackButton, marginLeft: 'auto' }}\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tif (dirty && !window.confirm(t('templates.editor.discardChanges'))) return;\n\t\t\t\t\t\t\t\tonAddLocale(type, { locales: missingTemplateLocales(templates, type) });\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t('templates.editor.addLocale')}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t\t<p style={styles.meta}>\n\t\t\t\t<strong>{locale ?? t('templates.defaultLocale')}</strong> · v{template?.version ?? 1}\n\t\t\t\t{system ? ` · ${t('templates.editor.builtInNote')}` : ''}\n\t\t\t</p>\n\n\t\t\t<div style={styles.split}>\n\t\t\t\t<div style={styles.column}>\n\t\t\t\t\t<form style={styles.form} onSubmit={handleSubmit}>\n\t\t\t\t\t\t<label style={styles.label} htmlFor=\"template-subject\">\n\t\t\t\t\t\t\t{t('templates.subject')}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tid=\"template-subject\"\n\t\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\t\tvalue={subject}\n\t\t\t\t\t\t\tonChange={(event) => setSubject(event.target.value)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<label style={styles.label} htmlFor=\"template-html\">\n\t\t\t\t\t\t\t{t('templates.htmlBody')}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<textarea\n\t\t\t\t\t\t\tid=\"template-html\"\n\t\t\t\t\t\t\tstyle={styles.textarea}\n\t\t\t\t\t\t\tvalue={html}\n\t\t\t\t\t\t\tonChange={(event) => setHtml(event.target.value)}\n\t\t\t\t\t\t\trows={8}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<label style={styles.label} htmlFor=\"template-text\">\n\t\t\t\t\t\t\t{t('templates.textBody')}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<textarea\n\t\t\t\t\t\t\tid=\"template-text\"\n\t\t\t\t\t\t\tstyle={styles.textarea}\n\t\t\t\t\t\t\tvalue={text}\n\t\t\t\t\t\t\tonChange={(event) => setText(event.target.value)}\n\t\t\t\t\t\t\trows={4}\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<label style={styles.checkboxLabel}>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\tchecked={active}\n\t\t\t\t\t\t\t\tonChange={(event) => setActive(event.target.checked)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{t('templates.editor.active')}\n\t\t\t\t\t\t</label>\n\n\t\t\t\t\t\t{saveError?.reason === 'VERSION_CONFLICT' ? (\n\t\t\t\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t\t\t\t{t('templates.editor.conflict')}{' '}\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tstyle={styles.rollbackButton}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tsetSaveError(null);\n\t\t\t\t\t\t\t\t\t\tvoid refresh();\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\t\t{t('common.reload')}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t) : saveError ? (\n\t\t\t\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t\t\t\t{saveError.explanation}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t) : null}\n\n\t\t\t\t\t\t<div style={styles.saveRow}>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tdisabled={isSaving || !dirty}\n\t\t\t\t\t\t\t\tstyle={dirty ? styles.button : styles.buttonDisabled}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{isSaving ? t('common.saving') : t('common.save')}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t{!dirty && !isSaving && (\n\t\t\t\t\t\t\t\t<span style={styles.meta}>{t('templates.editor.noChanges')}</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{!system ? (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={isDeleting}\n\t\t\t\t\t\t\t\t\tonClick={() => void handleDelete()}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t...styles.rollbackButton,\n\t\t\t\t\t\t\t\t\t\theight: 36,\n\t\t\t\t\t\t\t\t\t\tmarginLeft: 'auto',\n\t\t\t\t\t\t\t\t\t\tcolor: 'var(--fonderie-danger,#e00)',\n\t\t\t\t\t\t\t\t\t\tborderColor: 'color-mix(in srgb, var(--fonderie-danger,#e00) 40%, transparent)',\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\t\t{isDeleting ? t('common.deleting') : t('common.delete')}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</form>\n\n\t\t\t\t\t<label style={styles.label} htmlFor=\"template-sample\">\n\t\t\t\t\t\t{t('templates.editor.sampleData')}\n\t\t\t\t\t</label>\n\t\t\t\t\t<textarea\n\t\t\t\t\t\tid=\"template-sample\"\n\t\t\t\t\t\tstyle={styles.textarea}\n\t\t\t\t\t\tvalue={sampleJson}\n\t\t\t\t\t\tonChange={(event) => setSampleJson(event.target.value)}\n\t\t\t\t\t\trows={6}\n\t\t\t\t\t\tspellCheck={false}\n\t\t\t\t\t/>\n\t\t\t\t\t{sampleError && (\n\t\t\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t\t\t{sampleError}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t<div style={styles.previewColumn}>\n\t\t\t\t\t<div style={styles.previewHeader}>\n\t\t\t\t\t\t<span style={styles.label}>{t('templates.editor.preview')}</span>\n\t\t\t\t\t\t<span style={styles.meta}>\n\t\t\t\t\t\t\t{isPreviewing ? t('templates.editor.rendering') : t('templates.editor.live')}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{previewError && (\n\t\t\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t\t\t{previewError.explanation}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t\t{preview?.subject && <p style={styles.previewSubject}>{preview.subject}</p>}\n\t\t\t\t\t{preview?.html ? (\n\t\t\t\t\t\t// sandbox=\"\" — no scripts, no same-origin. This is operator-authored\n\t\t\t\t\t\t// HTML and it must never execute in the dashboard's origin, which is\n\t\t\t\t\t\t// where the admin token lives.\n\t\t\t\t\t\t<iframe\n\t\t\t\t\t\t\ttitle={t('templates.editor.previewTitle')}\n\t\t\t\t\t\t\tstyle={styles.previewFrame}\n\t\t\t\t\t\t\tsandbox=\"\"\n\t\t\t\t\t\t\tsrcDoc={preview.html}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : preview ? (\n\t\t\t\t\t\t<pre style={styles.previewText}>{preview.text}</pre>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<p style={styles.meta}>{t('templates.editor.nothingRendered')}</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{revisions.length > 0 && (\n\t\t\t\t<div style={styles.revisions}>\n\t\t\t\t\t<h2 style={styles.subtitle}>{t('templates.editor.history')}</h2>\n\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t{revisions.map((rev) => (\n\t\t\t\t\t\t\t<li key={rev.version} style={styles.row}>\n\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\tv{rev.version} — {rev.actor ?? t('templates.editor.unknownActor')} —{' '}\n\t\t\t\t\t\t\t\t\t{formatAdminDate(rev.createdAt, uiLocale)}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => rollback(rev.version)}\n\t\t\t\t\t\t\t\t\tstyle={styles.rollbackButton}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{t('templates.editor.rollBack')}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nconst tab: CSSProperties = {\n\theight: 32,\n\tpadding: '0 10px',\n\tbackground: 'none',\n\tborder: 'none',\n\tborderBottom: '2px solid transparent',\n\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n\tfontSize: 13,\n\tfontFamily:\n\t\t'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\tcursor: 'pointer',\n};\n\nconst styles: Record<string, CSSProperties> = {\n\tcontainer: { padding: '8px 40px 64px', maxWidth: 1400, boxSizing: 'border-box' },\n\t// One tab per locale of this email, underlined like a document's tabs.\n\ttabBar: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'flex-end',\n\t\tgap: 12,\n\t\tborderBottom: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tmargin: '4px 0 12px',\n\t\tpaddingBottom: 6,\n\t},\n\ttabs: { display: 'flex', flexWrap: 'wrap', gap: 4, marginBottom: -7 },\n\ttab,\n\ttabSelected: {\n\t\t...tab,\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t\tfontWeight: 600,\n\t\tborderBottomColor: 'var(--fonderie-text,#171717)',\n\t\tcursor: 'default',\n\t},\n\ttabInactive: { ...tab, opacity: 0.55, textDecoration: 'line-through' },\n\t// Two columns, always: the editor on the left, the rendered result on the\n\t// right. Stacking the 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: 24,\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: 16,\n\t},\n\tsaveRow: { display: 'flex', alignItems: 'center', gap: 12, marginTop: 16 },\n\tpreviewHeader: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tmarginTop: 12,\n\t},\n\tpreviewSubject: { fontSize: 14, fontWeight: 600, margin: '8px 0' },\n\tpreviewFrame: {\n\t\tboxShadow: 'var(--fonderie-shadow-card,0 2px 3px 0 rgba(0,0,0,.05))',\n\t\twidth: '100%',\n\t\theight: 520,\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 8,\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t},\n\tpreviewText: {\n\t\twhiteSpace: 'pre-wrap',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 8,\n\t\tpadding: 12,\n\t\tfontSize: 13,\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: 22,\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\tmeta: { fontSize: 13, color: 'var(--fonderie-text-muted,#5c5c5c)', marginBottom: 20 },\n\tstatus: { padding: 24, textAlign: 'center', color: 'var(--fonderie-text-muted,#5c5c5c)' },\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: 6,\n\t\tpadding: '8px 12px',\n\t\tmargin: '8px 0',\n\t\tfontSize: 13.5,\n\t},\n\tform: {\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tgap: 4,\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: 13, fontWeight: 500, marginTop: 14, marginBottom: 2 },\n\tinput: {\n\t\theight: 36,\n\t\tboxSizing: 'border-box',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 6,\n\t\tpadding: '0 10px',\n\t\tfontSize: 13.5,\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: 6,\n\t\tpadding: 10,\n\t\tfontSize: 13,\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: { display: 'flex', alignItems: 'center', gap: 8, marginTop: 12, fontSize: 14 },\n\tbutton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: 36,\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: 6,\n\t\tborder: '1px solid var(--fonderie-text,#171717)',\n\t\tfontSize: 13.5,\n\t\tfontWeight: 600,\n\t\tfontFamily: 'inherit',\n\t\tcursor: 'pointer',\n\t\talignSelf: 'flex-start',\n\t},\n\tbuttonDisabled: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: 36,\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: 6,\n\t\tborder: '1px solid var(--fonderie-text,#171717)',\n\t\tfontSize: 13.5,\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: 32 },\n\tsubtitle: {\n\t\tfontSize: 15,\n\t\tfontWeight: 600,\n\t\tmargin: '0 0 10px',\n\t\tletterSpacing: 'var(--fonderie-tracking-display,-0.05em)',\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},\n\trow: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tgap: 12,\n\t\tpadding: '9px 16px',\n\t\tborderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)',\n\t\tfontSize: 13,\n\t},\n\trollbackButton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: 28,\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: 6,\n\t\tpadding: '0 10px',\n\t\tfontSize: 12.5,\n\t\tfontWeight: 500,\n\t\tfontFamily: 'inherit',\n\t\tcursor: 'pointer',\n\t},\n};\n","import {\n\ttype AdminLocale,\n\ttype CourierAdminClient,\n\ttype ITemplateEntry,\n\tcreateAdminT,\n\tgroupTemplatesByType,\n} from '@fonderie/client';\nimport { useTemplates } from '@fonderie/react-courier-admin';\nimport type { CSSProperties } from 'react';\n\nexport interface ITemplateListScreenProps {\n\tclient: CourierAdminClient;\n\t/**\n\t * Receives the whole row — type AND locale, and whether it is built-in. The\n\t * list shows one row per email: clicking it opens the default locale, a\n\t * locale chip opens that locale.\n\t */\n\tonSelectTemplate?: (template: ITemplateEntry) => void;\n\t/** Shows a \"New template\" button. Receives the locales in use, to suggest. */\n\tonCreateTemplate?: (context: { locales: string[] }) => void;\n\t/** The console's language. Default English. */\n\tlocale?: AdminLocale | undefined;\n}\n\nexport function TemplateListScreen({\n\tclient,\n\tonSelectTemplate,\n\tonCreateTemplate,\n\tlocale,\n}: ITemplateListScreenProps) {\n\tconst t = createAdminT(locale);\n\tconst { templates, isLoading, error } = useTemplates(client);\n\tconst groups = groupTemplatesByType(templates);\n\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div\n\t\t\t\tstyle={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16 }}\n\t\t\t>\n\t\t\t\t<h1 style={styles.title}>{t('templates.list.title')}</h1>\n\t\t\t\t{onCreateTemplate ? (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\tonCreateTemplate({\n\t\t\t\t\t\t\t\tlocales: [\n\t\t\t\t\t\t\t\t\t...new Set(templates.map((row) => row.locale).filter((l): l is string => !!l)),\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\tstyle={styles.newButton}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('templates.list.newTemplate')}\n\t\t\t\t\t</button>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t\t<p style={styles.hint}>{t('templates.list.hint')}</p>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>{t('templates.list.loading')}</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t{groups.map((group) => (\n\t\t\t\t\t\t<li key={group.type} style={styles.row}>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => onSelectTemplate?.(group.primary)}\n\t\t\t\t\t\t\t\tstyle={styles.rowButton}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span style={styles.type}>{group.type}</span>\n\t\t\t\t\t\t\t\t{group.system ? (\n\t\t\t\t\t\t\t\t\t<span style={styles.builtIn}>{t('templates.builtInBadge')}</span>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t<span style={group.primary.active ? styles.active : styles.inactive}>\n\t\t\t\t\t\t\t\t\t<span style={styles.dot} />\n\t\t\t\t\t\t\t\t\t{group.primary.active ? t('common.status.active') : t('common.status.inactive')}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t{/* Siblings of the row button, not inside it: a button cannot hold buttons. */}\n\t\t\t\t\t\t\t<span style={styles.chips}>\n\t\t\t\t\t\t\t\t{group.entries.map((entry) => {\n\t\t\t\t\t\t\t\t\tconst name = entry.locale ?? t('templates.defaultChip');\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\tkey={entry.locale ?? ''}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => onSelectTemplate?.(entry)}\n\t\t\t\t\t\t\t\t\t\t\tstyle={entry.active ? styles.chip : styles.chipInactive}\n\t\t\t\t\t\t\t\t\t\t\taria-label={t('templates.list.openLocale', { type: group.type, locale: name })}\n\t\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\t>\n\t\t\t\t\t\t\t\t\t\t\t{name}\n\t\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})}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// Matches @fonderie/react-admin-screens' shell look with local values: this\n// package sits below the admin screens and cannot import their blocks.\nconst pill: CSSProperties = {\n\tdisplay: 'inline-flex',\n\talignItems: 'center',\n\tgap: 6,\n\tborderRadius: 999,\n\tpadding: '2px 9px 2px 8px',\n\tfontSize: 12,\n\tfontWeight: 600,\n\tlineHeight: 1.5,\n\tminWidth: 64,\n};\n\n// One per locale the email exists in. Monospace: they are language tags.\nconst chip: CSSProperties = {\n\theight: 24,\n\tboxSizing: 'border-box',\n\tpadding: '0 8px',\n\tborderRadius: 6,\n\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\tbackground: 'var(--fonderie-surface,#fff)',\n\tcolor: 'var(--fonderie-text,#171717)',\n\tfontSize: 12,\n\tfontFamily:\n\t\t'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\tcursor: 'pointer',\n};\n\nconst styles: Record<string, CSSProperties> = {\n\tcontainer: { padding: '32px 40px 64px', maxWidth: 1160, boxSizing: 'border-box' },\n\ttitle: {\n\t\tfontSize: 22,\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.5, color: 'var(--fonderie-text-muted,#5c5c5c)', margin: '4px 0 24px' },\n\tstatus: { padding: '24px 0', color: 'var(--fonderie-text-muted,#5c5c5c)', fontSize: 13.5 },\n\terror: { color: 'var(--fonderie-danger,#e00)', marginBottom: 12, fontSize: 14 },\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: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tgap: 8,\n\t\tpaddingRight: 16,\n\t\tborderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)',\n\t},\n\trowButton: {\n\t\tflex: 1,\n\t\tminWidth: 0,\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tgap: 16,\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: 13,\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\tchips: { display: 'flex', flexWrap: 'wrap', justifyContent: 'flex-end', gap: 6 },\n\tchip,\n\tchipInactive: { ...chip, opacity: 0.5, textDecoration: 'line-through' },\n\tdot: { width: 6, height: 6, borderRadius: 999, background: 'currentColor' },\n\tbuiltIn: {\n\t\tfontSize: 11,\n\t\tfontWeight: 500,\n\t\tpadding: '1px 7px',\n\t\tborderRadius: 999,\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n\t},\n\tnewButton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: 32,\n\t\tboxSizing: 'border-box',\n\t\tborderRadius: 6,\n\t\tpadding: '0 12px',\n\t\tfontSize: 13,\n\t\tfontWeight: 500,\n\t\tfontFamily: 'inherit',\n\t\tcursor: 'pointer',\n\t\tbackgroundColor: 'var(--fonderie-text,#171717)',\n\t\tcolor: 'var(--fonderie-surface,#fff)',\n\t\tborder: '1px solid var(--fonderie-text,#171717)',\n\t},\n\tactive: {\n\t\t...pill,\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\t...pill,\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};\n","import {\n\ttype AdminLocale,\n\ttype CourierAdminClient,\n\tFonderieApiError,\n\ttype ISetTemplateInput,\n\tcreateAdminT,\n} from '@fonderie/client';\nimport { useTemplatePreview } from '@fonderie/react-courier-admin';\nimport type { CSSProperties, FormEvent } from 'react';\nimport { useEffect, useRef, useState } from 'react';\n\nexport interface ITemplateCreateScreenProps {\n\tclient: CourierAdminClient;\n\t/**\n\t * Given ⇒ add a LOCALE of this existing template: the type is fixed and the\n\t * form starts from its default-locale copy. Omitted ⇒ a brand-new template\n\t * type (one the app sends that has no stored copy yet).\n\t */\n\ttype?: string;\n\t/** Locales already in use, offered as suggestions. */\n\tlocales?: string[];\n\t/** Called with what was created, so the caller can open it in the editor. */\n\tonCreated?: (created: { type: string; locale: string | null }) => void;\n\t/** The console's language. Default English. */\n\tlocale?: AdminLocale | undefined;\n}\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// Variables the layout injects — never sample values, as in the editor.\nconst IMPLICIT = new Set(['subject', 'preheader', 'brandName']);\nconst PREVIEW_DEBOUNCE_MS = 500;\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 function TemplateCreateScreen({\n\tclient,\n\ttype,\n\tlocales = [],\n\tonCreated,\n\tlocale,\n}: ITemplateCreateScreenProps) {\n\tconst tr = createAdminT(locale);\n\tconst addingLocale = type !== undefined;\n\tconst [newType, setNewType] = useState('');\n\tconst [targetLocale, setTargetLocale] = useState('');\n\tconst [subject, setSubject] = useState('');\n\tconst [html, setHtml] = useState('');\n\tconst [text, setText] = useState('');\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [busy, setBusy] = useState(false);\n\t// The default copy this locale started from, to flag fields not yet translated.\n\tconst [source, setSource] = useState<{ subject: string; html: string; text: string } | null>(\n\t\tnull,\n\t);\n\tconst { preview, isPreviewing, error: previewError, renderPreview } = useTemplatePreview(client);\n\t// Each variable renders as its own name, so the preview shows where it lands.\n\t// Learned from the server's answer, not re-parsed here.\n\tconst variables = useRef<string[]>([]);\n\n\t// A new locale starts from the default copy, so translating is editing.\n\tuseEffect(() => {\n\t\tif (!type) return;\n\t\tclient\n\t\t\t.getTemplate(type, null)\n\t\t\t.then(({ result }) => {\n\t\t\t\tsetSubject(result.subject ?? '');\n\t\t\t\tsetHtml(result.html ?? '');\n\t\t\t\tsetText(result.text);\n\t\t\t\tsetSource({ subject: result.subject ?? '', html: result.html ?? '', text: result.text });\n\t\t\t})\n\t\t\t.catch(() => undefined);\n\t}, [client, type]);\n\n\t// Live preview, as in the editor: translating is where it matters most — a\n\t// half-translated email looks finished in a textarea and wrong in the render.\n\tconst previewType = addingLocale ? (type as string) : newType.trim();\n\tconst previewLocale = LOCALE_RE.test(targetLocale.trim()) ? targetLocale.trim() : null;\n\tuseEffect(() => {\n\t\tif (!TYPE_RE.test(previewType) || !text.trim()) return;\n\t\tconst timer = setTimeout(async () => {\n\t\t\tconst input = { text, ...(subject ? { subject } : {}), ...(html ? { html } : {}) };\n\t\t\tconst render = () =>\n\t\t\t\trenderPreview(\n\t\t\t\t\tpreviewType,\n\t\t\t\t\t{ ...input, data: Object.fromEntries(variables.current.map((v) => [v, v])) },\n\t\t\t\t\tpreviewLocale,\n\t\t\t\t);\n\t\t\ttry {\n\t\t\t\tconst result = await render();\n\t\t\t\tconst used = result.variables.filter((v) => !IMPLICIT.has(v));\n\t\t\t\t// A variable not seen before rendered empty: render once more with it.\n\t\t\t\tif (used.some((v) => !variables.current.includes(v))) {\n\t\t\t\t\tvariables.current = used;\n\t\t\t\t\tawait render();\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Shown through previewError.\n\t\t\t}\n\t\t}, PREVIEW_DEBOUNCE_MS);\n\t\treturn () => clearTimeout(timer);\n\t}, [renderPreview, previewType, previewLocale, subject, html, text]);\n\n\tconst untranslated = source\n\t\t? [\n\t\t\t\tsubject && subject === source.subject ? tr('templates.subject') : null,\n\t\t\t\thtml && html === source.html ? tr('templates.htmlBody') : null,\n\t\t\t\ttext === source.text ? tr('templates.textBody') : null,\n\t\t\t].filter((f): f is string => f !== null)\n\t\t: [];\n\n\tconst submit = async (e: FormEvent) => {\n\t\te.preventDefault();\n\t\tsetError(null);\n\t\tconst t = addingLocale ? (type as string) : newType.trim();\n\t\tconst l = targetLocale.trim() || null;\n\t\tif (!TYPE_RE.test(t)) return setError(tr('templates.create.errorType'));\n\t\tif (addingLocale && !l) return setError(tr('templates.create.errorLocaleRequired'));\n\t\tif (l && !LOCALE_RE.test(l)) return setError(tr('templates.create.errorLocale'));\n\t\tif (!text.trim()) return setError(tr('templates.create.errorText'));\n\t\tsetBusy(true);\n\t\ttry {\n\t\t\t// Refuse to overwrite: creating an existing row would replace it.\n\t\t\tconst exists = await client.getTemplate(t, l).then(\n\t\t\t\t() => true,\n\t\t\t\t(err: unknown) => !(err instanceof FonderieApiError && err.status === 404),\n\t\t\t);\n\t\t\tif (exists) {\n\t\t\t\tsetError(\n\t\t\t\t\tl\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);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst input: ISetTemplateInput = { text, active: true };\n\t\t\tif (subject) input.subject = subject;\n\t\t\tif (html) input.html = html;\n\t\t\tawait client.setTemplate(t, input, l);\n\t\t\tonCreated?.({ type: t, locale: l });\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof FonderieApiError ? err.explanation : String(err));\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>\n\t\t\t\t{addingLocale\n\t\t\t\t\t? tr('templates.create.titleLocale', { type: type as string })\n\t\t\t\t\t: tr('templates.create.titleNew')}\n\t\t\t</h1>\n\t\t\t<p style={styles.meta}>\n\t\t\t\t{addingLocale ? tr('templates.create.hintLocale') : tr('templates.create.hintNew')}\n\t\t\t</p>\n\t\t\t<div style={styles.split}>\n\t\t\t\t<form style={styles.form} onSubmit={(e) => void submit(e)}>\n\t\t\t\t\t{!addingLocale ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<label style={styles.label} htmlFor=\"new-template-type\">\n\t\t\t\t\t\t\t\t{tr('templates.create.type')}\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\tid=\"new-template-type\"\n\t\t\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\t\t\tvalue={newType}\n\t\t\t\t\t\t\t\tplaceholder=\"weekly-digest\"\n\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\tspellCheck={false}\n\t\t\t\t\t\t\t\tonChange={(e) => setNewType(e.target.value)}\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\t\t<label style={styles.label} htmlFor=\"new-template-locale\">\n\t\t\t\t\t\t{addingLocale ? tr('templates.create.locale') : tr('templates.create.localeOptional')}\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\tid=\"new-template-locale\"\n\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\tvalue={targetLocale}\n\t\t\t\t\t\tplaceholder=\"fr\"\n\t\t\t\t\t\tlist=\"new-template-locales\"\n\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\tspellCheck={false}\n\t\t\t\t\t\tonChange={(e) => setTargetLocale(e.target.value)}\n\t\t\t\t\t/>\n\t\t\t\t\t<datalist id=\"new-template-locales\">\n\t\t\t\t\t\t{[...new Set(locales)].map((l) => (\n\t\t\t\t\t\t\t<option key={l} value={l} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</datalist>\n\t\t\t\t\t<label style={styles.label} htmlFor=\"new-template-subject\">\n\t\t\t\t\t\t{tr('templates.subject')}\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\tid=\"new-template-subject\"\n\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\tvalue={subject}\n\t\t\t\t\t\tonChange={(e) => setSubject(e.target.value)}\n\t\t\t\t\t/>\n\t\t\t\t\t<label style={styles.label} htmlFor=\"new-template-html\">\n\t\t\t\t\t\t{tr('templates.htmlBody')}\n\t\t\t\t\t</label>\n\t\t\t\t\t<textarea\n\t\t\t\t\t\tid=\"new-template-html\"\n\t\t\t\t\t\tstyle={{ ...styles.textarea, minHeight: 160 }}\n\t\t\t\t\t\tvalue={html}\n\t\t\t\t\t\tonChange={(e) => setHtml(e.target.value)}\n\t\t\t\t\t/>\n\t\t\t\t\t<label style={styles.label} htmlFor=\"new-template-text\">\n\t\t\t\t\t\t{tr('templates.textBody')}\n\t\t\t\t\t</label>\n\t\t\t\t\t<textarea\n\t\t\t\t\t\tid=\"new-template-text\"\n\t\t\t\t\t\tstyle={{ ...styles.textarea, minHeight: 100 }}\n\t\t\t\t\t\tvalue={text}\n\t\t\t\t\t\tonChange={(e) => setText(e.target.value)}\n\t\t\t\t\t/>\n\t\t\t\t\t{untranslated.length > 0 ? (\n\t\t\t\t\t\t<p style={styles.notice}>\n\t\t\t\t\t\t\t{tr('templates.create.untranslated', { fields: untranslated.join(', ') })}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{error ? (\n\t\t\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<button type=\"submit\" disabled={busy} style={styles.button}>\n\t\t\t\t\t\t{busy\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</button>\n\t\t\t\t</form>\n\n\t\t\t\t<div style={styles.previewColumn}>\n\t\t\t\t\t<div style={styles.previewHeader}>\n\t\t\t\t\t\t<span style={styles.label}>{tr('templates.editor.preview')}</span>\n\t\t\t\t\t\t<span style={styles.meta}>\n\t\t\t\t\t\t\t{isPreviewing ? tr('templates.editor.rendering') : tr('templates.editor.live')}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{previewError ? (\n\t\t\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t\t\t{previewError.explanation}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{preview?.subject ? <p style={styles.previewSubject}>{preview.subject}</p> : null}\n\t\t\t\t\t{preview?.html ? (\n\t\t\t\t\t\t// sandbox=\"\" — no scripts, no same-origin: operator-authored HTML must\n\t\t\t\t\t\t// never execute in the console's origin.\n\t\t\t\t\t\t<iframe\n\t\t\t\t\t\t\ttitle={tr('templates.editor.previewTitle')}\n\t\t\t\t\t\t\tstyle={styles.previewFrame}\n\t\t\t\t\t\t\tsandbox=\"\"\n\t\t\t\t\t\t\tsrcDoc={preview.html}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : preview ? (\n\t\t\t\t\t\t<pre style={styles.previewText}>{preview.text}</pre>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<p style={styles.meta}>{tr('templates.editor.nothingRendered')}</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nconst MONO =\n\t'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)';\nconst styles: Record<string, CSSProperties> = {\n\tcontainer: { padding: '8px 40px 64px', maxWidth: 1400, boxSizing: 'border-box' },\n\t// The editor's layout: the form on the left, the render pinned on the right.\n\tsplit: {\n\t\tdisplay: 'grid',\n\t\tgridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)',\n\t\tgap: 24,\n\t\talignItems: 'start',\n\t},\n\tpreviewColumn: {\n\t\tminWidth: 0,\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tposition: 'sticky',\n\t\ttop: 16,\n\t},\n\tpreviewHeader: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' },\n\tpreviewSubject: { fontSize: 14, fontWeight: 600, margin: '8px 0' },\n\tpreviewFrame: {\n\t\tboxShadow: 'var(--fonderie-shadow-card,0 2px 3px 0 rgba(0,0,0,.05))',\n\t\twidth: '100%',\n\t\theight: 520,\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 8,\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t},\n\tpreviewText: {\n\t\twhiteSpace: 'pre-wrap',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 8,\n\t\tpadding: 12,\n\t\tfontSize: 13,\n\t\tfontFamily: MONO,\n\t},\n\t// The console's warning token (the shell's amber), readable in both themes.\n\tnotice: {\n\t\tfontSize: 13,\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t\tbackground: 'color-mix(in srgb, var(--fonderie-warning,#f5a623) 16%, transparent)',\n\t\tborderRadius: 6,\n\t\tpadding: '8px 12px',\n\t\tmargin: '12px 0 0',\n\t},\n\ttitle: {\n\t\tfontSize: 22,\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\tmeta: {\n\t\tfontSize: 13,\n\t\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n\t\tmarginBottom: 20,\n\t\tlineHeight: 1.5,\n\t},\n\tform: {\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tgap: 4,\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},\n\tlabel: { fontSize: 13, fontWeight: 500, marginTop: 14, marginBottom: 2 },\n\tinput: {\n\t\theight: 36,\n\t\tboxSizing: 'border-box',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 6,\n\t\tpadding: '0 10px',\n\t\tfontSize: 13.5,\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: 6,\n\t\tpadding: 10,\n\t\tfontSize: 13,\n\t\tlineHeight: 1.55,\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t\tfontFamily: MONO,\n\t},\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: 6,\n\t\tpadding: '8px 12px',\n\t\tmargin: '8px 0',\n\t\tfontSize: 13.5,\n\t},\n\tbutton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: 36,\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: 6,\n\t\tborder: '1px solid var(--fonderie-text,#171717)',\n\t\tfontSize: 13.5,\n\t\tfontWeight: 600,\n\t\tfontFamily: 'inherit',\n\t\tcursor: 'pointer',\n\t\talignSelf: 'flex-start',\n\t\tmarginTop: 16,\n\t},\n};\n"],"mappings":"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","names":["createAdminT","groupTemplatesByType","useTemplates","jsx","jsxs","styles","createAdminT","useTemplatePreview","useEffect","useRef","useState","jsx","jsxs","IMPLICIT","PREVIEW_DEBOUNCE_MS","styles"]}
1
+ {"version":3,"sources":["../src/screens/TemplateEditorScreen.tsx","../src/screens/TemplateListScreen.tsx","../src/screens/TemplateCreateScreen.tsx"],"sourcesContent":["import {\n\ttype AdminLocale,\n\ttype CourierAdminClient,\n\ttype FonderieApiError,\n\ttype ISetTemplateInput,\n\tcreateAdminT,\n\tformatAdminDate,\n\tsuggestTemplateLocales,\n\ttemplateLanguages,\n} from '@fonderie/client';\nimport {\n\tuseBuiltInTemplate,\n\tuseTemplate,\n\tuseTemplateCatalog,\n\tuseTemplatePreview,\n\tuseTemplateResolution,\n\tuseTemplateRevisions,\n\tuseTemplates,\n} from '@fonderie/react-courier-admin';\nimport type { CSSProperties, FormEvent } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { ITemplateSelection } from './TemplateListScreen';\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\nconst PREVIEW_DEBOUNCE_MS = 500;\n\nexport interface ITemplateEditorScreenProps {\n\tclient: CourierAdminClient;\n\ttype: string;\n\tlocale?: string | null;\n\tonSaved?: () => void;\n\t/**\n\t * A built-in email's default-locale row (the list's `system` flag): it can\n\t * be edited and rolled back, never deleted — Delete is not offered.\n\t */\n\tsystem?: boolean;\n\t/** Called after a delete; the template no longer exists. */\n\tonDeleted?: () => void;\n\t/**\n\t * Shows \"Add locale\": create a translation of this template. `locales` are\n\t * the ones the app uses elsewhere that this email lacks — suggest them first.\n\t */\n\tonAddLocale?: (type: string, context: { locales: string[]; defaultLocale?: string }) => void;\n\t/**\n\t * Shows a tab per locale this email exists in; receives the row to open.\n\t * Unsaved edits are confirmed before switching away.\n\t */\n\tonSelectLocale?: (template: ITemplateSelection) => void;\n\t/**\n\t * The CONSOLE's language (default English). Named `uiLocale` because\n\t * `locale` here is the template's own locale.\n\t */\n\tuiLocale?: AdminLocale | undefined;\n}\n\nexport function TemplateEditorScreen({\n\tclient,\n\ttype,\n\tlocale,\n\tonSaved,\n\tsystem = false,\n\tonDeleted,\n\tonAddLocale,\n\tonSelectLocale,\n\tuiLocale,\n}: ITemplateEditorScreenProps) {\n\t// Memoized: `run` below depends on it, and a new translator per render would\n\t// restart the preview debounce on every render.\n\tconst t = useMemo(() => createAdminT(uiLocale), [uiLocale]);\n\tconst { template, isLoading, error, refresh } = useTemplate(client, type, locale);\n\t// No saved version in this language is not an error: it may be Fonderie's\n\t// built-in copy, which opens prefilled and saves as the app's own version.\n\tconst notSaved = error?.status === 404;\n\tconst { builtIn, isLoading: builtInLoading } = useBuiltInTemplate(client, type, locale);\n\tconst { catalog, refresh: refreshCatalog } = useTemplateCatalog(client);\n\tconst defaultLocale = catalog?.defaultLocale ?? 'en-US';\n\tconst email = catalog?.emails.find((e) => e.type === type);\n\tconst languages = email ? templateLanguages(email, defaultLocale) : [];\n\t// What the fields start from, and what \"dirty\" is measured against.\n\tconst source = template ?? (notSaved ? builtIn : null);\n\tconst { resolution, resolve } = useTemplateResolution(client);\n\tconst [probe, setProbe] = useState('');\n\t// Saves go through the list hook (which re-fetches the template list after\n\t// each write); mounting it adds a template-list fetch to this single-template\n\t// editor — acceptable for an admin dashboard. Its isLoading/error track that\n\t// list fetch, so the save action keeps local state.\n\tconst { saveTemplate, removeTemplate } = useTemplates(client);\n\tconst [isDeleting, setIsDeleting] = useState(false);\n\tconst { revisions, rollback } = useTemplateRevisions(client, type, locale);\n\tconst [isSaving, setIsSaving] = useState(false);\n\tconst [saveError, setSaveError] = useState<FonderieApiError | null>(null);\n\n\tconst [subject, setSubject] = useState('');\n\tconst [html, setHtml] = useState('');\n\tconst [text, setText] = useState('');\n\tconst [active, setActive] = useState(true);\n\n\tconst { preview, isPreviewing, error: previewError, renderPreview } = useTemplatePreview(client);\n\t// The sample values, as JSON the operator can edit. Text rather than an\n\t// object so a half-typed value does not have to parse on every keystroke.\n\tconst [sampleJson, setSampleJson] = useState('{}');\n\tconst [sampleError, setSampleError] = useState<string | null>(null);\n\n\tuseEffect(() => {\n\t\tif (!source) return;\n\t\tsetSubject(source.subject ?? '');\n\t\tsetHtml(source.html ?? '');\n\t\tsetText(source.text);\n\t\tsetActive(template ? template.active : true);\n\t}, [source, template]);\n\n\t// The chain this language falls back along, from the server's own decision.\n\tuseEffect(() => {\n\t\tvoid resolve(type, locale ?? defaultLocale);\n\t}, [resolve, type, locale, defaultLocale]);\n\n\tconst run = useCallback(async () => {\n\t\tlet data: Record<string, unknown> = {};\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(sampleJson || '{}');\n\t\t\tif (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n\t\t\t\tsetSampleError(t('templates.editor.sampleNotObject'));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdata = parsed as Record<string, unknown>;\n\t\t\tsetSampleError(null);\n\t\t} catch {\n\t\t\tsetSampleError(t('templates.editor.sampleInvalid'));\n\t\t\treturn;\n\t\t}\n\t\tconst result = await renderPreview(\n\t\t\ttype,\n\t\t\t{ text, data, ...(subject ? { subject } : {}), ...(html ? { html } : {}) },\n\t\t\tlocale,\n\t\t);\n\t\t// The server reports which variables this content uses; seed the ones\n\t\t// that have no value yet with their own name, so the render shows where\n\t\t// each lands. Never overwrite something already typed.\n\t\tconst missing = result.variables.filter((v) => !IMPLICIT.has(v) && !(v in data));\n\t\tif (missing.length > 0) {\n\t\t\tconst seeded = { ...data, ...Object.fromEntries(missing.map((v) => [v, v])) };\n\t\t\tsetSampleJson(JSON.stringify(seeded, null, 2));\n\t\t}\n\t}, [renderPreview, type, text, subject, html, locale, sampleJson, t]);\n\n\t// The preview is always live: it renders once the template loads, then again\n\t// PREVIEW_DEBOUNCE_MS after the last edit to the content or the sample data.\n\t// Debounced, not per keystroke, so typing a paragraph costs one request.\n\t// `run` is a new function on every keystroke (it closes over the fields), so\n\t// the effect keys on the fields themselves and calls the latest `run`.\n\tconst runRef = useRef(run);\n\trunRef.current = run;\n\tconst loadedType = source ? `${type}:${locale ?? ''}` : null;\n\t// The fields ARE the trigger: each edit restarts the debounce. The effect\n\t// body reads the latest `run` through the ref, so it does not use them.\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: see above\n\tuseEffect(() => {\n\t\tif (!loadedType) return;\n\t\tconst timer = setTimeout(() => void runRef.current(), PREVIEW_DEBOUNCE_MS);\n\t\treturn () => clearTimeout(timer);\n\t}, [loadedType, subject, html, text, sampleJson]);\n\n\t// Saving what is already stored would only mint an identical version (the\n\t// server treats it as a no-op anyway), so Save waits for a real change.\n\t// A built-in copy nobody saved is always saveable: saving is what makes it\n\t// the app's own version.\n\tconst dirty =\n\t\t(notSaved && !!builtIn) ||\n\t\t(!!template &&\n\t\t\t(subject !== (template.subject ?? '') ||\n\t\t\t\thtml !== (template.html ?? '') ||\n\t\t\t\ttext !== template.text ||\n\t\t\t\tactive !== template.active));\n\t// Only the default version of a built-in email is protected; its language\n\t// versions are the app's to delete (the built-in copy then sends again).\n\tconst protectedRow = !locale && (email?.system ?? system);\n\t// Fonderie ships this language (or, for the default version, the English).\n\tconst shipsHere = locale\n\t\t? languages.some((l) => l.locale === locale && l.builtIn)\n\t\t: !!email?.builtIn.default;\n\n\tconst handleSubmit = async (event: FormEvent) => {\n\t\tevent.preventDefault();\n\t\tsetIsSaving(true);\n\t\tsetSaveError(null);\n\t\ttry {\n\t\t\tconst input: ISetTemplateInput = { text, active };\n\t\t\tif (subject) input.subject = subject;\n\t\t\tif (html) input.html = html;\n\t\t\tif (template?.version !== undefined) input.ifVersion = template.version;\n\t\t\tawait saveTemplate(type, input, locale);\n\t\t\t// The list hook refreshes its own list; this screen renders the single\n\t\t\t// template and the tabs, so re-read both.\n\t\t\tawait Promise.all([refresh(), refreshCatalog()]);\n\t\t\tonSaved?.();\n\t\t} catch (err) {\n\t\t\t// useTemplates normalizes every failure to FonderieApiError before throwing.\n\t\t\tsetSaveError(err as FonderieApiError);\n\t\t} finally {\n\t\t\tsetIsSaving(false);\n\t\t}\n\t};\n\n\tconst switchTo = (next: ITemplateSelection) => {\n\t\tif (dirty && !(notSaved && !!builtIn) && !window.confirm(t('templates.editor.discardChanges')))\n\t\t\treturn;\n\t\tonSelectLocale?.(next);\n\t};\n\n\t// Back to what Fonderie ships. A language version is deleted, so the built-in\n\t// copy sends again and later Fonderie updates reach it; the default version\n\t// of a built-in email cannot be deleted, so it is saved over with the\n\t// built-in copy as a new version — its history keeps the old one.\n\tconst handleReset = async () => {\n\t\tif (\n\t\t\t!builtIn ||\n\t\t\t!window.confirm(t('templates.editor.confirmReset', { locale: locale ?? defaultLocale }))\n\t\t)\n\t\t\treturn;\n\t\tsetIsDeleting(true);\n\t\tsetSaveError(null);\n\t\ttry {\n\t\t\tif (locale) {\n\t\t\t\tawait removeTemplate(type, locale);\n\t\t\t} else {\n\t\t\t\tconst input: ISetTemplateInput = { text: builtIn.text, active };\n\t\t\t\tif (builtIn.subject) input.subject = builtIn.subject;\n\t\t\t\tif (builtIn.html) input.html = builtIn.html;\n\t\t\t\tif (template?.version !== undefined) input.ifVersion = template.version;\n\t\t\t\tawait saveTemplate(type, input, null);\n\t\t\t}\n\t\t\tawait Promise.all([refresh(), refreshCatalog()]);\n\t\t} catch (err) {\n\t\t\tsetSaveError(err as FonderieApiError);\n\t\t} finally {\n\t\t\tsetIsDeleting(false);\n\t\t}\n\t};\n\n\tconst handleDelete = async () => {\n\t\tconst message = locale\n\t\t\t? t('templates.editor.confirmDeleteLocale', { type, locale })\n\t\t\t: t('templates.editor.confirmDelete', { type });\n\t\tif (!window.confirm(message)) return;\n\t\tsetIsDeleting(true);\n\t\tsetSaveError(null);\n\t\ttry {\n\t\t\tawait removeTemplate(type, locale);\n\t\t\tonDeleted?.();\n\t\t} catch (err) {\n\t\t\tsetSaveError(err as FonderieApiError);\n\t\t} finally {\n\t\t\tsetIsDeleting(false);\n\t\t}\n\t};\n\n\tif (isLoading || (notSaved && builtInLoading))\n\t\treturn <p style={styles.status}>{t('templates.editor.loading')}</p>;\n\tif (error && !(notSaved && builtIn))\n\t\treturn (\n\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t{error.explanation}\n\t\t\t</p>\n\t\t);\n\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>{type}</h1>\n\t\t\t{onSelectLocale || onAddLocale ? (\n\t\t\t\t<div style={styles.tabBar}>\n\t\t\t\t\t{onSelectLocale ? (\n\t\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\t<nav aria-label={t('templates.editor.locales')} style={styles.tabs}>\n\t\t\t\t\t\t\t{languages.map((l) => {\n\t\t\t\t\t\t\t\tconst selected = l.locale === (locale ?? null);\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\tkey={l.label}\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\taria-current={selected ? 'true' : undefined}\n\t\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\t\tselected\n\t\t\t\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t\t\t\t: switchTo({ type, locale: l.locale, system: !!email?.system })\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t...(selected ? styles.tabSelected : styles.tab),\n\t\t\t\t\t\t\t\t\t\t\t...(l.saved ? {} : styles.tabBuiltIn),\n\t\t\t\t\t\t\t\t\t\t\t...(l.active ? {} : styles.tabInactive),\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\ttitle={l.active ? undefined : t('common.status.inactive')}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{l.label}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</nav>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{onAddLocale ? (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tstyle={{ ...styles.rollbackButton, marginLeft: 'auto' }}\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tif (dirty && !window.confirm(t('templates.editor.discardChanges'))) return;\n\t\t\t\t\t\t\t\tonAddLocale(type, {\n\t\t\t\t\t\t\t\t\tlocales: catalog ? suggestTemplateLocales(catalog, type) : [],\n\t\t\t\t\t\t\t\t\tdefaultLocale,\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\t\t{t('templates.editor.addLocale')}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t\t<p style={styles.meta}>\n\t\t\t\t<strong>{locale ?? defaultLocale}</strong>\n\t\t\t\t{template ? ` · v${template.version}` : ''}\n\t\t\t\t{template && protectedRow ? ` · ${t('templates.editor.builtInNote')}` : ''}\n\t\t\t\t{!template && builtIn ? ` · ${t('templates.editor.builtInCopy')}` : ''}\n\t\t\t\t{resolution &&\n\t\t\t\tresolution.chain.length > 1 &&\n\t\t\t\tresolution.requested === (locale ?? defaultLocale)\n\t\t\t\t\t? ` · ${t('templates.editor.chain', { chain: [...resolution.chain, defaultLocale].join(' → ') })}`\n\t\t\t\t\t: ''}\n\t\t\t</p>\n\n\t\t\t<div style={styles.split}>\n\t\t\t\t<div style={styles.column}>\n\t\t\t\t\t<form style={styles.form} onSubmit={handleSubmit}>\n\t\t\t\t\t\t<label style={styles.label} htmlFor=\"template-subject\">\n\t\t\t\t\t\t\t{t('templates.subject')}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tid=\"template-subject\"\n\t\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\t\tvalue={subject}\n\t\t\t\t\t\t\tonChange={(event) => setSubject(event.target.value)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<label style={styles.label} htmlFor=\"template-html\">\n\t\t\t\t\t\t\t{t('templates.htmlBody')}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<textarea\n\t\t\t\t\t\t\tid=\"template-html\"\n\t\t\t\t\t\t\tstyle={styles.textarea}\n\t\t\t\t\t\t\tvalue={html}\n\t\t\t\t\t\t\tonChange={(event) => setHtml(event.target.value)}\n\t\t\t\t\t\t\trows={8}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<label style={styles.label} htmlFor=\"template-text\">\n\t\t\t\t\t\t\t{t('templates.textBody')}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<textarea\n\t\t\t\t\t\t\tid=\"template-text\"\n\t\t\t\t\t\t\tstyle={styles.textarea}\n\t\t\t\t\t\t\tvalue={text}\n\t\t\t\t\t\t\tonChange={(event) => setText(event.target.value)}\n\t\t\t\t\t\t\trows={4}\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<label style={styles.checkboxLabel}>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\tchecked={active}\n\t\t\t\t\t\t\t\tonChange={(event) => setActive(event.target.checked)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{t('templates.editor.active')}\n\t\t\t\t\t\t</label>\n\n\t\t\t\t\t\t{saveError?.reason === 'VERSION_CONFLICT' ? (\n\t\t\t\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t\t\t\t{t('templates.editor.conflict')}{' '}\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tstyle={styles.rollbackButton}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tsetSaveError(null);\n\t\t\t\t\t\t\t\t\t\tvoid refresh();\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\t\t{t('common.reload')}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t) : saveError ? (\n\t\t\t\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t\t\t\t{saveError.explanation}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t) : null}\n\n\t\t\t\t\t\t<div style={styles.saveRow}>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tdisabled={isSaving || !dirty}\n\t\t\t\t\t\t\t\tstyle={dirty ? styles.button : styles.buttonDisabled}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{isSaving ? t('common.saving') : t('common.save')}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t{!dirty && !isSaving && (\n\t\t\t\t\t\t\t\t<span style={styles.meta}>{t('templates.editor.noChanges')}</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{template && shipsHere && builtIn ? (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={isDeleting}\n\t\t\t\t\t\t\t\t\tonClick={() => void handleReset()}\n\t\t\t\t\t\t\t\t\tstyle={{ ...styles.rollbackButton, height: 36, marginLeft: 'auto' }}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{t('templates.editor.resetToBuiltIn')}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t) : template && !protectedRow ? (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tdisabled={isDeleting}\n\t\t\t\t\t\t\t\t\tonClick={() => void handleDelete()}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t...styles.rollbackButton,\n\t\t\t\t\t\t\t\t\t\theight: 36,\n\t\t\t\t\t\t\t\t\t\tmarginLeft: 'auto',\n\t\t\t\t\t\t\t\t\t\tcolor: 'var(--fonderie-danger,#e00)',\n\t\t\t\t\t\t\t\t\t\tborderColor: 'color-mix(in srgb, var(--fonderie-danger,#e00) 40%, transparent)',\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\t\t{isDeleting ? t('common.deleting') : t('common.delete')}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</form>\n\n\t\t\t\t\t<label style={styles.label} htmlFor=\"template-sample\">\n\t\t\t\t\t\t{t('templates.editor.sampleData')}\n\t\t\t\t\t</label>\n\t\t\t\t\t<textarea\n\t\t\t\t\t\tid=\"template-sample\"\n\t\t\t\t\t\tstyle={styles.textarea}\n\t\t\t\t\t\tvalue={sampleJson}\n\t\t\t\t\t\tonChange={(event) => setSampleJson(event.target.value)}\n\t\t\t\t\t\trows={6}\n\t\t\t\t\t\tspellCheck={false}\n\t\t\t\t\t/>\n\t\t\t\t\t{sampleError && (\n\t\t\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t\t\t{sampleError}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t<div style={styles.previewColumn}>\n\t\t\t\t\t<div style={styles.previewHeader}>\n\t\t\t\t\t\t<span style={styles.label}>{t('templates.editor.preview')}</span>\n\t\t\t\t\t\t<span style={styles.meta}>\n\t\t\t\t\t\t\t{isPreviewing ? t('templates.editor.rendering') : t('templates.editor.live')}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{previewError && (\n\t\t\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t\t\t{previewError.explanation}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t\t{preview?.subject && <p style={styles.previewSubject}>{preview.subject}</p>}\n\t\t\t\t\t{preview?.html ? (\n\t\t\t\t\t\t// sandbox=\"\" — no scripts, no same-origin. This is operator-authored\n\t\t\t\t\t\t// HTML and it must never execute in the dashboard's origin, which is\n\t\t\t\t\t\t// where the admin token lives.\n\t\t\t\t\t\t<iframe\n\t\t\t\t\t\t\ttitle={t('templates.editor.previewTitle')}\n\t\t\t\t\t\t\tstyle={styles.previewFrame}\n\t\t\t\t\t\t\tsandbox=\"\"\n\t\t\t\t\t\t\tsrcDoc={preview.html}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : preview ? (\n\t\t\t\t\t\t<pre style={styles.previewText}>{preview.text}</pre>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<p style={styles.meta}>{t('templates.editor.nothingRendered')}</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Who receives what: any locale, answered by the same decision a send makes. */}\n\t\t\t<div style={styles.revisions}>\n\t\t\t\t<h2 style={styles.subtitle}>{t('templates.editor.whoReceives')}</h2>\n\t\t\t\t<form\n\t\t\t\t\tstyle={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}\n\t\t\t\t\tonSubmit={(event) => {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tif (probe.trim()) void resolve(type, probe.trim());\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<input\n\t\t\t\t\t\taria-label={t('templates.editor.whoReceives')}\n\t\t\t\t\t\tstyle={{ ...styles.input, width: 200 }}\n\t\t\t\t\t\tvalue={probe}\n\t\t\t\t\t\tplaceholder={t('templates.editor.whoPlaceholder')}\n\t\t\t\t\t\tspellCheck={false}\n\t\t\t\t\t\tonChange={(event) => setProbe(event.target.value)}\n\t\t\t\t\t/>\n\t\t\t\t\t<button type=\"submit\" style={{ ...styles.rollbackButton, height: 36 }}>\n\t\t\t\t\t\t{t('templates.editor.check')}\n\t\t\t\t\t</button>\n\t\t\t\t\t{resolution && probe.trim() ? (\n\t\t\t\t\t\t<span style={{ ...styles.meta, marginBottom: 0 }} role=\"status\">\n\t\t\t\t\t\t\t{t('templates.editor.receives', {\n\t\t\t\t\t\t\t\trequested: resolution.requested,\n\t\t\t\t\t\t\t\tsent: resolution.sent,\n\t\t\t\t\t\t\t})}{' '}\n\t\t\t\t\t\t\t{resolution.source === 'saved'\n\t\t\t\t\t\t\t\t? t('templates.editor.sourceSaved')\n\t\t\t\t\t\t\t\t: t('templates.editor.sourceBuiltIn')}{' '}\n\t\t\t\t\t\t\t{resolution.chain.length > 0\n\t\t\t\t\t\t\t\t? `(${[...resolution.chain, resolution.defaultLocale].join(' → ')})`\n\t\t\t\t\t\t\t\t: ''}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : null}\n\t\t\t\t</form>\n\t\t\t</div>\n\n\t\t\t{revisions.length > 0 && (\n\t\t\t\t<div style={styles.revisions}>\n\t\t\t\t\t<h2 style={styles.subtitle}>{t('templates.editor.history')}</h2>\n\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t{revisions.map((rev) => (\n\t\t\t\t\t\t\t<li key={rev.version} style={styles.row}>\n\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\tv{rev.version} — {rev.actor ?? t('templates.editor.unknownActor')} —{' '}\n\t\t\t\t\t\t\t\t\t{formatAdminDate(rev.createdAt, uiLocale)}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => rollback(rev.version)}\n\t\t\t\t\t\t\t\t\tstyle={styles.rollbackButton}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{t('templates.editor.rollBack')}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nconst tab: CSSProperties = {\n\theight: 32,\n\tpadding: '0 10px',\n\tbackground: 'none',\n\tborder: 'none',\n\tborderBottom: '2px solid transparent',\n\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n\tfontSize: 13,\n\tfontFamily:\n\t\t'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)',\n\tcursor: 'pointer',\n};\n\nconst styles: Record<string, CSSProperties> = {\n\tcontainer: { padding: '8px 40px 64px', maxWidth: 1400, boxSizing: 'border-box' },\n\t// One tab per locale of this email, underlined like a document's tabs.\n\ttabBar: {\n\t\tdisplay: 'flex',\n\t\talignItems: 'flex-end',\n\t\tgap: 12,\n\t\tborderBottom: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tmargin: '4px 0 12px',\n\t\tpaddingBottom: 6,\n\t},\n\ttabs: { display: 'flex', flexWrap: 'wrap', gap: 4, marginBottom: -7 },\n\ttab,\n\ttabSelected: {\n\t\t...tab,\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t\tfontWeight: 600,\n\t\tborderBottomColor: 'var(--fonderie-text,#171717)',\n\t\tcursor: 'default',\n\t},\n\ttabInactive: { opacity: 0.55, textDecoration: 'line-through' },\n\t// Fonderie's built-in copy, not saved by the app — the list's dashed chip.\n\ttabBuiltIn: { fontStyle: 'italic' },\n\t// Two columns, always: the editor on the left, the rendered result on the\n\t// right. Stacking the 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: 24,\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: 16,\n\t},\n\tsaveRow: { display: 'flex', alignItems: 'center', gap: 12, marginTop: 16 },\n\tpreviewHeader: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tmarginTop: 12,\n\t},\n\tpreviewSubject: { fontSize: 14, fontWeight: 600, margin: '8px 0' },\n\tpreviewFrame: {\n\t\tboxShadow: 'var(--fonderie-shadow-card,0 2px 3px 0 rgba(0,0,0,.05))',\n\t\twidth: '100%',\n\t\theight: 520,\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 8,\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t},\n\tpreviewText: {\n\t\twhiteSpace: 'pre-wrap',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 8,\n\t\tpadding: 12,\n\t\tfontSize: 13,\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: 22,\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\tmeta: { fontSize: 13, color: 'var(--fonderie-text-muted,#5c5c5c)', marginBottom: 20 },\n\tstatus: { padding: 24, textAlign: 'center', color: 'var(--fonderie-text-muted,#5c5c5c)' },\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: 6,\n\t\tpadding: '8px 12px',\n\t\tmargin: '8px 0',\n\t\tfontSize: 13.5,\n\t},\n\tform: {\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tgap: 4,\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: 13, fontWeight: 500, marginTop: 14, marginBottom: 2 },\n\tinput: {\n\t\theight: 36,\n\t\tboxSizing: 'border-box',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 6,\n\t\tpadding: '0 10px',\n\t\tfontSize: 13.5,\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: 6,\n\t\tpadding: 10,\n\t\tfontSize: 13,\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: { display: 'flex', alignItems: 'center', gap: 8, marginTop: 12, fontSize: 14 },\n\tbutton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: 36,\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: 6,\n\t\tborder: '1px solid var(--fonderie-text,#171717)',\n\t\tfontSize: 13.5,\n\t\tfontWeight: 600,\n\t\tfontFamily: 'inherit',\n\t\tcursor: 'pointer',\n\t\talignSelf: 'flex-start',\n\t},\n\tbuttonDisabled: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: 36,\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: 6,\n\t\tborder: '1px solid var(--fonderie-text,#171717)',\n\t\tfontSize: 13.5,\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: 32 },\n\tsubtitle: {\n\t\tfontSize: 15,\n\t\tfontWeight: 600,\n\t\tmargin: '0 0 10px',\n\t\tletterSpacing: 'var(--fonderie-tracking-display,-0.05em)',\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},\n\trow: {\n\t\tdisplay: 'flex',\n\t\tjustifyContent: 'space-between',\n\t\talignItems: 'center',\n\t\tgap: 12,\n\t\tpadding: '9px 16px',\n\t\tborderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)',\n\t\tfontSize: 13,\n\t},\n\trollbackButton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: 28,\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: 6,\n\t\tpadding: '0 10px',\n\t\tfontSize: 12.5,\n\t\tfontWeight: 500,\n\t\tfontFamily: 'inherit',\n\t\tcursor: 'pointer',\n\t},\n};\n","import {\n\ttype AdminLocale,\n\ttype CourierAdminClient,\n\ttype ITemplateLanguage,\n\tcreateAdminT,\n\ttemplateLanguages,\n} from '@fonderie/client';\nimport { useTemplateCatalog } from '@fonderie/react-courier-admin';\nimport type { CSSProperties } from 'react';\n\n/** Which version of which email to open. `locale` null is the default version. */\nexport interface ITemplateSelection {\n\ttype: string;\n\tlocale: string | null;\n\t/** A built-in email: its default version can be edited, never deleted. */\n\tsystem: boolean;\n}\n\nexport interface ITemplateListScreenProps {\n\tclient: CourierAdminClient;\n\t/**\n\t * One row per email — built-in ones included, even when nobody saved a copy.\n\t * The row opens the default version; a language chip opens that language.\n\t */\n\tonSelectTemplate?: (template: ITemplateSelection) => void;\n\t/** Shows a \"New template\" button. Receives the locales in use, to suggest. */\n\tonCreateTemplate?: (context: { locales: string[] }) => void;\n\t/** The console's language. Default English. */\n\tlocale?: AdminLocale | undefined;\n}\n\nexport function TemplateListScreen({\n\tclient,\n\tonSelectTemplate,\n\tonCreateTemplate,\n\tlocale,\n}: ITemplateListScreenProps) {\n\tconst t = createAdminT(locale);\n\tconst { catalog, isLoading, error } = useTemplateCatalog(client);\n\tconst emails = catalog?.emails ?? [];\n\tconst defaultLocale = catalog?.defaultLocale ?? 'en-US';\n\n\tconst chipStyle = (l: ITemplateLanguage): CSSProperties => ({\n\t\t...chip,\n\t\t...(l.saved ? {} : chipBuiltIn),\n\t\t...(l.active ? {} : chipOff),\n\t});\n\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div\n\t\t\t\tstyle={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16 }}\n\t\t\t>\n\t\t\t\t<h1 style={styles.title}>{t('templates.list.title')}</h1>\n\t\t\t\t{onCreateTemplate ? (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\tonCreateTemplate({\n\t\t\t\t\t\t\t\tlocales: [\n\t\t\t\t\t\t\t\t\t...new Set(\n\t\t\t\t\t\t\t\t\t\temails.flatMap((e) =>\n\t\t\t\t\t\t\t\t\t\t\ttemplateLanguages(e, defaultLocale)\n\t\t\t\t\t\t\t\t\t\t\t\t.filter((l) => l.locale !== null)\n\t\t\t\t\t\t\t\t\t\t\t\t.map((l) => l.label),\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].sort(),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstyle={styles.newButton}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('templates.list.newTemplate')}\n\t\t\t\t\t</button>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t\t<p style={styles.hint}>{t('templates.list.hint')}</p>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>{t('templates.list.loading')}</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t{emails.map((email) => {\n\t\t\t\t\t\t\tconst languages = templateLanguages(email, defaultLocale);\n\t\t\t\t\t\t\tconst primary = languages.find((l) => l.locale === null) ?? languages[0];\n\t\t\t\t\t\t\tconst open = (l: ITemplateLanguage | undefined) =>\n\t\t\t\t\t\t\t\tonSelectTemplate?.({\n\t\t\t\t\t\t\t\t\ttype: email.type,\n\t\t\t\t\t\t\t\t\tlocale: l?.locale ?? null,\n\t\t\t\t\t\t\t\t\tsystem: email.system,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t// Columns, not a flex row: the language chips line up down the\n\t\t\t\t\t\t\t\t// list whatever the email name or badge.\n\t\t\t\t\t\t\t\t<li key={email.type} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<button type=\"button\" onClick={() => open(primary)} style={styles.rowButton}>\n\t\t\t\t\t\t\t\t\t\t<span style={styles.type}>{email.type}</span>\n\t\t\t\t\t\t\t\t\t\t{email.system ? (\n\t\t\t\t\t\t\t\t\t\t\t<span style={styles.builtIn}>{t('templates.builtInBadge')}</span>\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t<span />\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t{/* Siblings of the row button: a button cannot hold buttons. */}\n\t\t\t\t\t\t\t\t\t{/* Each chip names its email and language for screen readers. */}\n\t\t\t\t\t\t\t\t\t<span style={styles.chips}>\n\t\t\t\t\t\t\t\t\t\t{languages.map((l) => (\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\tkey={l.label}\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\tonClick={() => open(l)}\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={chipStyle(l)}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label={t('templates.list.openLocale', {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: email.type,\n\t\t\t\t\t\t\t\t\t\t\t\t\tlocale: l.label,\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\ttitle={l.active ? undefined : t('common.status.inactive')}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{l.label}\n\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span style={primary?.active === false ? styles.inactive : styles.active}>\n\t\t\t\t\t\t\t\t\t\t<span style={styles.dot} />\n\t\t\t\t\t\t\t\t\t\t{primary?.active === false\n\t\t\t\t\t\t\t\t\t\t\t? t('common.status.inactive')\n\t\t\t\t\t\t\t\t\t\t\t: t('common.status.active')}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</ul>\n\t\t\t\t\t<p style={styles.legend}>{t('templates.list.legend')}</p>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// Matches @fonderie/react-admin-screens' shell look with local values: this\n// package sits below the admin screens and cannot import their blocks.\nconst pill: CSSProperties = {\n\tdisplay: 'inline-flex',\n\talignItems: 'center',\n\tgap: 6,\n\tborderRadius: 999,\n\tpadding: '2px 9px 2px 8px',\n\tfontSize: 12,\n\tfontWeight: 600,\n\tlineHeight: 1.5,\n\tminWidth: 64,\n};\n\nconst MONO =\n\t'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)';\n\n// One per language the email exists in. Monospace: they are language tags.\n// Solid = a version the app saved; dashed = Fonderie's built-in copy, untouched.\nconst chip: CSSProperties = {\n\theight: 24,\n\tboxSizing: 'border-box',\n\tpadding: '0 8px',\n\tborderRadius: 6,\n\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\tbackground: 'var(--fonderie-surface,#fff)',\n\tcolor: 'var(--fonderie-text,#171717)',\n\tfontSize: 12,\n\tfontFamily: MONO,\n\tcursor: 'pointer',\n};\nconst chipBuiltIn: CSSProperties = {\n\tborderStyle: 'dashed',\n\tbackground: 'transparent',\n\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n};\nconst chipOff: CSSProperties = { opacity: 0.5, textDecoration: 'line-through' };\n\nconst styles: Record<string, CSSProperties> = {\n\tcontainer: { padding: '32px 40px 64px', maxWidth: 1160, boxSizing: 'border-box' },\n\ttitle: {\n\t\tfontSize: 22,\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.5, color: 'var(--fonderie-text-muted,#5c5c5c)', margin: '4px 0 24px' },\n\tlegend: { fontSize: 12.5, color: 'var(--fonderie-text-muted,#5c5c5c)', margin: '10px 2px 0' },\n\tstatus: { padding: '24px 0', color: 'var(--fonderie-text-muted,#5c5c5c)', fontSize: 13.5 },\n\terror: { color: 'var(--fonderie-danger,#e00)', marginBottom: 12, fontSize: 14 },\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\t// name + badge | languages | status — fixed tracks so every column aligns.\n\trow: {\n\t\tdisplay: 'grid',\n\t\tgridTemplateColumns: 'minmax(0, 1fr) minmax(180px, 280px) 88px',\n\t\talignItems: 'center',\n\t\tgap: 16,\n\t\tpaddingRight: 16,\n\t\tborderBottom: '1px solid var(--fonderie-border-light,#f5f5f5)',\n\t},\n\trowButton: {\n\t\tminWidth: 0,\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tgap: 12,\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: 13,\n\t\tfontWeight: 600,\n\t\toverflow: 'hidden',\n\t\ttextOverflow: 'ellipsis',\n\t\twhiteSpace: 'nowrap',\n\t\tfontFamily: MONO,\n\t},\n\tchips: { display: 'flex', flexWrap: 'wrap', gap: 6 },\n\tdot: { width: 6, height: 6, borderRadius: 999, background: 'currentColor' },\n\tbuiltIn: {\n\t\tfontSize: 11,\n\t\tfontWeight: 500,\n\t\tpadding: '1px 7px',\n\t\tborderRadius: 999,\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n\t\tflexShrink: 0,\n\t},\n\tnewButton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: 32,\n\t\tboxSizing: 'border-box',\n\t\tborderRadius: 6,\n\t\tpadding: '0 12px',\n\t\tfontSize: 13,\n\t\tfontWeight: 500,\n\t\tfontFamily: 'inherit',\n\t\tcursor: 'pointer',\n\t\tbackgroundColor: 'var(--fonderie-text,#171717)',\n\t\tcolor: 'var(--fonderie-surface,#fff)',\n\t\tborder: '1px solid var(--fonderie-text,#171717)',\n\t},\n\tactive: {\n\t\t...pill,\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\t...pill,\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};\n","import {\n\ttype AdminLocale,\n\ttype CourierAdminClient,\n\tFonderieApiError,\n\ttype ISetTemplateInput,\n\tcreateAdminT,\n} from '@fonderie/client';\nimport { useTemplatePreview } from '@fonderie/react-courier-admin';\nimport type { CSSProperties, FormEvent } from 'react';\nimport { useEffect, useRef, useState } from 'react';\n\nexport interface ITemplateCreateScreenProps {\n\tclient: CourierAdminClient;\n\t/**\n\t * Given ⇒ add a LOCALE of this existing template: the type is fixed and the\n\t * form starts from its default-locale copy. Omitted ⇒ a brand-new template\n\t * type (one the app sends that has no stored copy yet).\n\t */\n\ttype?: string;\n\t/** Locales already in use, offered as suggestions. */\n\tlocales?: string[];\n\t/** The system locale: the default version already is it, so adding it is refused. */\n\tdefaultLocale?: string;\n\t/** Called with what was created, so the caller can open it in the editor. */\n\tonCreated?: (created: { type: string; locale: string | null }) => void;\n\t/** The console's language. Default English. */\n\tlocale?: AdminLocale | undefined;\n}\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// Variables the layout injects — never sample values, as in the editor.\nconst IMPLICIT = new Set(['subject', 'preheader', 'brandName']);\nconst PREVIEW_DEBOUNCE_MS = 500;\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 function TemplateCreateScreen({\n\tclient,\n\ttype,\n\tlocales = [],\n\tdefaultLocale,\n\tonCreated,\n\tlocale,\n}: ITemplateCreateScreenProps) {\n\tconst tr = createAdminT(locale);\n\tconst addingLocale = type !== undefined;\n\tconst [newType, setNewType] = useState('');\n\tconst [targetLocale, setTargetLocale] = useState('');\n\tconst [subject, setSubject] = useState('');\n\tconst [html, setHtml] = useState('');\n\tconst [text, setText] = useState('');\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [busy, setBusy] = useState(false);\n\t// The default copy this locale started from, to flag fields not yet translated.\n\tconst [source, setSource] = useState<{ subject: string; html: string; text: string } | null>(\n\t\tnull,\n\t);\n\tconst { preview, isPreviewing, error: previewError, renderPreview } = useTemplatePreview(client);\n\t// Each variable renders as its own name, so the preview shows where it lands.\n\t// Learned from the server's answer, not re-parsed here.\n\tconst variables = useRef<string[]>([]);\n\n\t// A new locale starts from the default copy, so translating is editing.\n\tuseEffect(() => {\n\t\tif (!type) return;\n\t\tclient\n\t\t\t.getTemplate(type, null)\n\t\t\t// A built-in email nobody saved has no stored default: start from\n\t\t\t// Fonderie's English instead of an empty form.\n\t\t\t.catch(() => client.getBuiltInTemplate(type, null))\n\t\t\t.then(({ result }) => {\n\t\t\t\tsetSubject(result.subject ?? '');\n\t\t\t\tsetHtml(result.html ?? '');\n\t\t\t\tsetText(result.text);\n\t\t\t\tsetSource({ subject: result.subject ?? '', html: result.html ?? '', text: result.text });\n\t\t\t})\n\t\t\t.catch(() => undefined);\n\t}, [client, type]);\n\n\t// Live preview, as in the editor: translating is where it matters most — a\n\t// half-translated email looks finished in a textarea and wrong in the render.\n\tconst previewType = addingLocale ? (type as string) : newType.trim();\n\tconst previewLocale = LOCALE_RE.test(targetLocale.trim()) ? targetLocale.trim() : null;\n\tuseEffect(() => {\n\t\tif (!TYPE_RE.test(previewType) || !text.trim()) return;\n\t\tconst timer = setTimeout(async () => {\n\t\t\tconst input = { text, ...(subject ? { subject } : {}), ...(html ? { html } : {}) };\n\t\t\tconst render = () =>\n\t\t\t\trenderPreview(\n\t\t\t\t\tpreviewType,\n\t\t\t\t\t{ ...input, data: Object.fromEntries(variables.current.map((v) => [v, v])) },\n\t\t\t\t\tpreviewLocale,\n\t\t\t\t);\n\t\t\ttry {\n\t\t\t\tconst result = await render();\n\t\t\t\tconst used = result.variables.filter((v) => !IMPLICIT.has(v));\n\t\t\t\t// A variable not seen before rendered empty: render once more with it.\n\t\t\t\tif (used.some((v) => !variables.current.includes(v))) {\n\t\t\t\t\tvariables.current = used;\n\t\t\t\t\tawait render();\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Shown through previewError.\n\t\t\t}\n\t\t}, PREVIEW_DEBOUNCE_MS);\n\t\treturn () => clearTimeout(timer);\n\t}, [renderPreview, previewType, previewLocale, subject, html, text]);\n\n\tconst untranslated = source\n\t\t? [\n\t\t\t\tsubject && subject === source.subject ? tr('templates.subject') : null,\n\t\t\t\thtml && html === source.html ? tr('templates.htmlBody') : null,\n\t\t\t\ttext === source.text ? tr('templates.textBody') : null,\n\t\t\t].filter((f): f is string => f !== null)\n\t\t: [];\n\n\tconst submit = async (e: FormEvent) => {\n\t\te.preventDefault();\n\t\tsetError(null);\n\t\tconst t = addingLocale ? (type as string) : newType.trim();\n\t\tconst l = targetLocale.trim() || null;\n\t\tif (!TYPE_RE.test(t)) return setError(tr('templates.create.errorType'));\n\t\tif (addingLocale && !l) return setError(tr('templates.create.errorLocaleRequired'));\n\t\tif (l && !LOCALE_RE.test(l)) return setError(tr('templates.create.errorLocale'));\n\t\tif (l && defaultLocale && l.toLowerCase() === defaultLocale.toLowerCase()) {\n\t\t\treturn setError(tr('templates.create.errorDefaultLocale', { locale: defaultLocale }));\n\t\t}\n\t\tif (!text.trim()) return setError(tr('templates.create.errorText'));\n\t\tsetBusy(true);\n\t\ttry {\n\t\t\t// Refuse to overwrite: creating an existing row would replace it.\n\t\t\tconst exists = await client.getTemplate(t, l).then(\n\t\t\t\t() => true,\n\t\t\t\t(err: unknown) => !(err instanceof FonderieApiError && err.status === 404),\n\t\t\t);\n\t\t\tif (exists) {\n\t\t\t\tsetError(\n\t\t\t\t\tl\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);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst input: ISetTemplateInput = { text, active: true };\n\t\t\tif (subject) input.subject = subject;\n\t\t\tif (html) input.html = html;\n\t\t\tawait client.setTemplate(t, input, l);\n\t\t\tonCreated?.({ type: t, locale: l });\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof FonderieApiError ? err.explanation : String(err));\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>\n\t\t\t\t{addingLocale\n\t\t\t\t\t? tr('templates.create.titleLocale', { type: type as string })\n\t\t\t\t\t: tr('templates.create.titleNew')}\n\t\t\t</h1>\n\t\t\t<p style={styles.meta}>\n\t\t\t\t{addingLocale ? tr('templates.create.hintLocale') : tr('templates.create.hintNew')}\n\t\t\t</p>\n\t\t\t<div style={styles.split}>\n\t\t\t\t<form style={styles.form} onSubmit={(e) => void submit(e)}>\n\t\t\t\t\t{!addingLocale ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<label style={styles.label} htmlFor=\"new-template-type\">\n\t\t\t\t\t\t\t\t{tr('templates.create.type')}\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\tid=\"new-template-type\"\n\t\t\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\t\t\tvalue={newType}\n\t\t\t\t\t\t\t\tplaceholder=\"weekly-digest\"\n\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\tspellCheck={false}\n\t\t\t\t\t\t\t\tonChange={(e) => setNewType(e.target.value)}\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\t\t<label style={styles.label} htmlFor=\"new-template-locale\">\n\t\t\t\t\t\t{addingLocale ? tr('templates.create.locale') : tr('templates.create.localeOptional')}\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\tid=\"new-template-locale\"\n\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\tvalue={targetLocale}\n\t\t\t\t\t\tplaceholder=\"fr\"\n\t\t\t\t\t\tlist=\"new-template-locales\"\n\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\tspellCheck={false}\n\t\t\t\t\t\tonChange={(e) => setTargetLocale(e.target.value)}\n\t\t\t\t\t/>\n\t\t\t\t\t<datalist id=\"new-template-locales\">\n\t\t\t\t\t\t{[...new Set(locales)].map((l) => (\n\t\t\t\t\t\t\t<option key={l} value={l} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</datalist>\n\t\t\t\t\t<label style={styles.label} htmlFor=\"new-template-subject\">\n\t\t\t\t\t\t{tr('templates.subject')}\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\tid=\"new-template-subject\"\n\t\t\t\t\t\tstyle={styles.input}\n\t\t\t\t\t\tvalue={subject}\n\t\t\t\t\t\tonChange={(e) => setSubject(e.target.value)}\n\t\t\t\t\t/>\n\t\t\t\t\t<label style={styles.label} htmlFor=\"new-template-html\">\n\t\t\t\t\t\t{tr('templates.htmlBody')}\n\t\t\t\t\t</label>\n\t\t\t\t\t<textarea\n\t\t\t\t\t\tid=\"new-template-html\"\n\t\t\t\t\t\tstyle={{ ...styles.textarea, minHeight: 160 }}\n\t\t\t\t\t\tvalue={html}\n\t\t\t\t\t\tonChange={(e) => setHtml(e.target.value)}\n\t\t\t\t\t/>\n\t\t\t\t\t<label style={styles.label} htmlFor=\"new-template-text\">\n\t\t\t\t\t\t{tr('templates.textBody')}\n\t\t\t\t\t</label>\n\t\t\t\t\t<textarea\n\t\t\t\t\t\tid=\"new-template-text\"\n\t\t\t\t\t\tstyle={{ ...styles.textarea, minHeight: 100 }}\n\t\t\t\t\t\tvalue={text}\n\t\t\t\t\t\tonChange={(e) => setText(e.target.value)}\n\t\t\t\t\t/>\n\t\t\t\t\t{untranslated.length > 0 ? (\n\t\t\t\t\t\t<p style={styles.notice}>\n\t\t\t\t\t\t\t{tr('templates.create.untranslated', { fields: untranslated.join(', ') })}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{error ? (\n\t\t\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<button type=\"submit\" disabled={busy} style={styles.button}>\n\t\t\t\t\t\t{busy\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</button>\n\t\t\t\t</form>\n\n\t\t\t\t<div style={styles.previewColumn}>\n\t\t\t\t\t<div style={styles.previewHeader}>\n\t\t\t\t\t\t<span style={styles.label}>{tr('templates.editor.preview')}</span>\n\t\t\t\t\t\t<span style={styles.meta}>\n\t\t\t\t\t\t\t{isPreviewing ? tr('templates.editor.rendering') : tr('templates.editor.live')}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{previewError ? (\n\t\t\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t\t\t{previewError.explanation}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{preview?.subject ? <p style={styles.previewSubject}>{preview.subject}</p> : null}\n\t\t\t\t\t{preview?.html ? (\n\t\t\t\t\t\t// sandbox=\"\" — no scripts, no same-origin: operator-authored HTML must\n\t\t\t\t\t\t// never execute in the console's origin.\n\t\t\t\t\t\t<iframe\n\t\t\t\t\t\t\ttitle={tr('templates.editor.previewTitle')}\n\t\t\t\t\t\t\tstyle={styles.previewFrame}\n\t\t\t\t\t\t\tsandbox=\"\"\n\t\t\t\t\t\t\tsrcDoc={preview.html}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : preview ? (\n\t\t\t\t\t\t<pre style={styles.previewText}>{preview.text}</pre>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<p style={styles.meta}>{tr('templates.editor.nothingRendered')}</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nconst MONO =\n\t'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace)';\nconst styles: Record<string, CSSProperties> = {\n\tcontainer: { padding: '8px 40px 64px', maxWidth: 1400, boxSizing: 'border-box' },\n\t// The editor's layout: the form on the left, the render pinned on the right.\n\tsplit: {\n\t\tdisplay: 'grid',\n\t\tgridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)',\n\t\tgap: 24,\n\t\talignItems: 'start',\n\t},\n\tpreviewColumn: {\n\t\tminWidth: 0,\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tposition: 'sticky',\n\t\ttop: 16,\n\t},\n\tpreviewHeader: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' },\n\tpreviewSubject: { fontSize: 14, fontWeight: 600, margin: '8px 0' },\n\tpreviewFrame: {\n\t\tboxShadow: 'var(--fonderie-shadow-card,0 2px 3px 0 rgba(0,0,0,.05))',\n\t\twidth: '100%',\n\t\theight: 520,\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 8,\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t},\n\tpreviewText: {\n\t\twhiteSpace: 'pre-wrap',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 8,\n\t\tpadding: 12,\n\t\tfontSize: 13,\n\t\tfontFamily: MONO,\n\t},\n\t// The console's warning token (the shell's amber), readable in both themes.\n\tnotice: {\n\t\tfontSize: 13,\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t\tbackground: 'color-mix(in srgb, var(--fonderie-warning,#f5a623) 16%, transparent)',\n\t\tborderRadius: 6,\n\t\tpadding: '8px 12px',\n\t\tmargin: '12px 0 0',\n\t},\n\ttitle: {\n\t\tfontSize: 22,\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\tmeta: {\n\t\tfontSize: 13,\n\t\tcolor: 'var(--fonderie-text-muted,#5c5c5c)',\n\t\tmarginBottom: 20,\n\t\tlineHeight: 1.5,\n\t},\n\tform: {\n\t\tdisplay: 'flex',\n\t\tflexDirection: 'column',\n\t\tgap: 4,\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},\n\tlabel: { fontSize: 13, fontWeight: 500, marginTop: 14, marginBottom: 2 },\n\tinput: {\n\t\theight: 36,\n\t\tboxSizing: 'border-box',\n\t\tborder: '1px solid var(--fonderie-border,#e0e0e0)',\n\t\tborderRadius: 6,\n\t\tpadding: '0 10px',\n\t\tfontSize: 13.5,\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: 6,\n\t\tpadding: 10,\n\t\tfontSize: 13,\n\t\tlineHeight: 1.55,\n\t\tbackground: 'var(--fonderie-surface,#fff)',\n\t\tcolor: 'var(--fonderie-text,#171717)',\n\t\tfontFamily: MONO,\n\t},\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: 6,\n\t\tpadding: '8px 12px',\n\t\tmargin: '8px 0',\n\t\tfontSize: 13.5,\n\t},\n\tbutton: {\n\t\tdisplay: 'inline-flex',\n\t\talignItems: 'center',\n\t\theight: 36,\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: 6,\n\t\tborder: '1px solid var(--fonderie-text,#171717)',\n\t\tfontSize: 13.5,\n\t\tfontWeight: 600,\n\t\tfontFamily: 'inherit',\n\t\tcursor: 'pointer',\n\t\talignSelf: 'flex-start',\n\t\tmarginTop: 16,\n\t},\n};\n"],"mappings":"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","names":["createAdminT","templateLanguages","useTemplateCatalog","jsx","jsxs","styles","createAdminT","useTemplatePreview","useEffect","useRef","useState","Fragment","jsx","jsxs","IMPLICIT","PREVIEW_DEBOUNCE_MS","styles","MONO"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonderie/react-courier-admin-screens",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Pre-built React screens for the Fonderie courier admin API — template list, template editor with revision history and rollback.",
5
5
  "keywords": [
6
6
  "fonderiejs",