best-email-builder 0.11.0 → 0.12.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/ai-server.js +3 -3
  3. package/dist/ai.js +6 -6
  4. package/dist/builder.js +8 -8
  5. package/dist/{chunk-PFGTD5CS.js → chunk-46ZVS2VX.js} +2 -2
  6. package/dist/{chunk-SQJ3TKEL.js → chunk-6CTFMKAQ.js} +27 -17
  7. package/dist/chunk-6CTFMKAQ.js.map +1 -0
  8. package/dist/{chunk-NV6IV4CU.js → chunk-FYIIO7LD.js} +2 -2
  9. package/dist/{chunk-A2MEYOR3.js → chunk-JFIXYIZ3.js} +7 -7
  10. package/dist/chunk-JFIXYIZ3.js.map +1 -0
  11. package/dist/{chunk-ACAQ2QTU.js → chunk-LAUNZIFX.js} +24 -3
  12. package/dist/chunk-LAUNZIFX.js.map +1 -0
  13. package/dist/{chunk-47WQSNER.js → chunk-LZYDCWVH.js} +3 -3
  14. package/dist/{chunk-47WQSNER.js.map → chunk-LZYDCWVH.js.map} +1 -1
  15. package/dist/{chunk-YQGPBUZ3.js → chunk-MOWQZKIQ.js} +2 -2
  16. package/dist/{chunk-7HDOSA5G.js → chunk-OACK2DIW.js} +20 -11
  17. package/dist/chunk-OACK2DIW.js.map +1 -0
  18. package/dist/{chunk-ONYPTZFK.js → chunk-RONYPWDK.js} +2 -2
  19. package/dist/{chunk-PYD5FOL2.js → chunk-RSTERB7K.js} +3 -3
  20. package/dist/{chunk-COZXOBR3.js → chunk-UUS325J7.js} +3 -3
  21. package/dist/index.js +10 -10
  22. package/dist/library.js +5 -5
  23. package/dist/server.js +5 -5
  24. package/dist/styles.css +1 -1
  25. package/dist/types/core/constants.d.ts +1 -1
  26. package/dist/types/engine/NativeAdapter.d.ts +1 -1
  27. package/dist/types/ui/primitives/misc.d.ts +14 -2
  28. package/package.json +1 -1
  29. package/dist/chunk-7HDOSA5G.js.map +0 -1
  30. package/dist/chunk-A2MEYOR3.js.map +0 -1
  31. package/dist/chunk-ACAQ2QTU.js.map +0 -1
  32. package/dist/chunk-SQJ3TKEL.js.map +0 -1
  33. /package/dist/{chunk-PFGTD5CS.js.map → chunk-46ZVS2VX.js.map} +0 -0
  34. /package/dist/{chunk-NV6IV4CU.js.map → chunk-FYIIO7LD.js.map} +0 -0
  35. /package/dist/{chunk-YQGPBUZ3.js.map → chunk-MOWQZKIQ.js.map} +0 -0
  36. /package/dist/{chunk-ONYPTZFK.js.map → chunk-RONYPWDK.js.map} +0 -0
  37. /package/dist/{chunk-PYD5FOL2.js.map → chunk-RSTERB7K.js.map} +0 -0
  38. /package/dist/{chunk-COZXOBR3.js.map → chunk-UUS325J7.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -6,6 +6,13 @@ All notable changes are documented here. The format follows
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.12.0] — 2026-10-20
10
+
11
+ ### Changed
12
+ - The tag filters of the library and of the *Templates* dialog have no
13
+ *All* chip: with no tag picked, every template shows. A reset icon next to
14
+ the tags unpicks them all (it rests, dimmed, while none is picked).
15
+
9
16
  ## [0.11.0] — 2026-10-19
10
17
 
11
18
  The library loses its bases and gains tags, which also filter it; the
package/dist/ai-server.js CHANGED
@@ -26,9 +26,9 @@ import {
26
26
  reviewFix,
27
27
  reviewRewrite,
28
28
  reviewSubjects
29
- } from "./chunk-PYD5FOL2.js";
30
- import "./chunk-PFGTD5CS.js";
31
- import "./chunk-A2MEYOR3.js";
29
+ } from "./chunk-RSTERB7K.js";
30
+ import "./chunk-46ZVS2VX.js";
31
+ import "./chunk-JFIXYIZ3.js";
32
32
 
33
33
  // src/ai/agentEndpoint.js
34
34
  var TASKS = ["rewrite", "subjects"];
package/dist/ai.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  cleanRichText
3
- } from "./chunk-ONYPTZFK.js";
3
+ } from "./chunk-RONYPWDK.js";
4
4
  import {
5
5
  Button,
6
6
  Dialog,
@@ -19,8 +19,8 @@ import {
19
19
  cn,
20
20
  createHttpCaller,
21
21
  useUi
22
- } from "./chunk-ACAQ2QTU.js";
23
- import "./chunk-47WQSNER.js";
22
+ } from "./chunk-LAUNZIFX.js";
23
+ import "./chunk-LZYDCWVH.js";
24
24
  import {
25
25
  AGENT_ERROR_CODES,
26
26
  AGENT_PROTOCOL,
@@ -43,9 +43,9 @@ import {
43
43
  providerEmailModel,
44
44
  resolveProvider,
45
45
  visibleText
46
- } from "./chunk-PYD5FOL2.js";
47
- import "./chunk-PFGTD5CS.js";
48
- import "./chunk-A2MEYOR3.js";
46
+ } from "./chunk-RSTERB7K.js";
47
+ import "./chunk-46ZVS2VX.js";
48
+ import "./chunk-JFIXYIZ3.js";
49
49
 
50
50
  // src/ai/keys.js
51
51
  var STORAGE_PREFIX = "best-email-builder:ai-key:";
package/dist/builder.js CHANGED
@@ -5,20 +5,20 @@ import {
5
5
  TEMPLATE_GALLERY,
6
6
  buildGallery,
7
7
  createStarterMjml
8
- } from "./chunk-7HDOSA5G.js";
9
- import "./chunk-COZXOBR3.js";
10
- import "./chunk-YQGPBUZ3.js";
8
+ } from "./chunk-OACK2DIW.js";
9
+ import "./chunk-UUS325J7.js";
10
+ import "./chunk-MOWQZKIQ.js";
11
11
  import "./chunk-UFKCLU2D.js";
12
- import "./chunk-ONYPTZFK.js";
12
+ import "./chunk-RONYPWDK.js";
13
13
  import {
14
14
  StorageError,
15
15
  createHttpStorage,
16
16
  createMemoryStorage
17
- } from "./chunk-ACAQ2QTU.js";
17
+ } from "./chunk-LAUNZIFX.js";
18
18
  import {
19
19
  EMAIL_BUILDER_VERSION
20
- } from "./chunk-47WQSNER.js";
21
- import "./chunk-PFGTD5CS.js";
20
+ } from "./chunk-LZYDCWVH.js";
21
+ import "./chunk-46ZVS2VX.js";
22
22
  import {
23
23
  CUSTOM_GROUP,
24
24
  DEFAULT_VARIABLES,
@@ -27,7 +27,7 @@ import {
27
27
  defineVariables,
28
28
  mergeVariables,
29
29
  translatorFor
30
- } from "./chunk-A2MEYOR3.js";
30
+ } from "./chunk-JFIXYIZ3.js";
31
31
  export {
32
32
  CUSTOM_GROUP,
33
33
  DEFAULT_VARIABLES,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  identity,
3
3
  isAssetPath
4
- } from "./chunk-A2MEYOR3.js";
4
+ } from "./chunk-JFIXYIZ3.js";
5
5
 
6
6
  // src/validation/urls.js
7
7
  var LINK_ATTRIBUTES = /* @__PURE__ */ new Set(["href", "action", "formaction", "xlink:href"]);
@@ -248,4 +248,4 @@ export {
248
248
  validateMjml,
249
249
  assertValidMjml
250
250
  };
