best-email-builder 0.12.0 → 0.13.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/CHANGELOG.md +15 -0
- package/dist/ai-server.js +3 -3
- package/dist/ai.js +6 -6
- package/dist/builder.js +8 -8
- package/dist/{chunk-FYIIO7LD.js → chunk-2KOI5SWV.js} +2 -2
- package/dist/{chunk-LAUNZIFX.js → chunk-6QTSXJG4.js} +5 -5
- package/dist/chunk-6QTSXJG4.js.map +1 -0
- package/dist/{chunk-46ZVS2VX.js → chunk-A4KF7NMP.js} +2 -2
- package/dist/{chunk-OACK2DIW.js → chunk-G7G3TRWG.js} +662 -441
- package/dist/chunk-G7G3TRWG.js.map +1 -0
- package/dist/{chunk-6CTFMKAQ.js → chunk-JJ56652Y.js} +4 -4
- package/dist/{chunk-UUS325J7.js → chunk-LSOR4OII.js} +3 -3
- package/dist/{chunk-MOWQZKIQ.js → chunk-Q2ZUJFOY.js} +2 -2
- package/dist/{chunk-LZYDCWVH.js → chunk-Q5UPFM7J.js} +3 -3
- package/dist/{chunk-LZYDCWVH.js.map → chunk-Q5UPFM7J.js.map} +1 -1
- package/dist/{chunk-RONYPWDK.js → chunk-UGF3YJ64.js} +2 -2
- package/dist/{chunk-RSTERB7K.js → chunk-XF25DLD4.js} +3 -3
- package/dist/{chunk-JFIXYIZ3.js → chunk-ZTUW25BG.js} +7 -1
- package/dist/chunk-ZTUW25BG.js.map +1 -0
- package/dist/index.js +10 -10
- package/dist/library.js +5 -5
- package/dist/server.js +5 -5
- package/dist/styles.css +1 -1
- package/dist/types/core/EmailEditor.d.ts +16 -4
- package/dist/types/core/constants.d.ts +1 -1
- package/dist/types/engine/NativeAdapter.d.ts +1 -1
- package/dist/types/engine/canvas/CanvasView.d.ts +3 -0
- package/dist/types/engine/canvas/canvasStyles.d.ts +1 -1
- package/dist/types/features/variables/VariablesBar.d.ts +16 -0
- package/dist/types/ui/primitives/misc.d.ts +6 -2
- package/package.json +1 -1
- package/dist/chunk-JFIXYIZ3.js.map +0 -1
- package/dist/chunk-LAUNZIFX.js.map +0 -1
- package/dist/chunk-OACK2DIW.js.map +0 -1
- /package/dist/{chunk-FYIIO7LD.js.map → chunk-2KOI5SWV.js.map} +0 -0
- /package/dist/{chunk-46ZVS2VX.js.map → chunk-A4KF7NMP.js.map} +0 -0
- /package/dist/{chunk-6CTFMKAQ.js.map → chunk-JJ56652Y.js.map} +0 -0
- /package/dist/{chunk-UUS325J7.js.map → chunk-LSOR4OII.js.map} +0 -0
- /package/dist/{chunk-MOWQZKIQ.js.map → chunk-Q2ZUJFOY.js.map} +0 -0
- /package/dist/{chunk-RONYPWDK.js.map → chunk-UGF3YJ64.js.map} +0 -0
- /package/dist/{chunk-RSTERB7K.js.map → chunk-XF25DLD4.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,21 @@ All notable changes are documented here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.13.0] — 2026-10-20
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- A *Personalization fields* bar above the canvas. It is thin until the
|
|
13
|
+
pointer comes over it (or a click opens it), then lists the variables as
|
|
14
|
+
badges, whose tooltip names their tag. A badge under the pointer types its
|
|
15
|
+
tag into the selected text or button, as it will look, and wipes it out
|
|
16
|
+
when the pointer leaves; a click inserts it. The unsubscribe link stays in
|
|
17
|
+
the *Variables* menu.
|
|
18
|
+
- `editor.previewText(text)` and `editor.clearPreview()`: show a text where
|
|
19
|
+
`insertText` would put it, without changing the email. An adapter opts in
|
|
20
|
+
with `previewText` and `clearPreview`.
|
|
21
|
+
- A feature may declare `canvasBar`: a component shown as a bar above the
|
|
22
|
+
canvas, like `toolbar` in the toolbar.
|
|
23
|
+
|
|
9
24
|
## [0.12.0] — 2026-10-20
|
|
10
25
|
|
|
11
26
|
### Changed
|
package/dist/ai-server.js
CHANGED
|
@@ -26,9 +26,9 @@ import {
|
|
|
26
26
|
reviewFix,
|
|
27
27
|
reviewRewrite,
|
|
28
28
|
reviewSubjects
|
|
29
|
-
} from "./chunk-
|
|
30
|
-
import "./chunk-
|
|
31
|
-
import "./chunk-
|
|
29
|
+
} from "./chunk-XF25DLD4.js";
|
|
30
|
+
import "./chunk-A4KF7NMP.js";
|
|
31
|
+
import "./chunk-ZTUW25BG.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-
|
|
3
|
+
} from "./chunk-UGF3YJ64.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-
|
|
23
|
-
import "./chunk-
|
|
22
|
+
} from "./chunk-6QTSXJG4.js";
|
|
23
|
+
import "./chunk-Q5UPFM7J.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-
|
|
47
|
-
import "./chunk-
|
|
48
|
-
import "./chunk-
|
|
46
|
+
} from "./chunk-XF25DLD4.js";
|
|
47
|
+
import "./chunk-A4KF7NMP.js";
|
|
48
|
+
import "./chunk-ZTUW25BG.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-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-G7G3TRWG.js";
|
|
9
|
+
import "./chunk-LSOR4OII.js";
|
|
10
|
+
import "./chunk-Q2ZUJFOY.js";
|
|
11
11
|
import "./chunk-UFKCLU2D.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-UGF3YJ64.js";
|
|
13
13
|
import {
|
|
14
14
|
StorageError,
|
|
15
15
|
createHttpStorage,
|
|
16
16
|
createMemoryStorage
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-6QTSXJG4.js";
|
|
18
18
|
import {
|
|
19
19
|
EMAIL_BUILDER_VERSION
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-Q5UPFM7J.js";
|
|
21
|
+
import "./chunk-A4KF7NMP.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-
|
|
30
|
+
} from "./chunk-ZTUW25BG.js";
|
|
31
31
|
export {
|
|
32
32
|
CUSTOM_GROUP,
|
|
33
33
|
DEFAULT_VARIABLES,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_VARIABLES
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZTUW25BG.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-
|
|
73
|
+
//# sourceMappingURL=chunk-2KOI5SWV.js.map
|
|
@@ -7,14 +7,14 @@ import {
|
|
|
7
7
|
readDocument,
|
|
8
8
|
sortTags,
|
|
9
9
|
validateTag
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-Q5UPFM7J.js";
|
|
11
11
|
import {
|
|
12
12
|
DEFAULT_ASSETS_PATH,
|
|
13
13
|
DEFAULT_VARIABLES,
|
|
14
14
|
identity,
|
|
15
15
|
translatorFor,
|
|
16
16
|
validateCustomVariable
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-ZTUW25BG.js";
|
|
18
18
|
|
|
19
19
|
// src/ui/context.jsx
|
|
20
20
|
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
@@ -401,9 +401,9 @@ function TooltipContent({ className, sideOffset = 4, children, ...props }) {
|
|
|
401
401
|
}
|
|
402
402
|
) });
|
|
403
403
|
}
|
|
404
|
-
function TooltipWrap({ label, side = "top", children, asChild = true, delayDuration }) {
|
|
404
|
+
function TooltipWrap({ label, side = "top", children, asChild = true, delayDuration, hoverable = true }) {
|
|
405
405
|
if (!label) return children;
|
|
406
|
-
return /* @__PURE__ */ jsxs2(Tooltip, { delayDuration, children: [
|
|
406
|
+
return /* @__PURE__ */ jsxs2(Tooltip, { delayDuration, disableHoverableContent: !hoverable, children: [
|
|
407
407
|
/* @__PURE__ */ jsx3(TooltipTrigger, { asChild, children }),
|
|
408
408
|
/* @__PURE__ */ jsx3(TooltipContent, { side, className: "eb:px-2 eb:py-1 eb:text-[11px]", children: label })
|
|
409
409
|
] });
|
|
@@ -948,4 +948,4 @@ export {
|
|
|
948
948
|
createHttpStorage,
|
|
949
949
|
createMemoryStorage
|
|
950
950
|
};
|
|
951
|
-
//# sourceMappingURL=chunk-
|
|
951
|
+
//# sourceMappingURL=chunk-6QTSXJG4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ui/context.jsx","../src/ui/primitives/overlays.jsx","../src/ui/primitives/cn.js","../src/ui/primitives/button.jsx","../src/ui/primitives/misc.jsx","../src/storage/client.js","../src/ui/primitives/fields.jsx"],"sourcesContent":["import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { AlertCircle, CheckCircle2, Info, TriangleAlert, X } from 'lucide-react';\nimport { identity, translatorFor } from '../i18n/index.js';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogTitle,\n} from './primitives/overlays.jsx';\nimport { buttonVariants } from './primitives/button.jsx';\nimport { TooltipProvider } from './primitives/misc.jsx';\nimport { cn } from './primitives/cn.js';\n\n/**\n * Interface services shared by every component of the builder:\n *\n * t translation (see src/i18n) ;\n * locale BCP 47 tag used for dates and times ;\n * notify short messages (`success`, `info`, `warning`, `error`) — shown by\n * the builder itself, or handed to the host's own toaster through\n * the `onNotify` prop ;\n * confirm asynchronous confirmation dialog → Promise<boolean>.\n */\n\n/**\n * @typedef {'success'|'info'|'warning'|'error'} NotifyLevel\n * @typedef {{title?: string, description?: string, confirmLabel?: string,\n * cancelLabel?: string, destructive?: boolean}} ConfirmOptions\n */\n\nconst NoticeContext = createContext({ notices: [], dismiss: () => {} });\n\nconst UiContext = createContext({\n t: identity,\n locale: 'en',\n /** @type {(level: NotifyLevel, message: string) => void} */\n notify: () => {},\n /** @type {(options: ConfirmOptions) => Promise<boolean>} */\n confirm: async () => false,\n});\n\nexport const useUi = () => useContext(UiContext);\nexport const useT = () => useContext(UiContext).t;\n\nconst NOTICE_ICON = { success: CheckCircle2, info: Info, warning: TriangleAlert, error: AlertCircle };\nconst NOTICE_TTL = { success: 3500, info: 4000, warning: 6000, error: 7000 };\n\n/** Where the builder's own notices appear (bottom-right of its root element). */\nexport function NoticeArea() {\n const t = useT();\n const { notices, dismiss: onDismiss } = useContext(NoticeContext);\n return (\n <div className=\"eb:pointer-events-none eb:absolute eb:right-3 eb:bottom-3 eb:z-40 eb:flex eb:w-80 eb:max-w-[calc(100%-1.5rem)] eb:flex-col eb:gap-2\">\n {notices.map((notice) => {\n const Icon = NOTICE_ICON[notice.level] || Info;\n return (\n <div\n key={notice.id}\n role={notice.level === 'error' ? 'alert' : 'status'}\n data-level={notice.level}\n className=\"eb:pointer-events-auto eb:flex eb:items-start eb:gap-2 eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:px-3 eb:py-2.5 eb:text-[13px] eb:text-popover-foreground eb:shadow-lg\"\n >\n <Icon\n aria-hidden=\"true\"\n className={cn(\n 'eb:mt-0.5 eb:size-4 eb:shrink-0',\n notice.level === 'error' && 'eb:text-destructive',\n notice.level === 'warning' && 'eb:text-warning',\n notice.level === 'success' && 'eb:text-success',\n notice.level === 'info' && 'eb:text-foreground-muted'\n )}\n />\n <p className=\"eb:min-w-0 eb:flex-1\">{notice.message}</p>\n <button\n type=\"button\"\n aria-label={t('Dismiss')}\n className=\"eb:shrink-0 eb:rounded-sm eb:text-foreground-muted eb:hover:text-foreground\"\n onClick={() => onDismiss(notice.id)}\n >\n <X className=\"eb:size-3.5\" />\n </button>\n </div>\n );\n })}\n </div>\n );\n}\n\n/**\n * @param {{\n * locale?: string,\n * messages?: Record<string, string>,\n * onNotify?: (level: NotifyLevel, message: string) => void,\n * children: import('react').ReactNode,\n * }} props\n */\nexport function UiProvider({ locale = 'en', messages, onNotify, children }) {\n const t = useMemo(() => translatorFor(locale, messages), [locale, messages]);\n\n /* ── Notices ── */\n const [notices, setNotices] = useState([]);\n const timers = useRef(new Map());\n const dismiss = useCallback((id) => {\n clearTimeout(timers.current.get(id));\n timers.current.delete(id);\n setNotices((list) => list.filter((n) => n.id !== id));\n }, []);\n const hostNotify = useRef(onNotify);\n hostNotify.current = onNotify;\n const nextId = useRef(0);\n const notify = useCallback(\n (level, message) => {\n if (hostNotify.current) {\n hostNotify.current(level, message);\n return;\n }\n const id = (nextId.current += 1);\n // The same message again replaces the one shown (three rewrites in a\n // row: one notice, not a pile). Clearing a timer twice is harmless.\n setNotices((list) => {\n const same = list.filter((n) => n.level === level && n.message === message);\n for (const notice of same) {\n clearTimeout(timers.current.get(notice.id));\n timers.current.delete(notice.id);\n }\n return [...list.filter((n) => !same.includes(n)).slice(-3), { id, level, message }];\n });\n timers.current.set(\n id,\n setTimeout(() => dismiss(id), NOTICE_TTL[level] || 4000)\n );\n },\n [dismiss]\n );\n useEffect(() => {\n const pending = timers.current;\n return () => pending.forEach((timer) => clearTimeout(timer));\n }, []);\n\n /* ── Confirmation ── */\n const [request, setRequest] = useState(null);\n const confirm = useCallback(\n (options = {}) =>\n new Promise((resolve) => {\n setRequest((current) => {\n current?.resolve(false);\n return { options, resolve };\n });\n }),\n []\n );\n const settle = (result) => {\n request?.resolve(result);\n setRequest(null);\n };\n\n const value = useMemo(() => ({ t, locale, notify, confirm }), [t, locale, notify, confirm]);\n const noticeValue = useMemo(() => ({ notices, dismiss }), [notices, dismiss]);\n const options = request?.options || {};\n\n return (\n <UiContext.Provider value={value}>\n <TooltipProvider delayDuration={300}>\n <NoticeContext.Provider value={noticeValue}>{children}</NoticeContext.Provider>\n <AlertDialog open={Boolean(request)} onOpenChange={(open) => !open && settle(false)}>\n <AlertDialogContent>\n <div className=\"eb:flex eb:items-center eb:gap-3\">\n <span\n className={cn(\n 'eb:flex eb:size-10 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-lg2',\n options.destructive ? 'eb:bg-destructive/10 eb:text-destructive' : 'eb:bg-primary/10 eb:text-primary'\n )}\n >\n <AlertCircle className=\"eb:size-5\" />\n </span>\n <AlertDialogTitle className=\"eb:text-base\">{options.title || t('Confirm')}</AlertDialogTitle>\n </div>\n {options.description && (\n <AlertDialogDescription className=\"eb:text-[13px] eb:leading-relaxed\">{options.description}</AlertDialogDescription>\n )}\n <div className=\"eb:flex eb:flex-col-reverse eb:gap-2 eb:sm:flex-row eb:sm:justify-end\">\n <AlertDialogCancel className={buttonVariants({ variant: 'outline' })} onClick={() => settle(false)}>\n {options.cancelLabel || t('Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n className={buttonVariants({ variant: options.destructive ? 'destructive' : 'default' })}\n onClick={() => settle(true)}\n >\n {options.confirmLabel || t('Confirm')}\n </AlertDialogAction>\n </div>\n </AlertDialogContent>\n </AlertDialog>\n </TooltipProvider>\n </UiContext.Provider>\n );\n}\n","import {\n AlertDialog as AlertDialogPrimitive,\n Dialog as DialogPrimitive,\n DropdownMenu as DropdownMenuPrimitive,\n Popover as PopoverPrimitive,\n Select as SelectPrimitive,\n} from 'radix-ui';\nimport { CheckIcon, ChevronDownIcon, XIcon } from 'lucide-react';\nimport { useT } from '../context.jsx';\nimport { cn } from './cn.js';\n\n/*\n * Overlays render in a portal, outside the builder's root element: each one\n * carries the `eb-scope` class so the package's base styles reach it.\n */\n\nconst FADE_ZOOM =\n 'eb:data-[state=open]:animate-in eb:data-[state=open]:fade-in-0 eb:data-[state=open]:zoom-in-95 eb:data-[state=closed]:animate-out eb:data-[state=closed]:fade-out-0 eb:data-[state=closed]:zoom-out-95';\n\n/* ── Dialog ───────────────────────────────────────────────────────────── */\n\nexport function Dialog(props) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nexport function DialogContent({ className, children, showCloseButton = true, ...props }) {\n const t = useT();\n return (\n <DialogPrimitive.Portal>\n <DialogPrimitive.Overlay className=\"eb-scope eb:fixed eb:inset-0 eb:z-50 eb:bg-black/50 eb:data-[state=open]:animate-in eb:data-[state=open]:fade-in-0 eb:data-[state=closed]:animate-out eb:data-[state=closed]:fade-out-0\" />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n 'eb-scope eb:fixed eb:top-[50%] eb:left-[50%] eb:z-50 eb:grid eb:w-full eb:max-w-[calc(100%-2rem)] eb:translate-x-[-50%] eb:translate-y-[-50%] eb:gap-4 eb:rounded-lg2 eb:border eb:border-border eb:bg-background eb:p-6 eb:text-foreground eb:shadow-lg eb:duration-200 eb:outline-none eb:sm:max-w-lg',\n FADE_ZOOM,\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close className=\"eb:absolute eb:top-4 eb:right-4 eb:rounded-xs eb:opacity-70 eb:transition-opacity eb:hover:opacity-100 eb:focus:ring-2 eb:focus:ring-ring eb:focus:ring-offset-2 eb:focus:outline-hidden eb:disabled:pointer-events-none eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\">\n <XIcon />\n <span className=\"eb:sr-only\">{t('Close')}</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n );\n}\n\nexport function DialogHeader({ className, ...props }) {\n return <div className={cn('eb:flex eb:flex-col eb:gap-2 eb:text-left', className)} {...props} />;\n}\n\nexport function DialogFooter({ className, ...props }) {\n return <div className={cn('eb:flex eb:flex-col-reverse eb:gap-2 eb:sm:flex-row eb:sm:justify-end', className)} {...props} />;\n}\n\nexport function DialogTitle({ className, ...props }) {\n return <DialogPrimitive.Title className={cn('eb:text-lg eb:leading-none eb:font-semibold', className)} {...props} />;\n}\n\nexport function DialogDescription({ className, ...props }) {\n return <DialogPrimitive.Description className={cn('eb:text-sm eb:text-muted-foreground', className)} {...props} />;\n}\n\n/* ── Alert dialog (confirmations) ─────────────────────────────────────── */\n\nexport function AlertDialog(props) {\n return <AlertDialogPrimitive.Root {...props} />;\n}\n\nexport function AlertDialogContent({ className, ...props }) {\n return (\n <AlertDialogPrimitive.Portal>\n <AlertDialogPrimitive.Overlay className=\"eb-scope eb:fixed eb:inset-0 eb:z-50 eb:bg-black/50 eb:data-[state=open]:animate-in eb:data-[state=open]:fade-in-0 eb:data-[state=closed]:animate-out eb:data-[state=closed]:fade-out-0\" />\n <AlertDialogPrimitive.Content\n className={cn(\n 'eb-scope eb:fixed eb:top-[50%] eb:left-[50%] eb:z-50 eb:grid eb:w-full eb:max-w-[calc(100%-2rem)] eb:translate-x-[-50%] eb:translate-y-[-50%] eb:gap-4 eb:rounded-lg2 eb:border eb:border-border eb:bg-background eb:p-6 eb:text-foreground eb:shadow-lg eb:duration-200 eb:sm:max-w-lg',\n FADE_ZOOM,\n className\n )}\n {...props}\n />\n </AlertDialogPrimitive.Portal>\n );\n}\n\nexport const AlertDialogTitle = ({ className, ...props }) => (\n <AlertDialogPrimitive.Title className={cn('eb:text-lg eb:font-semibold', className)} {...props} />\n);\nexport const AlertDialogDescription = ({ className, ...props }) => (\n <AlertDialogPrimitive.Description className={cn('eb:text-sm eb:text-muted-foreground', className)} {...props} />\n);\nexport const AlertDialogAction = AlertDialogPrimitive.Action;\nexport const AlertDialogCancel = AlertDialogPrimitive.Cancel;\n\n/* ── Popover ──────────────────────────────────────────────────────────── */\n\nexport function Popover(props) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\n\nexport function PopoverTrigger(props) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n}\n\nexport function PopoverContent({ className, align = 'center', sideOffset = 4, ...props }) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n 'eb-scope eb:z-50 eb:w-72 eb:origin-(--radix-popover-content-transform-origin) eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:p-4 eb:text-popover-foreground eb:shadow-md eb:outline-hidden',\n FADE_ZOOM,\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n );\n}\n\n/* ── Dropdown menu ────────────────────────────────────────────────────── */\n\nexport function DropdownMenu(props) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nexport function DropdownMenuTrigger(props) {\n return <DropdownMenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />;\n}\n\nexport function DropdownMenuContent({ className, sideOffset = 4, ...props }) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n 'eb-scope eb:z-50 eb:max-h-(--radix-dropdown-menu-content-available-height) eb:min-w-[8rem] eb:origin-(--radix-dropdown-menu-content-transform-origin) eb:overflow-x-hidden eb:overflow-y-auto eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:p-1 eb:text-popover-foreground eb:shadow-md',\n FADE_ZOOM,\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nexport function DropdownMenuGroup(props) {\n return <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n}\n\nexport function DropdownMenuItem({ className, ...props }) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n className={cn(\n \"eb:relative eb:flex eb:cursor-default eb:items-center eb:gap-2 eb:rounded-sm eb:px-2 eb:py-1.5 eb:text-[13px] eb:outline-hidden eb:select-none eb:focus:bg-accent eb:focus:text-accent-foreground eb:data-[disabled]:pointer-events-none eb:data-[disabled]:opacity-50 eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport function DropdownMenuLabel({ className, ...props }) {\n return <DropdownMenuPrimitive.Label className={cn('eb:px-2 eb:py-1.5 eb:text-[13px] eb:font-medium', className)} {...props} />;\n}\n\nexport function DropdownMenuSeparator({ className, ...props }) {\n return <DropdownMenuPrimitive.Separator className={cn('eb:-mx-1 eb:my-1 eb:h-px eb:bg-border', className)} {...props} />;\n}\n\n/* ── Select ───────────────────────────────────────────────────────────── */\n\nexport function Select(props) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\n\nexport function SelectValue(props) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\n\nexport function SelectTrigger({ className, children, ...props }) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n className={cn(\n \"eb:flex eb:h-8 eb:w-full eb:items-center eb:justify-between eb:gap-2 eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:px-3 eb:py-1 eb:text-[13px] eb:whitespace-nowrap eb:text-foreground eb:shadow-xs eb:transition-[color,box-shadow] eb:outline-none eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50 eb:disabled:cursor-not-allowed eb:disabled:opacity-50 eb:data-[placeholder]:text-foreground-muted eb:*:data-[slot=select-value]:line-clamp-1 eb:*:data-[slot=select-value]:flex eb:*:data-[slot=select-value]:items-center eb:*:data-[slot=select-value]:gap-2 eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"eb:size-4 eb:opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n}\n\nexport function SelectContent({ className, children, position = 'popper', ...props }) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n position={position}\n className={cn(\n 'eb-scope eb:relative eb:z-50 eb:max-h-(--radix-select-content-available-height) eb:min-w-[8rem] eb:origin-(--radix-select-content-transform-origin) eb:overflow-x-hidden eb:overflow-y-auto eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:text-popover-foreground eb:shadow-md',\n FADE_ZOOM,\n position === 'popper' && 'eb:data-[side=bottom]:translate-y-1 eb:data-[side=top]:-translate-y-1',\n className\n )}\n {...props}\n >\n <SelectPrimitive.Viewport\n className={cn(\n 'eb:p-1',\n position === 'popper' &&\n 'eb:h-[var(--radix-select-trigger-height)] eb:w-full eb:min-w-[var(--radix-select-trigger-width)] eb:scroll-my-1'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n );\n}\n\nexport function SelectItem({ className, children, ...props }) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n 'eb:relative eb:flex eb:w-full eb:cursor-default eb:items-center eb:gap-2 eb:rounded-sm eb:py-1.5 eb:pr-8 eb:pl-2 eb:text-[13px] eb:outline-hidden eb:select-none eb:focus:bg-accent eb:focus:text-accent-foreground eb:data-[disabled]:pointer-events-none eb:data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"eb:absolute eb:right-2 eb:flex eb:size-3.5 eb:items-center eb:justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"eb:size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n );\n}\n","import { clsx } from 'clsx';\nimport { extendTailwindMerge } from 'tailwind-merge';\n\n// Every utility class of the package carries the `eb:` prefix (see src/styles.css),\n// so class merging has to know about it.\nconst twMerge = extendTailwindMerge({ prefix: 'eb' });\n\n/** Joins class names and resolves conflicting utilities (the last one wins). */\nexport function cn(...inputs) {\n return twMerge(clsx(inputs));\n}\n","import { Slot } from 'radix-ui';\nimport { cva } from 'class-variance-authority';\nimport { cn } from './cn.js';\n\nexport const buttonVariants = cva(\n \"eb:inline-flex eb:shrink-0 eb:items-center eb:justify-center eb:gap-2 eb:whitespace-nowrap eb:rounded-lg2 eb:text-sm eb:font-medium eb:transition-all eb:outline-none eb:disabled:pointer-events-none eb:disabled:opacity-50 eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50 eb:aria-invalid:border-destructive eb:aria-invalid:ring-destructive/20 eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: 'eb:bg-primary eb:text-primary-foreground eb:hover:bg-primary/90',\n destructive: 'eb:bg-destructive eb:text-white eb:hover:bg-destructive/90 eb:focus-visible:ring-destructive/20',\n outline: 'eb:border eb:border-border eb:bg-background eb:text-foreground eb:shadow-xs eb:hover:bg-accent eb:hover:text-accent-foreground',\n secondary: 'eb:bg-secondary eb:text-secondary-foreground eb:hover:bg-secondary/80',\n ghost: 'eb:text-foreground eb:hover:bg-accent eb:hover:text-accent-foreground',\n link: 'eb:text-primary eb:underline-offset-4 eb:hover:underline',\n },\n size: {\n default: 'eb:h-8 eb:gap-1.5 eb:px-3 eb:text-[13px] eb:has-[>svg]:px-2.5',\n xs: \"eb:h-6 eb:gap-1 eb:px-2 eb:text-xs eb:has-[>svg]:px-1.5 eb:[&_svg:not([class*='size-'])]:size-3\",\n 'sm-compact': \"eb:h-7 eb:gap-1.5 eb:px-3 eb:text-xs eb:has-[>svg]:px-2.5 eb:[&_svg:not([class*='size-'])]:size-3\",\n sm: 'eb:h-8 eb:gap-1.5 eb:px-3 eb:text-[13px] eb:has-[>svg]:px-2.5',\n lg: 'eb:h-10 eb:px-6 eb:has-[>svg]:px-4',\n icon: 'eb:size-8',\n 'icon-xs': \"eb:size-6 eb:[&_svg:not([class*='size-'])]:size-3\",\n 'icon-sm-compact': \"eb:size-7 eb:[&_svg:not([class*='size-'])]:size-3\",\n 'icon-sm': 'eb:size-8',\n },\n },\n defaultVariants: { variant: 'default', size: 'default' },\n }\n);\n\nexport function Button({ className, variant = 'default', size = 'default', asChild = false, type, ...props }) {\n const Comp = asChild ? Slot.Root : 'button';\n return (\n <Comp\n data-slot=\"button\"\n type={asChild ? type : type || 'button'}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n />\n );\n}\n","import { RotateCcw } from 'lucide-react';\nimport { Separator as SeparatorPrimitive, Tabs as TabsPrimitive, Tooltip as TooltipPrimitive } from 'radix-ui';\nimport { cn } from './cn.js';\n\nexport function Separator({ className, orientation = 'horizontal', decorative = true, ...props }) {\n return (\n <SeparatorPrimitive.Root\n data-slot=\"separator\"\n decorative={decorative}\n orientation={orientation}\n className={cn(\n 'eb:shrink-0 eb:bg-border eb:data-[orientation=horizontal]:h-px eb:data-[orientation=horizontal]:w-full eb:data-[orientation=vertical]:h-full eb:data-[orientation=vertical]:w-px',\n className\n )}\n {...props}\n />\n );\n}\n\nexport function Skeleton({ className, as: Comp = 'div', ...props }) {\n return <Comp data-slot=\"skeleton\" className={cn('eb:animate-pulse eb:rounded-lg2 eb:bg-accent', className)} {...props} />;\n}\n\n/**\n * A filter that is on or off (`aria-pressed`): the tags under a search. None\n * on shows everything; `FilterReset` turns them all off.\n */\nexport function FilterChip({ pressed, className, ...props }) {\n return (\n <button\n type=\"button\"\n aria-pressed={pressed}\n className={cn(\n 'eb:inline-flex eb:h-7 eb:shrink-0 eb:cursor-pointer eb:items-center eb:gap-1.5 eb:rounded-full eb:border eb:px-3 eb:text-[12px] eb:font-medium eb:whitespace-nowrap eb:transition-colors eb:outline-none eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50',\n pressed\n ? 'eb:border-primary eb:bg-primary eb:text-primary-foreground eb:hover:bg-primary/90'\n : 'eb:border-border eb:bg-background eb:text-foreground eb:hover:border-primary/50 eb:hover:bg-primary/5',\n className\n )}\n {...props}\n />\n );\n}\n\n/**\n * Turns every filter of a row off, so everything shows again. Inert while\n * none is on, but still there (and focusable): the row never moves.\n * `label` names it, for screen readers and on hover.\n */\nexport function FilterReset({ label, active, onClick, className, ...props }) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n aria-disabled={!active}\n onClick={(event) => active && onClick?.(event)}\n className={cn(\n 'eb:inline-flex eb:size-7 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-full eb:border eb:border-border eb:bg-background eb:text-foreground-lighter eb:transition-colors eb:outline-none eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50',\n active ? 'eb:cursor-pointer eb:hover:border-primary/50 eb:hover:bg-primary/5 eb:hover:text-primary' : 'eb:cursor-default eb:opacity-40',\n className\n )}\n {...props}\n >\n <RotateCcw className=\"eb:size-3.5\" aria-hidden=\"true\" />\n </button>\n );\n}\n\n/** Small uppercase heading of a panel section. */\nexport function SectionLabel({ className, ...props }) {\n return (\n <span\n data-slot=\"section-label\"\n className={cn('eb:font-mono eb:text-[10px] eb:uppercase eb:tracking-[0.14em] eb:text-foreground-muted', className)}\n {...props}\n />\n );\n}\n\n/** One line of text, cut with an ellipsis when it overflows (full text on hover). */\nexport function TruncatedText({ children, className, as: Comp = 'span', ...props }) {\n return (\n <Comp\n className={cn('eb:block eb:truncate', className)}\n title={typeof children === 'string' ? children : undefined}\n {...props}\n >\n {children}\n </Comp>\n );\n}\n\n/* ── Tabs ─────────────────────────────────────────────────────────────── */\n\nexport function Tabs({ className, ...props }) {\n return <TabsPrimitive.Root data-slot=\"tabs\" className={cn('eb:flex eb:flex-col eb:gap-2', className)} {...props} />;\n}\n\nexport function TabsList({ className, ...props }) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n className={cn(\n 'eb:inline-flex eb:h-8 eb:w-fit eb:items-center eb:justify-center eb:rounded-lg2 eb:bg-muted eb:p-[3px] eb:text-muted-foreground',\n className\n )}\n {...props}\n />\n );\n}\n\nexport function TabsTrigger({ className, ...props }) {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"eb:inline-flex eb:h-[calc(100%-1px)] eb:flex-1 eb:items-center eb:justify-center eb:gap-1.5 eb:rounded-lg2 eb:border eb:border-transparent eb:px-2 eb:py-1 eb:text-[13px] eb:font-medium eb:whitespace-nowrap eb:text-foreground/60 eb:transition-all eb:hover:text-foreground eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50 eb:focus-visible:outline-1 eb:disabled:pointer-events-none eb:disabled:opacity-50 eb:data-[state=active]:bg-background eb:data-[state=active]:text-foreground eb:data-[state=active]:shadow-sm eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\n/* ── Tooltip ──────────────────────────────────────────────────────────── */\n\nexport function TooltipProvider({ delayDuration = 0, ...props }) {\n return <TooltipPrimitive.Provider delayDuration={delayDuration} {...props} />;\n}\n\nexport function Tooltip(props) {\n return <TooltipPrimitive.Root {...props} />;\n}\n\nexport function TooltipTrigger(props) {\n return <TooltipPrimitive.Trigger {...props} />;\n}\n\nexport function TooltipContent({ className, sideOffset = 4, children, ...props }) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(\n 'eb-scope eb:z-50 eb:w-fit eb:origin-(--radix-tooltip-content-transform-origin) eb:animate-in eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:px-3 eb:py-1.5 eb:text-xs eb:text-balance eb:text-popover-foreground eb:shadow-md eb:fade-in-0 eb:zoom-in-95 eb:data-[state=closed]:animate-out eb:data-[state=closed]:fade-out-0 eb:data-[state=closed]:zoom-out-95',\n className\n )}\n {...props}\n >\n {children}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n}\n\n/**\n * Wraps a control with a tooltip; without a label, renders the control alone.\n * `hoverable: false`: it closes as soon as the pointer leaves the control.\n */\nexport function TooltipWrap({ label, side = 'top', children, asChild = true, delayDuration, hoverable = true }) {\n if (!label) return children;\n return (\n <Tooltip delayDuration={delayDuration} disableHoverableContent={!hoverable}>\n <TooltipTrigger asChild={asChild}>{children}</TooltipTrigger>\n <TooltipContent side={side} className=\"eb:px-2 eb:py-1 eb:text-[11px]\">\n {label}\n </TooltipContent>\n </Tooltip>\n );\n}\n","// @ts-check\n/**\n * STORAGE on the browser side — the interface only knows this contract.\n *\n * list() → templates, most recently changed first,\n * without document, MJML or HTML (optional:\n * the library — `TemplateLibrary`)\n * load(id) → template (document, mjml, revision…)\n * remove(id) → void (optional)\n * create(payload) → { template, warnings }\n * duplicate(id) → { template, warnings }\n * save(id, payload) → { template, warnings, version }\n * listVersions(id) → versions, newest first\n * getVersion(id, versionId) → version, project included\n * uploadImage(file) → { path }: RELATIVE path of the uploaded image\n * render(input) → { html, warnings, quality } (optional: preview)\n * sendTest(input) → { sent, failed, invalid, results } (optional: test send)\n * listVariables() → custom variables (optional: user-defined\n * saveVariable(variable) → saved variable variables, shared by\n * deleteVariable(key) → void every template)\n * listTags() → the workspace's tags (optional: tags on\n * saveTag(tag) → saved tag templates, at most\n * deleteTag(id) → void three each; `list()`\n * setTemplateTags(id, tagIds) → the template's tag ids gives their ids)\n *\n * The AI is not part of this contract: it is a module of its own\n * (`createAi`, `best-email-builder/ai`), given to the builder as `ai`.\n *\n * Two implementations: HTTP (talks to `createEmailBuilderHandler` from\n * `best-email-builder/server`, or to any backend with the same routes) and memory\n * (stories, tests, demos). The interface cannot tell them apart.\n *\n * The document ALWAYS travels serialized then re-read (`readDocument`): a\n * project that would not survive JSON shows up in the memory implementation\n * already, not in production.\n */\n\nimport { readDocument } from '../core/document.js';\nimport { DEFAULT_ASSETS_PATH } from '../renderer/links.js';\nimport { IMAGE_TYPES, imageUploadError } from '../validation/images.js';\nimport { DEFAULT_VARIABLES, validateCustomVariable } from '../features/variables/catalog.js';\nimport { cleanBrand } from '../features/brand/brand.js';\nimport { MAX_TAGS, checkTemplateTags, sortTags, validateTag } from '../features/tags/tags.js';\n\n/**\n * @typedef {import('../core/document.js').EmailDocument} EmailDocument\n * @typedef {import('../features/variables/catalog.js').EmailVariable} EmailVariable\n *\n * @typedef {{\n * id: number|string,\n * name: string,\n * description?: string|null,\n * subject?: string|null,\n * preheader?: string|null,\n * revision?: string|null,\n * document?: EmailDocument,\n * mjml?: string,\n * html?: string,\n * tags?: string[],\n * createdAt?: string,\n * updatedAt?: string|null,\n * }} StoredTemplate\n *\n * @typedef {{\n * name?: string,\n * description?: string|null,\n * subject?: string|null,\n * preheader?: string|null,\n * document: EmailDocument,\n * mjml: string,\n * revision?: string|null,\n * createVersion?: boolean,\n * }} SavePayload\n *\n * @typedef {{\n * id: number|string,\n * versionNumber: number,\n * name?: string,\n * subject?: string|null,\n * createdBy?: string|null,\n * createdAt?: string,\n * }} TemplateVersion\n *\n * @typedef {{mjml: string, subject?: string|null, preheader?: string|null}} RenderInput\n * @typedef {{html: string, warnings: {message: string}[], quality: {code: string, level: string, message: string}[]}} RenderResult\n * @typedef {import('../features/brand/brand.js').Brand} Brand\n * @typedef {import('../features/tags/tags.js').TemplateTag} TemplateTag\n * @typedef {{brand: Brand, notes: string[]}} BrandImportResult\n * `notes`: what could not be read (`LOGO_NOT_FOUND`, `LOGO_UNSUPPORTED`,\n * `LOGO_ICON`, `COLORS_NOT_FOUND`).\n * @typedef {{email: string, ok: boolean, error: string|null}} TestResult\n * @typedef {{sent: number, failed: number, invalid: string[], results: TestResult[]}} SendTestResult\n *\n * @typedef {{\n * list?: () => Promise<StoredTemplate[]>,\n * load: (id: number|string) => Promise<StoredTemplate>,\n * remove?: (id: number|string) => Promise<void>,\n * create: (payload: SavePayload & {name: string}) => Promise<{template: StoredTemplate, warnings: object[]}>,\n * duplicate: (id: number|string) => Promise<{template: StoredTemplate, warnings: object[]}>,\n * save: (id: number|string, payload: SavePayload) => Promise<{template: StoredTemplate, warnings: object[], version: {id: number|string, versionNumber: number}|null}>,\n * listVersions: (id: number|string) => Promise<TemplateVersion[]>,\n * getVersion: (id: number|string, versionId: number|string) => Promise<TemplateVersion & {document: EmailDocument, mjml: string}>,\n * uploadImage: (file: Blob & {name?: string}) => Promise<{path: string}>,\n * render?: (input: RenderInput) => Promise<RenderResult>,\n * sendTest?: (input: RenderInput & {emails: string[]}) => Promise<SendTestResult>,\n * listVariables?: () => Promise<EmailVariable[]>,\n * saveVariable?: (variable: Partial<EmailVariable>, options?: {create?: boolean}) => Promise<EmailVariable>,\n * deleteVariable?: (key: string) => Promise<void>,\n * loadBrand?: () => Promise<Brand>,\n * saveBrand?: (brand: Brand) => Promise<Brand>,\n * importBrand?: (url: string, options?: {signal?: AbortSignal}) => Promise<BrandImportResult>,\n * listTags?: () => Promise<TemplateTag[]>,\n * saveTag?: (tag: {id?: string, label: string, color: string}, options?: {create?: boolean}) => Promise<TemplateTag>,\n * deleteTag?: (id: string) => Promise<void>,\n * setTemplateTags?: (id: number|string, tagIds: string[]) => Promise<string[]>,\n * }} TemplateStorage\n */\n\nexport class StorageError extends Error {\n /** @param {string} message @param {number} status @param {string} [code] */\n constructor(message, status, code) {\n super(message);\n this.name = 'StorageError';\n this.status = status;\n this.code = code;\n }\n}\n\n/** @param {{type?: string, size?: number}} file */\nfunction assertUploadable(file) {\n const error = imageUploadError(file);\n if (error) throw new StorageError(error, 415, 'UNSUPPORTED_IMAGE');\n}\n\n/** Re-reads the document of a received template (JSON → validated envelope). */\nfunction withDocument(template) {\n if (!template || !template.document) return template;\n return { ...template, document: readDocument(template.document) };\n}\n\n/**\n * The HTTP side of a client: JSON in and out, the host's headers, errors as\n * `StorageError` (with the server's code). Shared by `createHttpStorage` and\n * the AI module (`best-email-builder/ai`).\n *\n * @param {{baseUrl?: string, headers?: Record<string, string> | (() => Record<string, string>), fetch?: typeof fetch}} [options]\n */\nexport function createHttpCaller({ baseUrl = '/api/email-builder', headers = {}, fetch: fetchImpl } = {}) {\n const root = baseUrl.replace(/\\/+$/, '');\n const doFetch = fetchImpl || ((input, init) => fetch(input, init));\n const extraHeaders = () => (typeof headers === 'function' ? headers() : headers);\n\n /** @param {Response} res */\n async function unwrap(res) {\n const json = await res.json().catch(() => ({}));\n if (!res.ok || json.error) {\n throw new StorageError(json.error || `Request failed (HTTP ${res.status})`, res.status, json.code);\n }\n return json.data;\n }\n\n /** @param {string} path @param {RequestInit} [init] */\n async function call(path, init) {\n const res = await doFetch(`${root}${path}`, {\n ...init,\n headers: { 'Content-Type': 'application/json', ...extraHeaders(), ...(init?.headers || {}) },\n });\n return unwrap(res);\n }\n\n return { root, call, unwrap, doFetch, extraHeaders };\n}\n\n/**\n * Client for the routes of `createEmailBuilderHandler` (`best-email-builder/server`).\n * The AI is a module of its own: `createAi` (`best-email-builder/ai`).\n *\n * `brand: true` turns on the Brand button: the server must have a\n * `brandStore`, and a `brandImporter` to read a brand from a website\n * (`brand: {import: false}` when it has none). `tags: true` turns on the\n * library's tags: the server must have a `tagStore`.\n *\n * @param {{\n * baseUrl?: string,\n * headers?: Record<string, string> | (() => Record<string, string>),\n * fetch?: typeof fetch,\n * brand?: boolean|{import?: boolean},\n * tags?: boolean,\n * }} [options]\n * @returns {TemplateStorage}\n */\nexport function createHttpStorage({ baseUrl, headers, fetch: fetchImpl, brand = false, tags = false } = {}) {\n const { root, call, unwrap, doFetch, extraHeaders } = createHttpCaller({ baseUrl, headers, fetch: fetchImpl });\n\n /** @param {SavePayload} payload */\n function body(payload) {\n return JSON.stringify({ ...payload, document: readDocument(payload.document) });\n }\n\n return {\n list: async () => call('/templates'),\n load: async (id) => withDocument(await call(`/templates/${encodeURIComponent(id)}`)),\n remove: async (id) => {\n await call(`/templates/${encodeURIComponent(id)}`, { method: 'DELETE' });\n },\n create: async (payload) => call('/templates', { method: 'POST', body: body(payload) }),\n duplicate: async (id) => call('/templates', { method: 'POST', body: JSON.stringify({ duplicateOf: id }) }),\n save: async (id, payload) => call(`/templates/${encodeURIComponent(id)}`, { method: 'PUT', body: body(payload) }),\n listVersions: async (id) => call(`/templates/${encodeURIComponent(id)}/versions`),\n getVersion: async (id, versionId) =>\n withDocument(await call(`/templates/${encodeURIComponent(id)}/versions/${encodeURIComponent(versionId)}`)),\n render: async (input) => call('/render', { method: 'POST', body: JSON.stringify(input) }),\n sendTest: async (input) => call('/test', { method: 'POST', body: JSON.stringify(input) }),\n listVariables: async () => call('/variables'),\n saveVariable: async (variable, { create = false } = {}) =>\n create\n ? call('/variables', { method: 'POST', body: JSON.stringify(variable) })\n : call(`/variables/${encodeURIComponent(String(variable.key))}`, { method: 'PUT', body: JSON.stringify(variable) }),\n deleteVariable: async (key) => {\n await call(`/variables/${encodeURIComponent(key)}`, { method: 'DELETE' });\n },\n ...(brand\n ? {\n loadBrand: async () => call('/brand'),\n saveBrand: async (value) => call('/brand', { method: 'PUT', body: JSON.stringify(value) }),\n ...(brand === true || brand.import !== false\n ? {\n importBrand: async (url, { signal } = {}) =>\n call('/brand/import', { method: 'POST', body: JSON.stringify({ url }), signal }),\n }\n : {}),\n }\n : {}),\n ...(tags\n ? {\n listTags: async () => call('/tags'),\n saveTag: async (tag, { create = false } = {}) =>\n create\n ? call('/tags', { method: 'POST', body: JSON.stringify(tag) })\n : call(`/tags/${encodeURIComponent(String(tag.id))}`, { method: 'PUT', body: JSON.stringify(tag) }),\n deleteTag: async (id) => {\n await call(`/tags/${encodeURIComponent(id)}`, { method: 'DELETE' });\n },\n setTemplateTags: async (id, tagIds) =>\n call(`/templates/${encodeURIComponent(id)}/tags`, { method: 'PUT', body: JSON.stringify({ tags: tagIds }) }),\n }\n : {}),\n async uploadImage(file) {\n assertUploadable(file);\n const form = new FormData();\n form.append('file', file, file.name || 'image');\n // No Content-Type: the browser sets the multipart boundary itself.\n const res = await doFetch(`${root}/assets`, { method: 'POST', body: form, headers: extraHeaders() });\n const data = await unwrap(res);\n return { path: data.path };\n },\n };\n}\n\n/**\n * In-memory storage, same contract. Documents are kept SERIALIZED.\n * `render` and `sendTest` cannot run in a browser (MJML compiles on the\n * server): pass implementations to enable the preview and test buttons;\n * `importBrand` likewise for reading a brand from a website. The brand itself is kept in memory (`brand`: the\n * one to start with), the tags too.\n *\n * `compile` gives the templates their final HTML, as the server keeps it:\n * called on every create and save, its `html` comes back with `load()` (the\n * library's *Copy HTML* and *Download*).\n *\n * @param {{\n * render?: TemplateStorage['render'],\n * sendTest?: TemplateStorage['sendTest'],\n * importBrand?: TemplateStorage['importBrand'],\n * compile?: (input: RenderInput) => Promise<{html: string}>,\n * brand?: Brand|null,\n * assetsPath?: string,\n * systemVariables?: EmailVariable[],\n * }} [options] `systemVariables`: keys a custom variable may not take\n * @returns {TemplateStorage & {dump: () => object}}\n */\nexport function createMemoryStorage({\n render,\n sendTest,\n importBrand,\n compile,\n brand = null,\n assetsPath = DEFAULT_ASSETS_PATH,\n systemVariables = DEFAULT_VARIABLES,\n} = {}) {\n /** @type {Map<string, any>} */\n const rows = new Map();\n /** @type {Map<string, any[]>} */\n const versions = new Map();\n /** @type {Map<string, Blob>} */\n const images = new Map();\n /** @type {Map<string, EmailVariable>} */\n const customVariables = new Map();\n /** @type {Map<string, TemplateTag>} */\n const tags = new Map();\n let savedBrand = cleanBrand(brand);\n let nextId = 1;\n let nextTagId = 1;\n let tick = Date.parse('2026-01-01T00:00:00.000Z');\n const now = () => new Date((tick += 1000)).toISOString();\n\n /** @param {any} row */\n function toTemplate(row) {\n return {\n id: row.id,\n name: row.name,\n description: row.description,\n subject: row.subject,\n preheader: row.preheader,\n revision: row.revision,\n document: readDocument(row.documentJson),\n mjml: row.mjml,\n ...(row.html !== undefined ? { html: row.html } : {}),\n tags: [...row.tags],\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n }\n\n /** The final HTML, when the storage was given a compiler. */\n const htmlOf = async (/** @type {RenderInput} */ input) => (compile ? { html: (await compile(input)).html } : {});\n const tagList = () => sortTags([...tags.values()]);\n\n /** @param {any} row */\n function snapshot(row) {\n const list = versions.get(String(row.id)) || [];\n const entry = {\n id: list.length + 1,\n versionNumber: list.length + 1,\n name: row.name,\n subject: row.subject,\n createdBy: null,\n createdAt: row.revision,\n documentJson: row.documentJson,\n mjml: row.mjml,\n };\n versions.set(String(row.id), [...list, entry]);\n return { id: entry.id, versionNumber: entry.versionNumber };\n }\n\n /** @param {number|string} id */\n function rowOf(id) {\n const row = rows.get(String(id));\n if (!row) throw new StorageError('Template not found', 404, 'NOT_FOUND');\n return row;\n }\n\n /** @type {TemplateStorage & {dump: () => object}} */\n const storage = {\n async list() {\n return [...rows.values()]\n .sort((a, b) => (b.updatedAt || b.createdAt).localeCompare(a.updatedAt || a.createdAt))\n .map((row) => {\n const { document: _d, mjml: _m, html: _h, ...summary } = toTemplate(row);\n return summary;\n });\n },\n async load(id) {\n return toTemplate(rowOf(id));\n },\n async remove(id) {\n rowOf(id);\n rows.delete(String(id));\n versions.delete(String(id));\n },\n async create(payload) {\n if (!payload.name?.trim()) throw new StorageError('Name required', 400, 'NAME_REQUIRED');\n const documentJson = JSON.stringify(readDocument(payload.document));\n const compiled = await htmlOf({ mjml: payload.mjml, subject: payload.subject, preheader: payload.preheader });\n const at = now();\n const row = {\n id: nextId++,\n name: payload.name.trim(),\n description: payload.description ?? null,\n subject: payload.subject ?? null,\n preheader: payload.preheader ?? null,\n documentJson,\n mjml: payload.mjml,\n ...compiled,\n tags: [],\n createdAt: at,\n updatedAt: null,\n revision: at,\n };\n rows.set(String(row.id), row);\n snapshot(row);\n return { template: toTemplate(row), warnings: [] };\n },\n async duplicate(id) {\n const source = rowOf(id);\n const result = await storage.create({\n name: `${source.name} (copy)`,\n description: source.description,\n subject: source.subject,\n preheader: source.preheader,\n document: readDocument(source.documentJson),\n mjml: source.mjml,\n });\n // A copy keeps its tags.\n rowOf(result.template.id).tags = [...source.tags];\n return { ...result, template: { ...result.template, tags: [...source.tags] } };\n },\n async save(id, payload) {\n const row = rowOf(id);\n if (payload.revision && payload.revision !== row.revision) {\n throw new StorageError('Template changed in the meantime — reload it before saving', 409, 'CONFLICT');\n }\n const documentJson = JSON.stringify(readDocument(payload.document));\n const compiled = await htmlOf({\n mjml: payload.mjml,\n subject: payload.subject !== undefined ? payload.subject : row.subject,\n preheader: payload.preheader !== undefined ? payload.preheader : row.preheader,\n });\n const at = now();\n Object.assign(row, {\n ...(payload.name !== undefined ? { name: payload.name } : {}),\n ...(payload.description !== undefined ? { description: payload.description } : {}),\n ...(payload.subject !== undefined ? { subject: payload.subject } : {}),\n ...(payload.preheader !== undefined ? { preheader: payload.preheader } : {}),\n documentJson,\n mjml: payload.mjml,\n ...compiled,\n updatedAt: at,\n revision: at,\n });\n const version = payload.createVersion ? snapshot(row) : null;\n const { document: _omit, ...template } = toTemplate(row);\n return { template, warnings: [], version };\n },\n async listVersions(id) {\n rowOf(id);\n return [...(versions.get(String(id)) || [])].reverse().map(({ documentJson: _d, mjml: _m, ...v }) => v);\n },\n async getVersion(id, versionId) {\n const entry = (versions.get(String(id)) || []).find((v) => String(v.id) === String(versionId));\n if (!entry) throw new StorageError('Version not found', 404, 'NOT_FOUND');\n const { documentJson, ...version } = entry;\n return { ...version, document: readDocument(documentJson) };\n },\n async uploadImage(file) {\n assertUploadable(file);\n // Same key as the server: 32 hex characters of the hash + extension.\n const digest = await crypto.subtle.digest('SHA-256', await file.arrayBuffer());\n const hex = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('');\n const path = `${assetsPath}${hex.slice(0, 32)}.${IMAGE_TYPES[file.type]}`;\n images.set(path, file);\n return { path };\n },\n async listVariables() {\n return [...customVariables.values()].map((v) => ({ ...v }));\n },\n async saveVariable(input, { create = false } = {}) {\n const existing = [...systemVariables, ...customVariables.values()];\n if (!create && !customVariables.has(String(input?.key))) {\n throw new StorageError('Variable not found', 404, 'NOT_FOUND');\n }\n const base = create ? {} : customVariables.get(String(input.key));\n const { variable, errors } = validateCustomVariable({ ...base, ...input }, { existing, editing: create ? null : input.key });\n if (errors) throw new StorageError(Object.values(errors)[0], 400, 'INVALID_VARIABLE');\n customVariables.set(variable.key, variable);\n return { ...variable };\n },\n async deleteVariable(key) {\n if (!customVariables.delete(String(key))) throw new StorageError('Variable not found', 404, 'NOT_FOUND');\n },\n async loadBrand() {\n return { ...savedBrand };\n },\n async saveBrand(value) {\n savedBrand = cleanBrand(value);\n return { ...savedBrand };\n },\n async listTags() {\n return tagList().map((tag) => ({ ...tag }));\n },\n async saveTag(input, { create = false } = {}) {\n if (!create && !tags.has(String(input?.id))) throw new StorageError('Tag not found', 404, 'NOT_FOUND');\n if (create && tags.size >= MAX_TAGS) throw new StorageError(`${MAX_TAGS} tags at most`, 400, 'TOO_MANY_TAGS');\n const { tag, errors } = validateTag(input, { existing: tagList(), editing: create ? null : String(input.id) });\n if (errors) throw new StorageError(Object.values(errors)[0], 400, 'INVALID_TAG');\n const saved = { id: create ? String(nextTagId++) : String(input.id), ...tag };\n tags.set(saved.id, saved);\n return { ...saved };\n },\n async deleteTag(id) {\n if (!tags.delete(String(id))) throw new StorageError('Tag not found', 404, 'NOT_FOUND');\n for (const row of rows.values()) row.tags = row.tags.filter((tagId) => tagId !== String(id));\n },\n async setTemplateTags(id, tagIds) {\n const row = rowOf(id);\n const { ids, error } = checkTemplateTags(tagIds, tagList());\n if (error) throw new StorageError(error.message, 400, error.code);\n row.tags = ids;\n return [...ids];\n },\n ...(importBrand ? { importBrand } : {}),\n ...(render ? { render } : {}),\n ...(sendTest ? { sendTest } : {}),\n dump: () => ({\n rows: [...rows.values()],\n versions: Object.fromEntries(versions),\n images: [...images.keys()],\n variables: [...customVariables.values()],\n brand: savedBrand,\n tags: tagList(),\n }),\n };\n return storage;\n}\n","import { forwardRef } from 'react';\nimport { Label as LabelPrimitive } from 'radix-ui';\nimport { cn } from './cn.js';\n\n// forwardRef: React 18 does not pass `ref` as a prop.\nexport const Input = forwardRef(function Input({ className, type, ...props }, ref) {\n return (\n <input\n ref={ref}\n type={type}\n data-slot=\"input\"\n className={cn(\n 'eb:h-8 eb:w-full eb:min-w-0 eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:px-3 eb:py-1 eb:text-[13px] eb:text-foreground eb:shadow-xs eb:transition-[color,box-shadow] eb:outline-none eb:placeholder:text-foreground-muted eb:selection:bg-primary eb:selection:text-primary-foreground eb:disabled:pointer-events-none eb:disabled:cursor-not-allowed eb:disabled:opacity-50',\n 'eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50',\n 'eb:aria-invalid:border-destructive eb:aria-invalid:ring-destructive/20',\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Textarea = forwardRef(function Textarea({ className, ...props }, ref) {\n return (\n <textarea\n ref={ref}\n data-slot=\"textarea\"\n className={cn(\n 'eb:flex eb:field-sizing-content eb:min-h-16 eb:w-full eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:px-3 eb:py-2 eb:text-[13px] eb:text-foreground eb:shadow-xs eb:transition-[color,box-shadow] eb:outline-none eb:placeholder:text-foreground-muted eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50 eb:aria-invalid:border-destructive eb:aria-invalid:ring-destructive/20 eb:disabled:cursor-not-allowed eb:disabled:opacity-50',\n className\n )}\n {...props}\n />\n );\n});\n\nexport function Label({ className, ...props }) {\n return (\n <LabelPrimitive.Root\n data-slot=\"label\"\n className={cn(\n 'eb:flex eb:items-center eb:gap-2 eb:text-[13px] eb:leading-none eb:font-medium eb:text-foreground eb:select-none eb:peer-disabled:cursor-not-allowed eb:peer-disabled:opacity-50',\n className\n )}\n {...props}\n />\n );\n}\n"],"mappings":"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","names":["jsx","jsx","jsxs","jsx","jsxs","options","jsx","Input","Textarea"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
identity,
|
|
3
3
|
isAssetPath
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZTUW25BG.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-
|
|
251
|
+
//# sourceMappingURL=chunk-A4KF7NMP.js.map
|