251
- //# sourceMappingURL=chunk-PFGTD5CS.js.map
251
+ //# sourceMappingURL=chunk-46ZVS2VX.js.map
@@ -5,7 +5,7 @@ import {
5
5
  useLayoutWidth,
6
6
  useSearchShortcut,
7
7
  withPlaceholderImages
8
- } from "./chunk-COZXOBR3.js";
8
+ } from "./chunk-UUS325J7.js";
9
9
  import {
10
10
  Button,
11
11
  Dialog,
@@ -14,6 +14,7 @@ import {
14
14
  DialogHeader,
15
15
  DialogTitle,
16
16
  FilterChip,
17
+ FilterReset,
17
18
  Input,
18
19
  Label,
19
20
  NoticeArea,
@@ -22,14 +23,14 @@ import {
22
23
  cn,
23
24
  createHttpStorage,
24
25
  useUi
25
- } from "./chunk-ACAQ2QTU.js";
26
+ } from "./chunk-LAUNZIFX.js";
26
27
  import {
27
28
  MAX_TEMPLATE_TAGS,
28
29
  TAG_COLORS,
29
30
  TAG_LIMITS,
30
31
  sortTags,
31
32
  validateTag
32
- } from "./chunk-47WQSNER.js";
33
+ } from "./chunk-LZYDCWVH.js";
33
34
 
34
35
  // src/ui/library/TemplateLibrary.jsx
35
36
  import { useCallback, useEffect as useEffect2, useMemo, useRef, useState as useState2 } from "react";
@@ -612,16 +613,15 @@ function Library({
612
613
  /* @__PURE__ */ jsx3(SearchKeyHint, { children: query ? "Esc" : null })
613
614
  ] })
614
615
  ] }),
615
- usedTags.length > 0 && /* @__PURE__ */ jsxs2(
616
- "div",
617
- {
618
- role: "group",
619
- "aria-label": t("Filter by tag"),
620
- className: "eb:-m-1 eb:flex eb:max-h-[4.75rem] eb:flex-wrap eb:gap-1 eb:overflow-y-auto eb:p-1",
621
- "data-testid": "eb-library-tag-filter",
622
- children: [
623
- /* @__PURE__ */ jsx3(FilterChip, { pressed: active.size === 0, onClick: () => setPicked(/* @__PURE__ */ new Set()), className: "eb:h-6 eb:px-2.5 eb:text-[11.5px]", children: t("All") }),
624
- usedTags.map((tag) => /* @__PURE__ */ jsxs2(
616
+ usedTags.length > 0 && /* @__PURE__ */ jsxs2("div", { className: "eb:flex eb:items-start eb:gap-2.5", children: [
617
+ /* @__PURE__ */ jsx3(
618
+ "div",
619
+ {
620
+ role: "group",
621
+ "aria-label": t("Filter by tag"),
622
+ className: "eb:-m-1 eb:flex eb:max-h-[4.75rem] eb:min-w-0 eb:flex-1 eb:flex-wrap eb:gap-1 eb:overflow-y-auto eb:p-1",
623
+ "data-testid": "eb-library-tag-filter",
624
+ children: usedTags.map((tag) => /* @__PURE__ */ jsxs2(
625
625
  FilterChip,
626
626
  {
627
627
  pressed: active.has(String(tag.id)),
@@ -644,9 +644,19 @@ function Library({
644
644
  },
645
645
  tag.id
646
646
  ))
647
- ]
648
- }
649
- )
647
+ }
648
+ ),
649
+ /* @__PURE__ */ jsx3(
650
+ FilterReset,
651
+ {
652
+ label: t("Clear the tag filters"),
653
+ active: active.size > 0,
654
+ onClick: () => setPicked(/* @__PURE__ */ new Set()),
655
+ className: "eb:size-6",
656
+ "data-testid": "eb-library-tag-reset"
657
+ }
658
+ )
659
+ ] })
650
660
  ] }),
651
661
  /* @__PURE__ */ jsxs2("div", { className: "eb:flex eb:min-h-0 eb:flex-1 eb:flex-col eb:gap-4 eb:overflow-y-auto eb:p-3", children: [
652
662
  stars.enabled && favoriteEntries.length > 0 && /* @__PURE__ */ jsx3(Section, { label: t("Favorites"), role: "group", "aria-label": t("Favorites"), "data-testid": "eb-library-favorites", children: favoriteEntries.map((entry) => /* @__PURE__ */ jsx3(Row, { ...rowProps(entry) }, entry.key)) }),
@@ -852,4 +862,4 @@ function TemplateLibrary({ locale = "en", messages, onNotify, ...props }) {
852
862
  export {
853
863
  TemplateLibrary
854
864
  };
855
- //# sourceMappingURL=chunk-SQJ3TKEL.js.map
865
+ //# sourceMappingURL=chunk-6CTFMKAQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/library/TemplateLibrary.jsx","../src/ui/library/TagBadge.jsx","../src/ui/library/TagsDialog.jsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n AlertCircle,\n ArrowLeft,\n Copy,\n Download,\n LayoutTemplate,\n Loader2,\n PencilRuler,\n RefreshCw,\n Search,\n Star,\n Tags,\n Trash2,\n X,\n} from 'lucide-react';\nimport { withPlaceholderImages } from '../../features/templates/thumbnails.js';\nimport { EmailPreview } from '../../features/preview/PreviewButton.jsx';\nimport { createHttpStorage } from '../../storage/client.js';\nimport { NoticeArea, UiProvider, useUi } from '../context.jsx';\nimport { Button } from '../primitives/button.jsx';\nimport { cn } from '../primitives/cn.js';\nimport { Input } from '../primitives/fields.jsx';\nimport { FilterChip, FilterReset, SectionLabel } from '../primitives/misc.jsx';\nimport { SEARCH_KEYS, SearchKeyHint, useSearchShortcut } from '../primitives/searchShortcut.jsx';\nimport { useLayoutWidth } from '../useLayoutWidth.js';\nimport { TAG_SWATCHES, TagBadge } from './TagBadge.jsx';\nimport TagsDialog from './TagsDialog.jsx';\n\n/**\n * TEMPLATE LIBRARY — the first screen: pick a template, see it, open it.\n *\n * ┌──────────────────────────────────────────────────────────────────┐\n * │ ▣ Email template library × │\n * ├──────────────┬──────────────────────────┬────────────────────────┤\n * │ New template │ Name ☆ │ Desktop | Mobile │\n * │ 🔍 Ctrl K │ code │ ┌────────────────────┐ │\n * │ (All)(●Promo)│ Origin, subject, dates… │ │ rendered email │ │\n * │ FAVORITES │ │ │ │ │\n * │ TEMPLATES │ Tags [Promo] [Events] ✎ │ │ │ │\n * │ │ [ Edit ] [ Duplicate ] │ │ │ │\n * │ │ [Copy HTML] [Download] 🗑 │ └────────────────────┘ │\n * └──────────────┴──────────────────────────┴────────────────────────┘\n *\n * Standalone: it never mounts the editor. \"Edit\" and \"New template\" only\n * call `onEdit(template)` / `onCreate()`, and the host decides what opens —\n * `EmailBuilder` (see `EmailStudio`, which wires the two), its own screen, a\n * route. Likewise `EmailBuilder` works without it; a new template starts\n * from a base there, with its *Templates* button.\n *\n * Templates `storage.list()`; preview through `storage.render()` when the\n * storage has it, else the HTML compiled at the last save.\n * *Copy HTML* and *Download* take that HTML (`load()`).\n * Favorites the star of the details. A favorite leaves its section for the\n * one at the top. Kept in this browser (`favoritesKey`, `null`\n * turns favorites off).\n * Tags up to three colored tags on a template, chosen and created in\n * the tags dialog, when the storage has them (`listTags`…).\n * The search finds them too, and the tags under it filter\n * the list: one or several (a template with any of them), or\n * *All*. Only the tags some template carries are offered.\n *\n * Layout follows the library's own width, like the builder: three columns,\n * then the preview under the details, then (phone) list and details as two\n * screens.\n */\n\nconst DATE_FORMAT = { day: '2-digit', month: '2-digit', year: 'numeric' };\nconst DEFAULT_FAVORITES_KEY = 'best-email-builder:favorites';\n\nconst matches = (query, ...fields) => {\n const q = query.trim().toLowerCase();\n return !q || fields.some((f) => String(f || '').toLowerCase().includes(q));\n};\n\n/** `October newsletter` → `october_newsletter`: the code line under a name. */\nconst codeOf = (name, fallback) =>\n String(name || '')\n .normalize('NFD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .slice(0, 48) || fallback;\n\n/** Keys of the starred entries: `template:<id>`. */\nfunction useFavorites(storageKey) {\n const [favorites, setFavorites] = useState(() => {\n if (!storageKey) return new Set();\n try {\n return new Set(JSON.parse(localStorage.getItem(storageKey) || '[]'));\n } catch {\n return new Set();\n }\n });\n const toggle = useCallback(\n (key) =>\n setFavorites((current) => {\n const next = new Set(current);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n try {\n localStorage.setItem(storageKey, JSON.stringify([...next]));\n } catch {\n // Private window, blocked storage: the star holds until the page closes.\n }\n return next;\n }),\n [storageKey]\n );\n return { enabled: Boolean(storageKey), favorites, toggle };\n}\n\nfunction download(name, html) {\n const blob = new Blob([html], { type: 'text/html;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `${codeOf(name, 'email')}.html`;\n a.click();\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n}\n\nfunction Row({ entry, selected, favorite, onSelect }) {\n return (\n <button\n type=\"button\"\n onClick={onSelect}\n aria-current={selected ? 'true' : undefined}\n data-testid=\"eb-library-template\"\n className={cn(\n 'eb:w-full eb:rounded-lg2 eb:border eb:px-2.5 eb:py-2 eb:text-left eb:transition-colors eb:outline-none',\n 'eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50',\n selected ? 'eb:border-primary/50 eb:bg-primary/5' : 'eb:border-transparent eb:hover:bg-surface-75'\n )}\n >\n <span className=\"eb:flex eb:items-center eb:gap-1.5\">\n <span className=\"eb:min-w-0 eb:flex-1 eb:truncate eb:text-[13px] eb:text-foreground\">{entry.name}</span>\n {favorite && <Star className=\"eb:size-3.5 eb:shrink-0 eb:fill-current eb:text-warning\" aria-hidden=\"true\" />}\n </span>\n <span className=\"eb:mt-0.5 eb:block eb:truncate eb:font-mono eb:text-[11px] eb:text-foreground-lighter\">{entry.code}</span>\n {/* One line whatever the tags: too many fade out before the date, and\n every row keeps the same height. */}\n <span className=\"eb:mt-1 eb:flex eb:min-h-[18px] eb:items-center eb:gap-2\">\n <span className=\"eb:flex eb:min-w-0 eb:flex-1 eb:gap-1 eb:overflow-hidden eb:[mask-image:linear-gradient(to_right,#000_calc(100%-1.5rem),transparent)]\">\n {entry.tags.map((tag) => (\n <TagBadge key={tag.id} tag={tag} className=\"eb:max-w-[7.5rem]\" />\n ))}\n </span>\n {entry.date && <span className=\"eb:shrink-0 eb:text-[10.5px] eb:text-foreground-muted\">{entry.date}</span>}\n </span>\n </button>\n );\n}\n\nfunction Section({ label, children, ...props }) {\n return (\n <div className=\"eb:flex eb:flex-col eb:gap-1.5\" {...props}>\n <SectionLabel>{label}</SectionLabel>\n {children}\n </div>\n );\n}\n\nfunction Library({\n storage: injectedStorage,\n title,\n description,\n selectedId = null,\n favoritesKey = DEFAULT_FAVORITES_KEY,\n deleteDisabled = null,\n onEdit,\n onCreate,\n onClose,\n className,\n}) {\n const { t, locale, notify, confirm } = useUi();\n const storage = useMemo(() => injectedStorage || createHttpStorage(), [injectedStorage]);\n const canTag = typeof storage.listTags === 'function' && typeof storage.setTemplateTags === 'function';\n const dateFormat = useMemo(() => new Intl.DateTimeFormat(locale, DATE_FORMAT), [locale]);\n const formatDate = useCallback((at) => (at ? dateFormat.format(new Date(at)) : ''), [dateFormat]);\n const stars = useFavorites(favoritesKey);\n\n const rootRef = useRef(null);\n const searchRef = useRef(null);\n const layout = useLayoutWidth(rootRef);\n\n const [items, setItems] = useState({ status: 'loading', list: [], error: null });\n /** The workspace's tags, by name. */\n const [tags, setTags] = useState([]);\n const [tagsOpen, setTagsOpen] = useState(false);\n const [query, setQuery] = useState('');\n /** The tags picked under the search (ids); none is *All*. */\n const [picked, setPicked] = useState(() => new Set());\n /** `template:<id>` */\n const [selection, setSelection] = useState(selectedId != null ? `template:${selectedId}` : null);\n /** Phone layout: the details screen is shown over the list. */\n const [detailsOpen, setDetailsOpen] = useState(false);\n const [detail, setDetail] = useState({ status: 'idle', template: null, error: null });\n const [preview, setPreview] = useState({ html: '', loading: false, error: null });\n const [device, setDevice] = useState('desktop');\n const [busy, setBusy] = useState(null);\n\n // Only the LAST read counts: a slow answer arriving after a newer one\n // (opening, then a duplicate) would show a stale list.\n const lastRead = useRef(0);\n const reload = useCallback(async () => {\n const ticket = ++lastRead.current;\n if (typeof storage.list !== 'function') {\n setItems({ status: 'ready', list: [], error: null });\n return;\n }\n setItems((s) => ({ ...s, status: s.list.length ? 'ready' : 'loading', error: null }));\n try {\n // Tags that cannot be read leave the templates readable, untagged.\n const [list, tagList] = await Promise.all([storage.list(), canTag ? storage.listTags().catch(() => []) : []]);\n if (ticket === lastRead.current) {\n setItems({ status: 'ready', list, error: null });\n setTags(tagList);\n }\n } catch (error) {\n if (ticket === lastRead.current) setItems({ status: 'error', list: [], error: error.message });\n }\n }, [storage, canTag]);\n\n useEffect(() => {\n reload();\n }, [reload]);\n\n /* ── entries ───────────────────────────────────────────────────────────── */\n\n const templateEntries = useMemo(() => {\n const byId = new Map(tags.map((tag) => [String(tag.id), tag]));\n return items.list.map((item) => ({\n key: `template:${item.id}`,\n id: item.id,\n name: item.name,\n code: codeOf(item.name, `#${item.id}`),\n tags: (item.tags || []).map((id) => byId.get(String(id))).filter(Boolean),\n date: formatDate(item.updatedAt || item.createdAt),\n subject: item.subject,\n item,\n }));\n }, [items.list, tags, formatDate]);\n /** The filters: the tags some template carries, by name. */\n const usedTags = useMemo(() => {\n const used = new Set(items.list.flatMap((item) => (item.tags || []).map(String)));\n return tags.filter((tag) => used.has(String(tag.id)));\n }, [items.list, tags]);\n // A picked tag deleted or left by every template no longer filters.\n const active = new Set(usedTags.map((tag) => String(tag.id)).filter((id) => picked.has(id)));\n const togglePicked = (id) =>\n setPicked((current) => {\n const next = new Set(current);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n const shown = templateEntries.filter(\n (e) =>\n (active.size === 0 || e.tags.some((tag) => active.has(String(tag.id)))) &&\n matches(query, e.name, e.code, e.subject, ...e.tags.map((tag) => tag.label))\n );\n const favoriteEntries = shown.filter((e) => stars.favorites.has(e.key));\n const otherTemplates = shown.filter((e) => !stars.favorites.has(e.key));\n\n // First selection: the requested template, else the most recent one.\n useEffect(() => {\n if (items.status !== 'ready' || selection) return;\n if (items.list.length) setSelection(`template:${items.list[0].id}`);\n }, [items, selection]);\n\n // Ctrl/Cmd+K focuses the search.\n useSearchShortcut(searchRef);\n\n const selected = templateEntries.find((e) => e.key === selection) || null;\n const templateId = selection?.startsWith('template:') ? selection.slice('template:'.length) : null;\n\n // Details of a saved template (MJML and compiled HTML are not in the list).\n useEffect(() => {\n if (templateId == null) {\n setDetail({ status: 'idle', template: null, error: null });\n return undefined;\n }\n let live = true;\n setDetail((d) => ({ status: 'loading', template: String(d.template?.id) === templateId ? d.template : null, error: null }));\n storage.load(templateId).then(\n (template) => live && setDetail({ status: 'ready', template, error: null }),\n (error) => live && setDetail({ status: 'error', template: null, error: error.message })\n );\n return () => {\n live = false;\n };\n }, [templateId, storage]);\n\n // Preview: rendered by the storage (server) when it can, else the saved HTML.\n const template = detail.template;\n const source = template\n ? { mjml: template.mjml, subject: template.subject, preheader: template.preheader, html: template.html || '' }\n : null;\n const sourceKey = template ? `template:${template.id}:${template.revision}` : '';\n useEffect(() => {\n if (!source) {\n setPreview({ html: '', loading: templateId != null && detail.status === 'loading', error: null });\n return undefined;\n }\n if (typeof storage.render !== 'function' || !source.mjml) {\n setPreview({ html: source.html, loading: false, error: source.html ? null : t('No preview: this storage cannot render emails.') });\n return undefined;\n }\n let live = true;\n setPreview((p) => ({ ...p, loading: true, error: null }));\n storage.render({ mjml: source.mjml, subject: source.subject, preheader: source.preheader }).then(\n (result) => live && setPreview({ html: withPlaceholderImages(result.html), loading: false, error: null }),\n (error) => live && setPreview({ html: source.html, loading: false, error: source.html ? null : error.message })\n );\n return () => {\n live = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [sourceKey, storage]);\n\n /* ── actions ───────────────────────────────────────────────────────────── */\n\n const select = (key) => {\n setSelection(key);\n setDetailsOpen(true);\n };\n\n const remove = async () => {\n if (deleteDisabled) {\n notify('info', deleteDisabled);\n return;\n }\n const ok = await confirm({\n title: t('Delete “{name}”?', { name: template.name }),\n description: t('The template and its versions will be deleted.'),\n confirmLabel: t('Delete'),\n destructive: true,\n });\n if (!ok) return;\n setBusy('delete');\n try {\n await storage.remove(template.id);\n setSelection(null);\n setDetailsOpen(false);\n await reload();\n notify('success', t('Template deleted.'));\n } catch (error) {\n notify('error', error.message);\n } finally {\n setBusy(null);\n }\n };\n\n const duplicate = async () => {\n setBusy('duplicate');\n try {\n const { template: copy } = await storage.duplicate(template.id);\n await reload();\n setSelection(`template:${copy.id}`);\n notify('success', t('Template duplicated.'));\n } catch (error) {\n notify('error', error.message);\n } finally {\n setBusy(null);\n }\n };\n\n const copyHtml = async () => {\n try {\n await navigator.clipboard.writeText(template.html);\n notify('success', t('HTML copied.'));\n } catch {\n notify('error', t('The browser refused to copy.'));\n }\n };\n\n /** The selected template's tags, as the dialog sets them. @param {string[]} ids */\n const setTemplateTags = (ids) =>\n setItems((s) => ({ ...s, list: s.list.map((item) => (String(item.id) === templateId ? { ...item, tags: ids } : item)) }));\n /** The list of tags after a change; a deleted tag leaves every template. */\n const changeTags = (list, { deleted } = {}) => {\n setTags(list);\n if (deleted == null) return;\n setItems((s) => ({\n ...s,\n list: s.list.map((item) => (item.tags?.includes(deleted) ? { ...item, tags: item.tags.filter((id) => id !== deleted) } : item)),\n }));\n };\n\n const canList = typeof storage.list === 'function';\n const rowProps = (entry) => ({\n entry,\n selected: entry.key === selection,\n favorite: stars.favorites.has(entry.key),\n onSelect: () => select(entry.key),\n });\n\n /* ── left column ───────────────────────────────────────────────────────── */\n\n const listColumn = (\n <div key=\"list\" className=\"eb:flex eb:min-h-0 eb:min-w-0 eb:flex-col\" data-testid=\"eb-library-list\">\n <div className=\"eb:flex eb:shrink-0 eb:flex-col eb:gap-2 eb:border-b eb:border-border eb:p-3\">\n {onCreate && (\n <Button className=\"eb:w-full\" onClick={() => onCreate()}>\n <PencilRuler />\n {t('New template')}\n </Button>\n )}\n <div className=\"eb:relative\">\n <Search className=\"eb:pointer-events-none eb:absolute eb:top-1/2 eb:left-2.5 eb:size-3.5 eb:-translate-y-1/2 eb:text-foreground-muted\" />\n <Input\n ref={searchRef}\n type=\"search\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Escape' && query) {\n e.preventDefault();\n setQuery('');\n }\n }}\n placeholder={t('Search templates')}\n aria-label={t('Search templates')}\n aria-keyshortcuts={SEARCH_KEYS}\n className=\"eb:pr-16 eb:pl-8 eb:[&::-webkit-search-cancel-button]:hidden\"\n />\n <div className=\"eb:absolute eb:top-1/2 eb:right-2 eb:flex eb:-translate-y-1/2 eb:items-center eb:gap-1\">\n {query && (\n <button type=\"button\" onClick={() => setQuery('')} aria-label={t('Clear the search')} className=\"eb:cursor-pointer\">\n <X className=\"eb:size-3.5 eb:text-foreground-muted eb:hover:text-foreground\" />\n </button>\n )}\n <SearchKeyHint>{query ? 'Esc' : null}</SearchKeyHint>\n </div>\n </div>\n {usedTags.length > 0 && (\n <div className=\"eb:flex eb:items-start eb:gap-2.5\">\n {/* No tag picked: every template. */}\n <div\n role=\"group\"\n aria-label={t('Filter by tag')}\n className=\"eb:-m-1 eb:flex eb:max-h-[4.75rem] eb:min-w-0 eb:flex-1 eb:flex-wrap eb:gap-1 eb:overflow-y-auto eb:p-1\"\n data-testid=\"eb-library-tag-filter\"\n >\n {usedTags.map((tag) => (\n <FilterChip\n key={tag.id}\n pressed={active.has(String(tag.id))}\n onClick={() => togglePicked(String(tag.id))}\n className=\"eb:h-6 eb:max-w-full eb:px-2.5 eb:text-[11.5px]\"\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n 'eb:size-2 eb:shrink-0 eb:rounded-full',\n TAG_SWATCHES[tag.color] || TAG_SWATCHES.gray,\n active.has(String(tag.id)) && 'eb:ring-1 eb:ring-primary-foreground'\n )}\n />\n <span className=\"eb:truncate\">{tag.label}</span>\n </FilterChip>\n ))}\n </div>\n <FilterReset\n label={t('Clear the tag filters')}\n active={active.size > 0}\n onClick={() => setPicked(new Set())}\n className=\"eb:size-6\"\n data-testid=\"eb-library-tag-reset\"\n />\n </div>\n )}\n </div>\n\n <div className=\"eb:flex eb:min-h-0 eb:flex-1 eb:flex-col eb:gap-4 eb:overflow-y-auto eb:p-3\">\n {stars.enabled && favoriteEntries.length > 0 && (\n <Section label={t('Favorites')} role=\"group\" aria-label={t('Favorites')} data-testid=\"eb-library-favorites\">\n {favoriteEntries.map((entry) => (\n <Row key={entry.key} {...rowProps(entry)} />\n ))}\n </Section>\n )}\n {canList && (\n <Section label={`${t('Templates')} (${otherTemplates.length})`} data-testid=\"eb-library-templates\">\n {items.status === 'loading' ? (\n <p className=\"eb:m-0 eb:flex eb:items-center eb:gap-2 eb:px-1 eb:text-[12px] eb:text-foreground-lighter\">\n <Loader2 className=\"eb:size-3.5 eb:animate-spin\" />\n {t('Loading…')}\n </p>\n ) : items.status === 'error' ? (\n <div className=\"eb:px-1 eb:text-[12px] eb:text-destructive\">\n <p className=\"eb:m-0\">{t('Could not load the templates.')}</p>\n <p className=\"eb:m-0 eb:mt-0.5 eb:text-foreground-muted\">{items.error}</p>\n <Button variant=\"outline\" size=\"sm-compact\" className=\"eb:mt-2\" onClick={reload}>\n <RefreshCw />\n {t('Retry')}\n </Button>\n </div>\n ) : otherTemplates.length === 0 ? (\n <p className=\"eb:m-0 eb:px-1 eb:text-[12px] eb:leading-relaxed eb:text-foreground-lighter\">\n {query\n ? t('Nothing matches “{query}”.', { query })\n : templateEntries.length\n ? t('All your templates are in the favorites.')\n : t('No template yet: create the first one.')}\n </p>\n ) : (\n otherTemplates.map((entry) => <Row key={entry.key} {...rowProps(entry)} />)\n )}\n </Section>\n )}\n </div>\n </div>\n );\n\n /* ── details ───────────────────────────────────────────────────────────── */\n\n const meta =\n selected || template\n ? {\n name: template?.name ?? selected.name,\n code: selected?.code ?? codeOf(template?.name, `#${templateId}`),\n description: template?.description ?? selected?.item?.description,\n origin: t('Builder'),\n subject: (template ?? selected?.item)?.subject,\n preheader: (template ?? selected?.item)?.preheader,\n createdAt: (template ?? selected?.item)?.createdAt,\n createdBy: (template ?? selected?.item)?.createdBy,\n updatedAt: (template ?? selected?.item)?.updatedAt,\n updatedBy: (template ?? selected?.item)?.updatedBy,\n }\n : null;\n const favorite = selection ? stars.favorites.has(selection) : false;\n\n const detailsBody =\n templateId != null && detail.status === 'error' ? (\n <p className=\"eb:m-0 eb:flex eb:items-start eb:gap-2 eb:text-[13px] eb:text-destructive\">\n <AlertCircle className=\"eb:mt-0.5 eb:size-4 eb:shrink-0\" />\n {detail.error}\n </p>\n ) : meta ? (\n <>\n <div className=\"eb:flex eb:flex-col eb:gap-1\">\n <div className=\"eb:flex eb:items-center eb:gap-2\">\n <h3 className=\"eb:m-0 eb:min-w-0 eb:flex-1 eb:text-[15px] eb:font-medium eb:text-foreground\">{meta.name}</h3>\n {stars.enabled && (\n <Button\n variant=\"ghost\"\n size=\"icon-sm-compact\"\n className={cn('eb:shrink-0', favorite ? 'eb:text-warning' : 'eb:text-foreground-muted eb:hover:text-warning')}\n onClick={() => stars.toggle(selection)}\n aria-pressed={favorite}\n aria-label={favorite ? t('Remove from favorites') : t('Add to favorites')}\n title={favorite ? t('Remove from favorites') : t('Add to favorites')}\n >\n <Star className={cn('eb:size-4', favorite && 'eb:fill-current')} />\n </Button>\n )}\n </div>\n <p className=\"eb:m-0 eb:font-mono eb:text-[11.5px] eb:text-foreground-lighter\">{meta.code}</p>\n {meta.description && (\n <p className=\"eb:m-0 eb:text-[12.5px] eb:leading-relaxed eb:text-foreground-lighter\">{meta.description}</p>\n )}\n </div>\n\n <dl className=\"eb:m-0 eb:grid eb:grid-cols-[110px_minmax(0,1fr)] eb:gap-x-3 eb:gap-y-1.5 eb:text-[12px]\">\n <dt className=\"eb:text-foreground-muted\">{t('Origin')}</dt>\n <dd className=\"eb:m-0 eb:text-foreground\">{meta.origin}</dd>\n <dt className=\"eb:text-foreground-muted\">{t('Subject')}</dt>\n <dd className=\"eb:m-0 eb:break-words eb:text-foreground\">{meta.subject || '—'}</dd>\n <dt className=\"eb:text-foreground-muted\">{t('Preview text')}</dt>\n <dd className=\"eb:m-0 eb:break-words eb:text-foreground-lighter\">{meta.preheader || '—'}</dd>\n <dt className=\"eb:text-foreground-muted\">{t('Created')}</dt>\n <dd className=\"eb:m-0 eb:text-foreground\">\n {formatDate(meta.createdAt) || '—'}\n {meta.createdBy ? ` ${t('by {name}', { name: meta.createdBy })}` : ''}\n </dd>\n {meta.updatedAt && (\n <>\n <dt className=\"eb:text-foreground-muted\">{t('Updated')}</dt>\n <dd className=\"eb:m-0 eb:text-foreground\">\n {formatDate(meta.updatedAt)}\n {meta.updatedBy ? ` ${t('by {name}', { name: meta.updatedBy })}` : ''}\n </dd>\n </>\n )}\n {canTag && selected && (\n <>\n <dt className=\"eb:flex eb:h-6 eb:items-center eb:text-foreground-muted\">{t('Tags')}</dt>\n <dd className=\"eb:m-0 eb:flex eb:min-w-0 eb:flex-wrap eb:items-center eb:gap-1\" data-testid=\"eb-library-tags\">\n {selected.tags.map((tag) => (\n <TagBadge key={tag.id} tag={tag} className=\"eb:text-[11.5px]\" />\n ))}\n <Button\n variant=\"ghost\"\n size=\"xs\"\n className=\"eb:text-foreground-lighter\"\n onClick={() => setTagsOpen(true)}\n data-testid=\"eb-library-tags-button\"\n >\n <Tags />\n {selected.tags.length ? t('Edit tags') : t('Add tags')}\n </Button>\n </dd>\n </>\n )}\n </dl>\n </>\n ) : (\n <div className=\"eb:flex eb:flex-1 eb:items-center eb:justify-center\">\n <div className=\"eb:flex eb:w-full eb:flex-col eb:items-center eb:justify-center eb:gap-2 eb:rounded-lg2 eb:border eb:border-border eb:bg-surface-75 eb:px-6 eb:py-12 eb:text-center\">\n <span className=\"eb:flex eb:size-12 eb:items-center eb:justify-center eb:rounded-full eb:bg-surface-200 eb:text-foreground-muted\">\n <LayoutTemplate className=\"eb:size-6\" />\n </span>\n <p className=\"eb:m-0 eb:text-[13px] eb:font-medium eb:text-foreground\">{t('Choose a template')}</p>\n <p className=\"eb:m-0 eb:max-w-sm eb:text-[13px] eb:leading-relaxed eb:text-foreground-muted\">\n {t('Select a template on the left.')}\n </p>\n </div>\n </div>\n );\n\n const actions = template ? (\n <>\n <div className=\"eb:flex eb:gap-2\">\n {onEdit && (\n <Button className=\"eb:flex-1\" onClick={() => onEdit(template)}>\n <PencilRuler />\n {t('Edit')}\n </Button>\n )}\n <Button variant=\"outline\" className=\"eb:flex-1\" disabled={!!busy} onClick={duplicate}>\n {busy === 'duplicate' ? <Loader2 className=\"eb:animate-spin\" /> : <Copy />}\n {t('Duplicate')}\n </Button>\n </div>\n {(template.html || typeof storage.remove === 'function') && (\n <div className=\"eb:flex eb:gap-2\">\n {template.html && (\n <>\n <Button variant=\"outline\" size=\"sm-compact\" className=\"eb:flex-1\" onClick={copyHtml}>\n <Copy />\n {t('Copy HTML')}\n </Button>\n <Button variant=\"outline\" size=\"sm-compact\" className=\"eb:flex-1\" onClick={() => download(template.name, template.html)}>\n <Download />\n {t('Download')}\n </Button>\n </>\n )}\n {typeof storage.remove === 'function' && (\n <Button\n variant=\"outline\"\n size=\"sm-compact\"\n className={cn('eb:text-destructive', !template.html && 'eb:ml-auto', deleteDisabled && 'eb:opacity-50 eb:hover:bg-background eb:hover:text-destructive')}\n disabled={!!busy}\n onClick={remove}\n aria-disabled={deleteDisabled ? true : undefined}\n aria-label={t('Delete')}\n title={deleteDisabled || t('Delete')}\n >\n {busy === 'delete' ? <Loader2 className=\"eb:animate-spin\" /> : <Trash2 />}\n {!template.html && t('Delete')}\n </Button>\n )}\n </div>\n )}\n </>\n ) : null;\n\n const previewPane =\n preview.html || preview.loading || preview.error ? (\n <EmailPreview html={preview.html} loading={preview.loading} error={preview.error} device={device} onDeviceChange={setDevice} />\n ) : (\n <div className=\"eb:flex eb:h-full eb:min-h-40 eb:items-center eb:justify-center eb:rounded-lg2 eb:border eb:border-dashed eb:border-border eb:p-6 eb:text-center eb:text-[13px] eb:text-foreground-lighter\">\n {t('The template preview appears here.')}\n </div>\n );\n\n const detailsColumn = (\n <div key=\"details\" className=\"eb:flex eb:min-h-0 eb:min-w-0 eb:flex-col\" data-testid=\"eb-library-details\">\n {layout === 'narrow' && (\n <div className=\"eb:shrink-0 eb:border-b eb:border-border eb:px-2 eb:py-1.5\">\n <Button variant=\"ghost\" size=\"sm-compact\" onClick={() => setDetailsOpen(false)}>\n <ArrowLeft />\n {t('All templates')}\n </Button>\n </div>\n )}\n <div className=\"eb:flex eb:min-h-0 eb:flex-1 eb:flex-col eb:gap-4 eb:overflow-y-auto eb:p-4\">\n {detailsBody}\n {layout !== 'wide' && meta && <div className=\"eb:h-[560px] eb:shrink-0\">{previewPane}</div>}\n </div>\n {actions && <div className=\"eb:flex eb:shrink-0 eb:flex-col eb:gap-2 eb:border-t eb:border-border eb:p-3\">{actions}</div>}\n </div>\n );\n\n return (\n <div\n ref={rootRef}\n className={cn('eb-root eb:relative eb:flex eb:h-full eb:min-h-0 eb:flex-col eb:bg-background eb:text-foreground', className)}\n data-testid=\"template-library\"\n data-layout={layout}\n >\n <header className=\"eb:flex eb:shrink-0 eb:items-center eb:gap-3 eb:border-b eb:border-border eb:px-5 eb:py-3.5\">\n <span className=\"eb:flex eb:size-10 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-lg2 eb:bg-primary/10 eb:text-primary\">\n <LayoutTemplate className=\"eb:size-5\" />\n </span>\n <div className=\"eb:min-w-0 eb:flex-1\">\n <h2 className=\"eb:m-0 eb:truncate eb:text-base eb:font-normal eb:text-foreground\">{title ?? t('Email template library')}</h2>\n <p className=\"eb:m-0 eb:truncate eb:text-[13px] eb:text-foreground-muted\">\n {description ?? t('Ready-made templates to copy into your campaigns.')}\n </p>\n </div>\n {onClose && (\n <Button variant=\"ghost\" size=\"icon-sm\" onClick={onClose} aria-label={t('Close')}>\n <X />\n </Button>\n )}\n </header>\n\n {canTag && selected && (\n <TagsDialog\n open={tagsOpen}\n onOpenChange={setTagsOpen}\n template={selected.item}\n tags={tags}\n storage={storage}\n onTagsChange={changeTags}\n onTemplateTags={setTemplateTags}\n />\n )}\n\n {layout === 'narrow' ? (\n <div className=\"eb:grid eb:min-h-0 eb:flex-1 eb:grid-cols-[minmax(0,1fr)]\">\n {detailsOpen && selection ? detailsColumn : listColumn}\n </div>\n ) : (\n <div\n className={cn(\n 'eb:grid eb:min-h-0 eb:flex-1 eb:grid-rows-1 eb:divide-x eb:divide-border eb:overflow-hidden',\n layout === 'wide' ? 'eb:grid-cols-[290px_minmax(0,1fr)_minmax(0,1fr)]' : 'eb:grid-cols-[260px_minmax(0,1fr)]'\n )}\n >\n {listColumn}\n {detailsColumn}\n {layout === 'wide' && (\n <div className=\"eb:min-h-0 eb:min-w-0 eb:p-3\" data-testid=\"eb-library-preview\">\n {previewPane}\n </div>\n )}\n </div>\n )}\n <NoticeArea />\n </div>\n );\n}\n\n/**\n * @param {{\n * storage?: import('../../storage/client.js').TemplateStorage,\n * locale?: string,\n * messages?: Record<string, string>,\n * onNotify?: (level: 'success'|'info'|'warning'|'error', message: string) => void,\n * title?: string,\n * description?: string,\n * selectedId?: string|number|null,\n * favoritesKey?: string|null,\n * deleteDisabled?: string|null,\n * onEdit?: (template: import('../../storage/client.js').StoredTemplate) => void,\n * onCreate?: () => void,\n * onClose?: () => void,\n * className?: string,\n * }} props `deleteDisabled`: *Delete* stays in its place but deletes\n * nothing — a click shows this text (a demo, a user without the right).\n */\nexport default function TemplateLibrary({ locale = 'en', messages, onNotify, ...props }) {\n return (\n <UiProvider locale={locale} messages={messages} onNotify={onNotify}>\n <Library {...props} />\n </UiProvider>\n );\n}\n","import { cn } from '../primitives/cn.js';\n\n/**\n * A tag as the library shows it. One class list per color of `TAG_COLORS`\n * (features/tags/tags.js), written out so the stylesheet has them all, and\n * readable in the light and the dark theme.\n */\nconst TAG_STYLES = {\n gray: 'eb:border-gray-500/30 eb:bg-gray-500/10 eb:text-gray-700 eb:dark:text-gray-300',\n red: 'eb:border-red-500/30 eb:bg-red-500/10 eb:text-red-700 eb:dark:text-red-300',\n orange: 'eb:border-orange-500/30 eb:bg-orange-500/10 eb:text-orange-700 eb:dark:text-orange-300',\n amber: 'eb:border-amber-500/40 eb:bg-amber-500/15 eb:text-amber-800 eb:dark:text-amber-300',\n lime: 'eb:border-lime-600/40 eb:bg-lime-500/15 eb:text-lime-800 eb:dark:text-lime-300',\n green: 'eb:border-green-600/30 eb:bg-green-500/10 eb:text-green-700 eb:dark:text-green-300',\n teal: 'eb:border-teal-600/30 eb:bg-teal-500/10 eb:text-teal-700 eb:dark:text-teal-300',\n cyan: 'eb:border-cyan-600/30 eb:bg-cyan-500/10 eb:text-cyan-700 eb:dark:text-cyan-300',\n blue: 'eb:border-blue-500/30 eb:bg-blue-500/10 eb:text-blue-700 eb:dark:text-blue-300',\n violet: 'eb:border-violet-500/30 eb:bg-violet-500/10 eb:text-violet-700 eb:dark:text-violet-300',\n fuchsia: 'eb:border-fuchsia-500/30 eb:bg-fuchsia-500/10 eb:text-fuchsia-700 eb:dark:text-fuchsia-300',\n pink: 'eb:border-pink-500/30 eb:bg-pink-500/10 eb:text-pink-700 eb:dark:text-pink-300',\n};\n\n/** The color's swatch in the tags dialog. */\nexport const TAG_SWATCHES = {\n gray: 'eb:bg-gray-500',\n red: 'eb:bg-red-500',\n orange: 'eb:bg-orange-500',\n amber: 'eb:bg-amber-500',\n lime: 'eb:bg-lime-500',\n green: 'eb:bg-green-600',\n teal: 'eb:bg-teal-600',\n cyan: 'eb:bg-cyan-500',\n blue: 'eb:bg-blue-500',\n violet: 'eb:bg-violet-500',\n fuchsia: 'eb:bg-fuchsia-500',\n pink: 'eb:bg-pink-500',\n};\n\n/** @param {{tag: import('../../features/tags/tags.js').TemplateTag, className?: string}} props */\nexport function TagBadge({ tag, className }) {\n return (\n <span\n data-testid=\"eb-tag\"\n data-color={tag.color}\n className={cn(\n 'eb:inline-block eb:max-w-full eb:shrink-0 eb:truncate eb:rounded-md eb:border eb:px-1.5 eb:py-0 eb:text-[10px]',\n TAG_STYLES[tag.color] || TAG_STYLES.gray,\n className\n )}\n >\n {tag.label}\n </span>\n );\n}\n","import { useEffect, useState } from 'react';\nimport { Check, Loader2, Pencil, Plus, Tags, Trash2 } from 'lucide-react';\nimport { MAX_TEMPLATE_TAGS, TAG_COLORS, TAG_LIMITS, sortTags, validateTag } from '../../features/tags/tags.js';\nimport { useUi } from '../context.jsx';\nimport { Button } from '../primitives/button.jsx';\nimport { cn } from '../primitives/cn.js';\nimport { Input, Label } from '../primitives/fields.jsx';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../primitives/overlays.jsx';\nimport { TAG_SWATCHES, TagBadge } from './TagBadge.jsx';\n\n/** A new tag takes the next color, so tags made in a row differ. */\nconst colorAfter = (tags) => TAG_COLORS[(TAG_COLORS.indexOf('blue') + tags.length) % TAG_COLORS.length];\n\n/**\n * TAGS — the tags of one template, and the workspace's list of tags.\n *\n * ┌─────────────────────────────────────────────┐\n * │ ▣ Tags × │\n * │ Up to 3 tags on “October newsletter”. │\n * │ ☑ [Marketing] ✎ 🗑 │\n * │ ☐ [Events] ✎ 🗑 │\n * │ 1 / 3 │\n * │ New tag [ Name ] │\n * │ ● ● ● ● ● ● ● ● ● ● ● ● [ + Create ] │\n * │ [ Done ] │\n * └─────────────────────────────────────────────┘\n *\n * Everything is saved as it is done: ticking a tag, creating one (ticked at\n * once while the template has room), renaming it, deleting it — from every\n * template. Errors show in the dialog: the library's notices are under it.\n *\n * @param {{\n * open: boolean,\n * onOpenChange: (open: boolean) => void,\n * template: {id: string|number, name: string, tags?: string[]},\n * tags: import('../../features/tags/tags.js').TemplateTag[],\n * storage: import('../../storage/client.js').TemplateStorage,\n * onTagsChange: (tags: import('../../features/tags/tags.js').TemplateTag[], change?: {deleted?: string}) => void,\n * onTemplateTags: (tagIds: string[]) => void,\n * }} props\n */\nexport default function TagsDialog({ open, onOpenChange, template, tags, storage, onTagsChange, onTemplateTags }) {\n const { t, confirm } = useUi();\n const chosen = (template.tags || []).map(String);\n const full = chosen.length >= MAX_TEMPLATE_TAGS;\n /** null: creating; else the id of the tag being edited. */\n const [editing, setEditing] = useState(null);\n const [form, setForm] = useState({ label: '', color: colorAfter(tags) });\n const [errors, setErrors] = useState({});\n const [failure, setFailure] = useState(null);\n /** What is being saved: `form`, `tick:<id>`, `delete:<id>`. */\n const [busy, setBusy] = useState(null);\n\n const colorName = {\n gray: t('Gray'),\n red: t('Red'),\n orange: t('Orange'),\n amber: t('Yellow'),\n lime: t('Lime'),\n green: t('Green'),\n teal: t('Teal'),\n cyan: t('Cyan'),\n blue: t('Blue'),\n violet: t('Violet'),\n fuchsia: t('Fuchsia'),\n pink: t('Pink'),\n };\n\n const reset = (list = tags) => {\n setEditing(null);\n setForm({ label: '', color: colorAfter(list) });\n setErrors({});\n };\n useEffect(() => {\n if (!open) return;\n reset();\n setFailure(null);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n /** @param {string} what @param {() => Promise<void>} work */\n const run = async (what, work) => {\n setBusy(what);\n setFailure(null);\n try {\n await work();\n } catch (error) {\n setFailure(error.message);\n } finally {\n setBusy(null);\n }\n };\n\n const tick = (id) =>\n run(`tick:${id}`, async () => {\n const next = chosen.includes(id) ? chosen.filter((tagId) => tagId !== id) : [...chosen, id];\n onTemplateTags(await storage.setTemplateTags(template.id, next));\n });\n\n const submit = (event) => {\n event.preventDefault();\n const check = validateTag(form, { existing: tags, editing, t });\n if (check.errors) {\n setErrors(check.errors);\n return;\n }\n run('form', async () => {\n const saved = await storage.saveTag(editing ? { id: editing, ...check.tag } : check.tag, { create: !editing });\n const list = sortTags([...tags.filter((tag) => tag.id !== saved.id), saved]);\n onTagsChange(list);\n if (!editing && !full) onTemplateTags(await storage.setTemplateTags(template.id, [...chosen, saved.id]));\n reset(list);\n });\n };\n\n const remove = async (tag) => {\n const ok = await confirm({\n title: t('Delete the tag “{name}”?', { name: tag.label }),\n description: t('It is removed from every template.'),\n confirmLabel: t('Delete'),\n destructive: true,\n });\n if (!ok) return;\n run(`delete:${tag.id}`, async () => {\n await storage.deleteTag(tag.id);\n const list = tags.filter((other) => other.id !== tag.id);\n onTagsChange(list, { deleted: tag.id });\n if (editing === tag.id) reset(list);\n });\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"eb:sm:max-w-[460px]\" data-testid=\"eb-tags-dialog\">\n <DialogHeader>\n <div className=\"eb:flex eb:items-center eb:gap-3\">\n <span className=\"eb:flex eb:size-10 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-lg2 eb:bg-primary/10 eb:text-primary\">\n <Tags className=\"eb:size-5\" />\n </span>\n <div className=\"eb:min-w-0\">\n <DialogTitle className=\"eb:text-base eb:font-normal\">{t('Tags')}</DialogTitle>\n <DialogDescription className=\"eb:text-[13px]\">\n {t('Up to {max} tags on “{name}”.', { max: MAX_TEMPLATE_TAGS, name: template.name })}\n </DialogDescription>\n </div>\n </div>\n </DialogHeader>\n\n <div className=\"eb:flex eb:flex-col eb:gap-1\">\n {tags.length === 0 ? (\n <p className=\"eb:m-0 eb:rounded-lg2 eb:border eb:border-dashed eb:border-border eb:p-3 eb:text-center eb:text-[12.5px] eb:text-foreground-lighter\">\n {t('No tag yet: create the first one below.')}\n </p>\n ) : (\n <ul className=\"eb:flex eb:max-h-56 eb:flex-col eb:gap-0.5 eb:overflow-y-auto\" aria-label={t('Tags')}>\n {tags.map((tag) => {\n const checked = chosen.includes(tag.id);\n const locked = !checked && full;\n return (\n <li\n key={tag.id}\n data-testid=\"eb-tags-option\"\n className={cn('eb:flex eb:items-center eb:gap-2 eb:rounded-md eb:px-2 eb:py-1', editing === tag.id ? 'eb:bg-primary/5' : 'eb:hover:bg-surface-75')}\n >\n <label\n className={cn('eb:flex eb:min-w-0 eb:flex-1 eb:items-center eb:gap-2.5', locked ? 'eb:cursor-not-allowed eb:opacity-50' : 'eb:cursor-pointer')}\n title={locked ? t('{max} tags at most: untick one to choose another.', { max: MAX_TEMPLATE_TAGS }) : undefined}\n >\n <input\n type=\"checkbox\"\n className=\"eb:size-4 eb:shrink-0 eb:accent-primary\"\n checked={checked}\n disabled={locked || busy !== null}\n onChange={() => tick(tag.id)}\n aria-label={tag.label}\n />\n <TagBadge tag={tag} className=\"eb:text-[12px]\" />\n {busy === `tick:${tag.id}` && <Loader2 className=\"eb:size-3.5 eb:animate-spin eb:text-foreground-muted\" />}\n </label>\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n className=\"eb:text-foreground-muted\"\n disabled={busy !== null}\n onClick={() => {\n setEditing(tag.id);\n setForm({ label: tag.label, color: tag.color });\n setErrors({});\n }}\n aria-label={t('Edit the tag “{name}”', { name: tag.label })}\n title={t('Edit')}\n >\n <Pencil />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n className=\"eb:text-foreground-muted eb:hover:text-destructive\"\n disabled={busy !== null}\n onClick={() => remove(tag)}\n aria-label={t('Delete the tag “{name}”', { name: tag.label })}\n title={t('Delete')}\n >\n {busy === `delete:${tag.id}` ? <Loader2 className=\"eb:animate-spin\" /> : <Trash2 />}\n </Button>\n </li>\n );\n })}\n </ul>\n )}\n {tags.length > 0 && (\n <p className=\"eb:m-0 eb:px-2 eb:text-right eb:text-[11.5px] eb:text-foreground-muted\" aria-live=\"polite\" data-testid=\"eb-tags-count\">\n {full ? t('{max} tags at most: untick one to choose another.', { max: MAX_TEMPLATE_TAGS }) : `${chosen.length} / ${MAX_TEMPLATE_TAGS}`}\n </p>\n )}\n </div>\n\n <form onSubmit={submit} className=\"eb:flex eb:flex-col eb:gap-2.5 eb:border-t eb:border-border eb:pt-4\" noValidate data-testid=\"eb-tags-form\">\n <Label htmlFor=\"eb-tag-label\">{editing ? t('Edit tag') : t('New tag')}</Label>\n <Input\n id=\"eb-tag-label\"\n value={form.label}\n maxLength={TAG_LIMITS.label}\n placeholder={t('Name')}\n onChange={(event) => {\n setForm((f) => ({ ...f, label: event.target.value }));\n setErrors((e) => ({ ...e, label: undefined }));\n }}\n aria-invalid={errors.label ? true : undefined}\n aria-describedby={errors.label ? 'eb-tag-label-error' : undefined}\n />\n {errors.label && (\n <p id=\"eb-tag-label-error\" className=\"eb:m-0 eb:text-[12px] eb:text-destructive\">\n {errors.label}\n </p>\n )}\n {/* The colors fill the row up to the buttons, shrinking a little in a\n long language; the buttons go under them when the row is too\n narrow (editing, a phone). A basis, not a width, so the colors\n never make the dialog wider than a phone. */}\n <div className=\"eb:flex eb:flex-wrap eb:items-center eb:gap-3\">\n <div role=\"radiogroup\" aria-label={t('Color')} className=\"eb:flex eb:min-w-0 eb:flex-[1_1_16rem] eb:items-center eb:justify-between eb:gap-1\">\n {TAG_COLORS.map((color) => {\n const picked = form.color === color;\n return (\n <button\n key={color}\n type=\"button\"\n role=\"radio\"\n aria-checked={picked}\n aria-label={colorName[color]}\n title={colorName[color]}\n onClick={() => setForm((f) => ({ ...f, color }))}\n className={cn(\n 'eb:flex eb:aspect-square eb:min-w-4 eb:shrink eb:basis-6 eb:items-center eb:justify-center eb:rounded-full eb:text-white eb:outline-none eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50',\n TAG_SWATCHES[color],\n picked && 'eb:ring-2 eb:ring-foreground/60 eb:ring-offset-2 eb:ring-offset-background'\n )}\n >\n {picked && <Check className=\"eb:size-3.5\" />}\n </button>\n );\n })}\n </div>\n <div className=\"eb:ml-auto eb:flex eb:gap-2\">\n {editing && (\n <Button variant=\"outline\" size=\"sm\" onClick={() => reset()} disabled={busy !== null}>\n {t('Cancel')}\n </Button>\n )}\n <Button type=\"submit\" size=\"sm\" variant={editing ? 'default' : 'outline'} disabled={busy !== null}>\n {busy === 'form' ? <Loader2 className=\"eb:animate-spin\" /> : !editing && <Plus />}\n {editing ? t('Save') : t('Create')}\n </Button>\n </div>\n </div>\n {form.label.trim() && !errors.label && (\n <p className=\"eb:m-0 eb:flex eb:items-center eb:gap-2 eb:text-[11.5px] eb:text-foreground-muted\">\n {t('Preview')}\n <TagBadge tag={{ id: 'preview', label: form.label.trim(), color: form.color }} className=\"eb:text-[12px]\" />\n </p>\n )}\n </form>\n\n {failure && (\n <p role=\"alert\" className=\"eb:m-0 eb:text-[12.5px] eb:text-destructive\">\n {failure}\n </p>\n )}\n\n <div className=\"eb:flex eb:justify-end\">\n <Button onClick={() => onOpenChange(false)}>{t('Done')}</Button>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":["useEffect","useState","Loader2","Tags","Trash2","jsx","jsx","jsxs","useState","useEffect","template","Loader2","Tags","Trash2"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  DEFAULT_VARIABLES
3
- } from "./chunk-A2MEYOR3.js";
3
+ } from "./chunk-JFIXYIZ3.js";
4
4
 
5
5
  // src/features/variables/service.js
6
6
  function escapeHtml(text) {
@@ -70,4 +70,4 @@ export {
70
70
  unknownVariables,
71
71
  sampleValues
72
72
  };
73
- //# sourceMappingURL=chunk-NV6IV4CU.js.map
73
+ //# sourceMappingURL=chunk-FYIIO7LD.js.map
@@ -94,8 +94,8 @@ var de = {
94
94
  "Original size": "Originalgr\xF6\xDFe",
95
95
  "Our offices, 1 Main Street": "Unsere B\xFCror\xE4ume, Hauptstra\xDFe 1",
96
96
  "Picking a template replaces the email being edited.": "Wenn Sie eine Vorlage ausw\xE4hlen, wird die aktuell bearbeitete E-Mail ersetzt.",
97
- "All": "Alle",
98
97
  "Filter by tag": "Nach Label filtern",
98
+ "Clear the tag filters": "Label-Filter zur\xFCcksetzen",
99
99
  "Basics": "Basis",
100
100
  "Marketing": "Marketing",
101
101
  "News": "Neuigkeiten",
@@ -637,8 +637,8 @@ var es = {
637
637
  "Original size": "Tama\xF1o original",
638
638
  "Our offices, 1 Main Street": "Nuestras oficinas, Calle Mayor 1",
639
639
  "Picking a template replaces the email being edited.": "Al elegir una plantilla, se reemplaza el correo que est\xE1s editando.",
640
- "All": "Todas",
641
640
  "Filter by tag": "Filtrar por etiqueta",
641
+ "Clear the tag filters": "Quitar los filtros de etiqueta",
642
642
  "Basics": "B\xE1sicas",
643
643
  "Marketing": "Marketing",
644
644
  "News": "Noticias",
@@ -1180,8 +1180,8 @@ var fr = {
1180
1180
  "Original size": "Taille d'origine",
1181
1181
  "Our offices, 1 Main Street": "Nos bureaux, 1 rue Principale",
1182
1182
  "Picking a template replaces the email being edited.": "Choisir un mod\xE8le remplace l'e-mail en cours de modification.",
1183
- "All": "Tous",
1184
1183
  "Filter by tag": "Filtrer par \xE9tiquette",
1184
+ "Clear the tag filters": "Effacer les filtres par \xE9tiquette",
1185
1185
  "Basics": "Essentiels",
1186
1186
  "Marketing": "Marketing",
1187
1187
  "News": "Actualit\xE9s",
@@ -1723,8 +1723,8 @@ var pt = {
1723
1723
  "Original size": "Tamanho original",
1724
1724
  "Our offices, 1 Main Street": "Nosso escrit\xF3rio, Rua Principal, 1",
1725
1725
  "Picking a template replaces the email being edited.": "Escolher um modelo substitui o e-mail em edi\xE7\xE3o.",
1726
- "All": "Todas",
1727
1726
  "Filter by tag": "Filtrar por etiqueta",
1727
+ "Clear the tag filters": "Limpar os filtros de etiqueta",
1728
1728
  "Basics": "B\xE1sicas",
1729
1729
  "Marketing": "Marketing",
1730
1730
  "News": "Not\xEDcias",
@@ -2266,8 +2266,8 @@ var ru = {
2266
2266
  "Original size": "\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u0440\u0430\u0437\u043C\u0435\u0440",
2267
2267
  "Our offices, 1 Main Street": "\u041D\u0430\u0448 \u043E\u0444\u0438\u0441, \u0443\u043B. \u0426\u0435\u043D\u0442\u0440\u0430\u043B\u044C\u043D\u0430\u044F, 1",
2268
2268
  "Picking a template replaces the email being edited.": "\u0412\u044B\u0431\u0440\u0430\u043D\u043D\u044B\u0439 \u0448\u0430\u0431\u043B\u043E\u043D \u0437\u0430\u043C\u0435\u043D\u0438\u0442 \u043F\u0438\u0441\u044C\u043C\u043E, \u043A\u043E\u0442\u043E\u0440\u043E\u0435 \u0432\u044B \u0441\u0435\u0439\u0447\u0430\u0441 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u0443\u0435\u0442\u0435.",
2269
- "All": "\u0412\u0441\u0435",
2270
2269
  "Filter by tag": "\u0424\u0438\u043B\u044C\u0442\u0440 \u043F\u043E \u043C\u0435\u0442\u043A\u0430\u043C",
2270
+ "Clear the tag filters": "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u0444\u0438\u043B\u044C\u0442\u0440 \u043F\u043E \u043C\u0435\u0442\u043A\u0430\u043C",
2271
2271
  "Basics": "\u0411\u0430\u0437\u043E\u0432\u044B\u0435",
2272
2272
  "Marketing": "\u041C\u0430\u0440\u043A\u0435\u0442\u0438\u043D\u0433",
2273
2273
  "News": "\u041D\u043E\u0432\u043E\u0441\u0442\u0438",
@@ -2809,8 +2809,8 @@ var zh = {
2809
2809
  "Original size": "\u539F\u59CB\u5C3A\u5BF8",
2810
2810
  "Our offices, 1 Main Street": "\u6211\u4EEC\u7684\u529E\u516C\u5BA4\uFF08\u4E3B\u8857 1 \u53F7\uFF09",
2811
2811
  "Picking a template replaces the email being edited.": "\u9009\u62E9\u6A21\u677F\u4F1A\u66FF\u6362\u5F53\u524D\u6B63\u5728\u7F16\u8F91\u7684\u90AE\u4EF6\u3002",
2812
- "All": "\u5168\u90E8",
2813
2812
  "Filter by tag": "\u6309\u6807\u7B7E\u7B5B\u9009",
2813
+ "Clear the tag filters": "\u6E05\u9664\u6807\u7B7E\u7B5B\u9009",
2814
2814
  "Basics": "\u57FA\u7840",
2815
2815
  "Marketing": "\u8425\u9500",
2816
2816
  "News": "\u8D44\u8BAF",
@@ -3396,4 +3396,4 @@ export {
3396
3396
  absoluteAssetUrls,
3397
3397
  applyServiceLinks
3398
3398
  };
3399
- //# sourceMappingURL=chunk-A2MEYOR3.js.map
3399
+ //# sourceMappingURL=chunk-JFIXYIZ3.js.map